class Bosh::OpenStackCloud::NetworkConfigurator

Represents OpenStack server network config. OpenStack server has single NIC with a dynamic or manual IP's address and (optionally) a single floating IP address which server itself is not aware of (vip). Thus we should perform a number of sanity checks for the network spec provided by director to make sure we don't apply something OpenStack doesn't understand how to deal with.

Public Class Methods

new(spec) click to toggle source

Creates new network spec

@param [Hash] spec Raw network spec passed by director

# File lib/cloud/openstack/network_configurator.rb, line 19
def initialize(spec)
  unless spec.is_a?(Hash)
    raise ArgumentError, "Invalid spec, Hash expected, #{spec.class} provided"
  end

  @logger = Bosh::Clouds::Config.logger
  @networks = []
  @vip_network = nil
  @security_groups = []
  @net_ids = []
  @dynamic_network = nil

  spec.each_pair do |name, network_spec|
    initialize_network(name, network_spec)
  end

  cloud_error("At least one dynamic or manual network should be defined") if @networks.empty?
end

Public Instance Methods

configure(openstack, server) click to toggle source

Applies network configuration to the vm

@param [Fog::Compute::OpenStack] openstack Fog OpenStack Compute client @param [Fog::Compute::OpenStack::Server] server OpenStack server to

configure
# File lib/cloud/openstack/network_configurator.rb, line 82
def configure(openstack, server)
  @networks.each do |network_info|
    network = network_info["network"]
    network.configure(openstack, server)
  end

  if @vip_network
    @vip_network.configure(openstack, server)
  else
    # If there is no vip network we should disassociate any floating IP
    # currently held by server (as it might have had floating IP before)
    with_openstack do
      addresses = openstack.addresses
      addresses.each do |address|
        if address.instance_id == server.id
          @logger.info("Disassociating floating IP `#{address.ip}' " \
                       "from server `#{server.id}'")
          address.server = nil
        end
      end
    end
  end
end
initialize_network(name, network_spec) click to toggle source

Setup network configuration for one network spec.

@param [String] network spec name @param [Hash] network spec

configure
# File lib/cloud/openstack/network_configurator.rb, line 44
def initialize_network(name, network_spec)
  network_type = network_spec["type"] || "manual"

  case network_type
    when "dynamic"
      cloud_error("Only one dynamic network per instance should be defined") if @dynamic_network
      net_id = extract_net_id(network_spec)
      cloud_error("Dynamic network with id #{net_id} is already defined") if @net_ids.include?(net_id)
      network = DynamicNetwork.new(name, network_spec)
      @security_groups += extract_security_groups(network_spec)
      @networks << {"network" => network, "net_id" => net_id}
      @net_ids << net_id
      @dynamic_network = network
    when "manual"
      net_id = extract_net_id(network_spec)
      cloud_error("Manual network must have net_id") if net_id.nil?
      cloud_error("Manual network with id #{net_id} is already defined") if @net_ids.include?(net_id)
      network = ManualNetwork.new(name, network_spec)
      @security_groups += extract_security_groups(network_spec)
      @networks << {"network" => network, "net_id" => net_id}
      @net_ids << net_id
    when "vip"
      cloud_error("Only one VIP network per instance should be defined") if @vip_network
      @vip_network = VipNetwork.new(name, network_spec)
      @security_groups += extract_security_groups(network_spec)
    else
      cloud_error("Invalid network type `#{network_type}': OpenStack " \
                  "CPI can only handle `dynamic', 'manual' or `vip' " \
                  "network types")
  end
end
nics() click to toggle source

Returns the nics for this network configuration

@return [Array] nics

# File lib/cloud/openstack/network_configurator.rb, line 137
def nics
  @networks.inject([]) do |memo, network_info|
    net_id = network_info["net_id"]
    network = network_info["network"]
    nic = {}
    nic["net_id"] = net_id if net_id
    nic["v4_fixed_ip"] = network.private_ip if network.is_a?(ManualNetwork)
    memo << nic if nic.any?
    memo
  end
end
private_ips() click to toggle source

Returns the private IP addresses for this network configuration

@return [Array<String>] private ip addresses

# File lib/cloud/openstack/network_configurator.rb, line 125
def private_ips
  @networks.inject([]) do |memo, network_info|
    network = network_info["network"]
    memo << network.private_ip if network.is_a?(ManualNetwork)
    memo
  end
end
security_groups(default = nil) click to toggle source

Returns the security groups for this network configuration, or the default security groups if the configuration does not contain security groups

@param [Array] default Default security groups @return [Array] security groups

# File lib/cloud/openstack/network_configurator.rb, line 113
def security_groups(default = nil)
  if @security_groups.empty? && default
    default
  else
    @security_groups.sort
  end
end

Private Instance Methods

extract_net_id(network_spec) click to toggle source

Extracts the network ID from the network configuration

@param [Hash] network_spec Network specification @return [Hash] network ID

# File lib/cloud/openstack/network_configurator.rb, line 175
def extract_net_id(network_spec)
  if network_spec && network_spec["cloud_properties"]
    cloud_properties = network_spec["cloud_properties"]
    if cloud_properties && cloud_properties.has_key?("net_id")
      return cloud_properties["net_id"]
    end
  end
  nil
end
extract_security_groups(network_spec) click to toggle source

Extracts the security groups from the network configuration

@param [Hash] network_spec Network specification @return [Array] security groups @raise [ArgumentError] if the security groups in the network_spec is not an Array

# File lib/cloud/openstack/network_configurator.rb, line 157
def extract_security_groups(network_spec)
  if network_spec && network_spec["cloud_properties"]
    cloud_properties = network_spec["cloud_properties"]
    if cloud_properties && cloud_properties.has_key?("security_groups")
      unless cloud_properties["security_groups"].is_a?(Array)
        raise ArgumentError, "security groups must be an Array"
      end
      return cloud_properties["security_groups"]
    end
  end
  []
end