class VCenterDriver::ESXHost

Class ESXHost

Constants

PG_CREATE_TIMEOUT

Attributes

item[RW]

Public Class Methods

new(item, vi_client = nil) click to toggle source
# File lib/host.rb, line 1006
def initialize(item, vi_client = nil)
    @net_rollback = []
    @locking = true
    @item = item
    @vi_client = vi_client
end
new_from_ref(ref, vi_client) click to toggle source
# File lib/host.rb, line 1013
def self.new_from_ref(ref, vi_client)
    new(RbVmomi::VIM::HostSystem.new(vi_client.vim, ref), vi_client)
end

Public Instance Methods

assign_proxy_switch(dvs, switch_name, pnics, _pnics_available) click to toggle source

Assign a host to a a distributed vcenter switch (proxy switch)

# File lib/host.rb, line 1257
def assign_proxy_switch(dvs, switch_name, pnics, _pnics_available)
    dvs = dvs.item

    # Return if host is already assigned
    return dvs unless dvs['config.host']
                      .select do |host|
                          host.config.host._ref == self['_ref']
                      end.empty?

    # Prepare spec for DVS reconfiguration
    config_spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
    config_spec.name = switch_name
    config_spec.configVersion = dvs['config.configVersion']

    # Check if host is already assigned to distributed switch
    operation = 'add'
    # #operation = "edit" if !dvs['config.host'].select
    # { |host| host.config.host._ref == self['_ref'] }.empty?

    # Add host members to the distributed virtual switch
    host_member_spec =
        RbVmomi::VIM::DistributedVirtualSwitchHostMemberConfigSpec
        .new
    host_member_spec.host = @item
    host_member_spec.operation = operation
    host_member_spec.backing =
        RbVmomi::VIM::DistributedVirtualSwitchHostMemberPnicBacking
        .new
    host_member_spec.backing.pnicSpec = []

    # If pnics are needed assign pnics for uplinks
    if pnics
        pnics = pnics.split(',')
        # Get uplink portgroup from dvswitch
        uplink_key = dvs['config.uplinkPortgroup'].select do |ul|
                         ul.name == "#{switch_name}-uplink-pg"
                     end.first.key rescue nil

        unless uplink_key
            raise "Cannot find the uplink portgroup for #{switch_name}"
        end

        pnics.each do |pnic|
            pnic_spec =
                RbVmomi::VIM::DistributedVirtualSwitchHostMemberPnicSpec
                .new
            pnic_spec.pnicDevice = pnic
            pnic_spec.uplinkPortgroupKey = uplink_key
            host_member_spec.backing.pnicSpec << pnic_spec
        end
    end

    config_spec.host = [host_member_spec]

    # The DVS must be reconfigured
    dvs_reconfigure_task = dvs.ReconfigureDvs_Task(:spec => config_spec)
    dvs_reconfigure_task.wait_for_completion
    if dvs_reconfigure_task.info.state != 'success'
        raise "It wasn't possible to assign host \
        #{self['name']} as a member of #{switch_name}'"
    end

    dvs
end
available_pnics() click to toggle source

Get physical nics that are available in a host

# File lib/host.rb, line 1197
def available_pnics
    pnics_in_use = []
    pnics_available = []

    # Get pnics in use in standard switches
    @item.config.network.vswitch.each do |vs|
        vs.pnic.each do |pnic|
            next unless pnic.instance_of?(String)

            pnic.slice!('key-vim.host.PhysicalNic-')
            pnics_in_use << pnic
        end
    end

    # Get pnics in host
    self['config.network'].pnic.each do |pnic|
        next if pnics_in_use
                .include?(pnic.device)

        pnics_available << pnic
                           .device
    end

    pnics_available
end
create_pg(pgname, vswitch, vlan = 0) click to toggle source

Create a standard port group

# File lib/host.rb, line 1326
def create_pg(pgname, vswitch, vlan = 0)
    spec = RbVmomi::VIM.HostPortGroupSpec(
        :name => pgname,
        :vlanId => vlan,
        :vswitchName => vswitch,
        :policy => RbVmomi::VIM.HostNetworkPolicy
    )

    nws = self['configManager.networkSystem']

    begin
        nws.AddPortGroup(:portgrp => spec)
    rescue StandardError => e
        raise "A port group with name #{pgname} \
        could not be created. Reason: #{e.message}"
    end

    @net_rollback << { :action => :delete_pg, :name => pgname }

    # wait until the network is ready and we have a reference
    networks = @item['network'].select {|net| net.name == pgname }
    (0..PG_CREATE_TIMEOUT).each do
        break unless networks.empty?

        networks = @item['network'].select {|net| net.name == pgname }
        sleep 1
    end

    if networks.empty?
        raise 'Cannot get VCENTER_NET_REF for new port group'
    end

    networks.first._ref
end
create_vss( name, num_ports, pnics = nil, mtu = 1500, pnics_available = nil ) click to toggle source

Create a standard vcenter switch in an ESX host

# File lib/host.rb, line 1049
def create_vss(
    name,
    num_ports,
    pnics = nil,
    mtu = 1500,
    pnics_available = nil
)
    # Get NetworkSystem
    nws = self['configManager.networkSystem']
    hostbridge = nil
    nics = []

    num_ports = 128 if num_ports.nil?

    if pnics
        pnics = pnics.split(',')
        pnics.each do |pnic|
            # Add nics if not in use
            nics << pnic if pnics_available.include?(pnic)
        end

        if !nics.empty?
            hostbridge =
                RbVmomi::VIM::HostVirtualSwitchBondBridge(
                    :nicDevice => nics
                )
        end
    end

    # Create spec
    vswitchspec =
        RbVmomi::VIM::HostVirtualSwitchSpec(
            :bridge => hostbridge,
            :mtu => mtu,
            :numPorts => num_ports
        )

    # add vSwitch to the host
    begin
        nws.AddVirtualSwitch(:vswitchName => name, :spec => vswitchspec)
    rescue StandardError => e
        raise "The standard vSwitch #{name} could not be \
        created. AddVirtualSwitch failed Reason: #{e.message}."
    end

    @net_rollback << { :action => :delete_sw, :name => name }

    name
end
lock() click to toggle source

Locking function. Similar to flock

# File lib/host.rb, line 1018
def lock
    hostlockname = @item['name'].downcase.tr(' ', '_')

    return unless @locking

    @locking_file =
        File
        .open("/tmp/vcenter-#{hostlockname}-lock", 'w')
    @locking_file.flock(File::LOCK_EX)
end
network_rollback() click to toggle source
# File lib/host.rb, line 1457
def network_rollback
    nws = self['configManager.networkSystem']

    @net_rollback.reverse_each do |nr|
        case nr[:action]
        when :update_pg
            begin
                nws
                    .UpdatePortGroup(
                        :pgName => nr[:name],
                        :portgrp => nr[:spec]
                    )
            rescue StandardError => e
                raise "A rollback operation for standard \
                port group #{nr[:name]} could not \
                be performed. Reason: #{e.message}"
            end
        when :update_sw
            begin
                nws
                    .UpdateVirtualSwitch(
                        :vswitchName => nr[:name],
                        :spec => nr[:spec]
                    )
            rescue StandardError => e
                raise "A rollback operation for standard \
                switch #{nr[:name]} could not \
                be performed. Reason: #{e.message}"
            end
        when :delete_sw
            begin
                nws.RemoveVirtualSwitch(:vswitchName=> nr[:name])
            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_pg
            begin
                nws.RemovePortGroup(:pgName => nr[:name])
            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
pg_changes_sw?(pg, switch_name) click to toggle source

Is the switch for the pg different?

# File lib/host.rb, line 1375
def pg_changes_sw?(pg, switch_name)
    pg
        .spec
        .respond_to?(
            :vswitchName
        ) && pg
            .spec
            .vswitchName != switch_name
end
pg_exists(pg_name) click to toggle source

Check if standard port group exists in host

# File lib/host.rb, line 1365
def pg_exists(pg_name)
    nws = self['configManager.networkSystem']
    portgroups = nws.networkInfo.portgroup
    portgroups.select {|pg| pg.spec.name == pg_name }.first rescue nil
end
pg_inside_host() click to toggle source

Get networks inside a host

# File lib/host.rb, line 1226
def pg_inside_host
    pg_inside = {}

    # Get pnics in use in standard switches
    @item.config.network.vswitch.each do |vs|
        pg_inside[vs.name] = []
        vs.portgroup.each do |pg|
            pg.slice!('key-vim.host.PortGroup-')
            pg_inside[vs.name] << pg
        end
    end

    pg_inside
end
proxy_switch_exists(switch_name) click to toggle source

Check if proxy switch exists in host for distributed virtual switch

# File lib/host.rb, line 1245
def proxy_switch_exists(switch_name)
    nws = self['configManager.networkSystem']
    proxy_switches = nws.networkInfo.proxySwitch
    proxy_switches
        .select {|ps| ps.dvsName == switch_name }
        .first rescue nil
end
remove_pg(pgname) click to toggle source

Remove a standard port group from the host

# File lib/host.rb, line 1427
def remove_pg(pgname)
    nws = self['configManager.networkSystem']

    swname = nil
    begin
        portgroups = nws.networkConfig.portgroup
        portgroups.each do |pg|
            if pg.spec.name == pgname
                swname = pg.spec.vswitchName
                break
            end
        end
        nws.RemovePortGroup(:pgName => pgname)
    rescue RbVmomi::VIM::ResourceInUse
        STDERR.puts "The standard portgroup \
        #{pgname} is in use so it cannot be deleted"
        return
    rescue RbVmomi::VIM::NotFound
        STDERR.puts "The standard portgroup \
        #{pgname} was not found in vCenter"
        return
    rescue StandardError => e
        raise "There was a failure while \
        deleting a standard portgroup #{pgname} \
        in vCenter. Reason: #{e.message}"
    end

    swname
end
remove_vss(vswitch_name) click to toggle source

Remove a standard vswitch from the host

# File lib/host.rb, line 1173
def remove_vss(vswitch_name)
    nws = self['configManager.networkSystem']

    begin
        nws.RemoveVirtualSwitch(:vswitchName => vswitch_name)
    rescue RbVmomi::VIM::ResourceInUse
        STDERR.puts "The standard switch #{vswitch_name} \
        is in use so it cannot be deleted"
        return
    rescue RbVmomi::VIM::NotFound
        STDERR.puts "The standard switch #{vswitch_name} \
        was not found in vCenter"
        return
    rescue StandardError => e
        raise "There was a failure while deleting a vcenter \
        standard switch #{vswitch_name}. Reason: #{e.message}"
    end

    vswitch_name
end
unlock() click to toggle source

Unlock driver execution mutex

# File lib/host.rb, line 1030
def unlock
    return unless @locking

    @locking_file.close
end
update_pg(pg, switch_name, vlan_id) click to toggle source

Update a standard port group

# File lib/host.rb, line 1389
def update_pg(pg, switch_name, vlan_id)
    unless pg.spec.respond_to?(:vlanId) && pg.spec.vlanId != vlan_id
        return; end

    # Backup original spec
    orig_spec = pg.spec

    # Create new spec
    pg_name = pg.spec.name

    spec = RbVmomi::VIM.HostPortGroupSpec(
        :name => pg_name,
        :vlanId => vlan_id,
        :vswitchName => switch_name,
        :policy => RbVmomi::VIM.HostNetworkPolicy
    )

    nws = self['configManager.networkSystem']

    begin
        nws.UpdatePortGroup(:pgName => pg_name, :portgrp => spec)
    rescue StandardError => e
        raise "A port group with name #{pg_name} \
        could not be updated. Reason: #{e.message}"
    end

    # Set rollback operation
    @net_rollback << {
        :action => :update_pg,
        :name => pg_name,
            :spec => orig_spec
    }
end
update_vss(switch, name, pnics, num_ports, mtu) click to toggle source

Update a standard vcenter switch in an ESX host

# File lib/host.rb, line 1102
def update_vss(switch, name, pnics, num_ports, mtu)
    pnics = pnics.split(',') rescue []

    # Backup switch spec for rollback
    orig_spec = switch.spec

    # Compare current configuration and return if switch hasn't changed
    switch_has_pnics = switch
                       .spec
                       .respond_to?(
                           :bridge
                       ) && switch
                       .spec
                       .bridge
                       .respond_to?(
                           :nicDevice
                       )

    same_switch = switch.spec.respond_to?(:mtu) && switch
                  .spec
                  .mtu == mtu &&
                  switch
                  .spec
                  .respond_to?(
                      :numPorts
                  ) && switch.spec.numPorts == num_ports &&
                  (!switch_has_pnics && pnics.empty? ||
                   switch_has_pnics && switch
                   .spec
                   .bridge
                   .nicDevice
                   .uniq
                   .sort == pnics.uniq.sort)
    return if same_switch

    # Let's create a new spec and update the switch
    hostbridge = nil
    nws = self['configManager.networkSystem']
    unless pnics.empty?
        hostbridge =
            RbVmomi::VIM::HostVirtualSwitchBondBridge(
                :nicDevice => pnics
            )
    end
    vswitchspec =
        RbVmomi::VIM::HostVirtualSwitchSpec(
            :bridge => hostbridge,
            :mtu => mtu,
            :numPorts => num_ports
        )
    begin
        nws
            .UpdateVirtualSwitch(
                :vswitchName => name,
                :spec => vswitchspec
            )
    rescue StandardError => e
        raise "The standard switch with name #{name} \
        could not be updated. Reason: #{e.message}"
    end

    @net_rollback << {
        :action => :update_sw,
        :name => name,
        :spec => orig_spec
    }
end
vss_exists(vswitch_name) click to toggle source

Check if standard switch exists in host

# File lib/host.rb, line 1040
def vss_exists(vswitch_name)
    vswitches = @item.configManager.networkSystem.networkInfo.vswitch
    vswitches.select {|vs| vs.name == vswitch_name }.first rescue nil
end