class Vio

Attributes

available_disks[R]
used_disks[R]

Public Class Methods

new(hmc,frame,name) click to toggle source
Calls superclass method Lpar::new
# File lib/rbvppc/vio.rb, line 15
def initialize(hmc,frame,name)

    raise StandardError.new("A VIO cannot be defined without a managing HMC") if hmc.nil?
    raise StandardError.new("A VIO cannot be defined without a name") if name.nil?
    raise StandardError.new("A VIO cannot be difined without specifying the frame that it resides on") if frame.nil?
    
    #Connect to the HMC and pull all of the LPAR attributes required for
    #the superclass' constructor
    hmc.connect
    options_hash = hmc.get_lpar_options(frame,name)        
                    
    super(options_hash)
    
    #Get an initial list of the available (and used) disks
    list_available_disks
end

Public Instance Methods

add_vscsi(server_lpar) click to toggle source
# File lib/rbvppc/vio.rb, line 428
def add_vscsi(server_lpar)
    warn "Unable to add vscsi on a VIO"
end
add_vscsi_dlpar(server_lpar,client_slot_to_use = nil, server_slot_to_use = nil) click to toggle source
# File lib/rbvppc/vio.rb, line 436
def add_vscsi_dlpar(server_lpar,client_slot_to_use = nil, server_slot_to_use = nil)
    warn "Unable to add vscsi on a VIO"
end
add_vscsi_to_profile(server_lpar) click to toggle source
# File lib/rbvppc/vio.rb, line 432
def add_vscsi_to_profile(server_lpar)
    warn "Unable to add vscsi on a VIO"
end
assign_disk_vhost(disk, vtd, vhost) click to toggle source

Assign Disk/Logical Volume to a vSCSI Host Adapter

# File lib/rbvppc/vio.rb, line 316
def assign_disk_vhost(disk, vtd, vhost)
    command = "mkvdev -vdev #{disk.name} -dev #{vtd} -vadapter #{vhost}"
    execute_vios_cmd(command)

    #If this succeeds, remove disk from @available_disks
    #and add it to @used_disks
    @available_disks.delete(disk)
    @used_disks.push(disk)
end
create() click to toggle source

Base LPAR function overrides to prevent VIOs from performing actions that may destroy/adversely effect an environment's VIOs ie, we shouldn't be able to delete, or create VIOs, just manage them.

# File lib/rbvppc/vio.rb, line 364
def create
    warn "Unable to execute create on a VIO"
end
create_vnic(vlan_id,addl_vlan_ids = "") click to toggle source
# File lib/rbvppc/vio.rb, line 440
def create_vnic(vlan_id,addl_vlan_ids = "")
    warn "Unable to create vnic on a VIO"
end
create_vnic_dlpar(slot_number,vlan_id) click to toggle source
# File lib/rbvppc/vio.rb, line 448
def create_vnic_dlpar(slot_number,vlan_id)
    warn "Unable to create vnic on a VIO"
end
create_vnic_profile(slot_number, vlan_id, addl_vlan_ids, is_trunk, is_required) click to toggle source
# File lib/rbvppc/vio.rb, line 444
def create_vnic_profile(slot_number, vlan_id, addl_vlan_ids, is_trunk, is_required)
    warn "Unable to create vnic on a VIO"
end
delete() click to toggle source
# File lib/rbvppc/vio.rb, line 368
def delete
    warn "Unable to execute delete on a VIO"
end
desired_memory=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 404
def desired_memory=(units)
    warn "Unable to change the memory on a VIO"
end
desired_proc_units=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 392
def desired_proc_units=(units)
    warn "Unable to change the proc units on a VIO"
end
desired_vcpu=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 380
def desired_vcpu=(units)
    warn "Unable to change the vcpu on a VIO"
end
find_vhost_given_virtual_slot(server_slot) click to toggle source

Find vhost to use when given the vSCSI adapter slot it occupies

# File lib/rbvppc/vio.rb, line 119
def find_vhost_given_virtual_slot(server_slot)
    command = "lsmap -all"
    
    #TODO: Save the vhost-to-virtualslot mapping somewhere in the class
    #and simply iterate over that, refreshing what the mappings are any
    #time an adapter is added or removed from this LPAR (???)
    
    #Execute an lsmap and grep for the line that contains the vhost
    #by finding the line that contains the physical adapter location.
    #This will definitely contain 'V#-C<slot number>' in it's name.
    result = execute_vios_cmd_grep(command,"V.-C#{server_slot}")
    raise StandardError.new("Unable to find vhost on #{name} for vSCSI adapter in slot #{server_slot}") if result.nil?
    
    #Split the result on whitespace to get the columns
    #vhost, physical location, client LPAR ID (in hex)
    mapping_cols = result.split(/[[:blank:]]+/)
    
    #The name of the vhost will be in the first column of the command output
    return mapping_cols[0]
end
get_attached_disks(vhost) click to toggle source

Get a list of all disknames attached to a vhost

# File lib/rbvppc/vio.rb, line 101
def get_attached_disks(vhost)
    cmd = "lsmap -vadapter #{vhost} -field backing -fmt :"
    diskname_output = execute_vios_cmd(cmd).chomp
    disk_names = diskname_output.split(/:/)
    disks = []

    #After getting the list of disk names, iterate
    #over the used disks and collect an array of the
    #Luns found to be used.
    used_disks.each do |disk|
        if disk_names.include?(disk.name)
            disks.push(disk)
        end
    end
    return disks
end
get_vio_version() click to toggle source

Get VIOS version

# File lib/rbvppc/vio.rb, line 33
def get_vio_version
    command = "ioslevel"
    execute_vios_cmd(command)
end
hard_shutdown() click to toggle source
# File lib/rbvppc/vio.rb, line 372
def hard_shutdown
    warn "Unable to execute hard_shutdown on a VIO"
end
list_available_disks() click to toggle source

List unmapped disks on VIOS

lspv -free  doesn't include disks that have been mapped before and contain a 'VGID'
# File lib/rbvppc/vio.rb, line 51
def list_available_disks
    command = "lspv -avail -fmt : -field name pvid size"
    all_disk_output = execute_vios_cmd(command)
    mapped_disks = list_mapped_disks
    unmapped_disks = []
    all_disk_output.each_line do |line|
        line.chomp!
        disk_name,disk_pvid,disk_size = line.split(/:/)
        temp_lun = Lun.new(disk_name,disk_pvid,disk_size)
        if !mapped_disks.include?(temp_lun)
            unmapped_disks.push(temp_lun)
        end
    end
    
    #Update the objects local list of available disks and return it
    @available_disks = unmapped_disks
    return unmapped_disks
end
list_mapped_disks() click to toggle source

List all Disk Mappings

# File lib/rbvppc/vio.rb, line 71
def list_mapped_disks
    command = "lsmap -all -type disk"
    result = execute_vios_cmd_grep(command, "Backing")

    mapped_disknames = []
    result.each_line do |line|
        line.chomp!
        line_elements=line.split(/[[:blank:]]+/)
        #3rd element should be disk name, since first is 'Backing' and
        #the second is 'device'
        disk_name = line_elements[2]
        mapped_disknames.push(disk_name) if !mapped_disknames.include?(disk_name)
    end

    command = "lspv -avail -fmt : -field name pvid size"
    full_disk_info = execute_vios_cmd_grep(command, "hdisk")
    mapped_disks = []
    full_disk_info.each_line do |line|
        line.chomp!
        disk_name,disk_pvid,disk_size = line.split(/:/)
        if mapped_disknames.include?(disk_name)
            mapped_disks.push(Lun.new(disk_name,disk_pvid,disk_size))
        end
    end

    @used_disks = mapped_disks
    return mapped_disks
end
list_shared_eth_adapters() click to toggle source

List Shared Ethernet Adapters on VIOS

# File lib/rbvppc/vio.rb, line 310
def list_shared_eth_adapters
    command = "lsmap -all -net"
    execute_vios_cmd(command)
end
map_any_disk(vhost, second_vio, second_vhost) click to toggle source

Map any disk on a pair of VIO's given the respective vhosts to map them to

# File lib/rbvppc/vio.rb, line 145
def map_any_disk(vhost, second_vio, second_vhost)
    #Select disk on each VIO and return a hash containing
    #the LUN object from each of the VIOs
    lun_hash = select_any_avail_disk(second_vio)

    #Generate the vtd name to use on each VIO
    #TODO: Need to enhance this.
    vtd1_name = "vtd_" + lun_hash[:on_vio1].name
    vtd2_name = "vtd_" + lun_hash[:on_vio2].name

    #Assign disk to the first VIO (self)
    assign_disk_vhost(lun_hash[:on_vio1],vtd1_name,vhost)

    #Assign disk to the second VIO
    second_vio.assign_disk_vhost(lun_hash[:on_vio2],vtd2_name,second_vhost)
end
map_by_pvid!(vhost, second_vhost, second_vio, pvid) click to toggle source

Map a disk on a pair of VIOs given the respective vhosts to map them to, as well as, the disk's PVID

# File lib/rbvppc/vio.rb, line 163
def map_by_pvid!(vhost, second_vhost, second_vio, pvid)
    #Select disk on each VIO and return a hash containing
    #the LUNC object from each of the VIOs
    lun_hash = select_disk_by_pvid(second_vio,pvid)

    #Generate the vtd name to use on each VIO
    #TODO: Need to enhance this.
    vtd1_name = "vtd_" + lun_hash[:on_vio1].name
    vtd2_name = "vtd_" + lun_hash[:on_vio2].name

    #Assign disk to the first VIO (self)
    assign_disk_vhost(lun_hash[:on_vio1],vtd1_name,vhost)

    #Assign disk to the second VIO
    second_vio.assign_disk_vhost(lun_hash[:on_vio2],vtd2_name,second_vhost)

end
map_by_size(vhost,second_vio,second_vhost,total_size_in_gb) click to toggle source

Maps a group of disks to the specified vhosts on a pair of VIOs based on a given total size requirement

# File lib/rbvppc/vio.rb, line 183
def map_by_size(vhost,second_vio,second_vhost,total_size_in_gb)
    lun_hash = select_disks_by_size(second_vio,total_size_in_gb)

    #Raise an error if lun_hash is an empty hash
    raise StandardError.new("VIO pair does not have a subset of available disks to satisfy the requested size of #{total_size_in_gb}") if lun_hash.empty?

    vio1_disks = lun_hash[:on_vio1]
    vio2_disks = lun_hash[:on_vio2]

    # TODO: Possibly find a way to test that the vhost exists
    # prior to doing anything (ie, make sure the client LPAR
    # that this serves has vSCSIs defined for this)

    #Assign all disks to first VIO
    vio1_disks.each do |disk|
        vtd_name = "vtd_" + disk.name
        assign_disk_vhost(disk,vtd_name,vhost)
    end

    #Assign all disks to second VIO
    vio2_disks.each do |disk|
        vtd_name = "vtd_" + disk.name
        second_vio.assign_disk_vhost(disk,vtd_name,second_vhost)
    end
end
map_single_disk_by_size(vhost,second_vio,second_vhost,total_size_in_gb) click to toggle source

Maps a group of disks to the specified vhosts on a pair of VIOs based on a given total size requirement

# File lib/rbvppc/vio.rb, line 211
def map_single_disk_by_size(vhost,second_vio,second_vhost,total_size_in_gb)
    lun_hash = select_single_disk_by_size(second_vio,total_size_in_gb)

    #Raise an error if lun_hash is an empty hash
    raise StandardError.new("VIO pair does not have a subset of available disks to satisfy the requested size of #{total_size_in_gb}") if lun_hash.empty?

    vio1_disks = lun_hash[:on_vio1]
    vio2_disks = lun_hash[:on_vio2]

    # TODO: Possibly find a way to test that the vhost exists
    # prior to doing anything (ie, make sure the client LPAR
    # that this serves has vSCSIs defined for this)

    #Assign all disks to first VIO
    vio1_disks.each do |disk|
        vtd_name = "vtd_" + disk.name
        assign_disk_vhost(disk,vtd_name,vhost)
    end

    #Assign all disks to second VIO
    vio2_disks.each do |disk|
        vtd_name = "vtd_" + disk.name
        second_vio.assign_disk_vhost(disk,vtd_name,second_vhost)
    end
end
max_memory=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 412
def max_memory=(units)
    warn "Unable to change the memeory on a VIO"
end
max_proc_units=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 396
def max_proc_units=(units)
    warn "Unable to change the proc units on a VIO"
end
max_vcpu=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 388
def max_vcpu=(units)
    warn "Unable to change the vcpu on a VIO"
end
min_memory=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 408
def min_memory=(units)
    warn "Unable to change the memory on a VIO"
end
min_proc_units=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 400
def min_proc_units=(units)
    warn "Unable to change the proc units on a VIO"
end
min_vcpu=(units) click to toggle source
# File lib/rbvppc/vio.rb, line 384
def min_vcpu=(units)
    warn "Unable to change the vcpu on a VIO"
end
reboot() click to toggle source

Reboot VIOS

# File lib/rbvppc/vio.rb, line 39
def reboot
    command ="shutdown -restart"
    execute_vios_cmd(command)
end
recursive_remove_vhost(vhost) click to toggle source

Recursively remove a Virtual SCSI Host Adapter

# File lib/rbvppc/vio.rb, line 327
def recursive_remove_vhost(vhost)
    command = "rmdev -dev #{vhost} -recursive"
    execute_vios_cmd(command)
end
remove_disk_from_vhost(disk) click to toggle source

Remove physical disk from vhost adapter

# File lib/rbvppc/vio.rb, line 339
def remove_disk_from_vhost(disk)
    command = "rmvdev -vdev #{disk.name}"
    execute_vios_cmd(command)

    #If this succeeds, remove disk from @used_disks
    #and add it to @available_disks
    @used_disks.delete(disk)
    @available_disks.push(disk)
end
remove_vhost(vhost) click to toggle source

Remove a Virtual SCSI Host Adapter

# File lib/rbvppc/vio.rb, line 350
def remove_vhost(vhost)
    command = "rmdev -dev #{vhost}"
    execute_vios_cmd(command)
end
remove_vscsi(server_lpar,adapter_details=nil) click to toggle source
# File lib/rbvppc/vio.rb, line 424
def remove_vscsi(server_lpar,adapter_details=nil)
    warn "Unable to remove vscsi on a VIO"
end
remove_vscsi_dlpar(server_lpar,vscsi) click to toggle source
# File lib/rbvppc/vio.rb, line 420
def remove_vscsi_dlpar(server_lpar,vscsi)
     warn "Unable to remove vscsi on a VIO"
end
remove_vscsi_from_profile(server_lpar,vscsi) click to toggle source
# File lib/rbvppc/vio.rb, line 416
def remove_vscsi_from_profile(server_lpar,vscsi)
    warn "Unable to remove vscsi from VIO object"
end
remove_vtd_from_vhost(vtd) click to toggle source

Remove Disk/Logical Volume from vSCSI Host Adapter

# File lib/rbvppc/vio.rb, line 333
def remove_vtd_from_vhost(vtd)
    command = "rmvdev -vtd #{vtd}"
    execute_vios_cmd(command)
end
soft_shutdown() click to toggle source
# File lib/rbvppc/vio.rb, line 376
def soft_shutdown
    warn "Unable to execute soft_shutdown on a VIO"
end
unmap_all_disks(second_vio,client_lpar) click to toggle source

Unmap all disks on given LPAR from this VIO and the given secondary VIO and remove their associated vSCSI adapters

# File lib/rbvppc/vio.rb, line 239
def unmap_all_disks(second_vio,client_lpar)
    vscsi_adapters = client_lpar.get_vscsi_adapters

    #Repeat for each vSCSI found on the client LPAR
    #TODO: Add better logic for determining which vSCSIs
    #to use to avoid cases where multiple vSCSIs to each VIO
    #exist.
    vscsi_adapters.each do |vscsi|            
        #Determine if this adapter is attached to the primary VIO (self)
        #or the secondary VIO (second_vio), and assign that to a temp
        #variable to prevent rewriting the same procedure for both VIOs.
        if vscsi.remote_lpar_name == name
            current_vio = self
        elsif vscsi.remote_lpar_name == second_vio.name
            current_vio = second_vio
        else
            next
        end

        #Find the vhost associated with this vSCSI on the current VIO
        vhost = current_vio.find_vhost_given_virtual_slot(vscsi.remote_slot_num)

        #Use the vhost to find all of the disks attached to it
        disks = current_vio.get_attached_disks(vhost)

        #Remove all of the disks from that vhost
        disks.each do |disk|
            current_vio.remove_disk_from_vhost(disk)
        end

        #Remove that vhost
        current_vio.remove_vhost(vhost)

        #Remove the client LPAR's vSCSI now that all the disks are detached from it
        client_lpar.remove_vscsi(current_vio,vscsi)

    end
end
unmap_by_pvid(second_vio,pvid) click to toggle source

Unmap a disk on the given LPAR from this VIO and the given secondary VIO by the disks PVID

# File lib/rbvppc/vio.rb, line 280
def unmap_by_pvid(second_vio,pvid)
    # Iterate over the primary VIO's used disks, find the one
    # we want to remove by it's PVID, find that disk on the Secondary VIO
    # and unmap this disk from each VIO
    used_disks.each do |vio1_disk|
        if vio1_disk.pvid == pvid
            #Find this disk on second_vio
            second_vio_disks = second_vio.used_disks
            i = second_vio_disks.index(vio1_disk)
            raise StandardError.new("Disk with PVID #{pvid} not mapped on #{second_vio.name}. Please ensure this disk is attached to both VIOs in the pair") if i.nil?
            vio2_disk = second_vio_disks[i]

            #Unmap disk on first VIO
            remove_disk_from_vhost(vio1_disk)

            #Unmap disk on second VIO
            second_vio.remove_disk_from_vhost(vio2_disk)

            return
        end
    end
    raise StandardError.new("Disk with PVID #{pvid} not mappped on #{name}. Please ensure this disk is attached to the VIO")
end

Private Instance Methods

execute_vios_cmd(command) click to toggle source

Execute VIOS commands via HMC

# File lib/rbvppc/vio.rb, line 711
def execute_vios_cmd(command)
    hmc.execute_cmd "viosvrcmd -m #{frame} -p #{name} -c \" #{command} \""
end
execute_vios_cmd_grep(command, grep_for) click to toggle source

Execute VIOS commands via HMC grepping for a specific item.

# File lib/rbvppc/vio.rb, line 716
def  execute_vios_cmd_grep(command, grep_for)
    hmc.execute_cmd "viosvrcmd -m #{frame} -p #{name} -c \" #{command} \" | grep #{grep_for}"
end
select_any_avail_disk(second_vio) click to toggle source

Use this in coordination with another VIO to find an available disk between the both of them A hash is returned with a selected Lun object on each VIO

# File lib/rbvppc/vio.rb, line 457
def select_any_avail_disk(second_vio)
    primary_vio_disks = available_disks
    secondary_vio_disks = second_vio.available_disks
    
    return {} if primary_vio_disks.empty? or secondary_vio_disks.empty?
    
    vio1_lun = primary_vio_disks[0]
    vio2_lun = nil
    secondary_vio_disks.each do |lun|
        if vio1_lun == lun
            vio2_lun = lun
            break
        end
    end

    if vio2_lun.nil?
        raise StandardError.new("LUN with PVID #{vio1_lun.pvid} not found on #{vio2}")
    end
    # return [vio1_disk_name, vio2_disk_name]
    # return [vio1_lun, vio2_lun]
    return {:on_vio1 => vio1_lun, :on_vio2 => vio2_lun}
end
select_disk_by_pvid(second_vio,pvid) click to toggle source

Use this in coordination with another VIO to find an available disk between the both of them via PVID A hash is returned with a selected Lun object on each VIO

# File lib/rbvppc/vio.rb, line 482
def select_disk_by_pvid(second_vio,pvid)
    primary_vio_disks = @available_disks + @used_disks
    secondary_vio_disks = second_vio.available_disks + second_vio.used_disks
    return{} if primary_vio_disks.empty? or secondary_vio_disks.empty?
    #loop through primary_vio_disks to find the pvid
    vio1_lun = nil
    vio2_lun = nil
    primary_vio_disks.each do |lun|
        if lun.pvid == pvid
            vio1_lun = lun
        end
    end
    secondary_vio_disks.each do |lun|
        if lun.pvid == pvid
            vio2_lun = lun
        end
    end
    if vio1_lun == vio2_lun
        return {:on_vio1 => vio1_lun, :on_vio2 => vio2_lun}
    else
        raise StandardError.new("LUN with PVID #{pvid} not found on both VIOs")
    end
    
end
select_disks_by_size(second_vio,total_size_in_gb) click to toggle source

Select a subset of available disks on this VIO and the given Secondary VIO that satisfies at least the size requirement provided

# File lib/rbvppc/vio.rb, line 509
def select_disks_by_size(second_vio,total_size_in_gb)
    primary_vio_disks = available_disks
    secondary_vio_disks = second_vio.available_disks

    #Return an empty hash if one or both of the VIOs have no free disks to use
    return {} if primary_vio_disks.empty? or secondary_vio_disks.empty?

    #Find a collection of disks that works on one of the VIOs
    sorted_disks = primary_vio_disks.sort { |x,y| y.size_in_mb <=> x.size_in_mb }

    #Convert the requested size to MB, as all LUN sizes are in those units
    #And initialize a variable to hold the 'currently' allocated amount in MB
    space_left = total_size_in_gb*1024
    space_allocated = 0

    #Let the upper limit of what we can allocate be
    #the total size in GB, plus 64GB (a typical size of a LUN), converted to MB
    upper_limit = (total_size_in_gb+64)*1024

    #Array that will be built up to hold the selected disks on the primary VIO
    selected_disks = []
    disks_found = false
    last_disk = nil
    until disks_found
        if space_left <= 0
            disks_found = true
            break
        end
        #Save the current space_left for use later to determine if it was decremented in this iteration
        old_space_left = space_left

        sorted_disks.each do |cur_disk|
            last_disk = cur_disk if last_disk.nil?
            cur_disk_size = cur_disk.size_in_mb
            #Test if this disk is larger than what is left and smaller than what our
            #upper bound limit on allocating is
            if (cur_disk_size >= space_left && space_allocated + cur_disk_size <= upper_limit)
                #puts "Entered block 1"
                #Add this disk to selected_disks
                selected_disks.push(cur_disk)
                #Decrement space_left
                space_left -= cur_disk_size
                #increment space_allocated
                space_allocated += cur_disk_size
                #set last_disk to cur_disk
                last_disk = cur_disk
                #remove cur_disk from sorted_disks
                sorted_disks.delete(cur_disk)
                #break out of loop to select next disk
                break
            end

            #Test if this disk is less than what we have left to allocate
            #and still does not put us over the upper bound
            if (cur_disk_size < space_left && cur_disk_size+space_allocated <= upper_limit)
                #puts "Entered block 2"
                if cur_disk_size <= (space_left - cur_disk_size)
                    #puts "Entered block 2.1"
                    #Add this disk to selected_disks
                    selected_disks.push(cur_disk)
                    #Decrement space_left
                    space_left -= cur_disk_size
                    #Increment space_allocated
                    space_allocated += cur_disk_size
                    #set last_disk to cur_disk
                    last_disk = cur_disk
                    #remove cur_disk from sorted_disks
                    sorted_disks.delete(cur_disk)
                    #break out of loop to select next disk
                    break
                else
                    #puts "Entered block 2.2"
                    old_poss_next_disk = nil
                    sorted_disks.reverse.each do |poss_next_disk|
                        old_poss_next_disk = poss_next_disk if old_poss_next_disk.nil?
                        poss_next_size = poss_next_disk.size_in_mb
                        if (cur_disk_size + poss_next_size + space_allocated) <= upper_limit
                            #Add this disk to selected_disks
                            selected_disks.push(cur_disk)
                            #decrement space_left
                            space_left -= cur_disk_size
                            #increment space_allocated
                            space_allocated += cur_disk_size
                            #Set last_disk to cur_disk
                            last_disk = cur_disk
                            #remove cur_disk from sorted_disks
                            sorted_disks.delete(cur_disk)
                            #break out of loop to select next disk
                            break
                        end
                    end
                end

            end
        end

        #If after iterating over the entire list of disks, we haven't
        #decremented space_left, then fail out, since it wasn't possible
        #to find another disk to fit the requested size
        if old_space_left == space_left
            warn "Unable to select a subset of disks that fulfills the size requested"
            return {}
        end
    end

    #Iterate over the disks that were found on the first VIO
    #and generate a list of their counterparts on the second VIO
    selected_disks_vio1 = selected_disks
    selected_disks_vio2 = []
    selected_disks_vio1.each do |disk|
        i = secondary_vio_disks.index(disk)
        selected_disks_vio2.push(secondary_vio_disks[i])
    end

    #Return a hash of two arrays, one of which is a list of Luns on the first VIO
    #and ther other of which is a list of their counterparts on the second VIO
    return { :on_vio1 => selected_disks_vio1, :on_vio2 => selected_disks_vio2}

end
select_single_disk_by_size(second_vio,total_size_in_gb) click to toggle source

Select a single available disk on this VIO and the given secondary VIO that satisfies at least the size requirement provided. This version of select by size is used for rootvg disks as it is best practice to have rootvg on a single disk.

# File lib/rbvppc/vio.rb, line 633
def select_single_disk_by_size(second_vio,total_size_in_gb)
    primary_vio_disks = available_disks
    secondary_vio_disks = second_vio.available_disks

    #Return an empty hash if one or both of the VIOs have no free disks to use
    return {} if primary_vio_disks.empty? or secondary_vio_disks.empty?

    #Find a collection of disks that works on one of the VIOs
    sorted_disks = primary_vio_disks.sort { |x,y| x.size_in_mb <=> y.size_in_mb }

    #Convert the requested size to MB, as all LUN sizes are in those units
    #And initialize a variable to hold the 'currently' allocated amount in MB
    space_left = total_size_in_gb*1024
    space_allocated = 0

    #Array that will be built up to hold the selected disks on the primary VIO
    selected_disks = []
    disks_found = false
    last_disk = nil
    until disks_found
        if space_left <= 0
            disks_found = true
            break
        end
        #Save the current space_left for use later to determine if it was decremented in this iteration
        old_space_left = space_left

        sorted_disks.each do |cur_disk|
            last_disk = cur_disk if last_disk.nil?
            cur_disk_size = cur_disk.size_in_mb
            #Test if this disk is larger than what is left and smaller than what our
            #upper bound limit on allocating is
            if (cur_disk_size >= space_left && space_allocated + cur_disk_size)
                #puts "Entered block 1"
                #Add this disk to selected_disks
                selected_disks.push(cur_disk)
                #Decrement space_left
                space_left -= cur_disk_size
                #increment space_allocated
                space_allocated += cur_disk_size
                #set last_disk to cur_disk
                last_disk = cur_disk
                #remove cur_disk from sorted_disks
                sorted_disks.delete(cur_disk)
                #break out of loop to select next disk
                break
            end
        end

        #If after iterating over the entire list of disks, we haven't
        #decremented space_left, then fail out, since it wasn't possible
        #to find another disk to fit the requested size
        if old_space_left == space_left
            warn "Unable to select a subset of disks that fulfills the size requested"
            return {}
        end
    end

    #Iterate over the disks that were found on the first VIO
    #and generate a list of their counterparts on the second VIO
    selected_disks_vio1 = selected_disks
    selected_disks_vio2 = []
    selected_disks_vio1.each do |disk|
        i = secondary_vio_disks.index(disk)
        selected_disks_vio2.push(secondary_vio_disks[i])
    end

    #Return a hash of two arrays, one of which is a list of Luns on the first VIO
    #and ther other of which is a list of their counterparts on the second VIO
    return { :on_vio1 => selected_disks_vio1, :on_vio2 => selected_disks_vio2}

end