diff --git a/install.sh b/install.sh index 6aee675b94..a0055ee90c 100755 --- a/install.sh +++ b/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 #------------------------------------------------------------------------------- diff --git a/share/hooks/vcenter/create_vcenter_net.rb b/share/hooks/vcenter/create_vcenter_net.rb index 211fc8fbc3..bc5cfb7221 100755 --- a/share/hooks/vcenter/create_vcenter_net.rb +++ b/share/hooks/vcenter/create_vcenter_net.rb @@ -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 = + "\ + #{ls_name}\ + #{ls_description}\ + virtual wire tenant\ + UNICAST_MODE\ + false\ + " + 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 diff --git a/share/hooks/vcenter/delete_vcenter_net.rb b/share/hooks/vcenter/delete_vcenter_net.rb index a69ca11870..08dc9c47cc 100755 --- a/share/hooks/vcenter/delete_vcenter_net.rb +++ b/share/hooks/vcenter/delete_vcenter_net.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb b/src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb new file mode 100644 index 0000000000..57b14f3815 --- /dev/null +++ b/src/vmm_mad/remotes/lib/nsx_driver/logical_switch.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb b/src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb new file mode 100644 index 0000000000..e8e0e3ded5 --- /dev/null +++ b/src/vmm_mad/remotes/lib/nsx_driver/nsx_client.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb b/src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb new file mode 100644 index 0000000000..f3d2de4f98 --- /dev/null +++ b/src/vmm_mad/remotes/lib/nsx_driver/opaque_network.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/nsx_driver/transport_zone.rb b/src/vmm_mad/remotes/lib/nsx_driver/transport_zone.rb new file mode 100644 index 0000000000..ef47954071 --- /dev/null +++ b/src/vmm_mad/remotes/lib/nsx_driver/transport_zone.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb b/src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb new file mode 100644 index 0000000000..e048d5d6bc --- /dev/null +++ b/src/vmm_mad/remotes/lib/nsx_driver/virtual_wire.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb b/src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb index 015c3511b6..67a1ddbb6c 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb @@ -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 ######################################################################## diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/host.rb b/src/vmm_mad/remotes/lib/vcenter_driver/host.rb index fc1692f0f1..2b8576d2e1 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/host.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/host.rb @@ -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) diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/network.rb b/src/vmm_mad/remotes/lib/vcenter_driver/network.rb index f2cef59a66..e3355f2c2c 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/network.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/network.rb @@ -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 diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb b/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb index 10ac169266..a3ebed570e 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb @@ -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 = { diff --git a/src/vmm_mad/remotes/nsx/nsx_driver.rb b/src/vmm_mad/remotes/nsx/nsx_driver.rb new file mode 100644 index 0000000000..0e4ea7a898 --- /dev/null +++ b/src/vmm_mad/remotes/nsx/nsx_driver.rb @@ -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