How to provision an OpenStack instance with multiple cloud networks?

automate

#1

Hi,
I have a service dialog that allows the request of multiple cloud networks (they are filtered by cloud tenant).

I already managed to find a way to provision multiple security groups, but this one eludes me.

Any tips?

Thank you for your time.
Rui


#2

Hi,

The MiQ API was not doing what I needed. I solved this task using Fog.

require 'fog/openstack'

prov = $evm.root["miq_provision"]

# Get the EMS ID
ems_id = prov.destination.ems_id
raise "invalid ems_id" if ems_id.nil?
ems = $evm.vmdb('ems').find_by_id(ems_id)
raise "ems not found" if ems.nil?

# Get the Tenant name for project below
tenant_id = prov.destination.cloud_tenant_id
raise "invalid tenant id" if tenant_id.nil?
tenant = $evm.vmdb('CloudTenant').find_by_id(tenant_id)
raise "invalid tenant" if tenant.nil?

# Authentication vars
auth_url = "http://#{ems.hostname}:35357/v3/auth/tokens"
username = ems.authentication_userid
password = ems.authentication_password
project = tenant.name
domain = 'Default'

# Create the compute object
compute = Fog::Compute::OpenStack.new(
  {
    :openstack_auth_url => auth_url,
    :openstack_username => username,
    :openstack_api_key  => password,
    :openstack_project_name => project,
    :openstack_domain_name => domain
    # Optional, self-signed certs
    #:connection_options => { :ssl_verify_peer => false }
    }
  )

raise "compute object creation failed!" if compute.nil?

# Create the Network object
network = Fog::Network::OpenStack.new(
  {
    :openstack_auth_url => auth_url,
    :openstack_username => username,
    :openstack_api_key  => password,
    :openstack_project_name => project,
    :openstack_domain_name => domain
    # Optional, self-signed certs
    #:connection_options => { :ssl_verify_peer => false }
    }
  )

raise "network object creation failed!" if network.nil?

#
# Action Plan to create multiple interfaces
#
# Required vars from ManageIQ:
# - instance name
# - desired network names
#
# The server object has a create_os_interface api. It requires:
# 1. server_id
# 2. Options Array: net_id
#
# From the server we get server_id, and already configured network names.
#
# for each not configured network, create the interface. for that
# we need the OSP net_id.

vm_name = prov.destination.name
$evm.log(:info, "VM Name: #{vm_name.class} -- #{vm_name}")

dialog = prov.miq_provision_request.options[:dialog]

requested_networks = dialog['Array::dialog_cloud_network'].split(",")
$evm.log(:info, "Networks: #{requested_networks.class} -- #{requested_networks}")

server = compute.servers.find { |vm| vm.name == vm_name }
raise "invalid server object" if server.nil?
$evm.log(:info, "Server: #{server.name} - #{server.id}")
$evm.log(:info, "Existing Networks: #{server.addresses.keys}")

requested_networks.each do |net_id|
  cloud_network = $evm.vmdb('CloudNetwork').find_by_id(net_id.to_i)
  raise "Invalid network #{net_id}" if cloud_network.nil?

  $evm.log(:info, "checking Cloud Network: #{net_id} - #{cloud_network.name}")
  tmpnet = network.networks.find { |nt| nt.name == cloud_network.name }
  raise "invalid network #{net_id} - #{cloud_network.name}" if tmpnet.nil?

  if server.addresses.keys.include? tmpnet.name
    $evm.log(:info, "Network '#{tmpnet.name}' exists. Skipping...")
  else
    # Create a new interface
    compute.create_os_interface(server.id, {:net_id => tmpnet.id})
  end
end