mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-02 09:47:00 +03:00
* F #3440: Create and delete NSX networks This allows to create and delete from command line both NSX-V netwoks and NSX-T networks. * F #1256: Allow attach created Opaque Networks This allows to attach a new created Opaque Network to a instance. * F #3440: Allows attach/detach created NSX-V networks Changes included: Allow attach and detach nics to a VM from nsx-v networks created from OpenNebula. Improve function to retrieve nsx-t network identifier on vc * M #-: Change Network types as constants Created new constans into Network class to identify the different types of networks Also changed order to detect Network avoiding incorrect detections due to its parent Classes * F #3440 #1256: Added NSX info to monitor Added the following NSX info to host monitor: NSX_MANAGER: "NSX Manager | NSX-T Manager" NSX_TYPE: "NSX-V | NSX-T" NSX_VERSION: "NSX-V or NSX-T version" NSX_URL: NSX Manager url * F #3440: Add Transport Zones to monitor host info If the folowing attributes are correct, the transport zones are listed into the host monitor information: NSX_MANAGER NSX_TYPE NSX_USER NSX_PASSWORD * F #3440: Change NSX parameters to Host object Some parameters created in first instance in vnet object for testing purposes, has been changed to its definitive placement, the Host object. * F #3440: Added NSX_STATUS Added NSX_STATUS attribute, checking the following: - NSX_USER (Check if attribute is setted) - NSX_PASSWORD (Check if attribute is setted) - NSX_TYPE (Check if attribute is setted) - NSX_MANAGER (Check if attribute is setted) - Check a correct connection with NSX Manager The result is shown in the attribute NSX_STATUS, that should be NSX_STATUS = "OK" if all is correct. * F #3440: Refactor and clean Refactor code into classes and clean. * F #3440: Clean and rubocop Set url as base_url + section + parameter Correction to avoid rubocop warnings * F #3440: Rubocop fixes Corrected rubocop warnings * F #3440: Fix rubocop warnings on hooks Fixed rubocop warnings on network hooks * F #3440: Fix rubocop warning on nsx_driver.rb * F #3440: Forgotten sleep to timeout Added a forgotten sleep into a timeout secuence. Added cosmetic changes to minimize code lines.
This commit is contained in:
parent
a297619227
commit
e5e169932f
13
install.sh
13
install.sh
@ -704,6 +704,7 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
|
||||
src/sunstone/OpenNebulaVNC.rb \
|
||||
src/sunstone/OpenNebulaAddons.rb \
|
||||
src/vmm_mad/remotes/vcenter/vcenter_driver.rb \
|
||||
src/vmm_mad/remotes/nsx/nsx_driver.rb \
|
||||
src/vmm_mad/remotes/az/az_driver.rb \
|
||||
src/vmm_mad/remotes/ec2/ec2_driver.rb \
|
||||
src/vmm_mad/remotes/one/opennebula_driver.rb \
|
||||
@ -805,7 +806,7 @@ VMM_EXEC_LIB_FILES="src/vmm_mad/remotes/lib/poll_common.rb"
|
||||
# $REMOTES_LOCATION/vmm/lib/vcenter
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb
|
||||
VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vi_client.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vcenter_importer.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/file_helper.rb \
|
||||
@ -824,6 +825,16 @@ VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_helper/vm_helper.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_monitor/vm_monitor.rb"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM Lib nsx files, used by the NSX Driver to be installed in
|
||||
# $REMOTES_LOCATION/vmm/lib/nsx
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
VMM_EXEC_LIB_NSX_FILES="src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb \
|
||||
src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb \
|
||||
src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb \
|
||||
src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM SH Driver LXD scripts, to be installed under $REMOTES_LOCATION/vmm/lxd
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -16,39 +16,41 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION=ENV["ONE_LOCATION"]
|
||||
ONE_LOCATION = ENV['ONE_LOCATION']
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
|
||||
VMDIR="/var/lib/one"
|
||||
CONFIG_FILE="/var/lib/one/config"
|
||||
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
||||
VMDIR = '/var/lib/one'
|
||||
CONFIG_FILE = '/var/lib/one/config'
|
||||
else
|
||||
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
|
||||
VMDIR=ONE_LOCATION+"/var"
|
||||
CONFIG_FILE=ONE_LOCATION+"/var/config"
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
||||
VMDIR = ONE_LOCATION + '/var'
|
||||
CONFIG_FILE = ONE_LOCATION + '/var/config'
|
||||
end
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION
|
||||
|
||||
require 'opennebula'
|
||||
require 'vcenter_driver'
|
||||
require 'base64'
|
||||
require 'nsx_driver'
|
||||
|
||||
network_id = ARGV[0]
|
||||
#base64_temp = ARGV[1]
|
||||
network_id = ARGV[0]
|
||||
# base64_temp = ARGV[1]
|
||||
|
||||
#template = OpenNebula::XMLElement.new
|
||||
#template.initialize_xml(Base64.decode64(base64_temp), 'VNET')
|
||||
# template = OpenNebula::XMLElement.new
|
||||
# template.initialize_xml(Base64.decode64(base64_temp), 'VNET')
|
||||
|
||||
# waits for a vlan_id attribute to be generated
|
||||
# only if automatic_vlan activated
|
||||
def wait_vlanid(vnet)
|
||||
retries = 5
|
||||
i = 0
|
||||
while vnet["VLAN_ID"].nil?
|
||||
raise "cannot get vlan_id" if i >= retries
|
||||
while vnet['VLAN_ID'].nil?
|
||||
raise 'cannot get vlan_id' if i >= retries
|
||||
|
||||
sleep 1
|
||||
i +=1
|
||||
i += 1
|
||||
vnet.info
|
||||
end
|
||||
end
|
||||
@ -58,59 +60,112 @@ def update_net(vnet, content)
|
||||
rc = vnet.update(content, true)
|
||||
vnet.lock(1)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
raise "Could not update the virtual network"
|
||||
end
|
||||
raise 'Could not update the virtual network' if OpenNebula.is_error?(rc)
|
||||
end
|
||||
|
||||
one_vnet = OpenNebula::VirtualNetwork.new_with_id(network_id, OpenNebula::Client.new)
|
||||
one_vnet = OpenNebula::VirtualNetwork
|
||||
.new_with_id(network_id, OpenNebula::Client.new)
|
||||
rc = one_vnet.info
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDERR.puts rc.message
|
||||
exit 1
|
||||
end
|
||||
one_vnet.lock(1)
|
||||
esx_rollback = [] #Track hosts that require a rollback
|
||||
managed = one_vnet["TEMPLATE/OPENNEBULA_MANAGED"] != "NO"
|
||||
imported = one_vnet["TEMPLATE/VCENTER_IMPORTED"]
|
||||
esx_rollback = [] # Track hosts that require a rollback
|
||||
managed = one_vnet['TEMPLATE/OPENNEBULA_MANAGED'] != 'NO'
|
||||
imported = one_vnet['TEMPLATE/VCENTER_IMPORTED']
|
||||
|
||||
begin
|
||||
# Step 0. Only execute for vcenter network driver && managed by one
|
||||
if one_vnet["VN_MAD"] == "vcenter" && managed && imported.nil?
|
||||
wait_vlanid(one_vnet) if one_vnet["VLAN_ID_AUTOMATIC"] == '1'
|
||||
if one_vnet['VN_MAD'] == 'vcenter' && managed && imported.nil?
|
||||
wait_vlanid(one_vnet) if one_vnet['VLAN_ID_AUTOMATIC'] == '1'
|
||||
# Step 1. Extract vnet settings
|
||||
host_id = one_vnet["TEMPLATE/VCENTER_ONE_HOST_ID"]
|
||||
raise "We require the ID of the OpenNebula host representing a vCenter cluster" if !host_id
|
||||
host_id = one_vnet['TEMPLATE/VCENTER_ONE_HOST_ID']
|
||||
raise 'Missing VCENTER_ONE_HOST_ID' unless host_id
|
||||
|
||||
pnics = one_vnet["TEMPLATE/PHYDEV"]
|
||||
pg_name = one_vnet["TEMPLATE/BRIDGE"]
|
||||
pg_type = one_vnet["TEMPLATE/VCENTER_PORTGROUP_TYPE"]
|
||||
sw_name = one_vnet["TEMPLATE/VCENTER_SWITCH_NAME"]
|
||||
mtu = one_vnet["TEMPLATE/MTU"]
|
||||
vlan_id = one_vnet["VLAN_ID"] || 0
|
||||
pnics = one_vnet['TEMPLATE/PHYDEV']
|
||||
pg_name = one_vnet['TEMPLATE/BRIDGE']
|
||||
pg_type = one_vnet['TEMPLATE/VCENTER_PORTGROUP_TYPE']
|
||||
sw_name = one_vnet['TEMPLATE/VCENTER_SWITCH_NAME']
|
||||
mtu = one_vnet['TEMPLATE/MTU']
|
||||
vlan_id = one_vnet['VLAN_ID'] || 0
|
||||
|
||||
if one_vnet["TEMPLATE/VCENTER_SWITCH_NPORTS"]
|
||||
nports = one_vnet["TEMPLATE/VCENTER_SWITCH_NPORTS"]
|
||||
# NSX parameters
|
||||
ls_name = one_vnet['NAME']
|
||||
ls_description = one_vnet['TEMPLATE/DESCRIPTION']
|
||||
tz_id = one_vnet['TEMPLATE/NSX_TZ_ID']
|
||||
|
||||
if one_vnet['TEMPLATE/VCENTER_SWITCH_NPORTS']
|
||||
nports = one_vnet['TEMPLATE/VCENTER_SWITCH_NPORTS']
|
||||
else
|
||||
nports = pg_type == "Port Group" ? 128 : 8
|
||||
pg_type == 'Port Group' ? nports = 128 : nports = 8
|
||||
end
|
||||
|
||||
# Step 2. Contact cluster and extract cluster's info
|
||||
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
||||
vc_uuid = vi_client.vim.serviceContent.about.instanceUuid
|
||||
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
||||
vc_uuid = vi_client.vim.serviceContent.about.instanceUuid
|
||||
one_client = OpenNebula::Client.new
|
||||
one_host = OpenNebula::Host.new_with_id(host_id, one_client)
|
||||
rc = one_host.info
|
||||
raise rc.message if OpenNebula::is_error? rc
|
||||
one_host = OpenNebula::Host.new_with_id(host_id, one_client)
|
||||
rc = one_host.info
|
||||
raise rc.message if OpenNebula.is_error? rc
|
||||
|
||||
vnet_ref = nil
|
||||
blocked = false
|
||||
ccr_ref = one_host["TEMPLATE/VCENTER_CCR_REF"]
|
||||
cluster = VCenterDriver::ClusterComputeResource.new_from_ref(ccr_ref, vi_client)
|
||||
blocked = false
|
||||
ccr_ref = one_host['TEMPLATE/VCENTER_CCR_REF']
|
||||
cluster = VCenterDriver::ClusterComputeResource
|
||||
.new_from_ref(ccr_ref, vi_client)
|
||||
dc = cluster.get_dc
|
||||
|
||||
ls_vni = nil
|
||||
net_info = ''
|
||||
|
||||
# NSX
|
||||
# nsxmgr = one_host['TEMPLATE/NSX_MANAGER']
|
||||
# nsx_user = one_host['TEMPLATE/NSX_USER']
|
||||
# nsx_pass_enc = one_host['TEMPLATE/NSX_MANAGER']
|
||||
# NSX
|
||||
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_NSXV
|
||||
nsx_client = NSXDriver::NSXClient.new(host_id)
|
||||
virtual_wire_spec =
|
||||
"<virtualWireCreateSpec>\
|
||||
<name>#{ls_name}</name>\
|
||||
<description>#{ls_description}</description>\
|
||||
<tenantId>virtual wire tenant</tenantId>\
|
||||
<controlPlaneMode>UNICAST_MODE</controlPlaneMode>\
|
||||
<guestVlanAllowed>false</guestVlanAllowed>\
|
||||
</virtualWireCreateSpec>"
|
||||
logical_switch = NSXDriver::VirtualWire
|
||||
.new(nsx_client, nil, tz_id, virtual_wire_spec)
|
||||
# Get reference will have in vcenter and vni
|
||||
vnet_ref = logical_switch.ls_vcenter_ref
|
||||
ls_vni = logical_switch.ls_vni
|
||||
net_info << "NSX_ID=\"#{logical_switch.ls_id}\"\n"
|
||||
net_info << "NSX_VNI=\"#{ls_vni}\"\n"
|
||||
end
|
||||
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
nsx_client = NSXDriver::NSXClient.new(host_id)
|
||||
opaque_network_spec = %(
|
||||
{
|
||||
"transport_zone_id": "#{tz_id}",
|
||||
"replication_mode": "MTEP",
|
||||
"admin_state": "UP",
|
||||
"display_name": "#{ls_name}",
|
||||
"description": "#{ls_description}"
|
||||
}
|
||||
)
|
||||
logical_switch = NSXDriver::OpaqueNetwork
|
||||
.new(nsx_client, nil, nil, opaque_network_spec)
|
||||
# Get NSX_VNI
|
||||
vnet_ref = dc.nsx_network(logical_switch.ls_id, pg_type)
|
||||
ls_vni = logical_switch.ls_vni
|
||||
net_info << "NSX_ID=\"#{logical_switch.ls_id}\"\n"
|
||||
net_info << "NSX_VNI=\"#{ls_vni}\"\n"
|
||||
end
|
||||
|
||||
# With DVS we have to work at datacenter level and then for each host
|
||||
if pg_type == "Distributed Port Group"
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
begin
|
||||
dc.lock
|
||||
net_folder = dc.network_folder
|
||||
@ -137,19 +192,18 @@ begin
|
||||
else
|
||||
blocked = true
|
||||
end
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
raise e
|
||||
ensure
|
||||
dc.unlock if dc
|
||||
end
|
||||
end
|
||||
|
||||
cluster["host"].each do |host|
|
||||
|
||||
cluster['host'].each do |host|
|
||||
# Step 3. Loop through hosts in clusters
|
||||
esx_host = VCenterDriver::ESXHost.new_from_ref(host._ref, vi_client)
|
||||
|
||||
if pg_type == "Port Group"
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_PG
|
||||
begin
|
||||
esx_host.lock # Exclusive lock for ESX host operation
|
||||
|
||||
@ -161,9 +215,9 @@ begin
|
||||
|
||||
# Disallow changes of switch name for existing pg
|
||||
if pg && esx_host.pg_changes_sw?(pg, sw_name)
|
||||
raise "The port group already exists in this host "\
|
||||
" for a different vCenter standard switch and this kind of "
|
||||
" change is not supported."
|
||||
raise 'The port group already exists in this host '\
|
||||
'for a different vCenter standard switch and '\
|
||||
'this kind of hange is not supported.'
|
||||
end
|
||||
|
||||
# Pg does not exits
|
||||
@ -172,15 +226,18 @@ begin
|
||||
vs = esx_host.vss_exists(sw_name)
|
||||
|
||||
if !vs
|
||||
sw_name = esx_host.create_vss(sw_name, pnics, nports, mtu, pnics_available)
|
||||
sw_name = esx_host.create_vss(sw_name,
|
||||
pnics,
|
||||
nports,
|
||||
mtu,
|
||||
pnics_available)
|
||||
end
|
||||
|
||||
vnet_ref = esx_host.create_pg(pg_name, sw_name, vlan_id)
|
||||
else
|
||||
blocked = true
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
raise e
|
||||
ensure
|
||||
esx_rollback << esx_host
|
||||
@ -188,88 +245,115 @@ begin
|
||||
end
|
||||
end
|
||||
|
||||
if pg_type == "Distributed Port Group"
|
||||
begin
|
||||
esx_host.lock
|
||||
if dvs
|
||||
pnics_available = nil
|
||||
pnics_available = esx_host.get_available_pnics if pnics && !pnics.empty?
|
||||
esx_host.assign_proxy_switch(dvs, sw_name, pnics, pnics_available)
|
||||
next unless pg_type == VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
|
||||
begin
|
||||
esx_host.lock
|
||||
if dvs
|
||||
pnics_available = nil
|
||||
if pnics && !pnics.empty?
|
||||
pnics_available = esx_host.get_available_pnics
|
||||
end
|
||||
rescue Exception => e
|
||||
raise e
|
||||
ensure
|
||||
esx_host.unlock if esx_host
|
||||
esx_host.assign_proxy_switch(dvs,
|
||||
sw_name,
|
||||
pnics,
|
||||
pnics_available)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise e
|
||||
ensure
|
||||
esx_host.unlock if esx_host
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# We must update XML so the VCENTER_NET_REF and VCENTER_INSTANCE_ID are added
|
||||
# Update network XML
|
||||
net_info << "VCENTER_NET_REF=\"#{vnet_ref}\"\n"
|
||||
net_info << "VCENTER_INSTANCE_ID=\"#{vc_uuid}\"\n"
|
||||
|
||||
if blocked
|
||||
update_net(one_vnet,"VCENTER_NET_REF=\"#{vnet_ref}\"\nVCENTER_INSTANCE_ID=\"#{vc_uuid}\"\nVCENTER_NET_STATE=\"ERROR\"\nVCENTER_NET_ERROR=\"vnet already exist in vcenter\"\n")
|
||||
net_info << "VCENTER_NET_STATE=\"ERROR\"\n"
|
||||
net_info << "VCENTER_NET_ERROR=\"vnet already exist in vcenter\"\n"
|
||||
else
|
||||
update_net(one_vnet,"VCENTER_NET_REF=\"#{vnet_ref}\"\nVCENTER_INSTANCE_ID=\"#{vc_uuid}\"\nVCENTER_NET_STATE=\"READY\"\nVCENTER_NET_ERROR=\"\"\n")
|
||||
net_info << "VCENTER_NET_STATE=\"READY\"\n"
|
||||
net_info << "VCENTER_NET_ERROR=\"\"\n"
|
||||
end
|
||||
update_net(one_vnet, net_info)
|
||||
|
||||
# Assign vnet to OpenNebula cluster
|
||||
cluster_id = one_host["CLUSTER_ID"]
|
||||
cluster_id = one_host['CLUSTER_ID']
|
||||
if cluster_id
|
||||
one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, cluster_id, false)
|
||||
one_cluster = VCenterDriver::VIHelper
|
||||
.one_item(OpenNebula::Cluster, cluster_id, false)
|
||||
if OpenNebula.is_error?(one_cluster)
|
||||
STDOUT.puts "Error retrieving cluster #{cluster_id}: #{rc.message}. You may have to place this vnet in the right cluster by hand"
|
||||
err_msg = "Error retrieving cluster #{cluster_id}: "\
|
||||
"#{rc.message}. You may have to place this vnet "\
|
||||
'in the right cluster by hand'
|
||||
STDOUT.puts(err_msg)
|
||||
end
|
||||
|
||||
one_vnet.unlock
|
||||
|
||||
rc = one_cluster.addvnet(network_id.to_i)
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDOUT.puts "Error adding vnet #{network_id} to OpenNebula cluster #{cluster_id}: #{rc.message}. You may have to place this vnet in the right cluster by hand"
|
||||
err_msg = "Error adding vnet #{network_id} to OpenNebula "\
|
||||
"cluster #{cluster_id}: #{rc.message}. "\
|
||||
'You may have to place this vnet in the '\
|
||||
'right cluster by hand'
|
||||
STDOUT.puts(err_msg)
|
||||
end
|
||||
|
||||
default_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, "0", false)
|
||||
default_cluster = VCenterDriver::VIHelper
|
||||
.one_item(OpenNebula::Cluster, '0', false)
|
||||
if OpenNebula.is_error?(default_cluster)
|
||||
STDOUT.puts "Error retrieving default cluster: #{rc.message}."
|
||||
end
|
||||
|
||||
rc = default_cluster.delvnet(network_id.to_i)
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDOUT.puts "Error removing vnet #{network_id} from default OpenNebula cluster: #{rc.message}."
|
||||
err_msg = "Error removing vnet #{network_id} from default "\
|
||||
"OpenNebula cluster: #{rc.message}."
|
||||
STDOUT.puts(err_msg)
|
||||
end
|
||||
|
||||
one_vnet.lock(1)
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
STDERR.puts("#{e.message}/#{e.backtrace}")
|
||||
|
||||
esx_rollback.each do |esx_host|
|
||||
begin
|
||||
esx_host.lock
|
||||
esx_host.network_rollback
|
||||
rescue Exception => e
|
||||
STDERR.puts("There was an issue performing the rollback in host #{esx_host["name"]} you may have to perform some actions by hand")
|
||||
rescue StandardError => e
|
||||
err_msg = 'here was an issue performing the rollback in '\
|
||||
"host #{esx_host['name']} you may have to perform "\
|
||||
'some actions by hand'
|
||||
STDERR.puts(err_msg)
|
||||
ensure
|
||||
esx_host.unlock
|
||||
end
|
||||
end
|
||||
|
||||
if dc && pg_type == "Distributed Port Group"
|
||||
if dc && pg_type == VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
begin
|
||||
dc.lock
|
||||
dc.network_rollback
|
||||
rescue Exception => e
|
||||
STDERR.puts("There was an issue performing the rollback in datacenter #{dc["name"]} you may have to perform some actions by hand")
|
||||
rescue StandardError => e
|
||||
err_msg = 'There was an issue performing the rollback in '\
|
||||
"datacenter #{dc['name']} you may have to perform "\
|
||||
'some actions by hand'
|
||||
STDERR.puts(err_msg)
|
||||
ensure
|
||||
dc.unlock
|
||||
end
|
||||
end
|
||||
|
||||
update_net(one_vnet, "VCENTER_NET_STATE=\"ERROR\"\nVCENTER_NET_ERROR=\"#{e.message}\"\n")
|
||||
net_info = "VCENTER_NET_STATE=\"ERROR\"\n"
|
||||
net_info << "VCENTER_NET_ERROR=\"#{e.message}\"\n"
|
||||
update_net(one_vnet, net_info)
|
||||
|
||||
exit -1
|
||||
exit(-1)
|
||||
ensure
|
||||
one_vnet.unlock
|
||||
vi_client.close_connection if vi_client
|
||||
|
@ -16,55 +16,64 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION=ENV["ONE_LOCATION"]
|
||||
ONE_LOCATION = ENV['ONE_LOCATION']
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
|
||||
VMDIR="/var/lib/one"
|
||||
CONFIG_FILE="/var/lib/one/config"
|
||||
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
||||
VMDIR = '/var/lib/one'
|
||||
CONFIG_FILE = '/var/lib/one/config'
|
||||
else
|
||||
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
|
||||
VMDIR=ONE_LOCATION+"/var"
|
||||
CONFIG_FILE=ONE_LOCATION+"/var/config"
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
||||
VMDIR = ONE_LOCATION + '/var'
|
||||
CONFIG_FILE = ONE_LOCATION + '/var/config'
|
||||
end
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION
|
||||
|
||||
require 'opennebula'
|
||||
require 'vcenter_driver'
|
||||
require 'base64'
|
||||
require 'nsx_driver'
|
||||
|
||||
base64_temp = ARGV[1]
|
||||
template = OpenNebula::XMLElement.new
|
||||
template.initialize_xml(Base64.decode64(base64_temp), 'VNET')
|
||||
managed = template["TEMPLATE/OPENNEBULA_MANAGED"] != "NO"
|
||||
imported = template["TEMPLATE/VCENTER_IMPORTED"]
|
||||
error = template["TEMPLATE/VCENTER_NET_STATE"] == "ERROR"
|
||||
managed = template['TEMPLATE/OPENNEBULA_MANAGED'] != 'NO'
|
||||
imported = template['TEMPLATE/VCENTER_IMPORTED']
|
||||
error = template['TEMPLATE/VCENTER_NET_STATE'] == 'ERROR'
|
||||
|
||||
begin
|
||||
# Step 0. Only execute for vcenter network driver
|
||||
if template["VN_MAD"] == "vcenter" && managed && !error && imported.nil?
|
||||
if template['VN_MAD'] == 'vcenter' && managed && !error && imported.nil?
|
||||
# Step 1. Extract vnet settings
|
||||
host_id = template["TEMPLATE/VCENTER_ONE_HOST_ID"]
|
||||
raise "We require the ID of the OpenNebula host representing a vCenter cluster" if !host_id
|
||||
host_id = template['TEMPLATE/VCENTER_ONE_HOST_ID']
|
||||
raise 'Missing VCENTER_ONE_HOST_ID' unless host_id
|
||||
|
||||
pg_name = template["TEMPLATE/BRIDGE"]
|
||||
pg_type = template["TEMPLATE/VCENTER_PORTGROUP_TYPE"]
|
||||
sw_name = template["TEMPLATE/VCENTER_SWITCH_NAME"]
|
||||
pg_name = template['TEMPLATE/BRIDGE']
|
||||
pg_type = template['TEMPLATE/VCENTER_PORTGROUP_TYPE']
|
||||
sw_name = template['TEMPLATE/VCENTER_SWITCH_NAME']
|
||||
|
||||
# Step 2. Contact cluster and extract cluster's info
|
||||
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
||||
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
||||
one_client = OpenNebula::Client.new
|
||||
one_host = OpenNebula::Host.new_with_id(host_id, one_client)
|
||||
rc = one_host.info
|
||||
raise rc.message if OpenNebula::is_error? rc
|
||||
one_host = OpenNebula::Host.new_with_id(host_id, one_client)
|
||||
rc = one_host.info
|
||||
raise rc.message if OpenNebula.is_error? rc
|
||||
|
||||
ccr_ref = one_host["TEMPLATE/VCENTER_CCR_REF"]
|
||||
cluster = VCenterDriver::ClusterComputeResource.new_from_ref(ccr_ref, vi_client)
|
||||
ccr_ref = one_host['TEMPLATE/VCENTER_CCR_REF']
|
||||
cluster = VCenterDriver::ClusterComputeResource
|
||||
.new_from_ref(ccr_ref, vi_client)
|
||||
dc = cluster.get_dc
|
||||
|
||||
# NSX
|
||||
# nsxmgr = one_host['TEMPLATE/NSX_MANAGER']
|
||||
# nsx_user = one_host['TEMPLATE/NSX_USER']
|
||||
# nsx_pass_enc = one_host['TEMPLATE/NSX_MANAGER']
|
||||
ls_id = template['TEMPLATE/NSX_ID']
|
||||
# NSX
|
||||
|
||||
# With DVS we have to work at datacenter level and then for each host
|
||||
if pg_type == "Distributed Port Group"
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
begin
|
||||
dc.lock
|
||||
|
||||
@ -84,48 +93,60 @@ begin
|
||||
dvs.item.summary.portgroupName[0] == "#{sw_name}-uplink-pg"
|
||||
dc.remove_dvs(dvs)
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
raise e
|
||||
ensure
|
||||
dc.unlock if dc
|
||||
end
|
||||
end
|
||||
|
||||
if pg_type == "Port Group"
|
||||
cluster["host"].each do |host|
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_PG
|
||||
cluster['host'].each do |host|
|
||||
# Step 3. Loop through hosts in clusters
|
||||
esx_host = VCenterDriver::ESXHost.new_from_ref(host._ref, vi_client)
|
||||
esx_host = VCenterDriver::ESXHost
|
||||
.new_from_ref(host._ref, vi_client)
|
||||
|
||||
begin
|
||||
esx_host.lock # Exclusive lock for ESX host operation
|
||||
|
||||
next if !esx_host.pg_exists(pg_name)
|
||||
next unless esx_host.pg_exists(pg_name)
|
||||
|
||||
swname = esx_host.remove_pg(pg_name)
|
||||
next if !swname || sw_name != swname
|
||||
|
||||
vswitch = esx_host.vss_exists(sw_name)
|
||||
next if !vswitch
|
||||
next unless vswitch
|
||||
|
||||
# Only remove switch if the port group being removed is
|
||||
# the last and only port group in the switch
|
||||
if vswitch.portgroup.size == 0
|
||||
swname = esx_host.remove_vss(sw_name)
|
||||
if vswitch.portgroup.empty?
|
||||
esx_host.remove_vss(sw_name)
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
raise e
|
||||
ensure
|
||||
esx_host.unlock if esx_host # Remove host lock
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_NSXV
|
||||
nsx_client = NSXDriver::NSXClient.new(host_id)
|
||||
logical_switch = NSXDriver::VirtualWire
|
||||
.new(nsx_client, ls_id, nil, nil)
|
||||
logical_switch.delete_logical_switch
|
||||
end
|
||||
|
||||
if pg_type == VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
nsx_client = NSXDriver::NSXClient.new(host_id)
|
||||
logical_switch = NSXDriver::OpaqueNetwork
|
||||
.new(nsx_client, ls_id, nil, nil)
|
||||
logical_switch.delete_logical_switch
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
STDERR.puts("#{e.message}/#{e.backtrace}")
|
||||
exit -1
|
||||
exit(-1)
|
||||
ensure
|
||||
vi_client.close_connection if vi_client
|
||||
end
|
||||
|
53
src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb
Normal file
53
src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb
Normal file
@ -0,0 +1,53 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module NSXDriver
|
||||
|
||||
# Class Logical Switch
|
||||
class LogicalSwitch
|
||||
|
||||
# ATTRIBUTES
|
||||
attr_reader :ls_id
|
||||
attr_reader :tz_id
|
||||
attr_reader :replication_mode
|
||||
attr_reader :display_name
|
||||
attr_reader :description
|
||||
|
||||
# CONSTRUCTOR
|
||||
|
||||
def initialize(nsx_client)
|
||||
@nsx_client = nsx_client
|
||||
end
|
||||
|
||||
def ls?; end
|
||||
|
||||
# Get logical switch's name
|
||||
def ls_name; end
|
||||
|
||||
# Get logical switch's vni
|
||||
def ls_vni; end
|
||||
|
||||
# Get the Transport Zone of the logical switch
|
||||
def ls_tz; end
|
||||
|
||||
# Create a new logical switch
|
||||
def new_logical_switch(ls_data); end
|
||||
|
||||
# Delete a logical switch
|
||||
def delete_logical_switch; end
|
||||
|
||||
end
|
||||
|
||||
end
|
149
src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb
Normal file
149
src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb
Normal file
@ -0,0 +1,149 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module NSXDriver
|
||||
|
||||
ONE_LOCATION = ENV['ONE_LOCATION']
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
||||
else
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
||||
end
|
||||
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION
|
||||
|
||||
require 'net/http'
|
||||
require 'json'
|
||||
require 'nokogiri'
|
||||
require 'opennebula'
|
||||
require 'vcenter_driver'
|
||||
|
||||
# Class NSXClient
|
||||
class NSXClient
|
||||
|
||||
# ATTIBUTES
|
||||
attr_accessor :nsxmgr
|
||||
attr_accessor :nsx_user
|
||||
attr_accessor :nsx_password
|
||||
HEADER_JSON = { :'Content-Type' => 'application/json' }
|
||||
HEADER_XML = { :'Content-Type' => 'application/xml' }
|
||||
|
||||
# CONSTRUCTORS
|
||||
def initialize(host_id)
|
||||
client = OpenNebula::Client.new
|
||||
host = OpenNebula::Host.new_with_id(host_id, client)
|
||||
rc = host.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
raise "Could not get host info for ID: \
|
||||
#{host_id} - #{rc.message}"
|
||||
end
|
||||
|
||||
@nsxmgr = host['TEMPLATE/NSX_MANAGER']
|
||||
@nsx_user = host['TEMPLATE/NSX_USER']
|
||||
@nsx_password = nsx_pass(host['TEMPLATE/NSX_PASSWORD'])
|
||||
end
|
||||
|
||||
def self.new_nsxmgr(nsxmgr, nsx_user, nsx_password)
|
||||
@nsxmgr = nsxmgr
|
||||
@nsx_user = nsx_user
|
||||
@nsx_password = nsx_pass(nsx_password)
|
||||
end
|
||||
|
||||
# METHODS
|
||||
|
||||
def check_response(response, code)
|
||||
response.code.to_i == code
|
||||
end
|
||||
|
||||
def nsx_pass(nsx_pass_enc)
|
||||
client = OpenNebula::Client.new
|
||||
system = OpenNebula::System.new(client)
|
||||
config = system.get_configuration
|
||||
|
||||
if OpenNebula.is_error?(config)
|
||||
raise "Error getting oned configuration : #{config.message}"
|
||||
end
|
||||
|
||||
token = config['ONE_KEY']
|
||||
@nsx_password = VCenterDriver::VIClient
|
||||
.decrypt(nsx_pass_enc, token)
|
||||
end
|
||||
|
||||
def get_xml(url)
|
||||
uri = URI.parse(url)
|
||||
request = Net::HTTP::Get.new(uri.request_uri, HEADER_XML)
|
||||
request.basic_auth(@nsx_user, @nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
||||
https.request(request)
|
||||
end
|
||||
return Nokogiri::XML response.body if check_response(response, 200)
|
||||
end
|
||||
|
||||
# Return: id of the created object
|
||||
def post_xml(url, ls_data)
|
||||
uri = URI.parse(url)
|
||||
request = Net::HTTP::Post.new(uri.request_uri, HEADER_XML)
|
||||
request.body = ls_data
|
||||
request.basic_auth(@nsx_user, @nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
||||
https.request(request)
|
||||
end
|
||||
return response.body if check_response(response, 201)
|
||||
end
|
||||
|
||||
def get_json(url)
|
||||
uri = URI.parse(url)
|
||||
request = Net::HTTP::Get.new(uri.request_uri, HEADER_JSON)
|
||||
request.basic_auth(@nsx_user, @nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
||||
https.request(request)
|
||||
end
|
||||
return JSON.parse(response.body) \
|
||||
if check_response(response, 200)
|
||||
end
|
||||
|
||||
# Return: id of the created object
|
||||
def post_json(url, ls_data)
|
||||
uri = URI.parse(url)
|
||||
request = Net::HTTP::Post.new(uri.request_uri, HEADER_JSON)
|
||||
request.body = ls_data
|
||||
request.basic_auth(@nsx_user, @nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
||||
https.request(request)
|
||||
end
|
||||
return JSON.parse(response.body)['id'] \
|
||||
if check_response(response, 201)
|
||||
end
|
||||
|
||||
def delete(url, header)
|
||||
uri = URI.parse(url)
|
||||
request = Net::HTTP::Delete.new(uri.request_uri, header)
|
||||
request.basic_auth(@nsx_user, @nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
||||
https.request(request)
|
||||
end
|
||||
check_response(response, 200)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
92
src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb
Normal file
92
src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb
Normal file
@ -0,0 +1,92 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module NSXDriver
|
||||
|
||||
# Class Opaque Network NSX-T Network
|
||||
class OpaqueNetwork < NSXDriver::LogicalSwitch
|
||||
|
||||
# ATTRIBUTES
|
||||
# attr_reader :ls_id, :admin_display
|
||||
HEADER = { :'Content-Type' => 'application/json' }
|
||||
SECTION_LS = '/logical-switches/'
|
||||
|
||||
# CONSTRUCTOR
|
||||
def initialize(nsx_client, ls_id = nil, _tz_id = nil, ls_data = nil)
|
||||
super(nsx_client)
|
||||
if ls_id
|
||||
initialize_with_id(ls_id)
|
||||
else
|
||||
if ls_data
|
||||
@ls_id = new_logical_switch(ls_data)
|
||||
@ls_vni = ls_vni
|
||||
@ls_name = ls_name
|
||||
@tz_id = ls_tz
|
||||
@admin_display = 'UP'
|
||||
end
|
||||
raise 'Missing logical switch data' unless ls_data
|
||||
end
|
||||
@base_url = "#{@nsx_client.nsxmgr}/api/v1"
|
||||
@base_url_ls = @BASE_URL + SECTION_LS
|
||||
@url_ls = @BASE_URL + SECTION_LS + @ls_id
|
||||
@base_url_tz = @BASE_URL + SECTION_TZ
|
||||
end
|
||||
|
||||
# Creates a NSXDriver::OpaqueNetwork from its id
|
||||
def initialize_with_id(ls_id)
|
||||
@ls_id = ls_id
|
||||
if ls?
|
||||
@ls_id = ls_id
|
||||
@ls_vni = ls_vni
|
||||
@ls_name = ls_name
|
||||
@admin_display = 'UP'
|
||||
end
|
||||
raise "Logical switch with id: #{ls_id} not found" unless ls?
|
||||
end
|
||||
|
||||
# METHODS
|
||||
# Check if logical switch exists
|
||||
def ls?
|
||||
@nsx_client.get_json(@url_ls) ? true : false
|
||||
end
|
||||
|
||||
# Get logical switch's name
|
||||
def ls_name
|
||||
@nsx_client.get_json(@url_ls)['display_name']
|
||||
end
|
||||
|
||||
# Get logical switch's vni
|
||||
def ls_vni
|
||||
@nsx_client.get_json(@url_ls)['vni']
|
||||
end
|
||||
|
||||
# Get the Transport Zone of the logical switch
|
||||
def ls_tz
|
||||
@nsx_client.get_json(@url_ls)['transport_zone_id']
|
||||
end
|
||||
|
||||
# Create a new logical switch (NSX-T: opaque network)
|
||||
def new_logical_switch(ls_data)
|
||||
@nsx_client.post_json(@base_url_ls, ls_data)
|
||||
end
|
||||
|
||||
# Delete a logical switch
|
||||
def delete_logical_switch
|
||||
@nsx_client.delete(@url_ls, HEADER)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
33
src/vmm_mad/remotes/lib/nsx_driver/transport_zone.rb
Normal file
33
src/vmm_mad/remotes/lib/nsx_driver/transport_zone.rb
Normal file
@ -0,0 +1,33 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module NSXDriver
|
||||
|
||||
# Class Transport Zone
|
||||
class TransportZone
|
||||
|
||||
# ATTRIBUTES
|
||||
attr_reader :tz_id
|
||||
|
||||
# CONSTRUCTOR
|
||||
def initialize(nsx_client)
|
||||
# In the future could create TZs
|
||||
end
|
||||
|
||||
# METHODS
|
||||
|
||||
end
|
||||
|
||||
end
|
113
src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb
Normal file
113
src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb
Normal file
@ -0,0 +1,113 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module NSXDriver
|
||||
|
||||
# Class VirtualWire NSX-V Network
|
||||
class VirtualWire < NSXDriver::LogicalSwitch
|
||||
|
||||
# ATTRIBUTES
|
||||
HEADER = { :'Content-Type' => 'application/xml' }
|
||||
NAME_XPATH = '//virtualWire/name'
|
||||
VNI_XPATH = '//virtualWire/vdnId'
|
||||
BACKING_XPATH = '//virtualWire/vdsContextWithBacking/backingValue'
|
||||
OBJECTID_XPATH = '//virtualWire/vdsContextWithBacking/switch/objectId'
|
||||
TZ_XPATH = '//virtualWire/vdnScopeId'
|
||||
SECTION_LS = '/vdn/virtualwires/'
|
||||
SECTION_TZ = '/vdn/scopes/'
|
||||
|
||||
# CONSTRUCTOR
|
||||
def initialize(nsx_client, ls_id = nil, tz_id = nil, ls_data = nil)
|
||||
super(nsx_client)
|
||||
if ls_id
|
||||
initialize_with_id(ls_id)
|
||||
else
|
||||
if tz_id
|
||||
if ls_data
|
||||
@ls_id = new_logical_switch(ls_data, tz_id)
|
||||
@ls_vni = ls_vni
|
||||
@ls_name = ls_name
|
||||
@tz_id = ls_tz
|
||||
@tenant_id = 'virtual wire tenant'
|
||||
@guest_vlan_allowed = false
|
||||
end
|
||||
raise 'Missing logical switch data' unless ls?
|
||||
end
|
||||
end
|
||||
# Construct base URLs
|
||||
@base_url = "#{@nsx_client.nsxmgr}/api/2.0"
|
||||
@url_ls = @BASE_URL + SECTION_LS + @ls_id
|
||||
@base_url_tz = @BASE_URL + SECTION_TZ
|
||||
end
|
||||
|
||||
# Creates a NSXDriver::VirtualWire from its id
|
||||
def initialize_with_id(ls_id)
|
||||
@ls_id = ls_id
|
||||
if ls?
|
||||
@ls_vni = ls_vni
|
||||
@ls_name = ls_name
|
||||
@tz_id = ls_tz
|
||||
@tenant_id = 'virtual wire tenant'
|
||||
@guest_vlan_allowed = false
|
||||
end
|
||||
raise "VirtualWire with id: #{ls_id} not found" unless ls?
|
||||
end
|
||||
|
||||
# METHODS
|
||||
|
||||
# Check if logical switch exists
|
||||
def ls?
|
||||
@nsx_client.get_xml(@url_ls) ? true : false
|
||||
end
|
||||
|
||||
# Get logical switch's name
|
||||
def ls_name
|
||||
@nsx_client.get_xml(@url_ls).xpath(NAME_XPATH).text
|
||||
end
|
||||
|
||||
# Get logical switch's vni
|
||||
def ls_vni
|
||||
@nsx_client.get_xml(@url_ls).xpath(VNI_XPATH).text
|
||||
end
|
||||
|
||||
# Get the Transport Zone of the logical switch
|
||||
def ls_tz
|
||||
@nsx_client.get_xml(@url_ls).xpath(TZ_XPATH).text
|
||||
end
|
||||
|
||||
# Get the logical switch reference into vcenter
|
||||
def ls_vcenter_ref
|
||||
@nsx_client.get_xml(@url_ls).xpath(BACKING_XPATH).text
|
||||
end
|
||||
|
||||
# Get the distributed virtual switch's ref associated to a LS
|
||||
def ls_dvs_ref
|
||||
@nsx_client.get_xml(@url_ls).xpath(OBJECTID_XPATH).text
|
||||
end
|
||||
|
||||
# Create a new logical switch (NSX-V: virtualwire)
|
||||
def new_logical_switch(ls_data, tz_id)
|
||||
url = "#{@base_url_tz}/#{tz_id}/virtualwires"
|
||||
@nsx_client.post_xml(url, ls_data)
|
||||
end
|
||||
|
||||
# Delete a logical switch
|
||||
def delete_logical_switch
|
||||
@nsx_client.delete(@url_ls, HEADER)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -376,15 +376,14 @@ class DatacenterFolder
|
||||
networks[r.obj._ref] = r.to_hash if r.obj.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) || r.obj.is_a?(RbVmomi::VIM::Network) || r.obj.is_a?(RbVmomi::VIM::OpaqueNetwork)
|
||||
|
||||
if r.obj.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup)
|
||||
networks[r.obj._ref][:network_type] = "Distributed Port Group"
|
||||
elsif r.obj.is_a?(RbVmomi::VIM::Network)
|
||||
networks[r.obj._ref][:network_type] = "Port Group"
|
||||
networks[r.obj._ref][:network_type] = VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
elsif r.obj.is_a?(RbVmomi::VIM::OpaqueNetwork)
|
||||
networks[r.obj._ref][:network_type] = "Opaque Network"
|
||||
networks[r.obj._ref][:network_type] = VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
elsif r.obj.is_a?(RbVmomi::VIM::Network)
|
||||
networks[r.obj._ref][:network_type] = VCenterDriver::Network::NETWORK_TYPE_PG
|
||||
else
|
||||
networks[r.obj._ref][:network_type] = "Unknown Network"
|
||||
networks[r.obj._ref][:network_type] = VCenterDriver::Network::NETWORK_TYPE_UNKNOWN
|
||||
end
|
||||
# networks[r.obj._ref][:network_type] = r.obj.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) ? "Distributed Port Group" : "Port Group"
|
||||
networks[r.obj._ref][:uplink] = false
|
||||
networks[r.obj._ref][:processed] = false
|
||||
|
||||
@ -681,13 +680,48 @@ class Datacenter
|
||||
# Check if distributed port group exists in datacenter
|
||||
########################################################################
|
||||
def dpg_exists(pg_name, net_folder)
|
||||
|
||||
return net_folder.items.values.select{ |dpg|
|
||||
dpg.instance_of?(VCenterDriver::DistributedPortGroup) &&
|
||||
dpg['name'] == pg_name
|
||||
}.first rescue nil
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Check if Opaque Network exists in datacenter
|
||||
########################################################################
|
||||
def nsx_network(nsx_id, pgType)
|
||||
timeout = 180
|
||||
if pgType == VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
while timeout > 0
|
||||
netFolder = self.network_folder
|
||||
netFolder.fetch!
|
||||
netFolder.items.values.each{ |net|
|
||||
if net.instance_of?(VCenterDriver::OpaqueNetwork) &&
|
||||
net.item.summary.opaqueNetworkId == nsx_id
|
||||
return net.item._ref
|
||||
end
|
||||
}
|
||||
sleep(1)
|
||||
timeout -= 1
|
||||
end
|
||||
# Not used right now, but maybe neccesary in the future.
|
||||
elsif pgType == VCenterDriver::Network::NETWORK_TYPE_NSXV
|
||||
while timeout > 0
|
||||
netFolder = self.network_folder
|
||||
netFolder.fetch!
|
||||
netFolder.items.values.each{ |net|
|
||||
if net.instance_of?(VCenterDriver::DistributedPortGroup) &&
|
||||
net.item.key == nsx_id
|
||||
return net.item._ref
|
||||
end
|
||||
}
|
||||
timeout -= 1
|
||||
end
|
||||
else
|
||||
raise "Unknown network Port Group type: #{pgType}"
|
||||
end
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Create a distributed vcenter port group
|
||||
########################################################################
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
module VCenterDriver
|
||||
|
||||
require 'json'
|
||||
|
||||
class HostFolder
|
||||
attr_accessor :item, :items
|
||||
|
||||
@ -94,6 +96,175 @@ class ClusterComputeResource
|
||||
rp_array
|
||||
end
|
||||
|
||||
def get_nsx
|
||||
nsx_info = ""
|
||||
nsx_obj = {}
|
||||
extensionList = []
|
||||
extensionList = @vi_client.vim.serviceContent.extensionManager.extensionList
|
||||
extensionList.each do |extList|
|
||||
if extList.key == "com.vmware.vShieldManager"
|
||||
nsx_obj['type'] = "NSX-V"
|
||||
urlFull = extList.client[0].url
|
||||
urlSplit = urlFull.split("/")
|
||||
# protocol = "https://"
|
||||
protocol = urlSplit[0] + "//"
|
||||
# ipPort = ip:port
|
||||
ipPort = urlSplit[2]
|
||||
nsx_obj['url'] = protocol + ipPort
|
||||
elsif extList.key == "com.vmware.nsx.management.nsxt"
|
||||
nsx_obj['type'] = "NSX-T"
|
||||
nsx_obj['url'] = extList.server[0].url
|
||||
else
|
||||
end
|
||||
nsx_obj['version'] = extList.version
|
||||
nsx_obj['label'] = extList.description.label
|
||||
end
|
||||
unless nsx_obj.nil?
|
||||
nsx_info << "NSX_MANAGER=\"#{nsx_obj['url']}\"\n"
|
||||
nsx_info << "NSX_TYPE=\"#{nsx_obj['type']}\"\n"
|
||||
nsx_info << "NSX_VERSION=\"#{nsx_obj['version']}\"\n"
|
||||
nsx_info << "NSX_LABEL=\"#{nsx_obj['label']}\"\n"
|
||||
end
|
||||
return nsx_info
|
||||
end
|
||||
|
||||
def nsx_ready?
|
||||
@one_item = VCenterDriver::VIHelper.one_item(OpenNebula::Host, @vi_client.instance_variable_get(:@host_id).to_i)
|
||||
|
||||
# Check if credentials are into the host template
|
||||
if [nil, ""].include?(@one_item["TEMPLATE/NSX_USER"])
|
||||
@nsx_status = "NSX_STATUS = \"Missing NSX_USER\"\n"
|
||||
return false
|
||||
end
|
||||
|
||||
if [nil, ""].include?(@one_item["TEMPLATE/NSX_PASSWORD"])
|
||||
@nsx_status = "NSX_STATUS = \"Missing NSX_PASSWORD\"\n"
|
||||
return false
|
||||
end
|
||||
|
||||
# Decrypt password
|
||||
client = OpenNebula::Client.new
|
||||
system = OpenNebula::System.new(client)
|
||||
config = system.get_configuration
|
||||
|
||||
if OpenNebula.is_error?(config)
|
||||
raise "Error getting oned configuration : #{config.message}"
|
||||
end
|
||||
|
||||
nsx_password = @one_item["TEMPLATE/NSX_PASSWORD"]
|
||||
token = config["ONE_KEY"]
|
||||
nsx_password = VIClient::decrypt(nsx_password, token)
|
||||
|
||||
# Check if NSX_TYPE is into the host template
|
||||
if [nil, ""].include?(@one_item["TEMPLATE/NSX_TYPE"])
|
||||
@nsx_status = "NSX_STATUS = \"Missing NSX_TYPE\"\n"
|
||||
return false
|
||||
end
|
||||
|
||||
# Check if NSX_MANAGER is into the host template
|
||||
if [nil, ""].include?(@one_item["TEMPLATE/NSX_MANAGER"])
|
||||
@nsx_status = "NSX_STATUS = \"Missing NSX_MANAGER\"\n"
|
||||
return false
|
||||
end
|
||||
|
||||
# Try a connection as part of NSX_STATUS
|
||||
if @one_item["TEMPLATE/NSX_TYPE"] == "NSX-V"
|
||||
header = {'Content-Type': 'application/xml'}
|
||||
uri = URI.parse("#{@one_item["TEMPLATE/NSX_MANAGER"]}/api/2.0/vdn/scopes")
|
||||
request = Net::HTTP::Get.new(uri.request_uri, header)
|
||||
request.basic_auth(@one_item["TEMPLATE/NSX_USER"], nsx_password)
|
||||
begin
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) {|https| https.request(request) }
|
||||
if response.code.to_i == 200
|
||||
return true
|
||||
else
|
||||
@nsx_status = "NSX_STATUS = \"Response code incorrect\"\n"
|
||||
return false
|
||||
end
|
||||
rescue
|
||||
@nsx_status = "NSX_STATUS = \"Error connecting to NSX_MANAGER\"\n"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if @one_item["TEMPLATE/NSX_TYPE"] == "NSX-T"
|
||||
header = {'Content-Type': 'application/json'}
|
||||
uri = URI.parse("#{@one_item["TEMPLATE/NSX_MANAGER"]}/api/v1/transport-zones")
|
||||
request = Net::HTTP::Get.new(uri.request_uri, header)
|
||||
request.basic_auth(@one_item["TEMPLATE/NSX_USER"], nsx_password)
|
||||
begin
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) {|https| https.request(request) }
|
||||
if response.code.to_i == 200
|
||||
return true
|
||||
else
|
||||
@nsx_status = "NSX_STATUS = \"Response code incorrect\"\n"
|
||||
return false
|
||||
end
|
||||
rescue
|
||||
@nsx_status = "NSX_STATUS = \"Error connecting to NSX_MANAGER\"\n"
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_tz
|
||||
@nsx_status = ""
|
||||
if !nsx_ready?
|
||||
tz_info = @nsx_status
|
||||
else
|
||||
tz_info = "NSX_STATUS = OK\n"
|
||||
tz_info << "NSX_TRANSPORT_ZONES = ["
|
||||
# Decrypt password
|
||||
client = OpenNebula::Client.new
|
||||
system = OpenNebula::System.new(client)
|
||||
config = system.get_configuration
|
||||
|
||||
if OpenNebula.is_error?(config)
|
||||
raise "Error getting oned configuration : #{config.message}"
|
||||
end
|
||||
|
||||
nsx_password = @one_item["TEMPLATE/NSX_PASSWORD"]
|
||||
token = config["ONE_KEY"]
|
||||
nsx_password = VIClient::decrypt(nsx_password, token)
|
||||
# NSX request to get Transport Zones
|
||||
if @one_item["TEMPLATE/NSX_TYPE"] == "NSX-V"
|
||||
header = {'Content-Type': 'application/xml'}
|
||||
uri = URI.parse("#{@one_item["TEMPLATE/NSX_MANAGER"]}/api/2.0/vdn/scopes")
|
||||
request = Net::HTTP::Get.new(uri.request_uri, header)
|
||||
request.basic_auth(@one_item["TEMPLATE/NSX_USER"], nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) {|https| https.request(request) }
|
||||
# checkResponse(response, 200)
|
||||
bodyXML = Nokogiri::XML response.body
|
||||
tzs = bodyXML.xpath("//vdnScope")
|
||||
tzs.each do |tz|
|
||||
tz_info << tz.xpath("name").text << "=\"" << tz.xpath("objectId").text << "\","
|
||||
end
|
||||
tz_info.chomp!(',')
|
||||
elsif @one_item["TEMPLATE/NSX_TYPE"] == "NSX-T"
|
||||
header = {'Content-Type': 'application/json'}
|
||||
uri = URI.parse("#{@one_item["TEMPLATE/NSX_MANAGER"]}/api/v1/transport-zones")
|
||||
request = Net::HTTP::Get.new(uri.request_uri, header)
|
||||
request.basic_auth(@one_item["TEMPLATE/NSX_USER"], nsx_password)
|
||||
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true,
|
||||
:verify_mode => OpenSSL::SSL::VERIFY_NONE) {|https| https.request(request) }
|
||||
# checkResponse(response, 200)
|
||||
r = JSON.parse(response.body)
|
||||
r["results"].each do |tz|
|
||||
tz_info << tz["display_name"] << "=\"" << tz["id"] << "\","
|
||||
end
|
||||
tz_info.chomp!(',')
|
||||
else
|
||||
raise "Unknown Port Group type #{@one_item["TEMPLATE/NSX_TYPE"]}"
|
||||
end
|
||||
tz_info << "]"
|
||||
return tz_info
|
||||
end
|
||||
return tz_info
|
||||
end
|
||||
|
||||
def monitor
|
||||
total_cpu,
|
||||
num_cpu_cores,
|
||||
@ -153,8 +324,14 @@ class ClusterComputeResource
|
||||
|
||||
# HA enabled
|
||||
str_info << "VCENTER_HA=" << ha_enabled.to_s << "\n"
|
||||
|
||||
# NSX info
|
||||
str_info << get_nsx
|
||||
str_info << get_tz
|
||||
|
||||
str_info << monitor_resource_pools(mhz_core)
|
||||
|
||||
|
||||
end
|
||||
|
||||
def monitor_resource_pools(mhz_core)
|
||||
|
@ -46,8 +46,15 @@ class NetworkFolder
|
||||
item_name = item._ref
|
||||
@items[item_name.to_sym] = DistributedVirtualSwitch.new(item)
|
||||
end
|
||||
|
||||
VIClient.get_entities(@item, "OpaqueNetwork").each do |item|
|
||||
item_name = item._ref
|
||||
@items[item_name.to_sym] = OpaqueNetwork.new(item)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
########################################################################
|
||||
# Returns a Network. Uses the cache if available.
|
||||
# @param ref [Symbol] the vcenter ref
|
||||
@ -68,6 +75,12 @@ class Network
|
||||
|
||||
include Memoize
|
||||
|
||||
NETWORK_TYPE_PG = "Port Group"
|
||||
NETWORK_TYPE_DPG = "Distributed Port Group"
|
||||
NETWORK_TYPE_NSXV = "NSX-V" #"Virtual Wire"
|
||||
NETWORK_TYPE_NSXT = "Opaque Network"
|
||||
NETWORK_TYPE_UNKNOWN = "Unknown Network"
|
||||
|
||||
def initialize(item, vi_client=nil)
|
||||
begin
|
||||
check_item(item, RbVmomi::VIM::Network)
|
||||
@ -209,13 +222,14 @@ class Network
|
||||
netString = network.class.to_s
|
||||
case netString
|
||||
when "DistributedVirtualPortgroup"
|
||||
return "Distributed Port Group"
|
||||
when "Network"
|
||||
return "Port Group"
|
||||
return VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
when "OpaqueNetwork"
|
||||
return "Opaque Network"
|
||||
return VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
when "Network"
|
||||
return VCenterDriver::Network::NETWORK_TYPE_PG
|
||||
|
||||
else
|
||||
return "Network not defined"
|
||||
return "Network not defined"
|
||||
end
|
||||
end
|
||||
|
||||
@ -258,7 +272,7 @@ class PortGroup < Network
|
||||
end
|
||||
|
||||
def network_type
|
||||
"Port Group"
|
||||
VCenterDriver::Network::NETWORK_TYPE_PG
|
||||
end
|
||||
end # class PortGroup
|
||||
|
||||
@ -286,7 +300,7 @@ class DistributedPortGroup < Network
|
||||
end
|
||||
|
||||
def network_type
|
||||
"Distributed Port Group"
|
||||
VCenterDriver::Network::NETWORK_TYPE_DPG
|
||||
end
|
||||
end # class DistributedPortGroup
|
||||
|
||||
@ -312,7 +326,7 @@ class OpaqueNetwork < Network
|
||||
end
|
||||
|
||||
def network_type
|
||||
"Opaque Network"
|
||||
VCenterDriver::Network::NETWORK_TYPE_NSXT
|
||||
end
|
||||
end # class OpaqueNetwork
|
||||
|
||||
|
@ -723,7 +723,7 @@ module VCenterDriver
|
||||
key = backing.port.portgroupKey
|
||||
elsif backing.class == OPAQUE_CARD
|
||||
# Select only Opaque Networks
|
||||
opaqueNetworks = @item.network.select{|net|
|
||||
opaqueNetworks = @item.network.select{|net|
|
||||
RbVmomi::VIM::OpaqueNetwork == net.class}
|
||||
opaqueNetwork = opaqueNetworks.find{|opn|
|
||||
backing.opaqueNetworkId == opn.summary.opaqueNetworkId}
|
||||
@ -1357,7 +1357,7 @@ module VCenterDriver
|
||||
backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(
|
||||
:deviceName => pg_name,
|
||||
:network => network)
|
||||
else
|
||||
elsif network.class == RbVmomi::VIM::DistributedVirtualPortgroup
|
||||
port = RbVmomi::VIM::DistributedVirtualSwitchPortConnection(
|
||||
:switchUuid =>
|
||||
network.config.distributedVirtualSwitch.uuid,
|
||||
@ -1365,6 +1365,12 @@ module VCenterDriver
|
||||
backing =
|
||||
RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo(
|
||||
:port => port)
|
||||
elsif network.class == RbVmomi::VIM::OpaqueNetwork
|
||||
backing = RbVmomi::VIM.VirtualEthernetCardOpaqueNetworkBackingInfo(
|
||||
:opaqueNetworkId => network.summary.opaqueNetworkId,
|
||||
:opaqueNetworkType => "nsx.LogicalSwitch")
|
||||
else
|
||||
raise "Unknown network class"
|
||||
end
|
||||
|
||||
card_spec = {
|
||||
|
50
src/vmm_mad/remotes/nsx/nsx_driver.rb
Normal file
50
src/vmm_mad/remotes/nsx/nsx_driver.rb
Normal file
@ -0,0 +1,50 @@
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Set up the environment for the driver #
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
|
||||
|
||||
if !ONE_LOCATION
|
||||
BIN_LOCATION = '/usr/bin' unless defined?(BIN_LOCATION)
|
||||
LIB_LOCATION = '/usr/lib/one' unless defined?(LIB_LOCATION)
|
||||
ETC_LOCATION = '/etc/one/' unless defined?(ETC_LOCATION)
|
||||
VAR_LOCATION = '/var/lib/one' unless defined?(VAR_LOCATION)
|
||||
else
|
||||
BIN_LOCATION = ONE_LOCATION + '/bin' unless defined?(BIN_LOCATION)
|
||||
LIB_LOCATION = ONE_LOCATION + '/lib' unless defined?(LIB_LOCATION)
|
||||
ETC_LOCATION = ONE_LOCATION + '/etc/' unless defined?(ETC_LOCATION)
|
||||
VAR_LOCATION = ONE_LOCATION + '/var/' unless defined?(VAR_LOCATION)
|
||||
end
|
||||
|
||||
ENV['LANG'] = 'C'
|
||||
|
||||
$LOAD_PATH << LIB_LOCATION + '/ruby'
|
||||
$LOAD_PATH << LIB_LOCATION + '/ruby/nsx_driver'
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# NSX Library #
|
||||
# ---------------------------------------------------------------------------- #
|
||||
require 'logical_switch'
|
||||
require 'nsx_client'
|
||||
require 'opaque_network'
|
||||
require 'virtual_wire'
|
||||
|
||||
# NSX Driver module
|
||||
module NSXDriver
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user