Class: Vio

Inherits:
Lpar show all
Defined in:
lib/rbvppc/vio.rb

Instance Attribute Summary collapse

Attributes inherited from Lpar

#current_profile, #default_profile, #desired_memory, #desired_proc_units, #desired_vcpu, #frame, #hmc, #hostname, #id, #max_memory, #max_proc_units, #max_vcpu, #max_virtual_slots, #min_memory, #min_proc_units, #min_vcpu, #name, #proc_mode, #sharing_mode, #uncap_weight

Instance Method Summary collapse

Methods inherited from Lpar

#activate, #add_storage, #check_state, #exists?, #get_available_slot, #get_info, #get_mac_address, #get_used_virtual_slots, #get_vnic_adapters, #get_vscsi_adapters, #is_running?, #list_vlans, #modify_resources, #modify_vnic!, #not_activated?, #reactivate, #remove_disk, #remove_storage, #remove_vnic, #remove_vnic_dlpar, #remove_vnic_profile, #rename, #set_attr_and_reactivate, #set_attr_profile, #set_multi_attr_profile, #validate_vlan_id

Constructor Details

#initialize(hmc, frame, name) ⇒ Vio

Returns a new instance of Vio.

Raises:

  • (StandardError)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 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

Instance Attribute Details

#available_disksObject (readonly)

Returns the value of attribute available_disks.



13
14
15
# File 'lib/rbvppc/vio.rb', line 13

def available_disks
  @available_disks
end

#used_disksObject (readonly)

Returns the value of attribute used_disks.



13
14
15
# File 'lib/rbvppc/vio.rb', line 13

def used_disks
  @used_disks
end

Instance Method Details

#add_vscsi(server_lpar) ⇒ Object



428
429
430
# 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) ⇒ Object



436
437
438
# 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) ⇒ Object



432
433
434
# 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) ⇒ Object

Assign Disk/Logical Volume to a vSCSI Host Adapter



316
317
318
319
320
321
322
323
324
# 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

#createObject

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.



364
365
366
# 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 = "") ⇒ Object



440
441
442
# 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) ⇒ Object



448
449
450
# 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) ⇒ Object



444
445
446
# 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

#deleteObject



368
369
370
# File 'lib/rbvppc/vio.rb', line 368

def delete
    warn "Unable to execute delete on a VIO"
end

#desired_memory=(units) ⇒ Object



404
405
406
# 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) ⇒ Object



392
393
394
# 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) ⇒ Object



380
381
382
# 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) ⇒ Object

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

Raises:

  • (StandardError)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 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) ⇒ Object

Get a list of all disknames attached to a vhost



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 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_versionObject

Get VIOS version



33
34
35
36
# File 'lib/rbvppc/vio.rb', line 33

def get_vio_version
    command = "ioslevel"
    execute_vios_cmd(command)
end

#hard_shutdownObject



372
373
374
# File 'lib/rbvppc/vio.rb', line 372

def hard_shutdown
    warn "Unable to execute hard_shutdown on a VIO"
end

#list_available_disksObject

List unmapped disks on VIOS

lspv -free  doesn't include disks that have been mapped before and contain a 'VGID'


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 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_disksObject

List all Disk Mappings



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 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_adaptersObject

List Shared Ethernet Adapters on VIOS



310
311
312
313
# 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) ⇒ Object

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



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# 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) ⇒ Object

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



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# 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) ⇒ Object

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

Raises:

  • (StandardError)


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# 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) ⇒ Object

based on a given total size requirement

Raises:

  • (StandardError)


211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# 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) ⇒ Object



412
413
414
# 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) ⇒ Object



396
397
398
# 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) ⇒ Object



388
389
390
# File 'lib/rbvppc/vio.rb', line 388

def max_vcpu=(units)
    warn "Unable to change the vcpu on a VIO"
end

#min_memory=(units) ⇒ Object



408
409
410
# 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) ⇒ Object



400
401
402
# 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) ⇒ Object



384
385
386
# File 'lib/rbvppc/vio.rb', line 384

def min_vcpu=(units)
    warn "Unable to change the vcpu on a VIO"
end

#rebootObject

Reboot VIOS



39
40
41
42
# File 'lib/rbvppc/vio.rb', line 39

def reboot
    command ="shutdown -restart"
    execute_vios_cmd(command)
end

#recursive_remove_vhost(vhost) ⇒ Object

Recursively remove a Virtual SCSI Host Adapter



327
328
329
330
# 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) ⇒ Object

Remove physical disk from vhost adapter



339
340
341
342
343
344
345
346
347
# 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) ⇒ Object

Remove a Virtual SCSI Host Adapter



350
351
352
353
# 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) ⇒ Object



424
425
426
# 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) ⇒ Object



420
421
422
# 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) ⇒ Object



416
417
418
# 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) ⇒ Object

Remove Disk/Logical Volume from vSCSI Host Adapter



333
334
335
336
# File 'lib/rbvppc/vio.rb', line 333

def remove_vtd_from_vhost(vtd)
    command = "rmvdev -vtd #{vtd}"
    execute_vios_cmd(command)
end

#soft_shutdownObject



376
377
378
# 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) ⇒ Object

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



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# 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) ⇒ Object

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

Raises:

  • (StandardError)


280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# 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