Class: Lpar

Inherits:
Object
  • Object
show all
Defined in:
lib/rbvppc/lpar.rb

Direct Known Subclasses

Vio

Constant Summary collapse

@@valid_attributes =

Class variable to hold all ‘valid’ attributes that can be set on an LPAR

["min_mem", "desired_mem", "max_mem", "min_num_huge_pages", "desired_num_huge_pages", "max_num_huge_pages",
"mem_mode", "hpt_ratio", "proc_mode", "min_proc_units", "desired_proc_units", "max_proc_units", "min_procs",
"desired_procs", "max_procs", "sharing_mode", "uncap_weight", "shared_proc_pool_id", "shared_proc_pool_name",
"io_slots", "lpar_io_pool_ids", "max_virtual_slots", "hca_adapters", "boot_mode", "conn_monitoring", "auto_start",
"power_ctrl_lpar_ids", "work_group_id", "redundant_err_path_reporting", "bsr_arrays", "lhea_logical_ports", "lhea_capabilities", "lpar_proc_compat_mode", "electronic_err_reporting"]
@@attr_mapping =

Small hash to handle translating HMC labels to Lpar class attributes

{"min_mem"            => "min_memory",
 "max_mem"            => "max_memory",
 "desired_mem"        => "desired_memory",
 "min_proc_units"     => "min_proc_units",
 "max_proc_units"     => "max_proc_units",
 "desired_proc_units" => "desired_proc_units",
 "min_procs"          => "min_vcpu",
 "max_procs"          => "max_vcpu",
 "desired_procs"      => "desired_vcpu"
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options_hash, disable_auto_reboot = false) ⇒ Lpar

Returns a new instance of Lpar.

Raises:

  • (StandardError)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rbvppc/lpar.rb', line 50

def initialize(options_hash, disable_auto_reboot = false)
    
    #Test for the explicitly required parameters
    raise StandardError.new("An Lpar cannot be defined without a managing HMC") if options_hash[:hmc].nil? or !options_hash[:hmc].respond_to?(:execute_cmd)
    raise StandardError.new("An Lpar cannot be defined without a name") if options_hash[:name].nil?
    raise StandardError.new("An Lpar cannot be defined without specifying the frame it resides/will reside on") if options_hash[:frame].nil?
    raise StandardError.new("An Lpar cannot be defined without specifying it's desired processing units") if options_hash[:des_proc].nil?
    raise StandardError.new("An Lpar cannot be defined without specifying it's desired virtual CPUs") if options_hash[:des_vcpu].nil?
    raise StandardError.new("An Lpar cannot be defined without specifying it's desired memory") if options_hash[:des_mem].nil?
    
    #TODO: We should not really be storing the hostname (or vlan_id, or management_ip) as an attribute of LPAR, much less any network configuration stuff...
    #Maybe we should consider a NetworkSettings class that is just an attribute of LPAR, which we leverage to find any network info we need here...?
    raise StandardError.new("An Lpar cannot be defined without specifying it's FQDN") if options_hash[:hostname].nil? && options_hash[:name].nil?
    
    #Parameters that are explicitly required to make an LPAR object
    @hmc        = options_hash[:hmc]
    @desired_proc_units = options_hash[:des_proc].to_f
    @desired_memory     = options_hash[:des_mem].to_i
    @desired_vcpu       = options_hash[:des_vcpu].to_i
    @frame        = options_hash[:frame]
    @name               = options_hash[:name]
    
    #Parameters that can be defaulted if they are not provided
    !options_hash[:hostname].nil? ? @hostname = options_hash[:hostname] : @hostname = @name
    !options_hash[:min_proc].nil? ? @min_proc_units = options_hash[:min_proc].to_f : @min_proc_units = @desired_proc_units
    !options_hash[:max_proc].nil? ? @max_proc_units = options_hash[:max_proc].to_f : @max_proc_units = @desired_proc_units
    !options_hash[:max_mem].nil? ? @max_memory = options_hash[:max_mem].to_i : @max_memory = @desired_memory
    !options_hash[:min_mem].nil? ? @min_memory = options_hash[:min_mem].to_i : @min_memory = @desired_memory
    !options_hash[:max_vcpu].nil? ? @max_vcpu = options_hash[:max_vcpu].to_i : @max_vcpu = @desired_vcpu
    !options_hash[:min_vcpu].nil? ? @min_vcpu = options_hash[:min_vcpu].to_i : @min_vcpu = @desired_vcpu
    !options_hash[:max_virt_slots].nil? ? @max_virtual_slots = options_hash[:max_virt_slots].to_i : @max_virtual_slots = 30
    !options_hash[:current_profile].nil? ? @current_profile = options_hash[:current_profile] : @current_profile = @name + "_profile"
    !options_hash[:default_profile].nil? ? @default_profile = options_hash[:default_profile] : @default_profile = @current_profile
    !options_hash[:sharing_mode].nil? ? @sharing_mode = options_hash[:sharing_mode] : @sharing_mode = "cap"
    @sharing_mode == "uncap" ? @uncap_weight = options_hash[:uncap_weight].to_i : @uncap_weight = nil
    !options_hash[:proc_mode].nil? ? @proc_mode = options_hash[:proc_mode] : @proc_mode = "shared"
    
    #Parameters that hold no value unless the LPAR already exists
    #or create() is called
    !options_hash[:id].nil? ? @id = options_hash[:id] : @id = nil
    @disable_auto_reboot = disable_auto_reboot
    #TODO: Implement the VIO pair as attributes of the LPAR???
end

Instance Attribute Details

#current_profileObject (readonly)

Get the Current Profile of an LPAR



225
226
227
# File 'lib/rbvppc/lpar.rb', line 225

def current_profile
  @current_profile
end

#default_profileObject (readonly)

Get the Default Profile of an LPAR



233
234
235
# File 'lib/rbvppc/lpar.rb', line 233

def default_profile
  @default_profile
end

#desired_memoryObject

Returns the value of attribute desired_memory.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def desired_memory
  @desired_memory
end

#desired_proc_unitsObject

Returns the value of attribute desired_proc_units.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def desired_proc_units
  @desired_proc_units
end

#desired_vcpuObject

Returns the value of attribute desired_vcpu.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def desired_vcpu
  @desired_vcpu
end

#frameObject (readonly)

Returns the value of attribute frame.



29
30
31
# File 'lib/rbvppc/lpar.rb', line 29

def frame
  @frame
end

#hmcObject (readonly)

Returns the value of attribute hmc.



29
30
31
# File 'lib/rbvppc/lpar.rb', line 29

def hmc
  @hmc
end

#hostnameObject

Returns the value of attribute hostname.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def hostname
  @hostname
end

#idObject (readonly)

Get the ID of an LPAR



215
216
217
# File 'lib/rbvppc/lpar.rb', line 215

def id
  @id
end

#max_memoryObject

Returns the value of attribute max_memory.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def max_memory
  @max_memory
end

#max_proc_unitsObject

Returns the value of attribute max_proc_units.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def max_proc_units
  @max_proc_units
end

#max_vcpuObject

Returns the value of attribute max_vcpu.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def max_vcpu
  @max_vcpu
end

#max_virtual_slotsObject

Returns the value of attribute max_virtual_slots.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def max_virtual_slots
  @max_virtual_slots
end

#min_memoryObject

Returns the value of attribute min_memory.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def min_memory
  @min_memory
end

#min_proc_unitsObject

Returns the value of attribute min_proc_units.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def min_proc_units
  @min_proc_units
end

#min_vcpuObject

Returns the value of attribute min_vcpu.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def min_vcpu
  @min_vcpu
end

#nameObject (readonly)

Returns the value of attribute name.



29
30
31
# File 'lib/rbvppc/lpar.rb', line 29

def name
  @name
end

#proc_modeObject (readonly)

Returns the value of attribute proc_mode.



29
30
31
# File 'lib/rbvppc/lpar.rb', line 29

def proc_mode
  @proc_mode
end

#sharing_modeObject (readonly)

Returns the value of attribute sharing_mode.



29
30
31
# File 'lib/rbvppc/lpar.rb', line 29

def sharing_mode
  @sharing_mode
end

#uncap_weightObject

Returns the value of attribute uncap_weight.



24
25
26
# File 'lib/rbvppc/lpar.rb', line 24

def uncap_weight
  @uncap_weight
end

Instance Method Details

#activate(profile_name = @current_profile) ⇒ Object

Active an LPAR using a profile



160
161
162
163
# File 'lib/rbvppc/lpar.rb', line 160

def activate(profile_name = @current_profile)
    hmc.execute_cmd "chsysstate -r lpar -m #{frame} -o on -n #{name} -f #{profile_name}"
    @current_profile = profile_name if @current_profile != profile_name
end

#add_storage(primary_vio, secondary_vio, size_in_gb) ⇒ Object

Adds storage to this LPAR using the provided Primary and Secondary VIOs and the amount of storage requested, in GB



717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
# File 'lib/rbvppc/lpar.rb', line 717

def add_storage(primary_vio,secondary_vio,size_in_gb)
    #Get info about all vSCSIs attached to this LPAR
    attached_vscsis = get_vscsi_adapters

    #Keep track of the number of vSCSI adapters that attach to the
    #VIOs. This should be 2 after finding the vSCSI adapters that attach
    #to each of the VIOs (one for each VIO). If it is more, then there must
    #be more than one vSCSI attached to one or both of the VIOs.
    adapter_count = 0
    primary_vscsi = nil
    secondary_vscsi = nil
    #Find the vSCSI adapters for each VIO
    attached_vscsis.each do |vscsi|
        if vscsi.remote_lpar_name == primary_vio.name
            primary_vscsi = vscsi
            adapter_count += 1
        end

        if vscsi.remote_lpar_name == secondary_vio.name
            secondary_vscsi = vscsi
            adapter_count += 1
        end
    end

    #If the adapter count is greater than 2, that means that at least one of the
    #VIOs in this pair has more than one vSCSI that attaches to this LPAR.
    #Fail out for now.
    #TODO: Add better handling logic that can avoid this issue.
    if adapter_count > 2
        warn "This LPAR has multiple adapter connections to it's VIOs; unable to determine which adapter to attach new disks to..."
        return nil
    end

    #If an adapter cannot not be found for either of the VIOs, fail out
    #because a disk cannot be attached.
    if primary_vscsi.nil? or secondary_vscsi.nil?
        raise StandardError.new("Cannot attach storage to this LPAR. It does not have a vSCSI adapter defined to one of it's VIOs")
    end

    #Use the remote_slot_num attribute of the two vSCSIs that were found
    #to find out the names of the vhosts they reference on each of the VIOs
    primary_vhost = primary_vio.find_vhost_given_virtual_slot(primary_vscsi.remote_slot_num)
    secondary_vhost = secondary_vio.find_vhost_given_virtual_slot(secondary_vscsi.remote_slot_num)

    #Use Vio map_by_size function to map the appropriate disks to both VIOs
    primary_vio.map_by_size(primary_vhost, secondary_vio, secondary_vhost, size_in_gb)
end

#add_vscsi(server_lpar) ⇒ Object

Add vSCSI to LPAR Handles adding to profile and via DLPAR



661
662
663
664
665
666
667
668
669
670
# File 'lib/rbvppc/lpar.rb', line 661

def add_vscsi(server_lpar)
    #Add vscsi to client and server LPAR profiles
    #Save the adapter slots used
    client_slot, server_slot = add_vscsi_to_profile(server_lpar)

    #Run DLPAR commands against LPARs themselves (if necessary)
    add_vscsi_dlpar(server_lpar, client_slot, server_slot)

    return [client_slot, server_slot]
end

#add_vscsi_dlpar(server_lpar, client_slot_to_use = nil, server_slot_to_use = nil) ⇒ Object

Add vSCSI adapter via DLPAR command



692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
# File 'lib/rbvppc/lpar.rb', line 692

def add_vscsi_dlpar(server_lpar,client_slot_to_use = nil, server_slot_to_use = nil)
    if client_slot_to_use.nil? or server_slot_to_use.nil?
        client_slot_to_use = get_available_slot
        server_slot_to_use = server_lpar.get_available_slot
    end

    #If the client LPAR is running, we have to do DLPAR on it.
    if is_running?
        hmc.execute_cmd("chhwres -r virtualio -m #{frame} -p #{name} -o a --rsubtype scsi -s #{client_slot_to_use} -a \"adapter_type=client,remote_lpar_name=#{server_lpar.name},remote_slot_num=#{server_slot_to_use}\" ")
    end

    #If the server LPAR is running, we have to do DLPAR on it.
    if server_lpar.is_running?
        hmc.execute_cmd("chhwres -r virtualio -m #{server_lpar.frame} -p #{server_lpar.name} -o a --rsubtype scsi -s #{server_slot_to_use} -a \"adapter_type=server,remote_lpar_name=#{name},remote_slot_num=#{client_slot_to_use}\" ")
    end
    #chhwres -r virtualio -m "FrameName" -p VioName -o a --rsubtype scsi -s 11 -a "adapter_type=server,remote_lpar_name=ClientLPAR,remote_slot_num=5" 
end

#add_vscsi_to_profile(server_lpar) ⇒ Object

Add vSCSI adapter to LPAR profile

Raises:

  • (StandardError)


673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
# File 'lib/rbvppc/lpar.rb', line 673

def add_vscsi_to_profile(server_lpar)
    virtual_slot_num = get_available_slot
    remote_slot_num = server_lpar.get_available_slot
    lpar_profile = current_profile
    remote_lpar_profile = server_lpar.current_profile

    raise StandardError.new("No available virtual adapter slots on client LPAR #{lpar}") if virtual_slot_num.nil?
    raise StandardError.new("No available virtual adapter slots on server LPAR #{server_lpar}") if remote_slot_num.nil?

    #Modify client LPAR's profile
    hmc.execute_cmd("chsyscfg -r prof -m #{frame} -i \"name=#{lpar_profile},lpar_name=#{name},virtual_scsi_adapters+=#{virtual_slot_num}/client//#{server_lpar.name}/#{remote_slot_num}/0\" ")
    #Modify server LPAR's profile
    hmc.execute_cmd("chsyscfg -r prof -m #{server_lpar.frame} -i \"name=#{remote_lpar_profile},lpar_name=#{server_lpar.name},virtual_scsi_adapters+=#{remote_slot_num}/server//#{name}/#{virtual_slot_num}/0\" ")

    #Return the client slot and server slot used in the LPAR profiles
    return [virtual_slot_num, remote_slot_num]
end

#check_stateObject

Get LPAR state



176
177
178
# File 'lib/rbvppc/lpar.rb', line 176

def check_state
    hmc.execute_cmd("lssyscfg -r lpar -m #{frame} --filter lpar_names=#{name} -F state").chomp
end

#createObject

Create an LPAR

Raises:

  • (StandardError)


95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/rbvppc/lpar.rb', line 95

def create
    
    #Stop the create from proceeding if this LPAR already exists
    raise StandardError.new("This LPAR already exists on #{frame}, cannot create #{name}") if exists?

    command = "mksyscfg -r lpar -m #{@frame} -i name=#{@name}, profile_name=#{@current_profile},boot_mode=norm," + 
        "auto_start=0,lpar_env=aixlinux,max_virtual_slots=#{@max_virtual_slots},desired_mem=#{@desired_memory}," + 
        "min_mem=#{@min_memory},max_mem=#{@max_memory},desired_procs=#{@desired_vcpu},min_procs=#{@min_vcpu}," + 
        "max_procs=#{@max_vcpu},proc_mode=#{@proc_mode},sharing_mode=#{@sharing_mode},desired_proc_units=#{@desired_proc_units}," + 
        "max_proc_units=#{@max_proc_units},min_proc_units=#{@min_proc_units}"
    command += ",uncap_weight=#{@uncap_weight}" if !@uncap_weight.nil?
    
    hmc.execute_cmd(command)
end

#create_vnic(vlan_id, addl_vlan_ids = "") ⇒ Object

Create vNIC on LPAR



813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'lib/rbvppc/lpar.rb', line 813

def create_vnic(vlan_id,addl_vlan_ids = "")
    if validate_vlan_id(vlan_id)
        #default value for is_trunk = 0
        #default value for is_required = 1
        slot_num = get_available_slot("eth")
        create_vnic_profile(slot_num,vlan_id,addl_vlan_ids,0,1)
    
        #TODO: Handle logic for dealing with an LPAR
        #that isn't Not Activated, but also isn't
        #Running
        create_vnic_dlpar(slot_num,vlan_id)

        #LPAR requires a power cycle in order to
        #get a MAC address from this vNIC
        if not_activated?
            activate 
            sleep(10) until !not_activated?
            soft_shutdown
        end
    else
       raise StandardError.new("VLAN ID: #{vlan_id} not found on #{frame}")
    end 
end

#create_vnic_dlpar(slot_number, vlan_id) ⇒ Object

Create vNIC on LPAR via DLPAR As writen today defaulting ieee_virtual_eth=1 sets us to Not IEEE 802.1Q compatible. To add compatability set value to 1



856
857
858
859
860
861
862
863
864
# File 'lib/rbvppc/lpar.rb', line 856

def create_vnic_dlpar(slot_number,vlan_id)
    if is_running?
        if validate_vlan_id(vlan_id)
            hmc.execute_cmd("chhwres -r virtualio -m #{frame} -o a -p #{name} --rsubtype eth -s #{slot_number} -a \"ieee_virtual_eth=1,port_vlan_id=#{vlan_id}\"")
        else
            raise StandardError.new("VLAN ID: #{vlan_id} not found on #{frame}")
        end      
    end
end

#create_vnic_profile(slot_number, vlan_id, addl_vlan_ids, is_trunk, is_required) ⇒ Object

Create vNIC on LPAR profile



838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
# File 'lib/rbvppc/lpar.rb', line 838

def create_vnic_profile(slot_number, vlan_id, addl_vlan_ids, is_trunk, is_required)
    if validate_vlan_id(vlan_id)
        ##chsyscfg -m Server-9117-MMA-SNxxxxx -r prof -i 'name=server_name,lpar_id=xx,"virtual_eth_adapters=596/1/596//0/1,506/1/506//0/1,"'
        #slot_number/is_ieee/port_vlan_id/"additional_vlan_id,additional_vlan_id"/is_trunk(number=priority)/is_required
        lpar_prof = current_profile
    
        #Going to assume adapter will always be ieee
        #For is Trunk how do we determine the number for priority? Do we just let the user pass it?
        hmc.execute_cmd("chsyscfg -m #{frame} -r prof -i \'name=#{lpar_prof},lpar_name=#{name},"+
            "\"virtual_eth_adapters+=#{slot_number}/1/#{vlan_id}/\"#{addl_vlan_ids}" +
            "\"/#{is_trunk}/#{is_required} \"\'")
    else
        raise StandardError.new("VLAN ID: #{vlan_id} not found on #{frame}")
    end    
end

#delete(vio_array = nil) ⇒ Object

Delete an LPAR Takes an optional array of Vio objects representing the VIO pair that serves storage to this LPAR.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rbvppc/lpar.rb', line 113

def delete(vio_array = nil)
    #Check that this LPAR exists before attempting to delete it.
    #If the LPAR does not exist, simply output a warning stating such
    if !exists?
        warn "This LPAR (#{name}) does not currently exist on #{frame} to be deleted."
        return
    end

    #Do a hard shutdown and then remove the LPAR definition
    hard_shutdown unless not_activated?
    sleep(10) until not_activated?

    #If not passed, try to find the VIO servers by looking
    #at this LPAR's vSCSI adapters
    server_lpars = []
    if vio_array.nil?
        vscsis = get_vscsi_adapters
        vscsis.each do |adapter|
            server_lpars.push(adapter.remote_lpar_name)
        end
        server_lpars.uniq!

        #Now if there are only two unique server LPARs
        #that serve this LPAR, we have our VIO servers
        if server_lpars.length == 2
            vio_array = []
            vio_array.push(Vio.new(hmc,frame,server_lpars[0]))
            vio_array.push(Vio.new(hmc,frame,server_lpars[1]))
        else
            warn "Unable to determine this LPAR's VIO servers, proceeding without removing disks"
            vio_array = nil
        end
    end

    #Attempt to remove all of the LPAR's disks/vSCSIs before deleting
    remove_storage(vio_array[0],vio_array[1]) if !vio_array.nil?
    
    hmc.execute_cmd "rmsyscfg -r lpar -m #{frame} -n #{name}"
end

#exists?Boolean

Returns true if this LPAR actually exists on it’s frame Returns false if it doesn’t

Returns:

  • (Boolean)


182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/rbvppc/lpar.rb', line 182

def exists?
    #List all LPARs residing underneath this frame
    result = hmc.execute_cmd("lssyscfg -r lpar -m #{frame} -F name").chomp
    #See if any of their names match this Lpar's name
    result.each_line do |line|
        line.chomp!
        if line == name
            return true
        end
    end
    #Return false if none the names listed match this Lpar's name
    return false
end

#get_available_slot(type = nil) ⇒ Object

Get next usable virtual slot on an LPAR Returns nil if no usable slots exist



575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/rbvppc/lpar.rb', line 575

def get_available_slot(type = nil)
    max_slots = max_virtual_slots
    used_slots = get_used_virtual_slots
    lowest_slot=11
    if !type.nil?
        lowest_slot=2 if type == "eth"
    end
    
    lowest_slot.upto(max_slots) do |n|
        if !used_slots.include?(n)
            return n
        end
    end
    return nil
end

#get_infoObject



209
210
211
212
# File 'lib/rbvppc/lpar.rb', line 209

def get_info
    info = hmc.execute_cmd "lssyscfg -r lpar -m \'#{frame}\' --filter lpar_names=\'#{name}\'"
    return info.chomp
end

#get_mac_addressObject

Get the MAC address of an LPAR



241
242
243
244
# File 'lib/rbvppc/lpar.rb', line 241

def get_mac_address
    result = hmc.execute_cmd("lshwres -r virtualio --rsubtype eth --level lpar -m #{frame} -F mac_addr --filter \"lpar_names=#{name}\" ")
    return result.chomp
end

#get_used_virtual_slotsObject

Return array of used virtual adapter slots for an LPAR



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
# File 'lib/rbvppc/lpar.rb', line 520

def get_used_virtual_slots
    #scsi_slot_output = execute_cmd "lshwres -r virtualio --rsubtype scsi -m #{frame} --level lpar --filter lpar_names=#{lpar} -F slot_num"
    #eth_slot_output = execute_cmd "lshwres -r virtualio --rsubtype eth -m #{frame} --level lpar --filter lpar_names=#{lpar} -F slot_num"
    #serial_slot_output = execute_cmd "lshwres -r virtualio --rsubtype serial -m #{frame} --level lpar --filter lpar_names=#{lpar} -F slot_num"
    #lpar_prof = get_lpar_curr_profile(frame,lpar)
    
    scsi_slot_output = clean_vadapter_string(hmc.execute_cmd "lssyscfg -r prof -m '#{frame}' --filter 'lpar_names=#{name},profile_names=#{current_profile}' -F virtual_scsi_adapters")
    serial_slot_output = clean_vadapter_string(hmc.execute_cmd "lssyscfg -r prof -m '#{frame}' --filter 'lpar_names=#{name},profile_names=#{current_profile}' -F virtual_serial_adapters")
    eth_slot_output = clean_vadapter_string(hmc.execute_cmd "lssyscfg -r prof -m '#{frame}' --filter 'lpar_names=#{name},profile_names=#{current_profile}' -F virtual_eth_adapters")
    used_slots = []
    
    if scsi_slot_output.include?(",")
        scsi_slots = scsi_slot_output.split(/,/)
    else
        scsi_slots = [scsi_slot_output]
    end
    
    if serial_slot_output.include?(",")
        serial_slots = serial_slot_output.split(/,/)
    else
        serial_slots = [serial_slot_output]
    end
    
    if eth_slot_output.include?(",")
        eth_slots = eth_slot_output.split(/,/)
    else
        eth_slots = [eth_slot_output]
    end
    
    scsi_slots.each do |adapter_line|
        if !adapter_line.empty?
            parse_hash = parse_vscsi_syntax(adapter_line)
            used_slots.push(parse_hash[:virtual_slot_num].to_i)
        end
    end
    
    serial_slots.each do |adapter_line|
        if !adapter_line.empty?
            parse_hash = parse_vserial_syntax(adapter_line)
            used_slots.push(parse_hash[:virtual_slot_num].to_i)
        end
    end
    
    eth_slots.each do |adapter_line|
        if !adapter_line.empty?
            parse_hash = parse_vnic_syntax(adapter_line)
            used_slots.push(parse_hash[:virtual_slot_num].to_i)
        end
    end
    
    return used_slots
end

#get_vnic_adaptersObject

Gets a list of vNIC objects



785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
# File 'lib/rbvppc/lpar.rb', line 785

def get_vnic_adapters
    #Get vNIC adapter info from this LPARs profile
    eth_adapter_output = clean_vadapter_string(hmc.execute_cmd("lssyscfg -r prof -m #{frame} --filter 'lpar_names=#{name},profile_names=#{current_profile}' -F virtual_eth_adapters").chomp)
    eth_adapters = []
    #If there are multiple vNICs,
    #they must be split on ',' and handled
    #individually
    if eth_adapter_output.include?(",")
        #TODO: 
        # => Test with vNICs that have Additional VLAN IDs.
        # => If Additional VLAN IDs have commas too, re-evaluate the logic here.
        adapters = eth_adapter_output.split(/,/)
        adapters.each do |adapter|
            split_adapter = adapter.split("/")
            vnic = Vnic.new(split_adapter[0],split_adapter[1],split_adapter[2],split_adapter[3],split_adapter[4],split_adapter[5])
            eth_adapters.push(vnic)
        end
    elsif !eth_adapter_output.empty?
        #If there are no ','s assume the there is only one vNIC defined
        split_adapter = eth_adapter_output.split("/")
        vnic = Vnic.new(split_adapter[0],split_adapter[1],split_adapter[2],split_adapter[3],split_adapter[4],split_adapter[5])
        eth_adapters.push(vnic)
    end

    return eth_adapters
end

#get_vscsi_adaptersObject

Returns array of output with vSCSI adapter information about the client LPAR



495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/rbvppc/lpar.rb', line 495

def get_vscsi_adapters
    
    #Get vSCSI adapter info from this LPAR's profile
    scsi_adapter_output = clean_vadapter_string(hmc.execute_cmd("lssyscfg -r prof -m #{frame} --filter 'lpar_names=#{name},profile_names=#{current_profile}' -F virtual_scsi_adapters").chomp)
    vscsi_adapters  = []
    if scsi_adapter_output.include?(",")
        scsi_adapters = scsi_adapter_output.split(/,/)
        #split on /
        #11/client/1/rslppc09a/17/0,12/client/2/rslppc09b/17/0
        scsi_adapters.each do |scsi_adapter|
          scsi_adapter = scsi_adapter.split("/")
          vscsi = Vscsi.new(scsi_adapter[0],scsi_adapter[1],scsi_adapter[2],scsi_adapter[3],scsi_adapter[4],scsi_adapter[5])
          vscsi_adapters.push(vscsi)
        end
    elsif !scsi_adapter_output.empty?
        scsi_adapter = scsi_adapter_output
        scsi_adapter = scsi_adapter.split("/")
        vscsi = Vscsi.new(scsi_adapter[0],scsi_adapter[1],scsi_adapter[2],scsi_adapter[3],scsi_adapter[4],scsi_adapter[5])
        vscsi_adapters.push(vscsi)
    end
    return vscsi_adapters
end

#hard_shutdownObject

Hard shutdown LPAR



166
167
168
# File 'lib/rbvppc/lpar.rb', line 166

def hard_shutdown
    hmc.execute_cmd "chsysstate -r lpar -m #{frame} -o shutdown --immed -n #{name}"
end

#is_running?Boolean

Returns true/false value depending on if the LPAR is running or not Since an LPAR can have states such as “Not Activated”, “Open Firmware”, “Shutting Down”, this function only helps for when we are explicitly looking for an LPAR to be either “Running” or not.

Returns:

  • (Boolean)


199
200
201
# File 'lib/rbvppc/lpar.rb', line 199

def is_running?
    return check_state == "Running" 
end

#list_vlansObject

list available vlans



881
882
883
884
885
# File 'lib/rbvppc/lpar.rb', line 881

def list_vlans
    vlans = []
    vlans = hmc.list_vlans_on_frame(frame)
    return vlans
end

#modify_resources(options, reboot = true, prevalidated = false) ⇒ Object

Bulk modifies an LPAR’s resources based on the provided hash. The Hash is required to have it’s keys represent labels for HMC attributes (ie, min_mem, max_mem, etc) while it’s values are what the user requests those attributes be set to for this LPAR. The LPAR is then reactivated once all of the changes are made for them to take effect. The Class Instance variable @@valid_attributes is used to determine if a key in options is a valid attribute. If an attribute in options is deemed invalid, nothing is done with respect to that attribute.



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/rbvppc/lpar.rb', line 282

def modify_resources(options, reboot = true, prevalidated = false)
  execute = false
  options.each do |key,val|
    execute = false
    if @@valid_attributes.include?(key)
      # Check for min/max/desired in the key to determine if
      # some bound needs to be checked first
      verify_and_handle_attr_bounds(options,key,val) unless prevalidated
      # Handle setting of any instance variables that should change
      # due to this
      map_key_to_attr(key, val)
      execute = true
    end
  end
  # Set LPAR profile
  set_multi_attr_profile(options) if execute
  reactivate if reboot
end

#modify_vnic!(slot_number, vlan_id, is_trunk, is_required) ⇒ Object

Change vlan id of vnic



867
868
869
870
871
872
873
874
875
876
877
878
# File 'lib/rbvppc/lpar.rb', line 867

def modify_vnic!(slot_number, vlan_id, is_trunk, is_required)

    if validate_vlan_id(vlan_id)
       #Power down
       soft_shutdown unless not_activated?
       sleep 5 until not_activated? 
       hmc.execute_cmd("chsyscfg -r prof -m #{frame} -i \'name=#{current_profile},lpar_name=#{name},\"virtual_eth_adapters=#{slot_number}/1//#{vlan_id}//#{is_trunk}/#{is_required}\"\'")
       activate
    else
      raise StandardError.new("VLAN ID: #{vlan_id} not found on #{frame}")
    end  
end

#not_activated?Boolean

Similar to is_running? - only returns true if the LPAR’s state is “Not Activated”. Any other state is percieved as false

Returns:

  • (Boolean)


205
206
207
# File 'lib/rbvppc/lpar.rb', line 205

def not_activated?
    return check_state == "Not Activated"
end

#reactivateObject

Shutdown and reactivate the LPAR so that the attribute changes take effect



267
268
269
270
271
272
273
274
# File 'lib/rbvppc/lpar.rb', line 267

def reactivate
    # Shut down the LPAR
    soft_shutdown unless not_activated?
    # Wait until it's state is "Not Activated"
    sleep(10) until not_activated?
    # Reactivate the LPAR so that the attribute changes take effect
    activate
end

#remove_disk(primary_vio, secondary_vio, pvid) ⇒ Object

Removes/deallocates a disk from the LPAR specified by it’s PVID. This disk is assumed to be supplied by the Primary and Secondary VIO specified



775
776
777
778
# File 'lib/rbvppc/lpar.rb', line 775

def remove_disk(primary_vio,secondary_vio,pvid)
    #Use unmap_by_pvid Vio function to unmap a single disk from this LPAR.
    primary_vio.unmap_by_pvid(secondary_vio, pvid)
end

#remove_storage(primary_vio, secondary_vio) ⇒ Object

Removes/deallocates all storage from this LPAR and unmaps all of these disks on the specified Primary and Secondary VIO servers. The disks attached to the LPAR are assumed to be supplied by the Primary and Secondary VIOs specified.



768
769
770
771
# File 'lib/rbvppc/lpar.rb', line 768

def remove_storage(primary_vio,secondary_vio)
    #Deallocates all storage and vSCSI adapters from this LPAR
    primary_vio.unmap_all_disks(secondary_vio, self)
end

#remove_vnic(slot_number) ⇒ Object

Removes a vNIC adapter on an LPAR based on the slot number that the vNIC occupies TODO: Overload parameters to allow a different way to remove vNICs ???

Raises:

  • (StandardError)


910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
# File 'lib/rbvppc/lpar.rb', line 910

def remove_vnic(slot_number)
    #Find the vNIC that is desired to be
    #removed
    vnics = get_vnic_adapters
    vnic = nil
    vnics.each do |adapter|
        if adapter.virtual_slot_num == slot_number
            vnic = adapter
        end
    end
    #If no vNIC occupies the slot specified, error out
    raise StandardError.new("vNIC adapter does not currently occupy slot #{slot_number}") if vnic.nil?
    #Remove the vNIC from this LPAR's profile
    remove_vnic_profile(vnic)
    #Remove the vNIC from the LPAR hardware if the LPAR is currently activated
    remove_vnic_dlpar(slot_number)
end

#remove_vnic_dlpar(slot_number) ⇒ Object

Remove a vNIC on the LPAR via DLPAR denoted by the virtual slot number occupied by the vNIC



938
939
940
941
942
# File 'lib/rbvppc/lpar.rb', line 938

def remove_vnic_dlpar(slot_number)
    if is_running?
        hmc.execute_cmd("chhwres -r virtualio -m #{frame} -o r -p #{name} --rsubtype eth -s #{slot_number}")
    end
end

#remove_vnic_profile(vnic) ⇒ Object

Remove a vNIC on the LPAR’s profile denoted by the virtual slot number occupied by the vNIC



930
931
932
933
934
# File 'lib/rbvppc/lpar.rb', line 930

def remove_vnic_profile(vnic)
    hmc.execute_cmd("chsyscfg -m #{frame} -r prof -i 'name=#{current_profile},lpar_name=#{name},"+
                    "\"virtual_eth_adapters-=#{vnic.virtual_slot_num}/#{vnic.is_ieee}/#{vnic.vlan_id}/#{vnic.additional_vlan_ids}" +
                    "/#{vnic.is_trunk}/#{vnic.is_required}\"'")
end

#remove_vscsi(server_lpar, adapter_details = nil) ⇒ Object

Remove vSCSI from LPAR Handles removing from the LPAR profiles as well as DLPAR Last parameter is optional and if it isn’t specified then it looks for an adapter on lpar that is attached to server_lpar and removes that from the profile/hardware of both the client and server MAY BE DANGEROUS- if multiple vSCSI adapters on a single lpar pointing at the same VIO



598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# File 'lib/rbvppc/lpar.rb', line 598

def remove_vscsi(server_lpar,adapter_details=nil)
    if adapter_details.nil?
        adapters = get_vscsi_adapters
        adapters.each do |adapter|
            adapter_details = adapter if adapter.remote_lpar_name == server_lpar.name
        end
    end
    
    #Remove this vSCSI from the lpar and server lpar profiles
    remove_vscsi_from_profile(server_lpar,adapter_details)

    #Remove this vSCSI from the actual hardware of lpar and server lpar
    remove_vscsi_dlpar(server_lpar,adapter_details)

end

#remove_vscsi_dlpar(server_lpar, vscsi) ⇒ Object

Remove vSCSI from LPARs via DLPAR



641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
# File 'lib/rbvppc/lpar.rb', line 641

def remove_vscsi_dlpar(server_lpar,vscsi)

    client_slot = vscsi.virtual_slot_num
    server_slot = vscsi.remote_slot_num

    #If the client LPAR is running, we have to do DLPAR on it.
    if is_running?
        hmc.execute_cmd("chhwres -r virtualio -m #{frame} -p #{name} -o r --rsubtype scsi -s #{client_slot}")
        #-a \"adapter_type=client,remote_lpar_name=#{server_lpar},remote_slot_num=#{server_slot}\" ")
    end

    #If the server LPAR is running, we have to do DLPAR on it.
    if server_lpar.is_running?
        hmc.execute_cmd("chhwres -r virtualio -m #{server_lpar.frame} -p #{server_lpar.name} -o r --rsubtype scsi -s #{server_slot}")
        #-a \"adapter_type=server,remote_lpar_name=#{lpar},remote_slot_num=#{client_slot}\" ")
    end
end

#remove_vscsi_from_profile(server_lpar, vscsi) ⇒ Object

Remove vSCSI from the LPAR profiles only



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# File 'lib/rbvppc/lpar.rb', line 615

def remove_vscsi_from_profile(server_lpar,vscsi)
    remote_lpar_profile = server_lpar.current_profile
    client_lpar_id = id
         
    client_slot = vscsi.virtual_slot_num
    server_lpar_id = vscsi.remote_lpar_id
    if server_lpar != vscsi.remote_lpar_name
        #server_lpar and the LPAR cited in the
        #vscsi hash aren't the same...
        #error out or do something else here...?
    end
    server_slot = vscsi.remote_slot_num
    is_req = vscsi.is_required

    #Modify client LPAR's profile to no longer include the adapter
    #whose details occupy the vscsi_hash
    hmc.execute_cmd("chsyscfg -r prof -m #{frame} -i \"name=#{current_profile},lpar_name=#{name}," +
        "virtual_scsi_adapters-=#{client_slot}/client/#{server_lpar_id}/#{server_lpar.name}/#{server_slot}/#{is_req}\" ")
      
    #Modify the server LPAR's profile to no longer include the client
    hmc.execute_cmd("chsyscfg -r prof -m #{server_lpar.frame} -i \"name=#{remote_lpar_profile},lpar_name=#{server_lpar.name}," +
        "virtual_scsi_adapters-=#{server_slot}/server/#{client_lpar_id}/#{name}/#{client_slot}/#{is_req}\" ")

end

#rename(newname) ⇒ Object

Rename an LPAR



154
155
156
157
# File 'lib/rbvppc/lpar.rb', line 154

def rename(newname)
    hmc.execute_cmd "chsyscfg -r lpar -m #{frame} -i \'name=#{name},new_name=#{newname}\'"
    @name = newname
end

#set_attr_and_reactivate(units, hmc_label) ⇒ Object

Function to use for all Min/Max attribute changing



260
261
262
263
264
# File 'lib/rbvppc/lpar.rb', line 260

def set_attr_and_reactivate(units,hmc_label)
    #Change the profile attribute
    set_attr_profile(units,hmc_label)
    reactivate unless @disable_auto_reboot
end

#set_attr_profile(units, hmc_label) ⇒ Object

Set an LPAR profile’s attribute, specifying the units to set the attribute to and the HMC label for the attribute



247
248
249
250
# File 'lib/rbvppc/lpar.rb', line 247

def set_attr_profile(units,hmc_label)
    cmd = "chsyscfg -m #{frame} -r prof -i \"name=#{current_profile}, lpar_name=#{name}, #{hmc_label}=#{units} \" "
    hmc.execute_cmd(cmd)
end

#set_multi_attr_profile(options) ⇒ Object

Set multiple LPAR profile attributes in a single call.



253
254
255
256
257
# File 'lib/rbvppc/lpar.rb', line 253

def set_multi_attr_profile(options)
    profile_options = options.map{|key,val| "#{key}=#{val}"}.join(',')
    cmd = "chsyscfg -m #{frame} -r prof -i \"name=#{current_profile}, lpar_name=#{name}, #{profile_options} \" "
    hmc.execute_cmd(cmd)
end

#soft_shutdownObject

Soft shutdown an LPAR



171
172
173
# File 'lib/rbvppc/lpar.rb', line 171

def soft_shutdown
    hmc.execute_cmd "chsysstate -r lpar -m #{frame} -o shutdown -n #{name}"
end

#validate_vlan_id(vlan_id) ⇒ Object

validate vlan exists on frame



888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
# File 'lib/rbvppc/lpar.rb', line 888

def validate_vlan_id(vlan_id)
    vlans = []
    vlans = hmc.list_vlans_on_frame(frame)
    count = 0 
    vlans_length = vlans.length
    vlans.each do |vlan|
        if vlan_id == vlan
           puts "VLAN ID is valid for #{frame}"
           return true
           break
        end            
        count+1
    end
    if count == vlans_length
        puts "VLAN ID not valid for #{frame}"
        return false
    end
end