class VCenterDriver::Datacenter

Class Datacenter

Constants

DPG_CREATE_TIMEOUT

Attributes

item[RW]

Public Class Methods

new(item, vi_client = nil) click to toggle source
# File lib/datacenter.rb, line 843
def initialize(item, vi_client = nil)
    check_item(item, RbVmomi::VIM::Datacenter)

    @vi_client = vi_client
    @item = item
    @net_rollback = []
    @locking = true
end
new_from_ref(ref, vi_client) click to toggle source
# File lib/datacenter.rb, line 1316
def self.new_from_ref(ref, vi_client)
    new(RbVmomi::VIM::Datacenter.new(vi_client.vim, ref), vi_client)
end

Public Instance Methods

create_dpg(dvs, pg_name, vlan_id, num_ports) click to toggle source

Create a distributed vcenter port group

# File lib/datacenter.rb, line 1102
def create_dpg(dvs, pg_name, vlan_id, num_ports)
    spec = RbVmomi::VIM::DVPortgroupConfigSpec.new

    # OpenNebula use DVS static port binding with autoexpand
    if num_ports
        spec.autoExpand = true
        spec.numPorts = num_ports
    end

    # Distributed port group name
    spec.name = pg_name

    # Set VLAN information
    spec.defaultPortConfig =
        RbVmomi::VIM::VMwareDVSPortSetting.new
    spec.defaultPortConfig.vlan =
        RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
    spec.defaultPortConfig.vlan.vlanId =
        vlan_id
    spec.defaultPortConfig.vlan.inherited =
        false

    # earlyBinding. A free DistributedVirtualPort will be selected and
    # assigned to a VirtualMachine when
    # the virtual machine is reconfigured
    # to connect to the portgroup.
    spec.type = 'earlyBinding'

    begin
        dvs
            .item
            .AddDVPortgroup_Task(
                :spec => [spec]
            ).wait_for_completion
    rescue StandardError => e
        raise "The Distributed port group #{pg_name} \
        could not be created. "\
              "Reason: #{e.message}"
    end

    # wait until the network is ready and we have a reference
    portgroups = dvs['portgroup'].select do |dpg|
        dpg.instance_of?(RbVmomi::VIM::DistributedVirtualPortgroup) &&
            dpg['name'] == pg_name
    end

    (0..DPG_CREATE_TIMEOUT).each do
        break unless portgroups.empty?

        portgroups = dvs['portgroup'].select do |dpg|
            dpg
                .instance_of?(
                    RbVmomi::VIM::DistributedVirtualPortgroup
                ) && dpg['name'] == pg_name
        end
        sleep 1
    end

    if portgroups.empty?
        raise 'Cannot get VCENTER_NET_REF \
        for new distributed port group'
    end

    @net_rollback << {
        :action => :delete_dpg,
         :dpg => portgroups.first,
          :name => pg_name
    }

    portgroups.first._ref
end
create_dvs(switch_name, pnics, mtu = 1500) click to toggle source

Create a distributed vcenter switch in a datacenter

# File lib/datacenter.rb, line 906
def create_dvs(switch_name, pnics, mtu = 1500)
    # Prepare spec for DVS creation
    spec = RbVmomi::VIM::DVSCreateSpec.new
    spec.configSpec = RbVmomi::VIM::VMwareDVSConfigSpec.new
    spec.configSpec.name = switch_name

    # Specify number of uplinks port for dpg
    if pnics
        pnics = pnics.split(',')
        if !pnics.empty?
            spec.configSpec.uplinkPortPolicy =
                RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
            spec.configSpec.uplinkPortPolicy.uplinkPortName = []
            (0..pnics.size-1).each do |index|
                spec
                    .configSpec
                    .uplinkPortPolicy
                    .uplinkPortName[index]="dvUplink#{index+1}"
            end
        end
    end

    # Set maximum MTU
    spec.configSpec.maxMtu = mtu

    # The DVS must be created in the networkFolder of the datacenter
    begin
        dvs_creation_task = @item
                            .networkFolder
                            .CreateDVS_Task(
                                :spec => spec
                            )
        dvs_creation_task.wait_for_completion

        # If task finished successfuly we rename the uplink portgroup
        dvs = nil
        if dvs_creation_task.info.state == 'success'
            dvs = dvs_creation_task.info.result
            dvs
                .config
                .uplinkPortgroup[0]
                .Rename_Task(
                    :newName => "#{switch_name}-uplink-pg"
                ).wait_for_completion
        else
            raise "The Distributed vSwitch #{switch_name} \
            could not be created. "
        end
    rescue StandardError => e
        raise e
    end

    @net_rollback << {
        :action => :delete_dvs,
        :dvs => dvs,
        :name => switch_name
    }

    VCenterDriver::DistributedVirtualSwitch.new(dvs, @vi_client)
end
datastore_folder() click to toggle source
# File lib/datacenter.rb, line 852
def datastore_folder
    DatastoreFolder.new(@item.datastoreFolder)
end
dpg_exists(pg_name, net_folder) click to toggle source

Check if distributed port group exists in datacenter

# File lib/datacenter.rb, line 1052
def dpg_exists(pg_name, net_folder)
    net_folder.items.values.select do |dpg|
        dpg.instance_of?(VCenterDriver::DistributedPortGroup) &&
            dpg['name'] == pg_name
    end.first rescue nil
end
dvs_exists(switch_name, net_folder) click to toggle source

Check if distributed virtual switch exists in host

# File lib/datacenter.rb, line 889
def dvs_exists(switch_name, net_folder)
    net_folder.items.values.select do |dvs|
        dvs.instance_of?(VCenterDriver::DistributedVirtualSwitch) &&
            dvs['name'] == switch_name
    end.first rescue nil
end
host_folder() click to toggle source
# File lib/datacenter.rb, line 856
def host_folder
    HostFolder.new(@item.hostFolder)
end
lock() click to toggle source

Locking function. Similar to flock

# File lib/datacenter.rb, line 869
def lock
    hostlockname = @item['name'].downcase.tr(' ', '_')
    return unless @locking

    @locking_file =
        File
        .open("/tmp/vcenter-dc-#{hostlockname}-lock", 'w')
    @locking_file.flock(File::LOCK_EX)
end
network_folder() click to toggle source
# File lib/datacenter.rb, line 864
def network_folder
    NetworkFolder.new(@item.networkFolder)
end
network_rollback() click to toggle source

Perform vcenter network rollback operations

# File lib/datacenter.rb, line 1260
def network_rollback
    @net_rollback.reverse_each do |nr|
        case nr[:action]
        when :update_dpg
            begin
                nr[:dpg].ReconfigureDVPortgroup_Task(:spec => nr[:spec])
                        .wait_for_completion
            rescue StandardError => e
                raise "A rollback operation for distributed \
                port group #{nr[:name]} could not \
                be performed. Reason: #{e.message}"
            end
        when :update_dvs
            begin
                nr[:dvs].ReconfigureDvs_Task(:spec => nr[:spec])
                        .wait_for_completion
            rescue StandardError => e
                raise "A rollback operation for distributed\
                 standard switch #{nr[:name]} could \
                 not be performed. Reason: #{e.message}"
            end
        when :delete_dvs
            begin
                nr[:dvs].Destroy_Task.wait_for_completion
            rescue RbVmomi::VIM::ResourceInUse
                next # Ignore if switch in use
            rescue RbVmomi::VIM::NotFound
                next # Ignore if switch not found
            rescue StandardError => e
                raise "A rollback operation \
                for standard switch #{nr[:name]} \
                    could not be performed. Reason: #{e.message}"
            end
        when :delete_dpg
            begin
                nr[:dpg].Destroy_Task.wait_for_completion
            rescue RbVmomi::VIM::ResourceInUse
                next # Ignore if pg in use
            rescue RbVmomi::VIM::NotFound
                next # Ignore if pg not found
            rescue StandardError => e
                raise "A rollback operation for \
                standard port group #{nr[:name]} could \
                not be performed. Reason: #{e.message}"
            end
        end
    end
end
nsx_network(nsx_id, pg_type) click to toggle source

Check if Opaque Network exists in datacenter

# File lib/datacenter.rb, line 1062
def nsx_network(nsx_id, pg_type)
    timeout = 180
    case pg_type
    when VCenterDriver::Network::NETWORK_TYPE_NSXT
        while timeout > 0
            net_folder = network_folder
            net_folder.fetch!
            net_folder.items.values.each do |net|
                if net.instance_of?(VCenterDriver::OpaqueNetwork) &&
                   net.item.summary.opaqueNetworkId == nsx_id
                    return net.item._ref
                end
            end
            sleep(1)
            timeout -= 1
        end
    # Not used right now, but maybe neccesary in the future.
    when VCenterDriver::Network::NETWORK_TYPE_NSXV
        while timeout > 0
            net_folder = network_folder
            net_folder.fetch!
            net_folder.items.values.each do |net|
                if net.instance_of?(
                    VCenterDriver::DistributedPortGroup
                ) &&
                   net.item.key == nsx_id
                    return net.item._ref
                end
            end
            sleep(1)
            timeout -= 1
        end
    else
        raise "Unknown network Port Group type: #{pg_type}"
    end
end
pg_changes_sw?(dpg, switch_name) click to toggle source

Is the distributed switch for the distributed pg different?

# File lib/datacenter.rb, line 899
def pg_changes_sw?(dpg, switch_name)
    dpg['config.distributedVirtualSwitch.name'] != switch_name
end
power_on_vm(vm) click to toggle source

PowerOn VMs

# File lib/datacenter.rb, line 1312
def power_on_vm(vm)
    @item.PowerOnMultiVM_Task({ :vm => [vm] }).wait_for_completion
end
remove_dpg(dpg) click to toggle source

Remove distributed port group from datacenter

# File lib/datacenter.rb, line 1244
def remove_dpg(dpg)
    begin
        dpg.item.Destroy_Task.wait_for_completion
    rescue RbVmomi::VIM::ResourceInUse
        STDERR.puts "The distributed portgroup \
        #{dpg['name']} is in use so it cannot be deleted"
        nil
    rescue StandardError => e
        raise "The Distributed portgroup #{dpg['name']} \
        could not be deleted. Reason: #{e.message} "
    end
end
remove_dvs(dvs) click to toggle source

Remove a distributed vcenter switch in a datacenter

# File lib/datacenter.rb, line 1041
def remove_dvs(dvs)
    begin
        dvs.item.Destroy_Task.wait_for_completion
    rescue StandardError
        # Ignore destroy task exception
    end
end
unlock() click to toggle source

Unlock driver execution mutex

# File lib/datacenter.rb, line 880
def unlock
    return unless @locking

    @locking_file.close
end
update_dpg(dpg, vlan_id, num_ports) click to toggle source

Update a distributed vcenter port group

# File lib/datacenter.rb, line 1177
def update_dpg(dpg, vlan_id, num_ports)
    spec = RbVmomi::VIM::DVPortgroupConfigSpec.new

    changed = false

    orig_spec =
        RbVmomi::VIM::DVPortgroupConfigSpec.new
    orig_spec.numPorts =
        dpg['config.numPorts']
    orig_spec.defaultPortConfig =
        RbVmomi::VIM::VMwareDVSPortSetting.new
    orig_spec.defaultPortConfig.vlan =
        RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
    orig_spec.defaultPortConfig.vlan.vlanId =
        dpg['config.defaultPortConfig.vlan.vlanId']
    orig_spec.defaultPortConfig.vlan.inherited =
        false

    if num_ports && num_ports != orig_spec.numPorts
        spec.numPorts = num_ports
        changed = true
    end

    # earlyBinding. A free DistributedVirtualPort
    # will be selected and
    # assigned to a VirtualMachine when
    # the virtual machine is reconfigured
    # to connect to the portgroup.
    spec.type = 'earlyBinding'

    if vlan_id != orig_spec.defaultPortConfig.vlan.vlanId
        spec.defaultPortConfig =
            RbVmomi::VIM::VMwareDVSPortSetting.new
        spec.defaultPortConfig.vlan =
            RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
        spec.defaultPortConfig.vlan.vlanId = vlan_id
        spec.defaultPortConfig.vlan.inherited = false
        changed = true
    end

    return unless changed

    spec.configVersion = dpg['config.configVersion']

    begin
        dpg
            .item
            .ReconfigureDVPortgroup_Task(
                :spec => spec
            ).wait_for_completion
    rescue StandardError => e
        raise "The Distributed port group #{dpg['name']} \
        could not be created. "\
                "Reason: #{e.message}"
    end

    @net_rollback << {
        :action => :update_dpg,
            :dpg => dpg.item,
            :name => dpg['name'],
            :spec => orig_spec
    }
end
update_dvs(dvs, pnics, mtu) click to toggle source

Update a distributed vcenter switch

# File lib/datacenter.rb, line 970
def update_dvs(dvs, pnics, mtu)
    # Prepare spec for DVS creation
    spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
    changed = false

    orig_spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
    orig_spec.maxMtu = dvs['config.maxMtu']
    orig_spec.uplinkPortPolicy =
        RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
    orig_spec.uplinkPortPolicy.uplinkPortName = []
    (0..dvs['config.uplinkPortgroup'].length-1).each do |index|
        orig_spec
            .uplinkPortPolicy
            .uplinkPortName[index]="dvUplink#{index+1}"
    end

    # Add more uplinks to default uplink
    # port group according to number of pnics
    if pnics
        pnics = pnics.split(',')
        if !pnics.empty? && dvs['config.uplinkPortgroup']
           .length != pnics.size
            spec.uplinkPortPolicy =
                RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
            spec.uplinkPortPolicy.uplinkPortName = []
            (dvs['config.uplinkPortgroup']
            .length..num_pnics-1)
                .each do |index|
                spec
                    .uplinkPortPolicy
                    .uplinkPortName[index] =
                    "dvUplink#{index+1}"
            end
            changed = true
        end
    end

    # Set maximum MTU
    if mtu != dvs['config.maxMtu']
        spec.maxMtu = mtu
        changed = true
    end

    # The DVS must be created in the networkFolder of the datacenter
    return unless changed

    spec.configVersion = dvs['config.configVersion']

    begin
        dvs
            .item
            .ReconfigureDvs_Task(
                :spec => spec
            ).wait_for_completion
    rescue StandardError => e
        raise "The Distributed switch #{dvs['name']} could \
        not be updated. "\
                "Reason: #{e.message}"
    end

    @net_rollback << {
        :action => :update_dvs,
            :dvs => dvs.item,
            :name => dvs['name'],
            :spec => orig_spec
    }
end
vm_folder() click to toggle source
# File lib/datacenter.rb, line 860
def vm_folder
    VirtualMachineFolder.new(@item.vmFolder)
end