your home for end-user virtualization!

RedHat CloudForms Service Dialog to resize a VMware virtual disk

Thanks to Matt Hyclak: Here’s what we’re using. We have a button attached to VMs that calls a Service Dialog to gather the disk information (size and disk). Currently we assume there’s only one SCSI controller, so there’s room for improvement, but this should do the heavy lifting.

###################################
#
# EVM Automate Method: expand_disk
#
# Notes: This method is used to increase the size of a VMWare VM disks.
#
# Inputs: $evm.root['vm'], dialog_size(GB)
#
###################################
begin
# Method for logging
def log(level, message)
@method = 'expand_disk'
$evm.log(level, "#{@method} - #{message}")
end

# dump_root
def dump_root()
log(:info, "Root:<$evm.root> Begin $evm.root.attributes")
$evm.root.attributes.sort.each { |k, v| log(:info, "Root:<$evm.root> Attribute - #{k}: #{v}")}
log(:info, "Root:<$evm.root> End $evm.root.attributes")
log(:info, "")
end

log(:info, "CFME Automate Method Started")

# dump all root attributes to the log
dump_root

def ensure_vm_available(vm_base, ems)
unavailable_reason = false
%w(ems vm_base).each do |nillable|
if eval(nillable).nil?
unavailable_reason = nillable
break
end
end

automate_retry(30, "#{unavailable_reason} is not available.") if unavailable_reason
end

def resizeDisk(vm, disk_number, new_disk_size_in_kb)
vm_base = vm.object_send('instance_eval', 'self')
ems = vm.ext_management_system

ensure_vm_available vm_base, ems

ems.object_send('instance_eval', '
def resize_disk(vm, diskIndex, new_disk_size_in_kb)
#self.get_vim_vm_by_mor(vm.ems_ref) do | vimVm |
vm.with_provider_object do | vimVm |
devices = vimVm.send(:getProp, "config.hardware")["config"]["hardware"]["device"]

matchedDev = nil
currentDiskIndex = 0
devices.each do | dev |
next if dev.xsiType != "VirtualDisk"
if diskIndex == currentDiskIndex
matchedDev = dev
break
end
currentDiskIndex += 1
end
raise "resize_disk: disk #{diskIndex} not found" unless matchedDev
$log.info("resize_disk: resizing using matched device at #{diskIndex}")

vmConfigSpec = VimHash.new("VirtualMachineConfigSpec") do |vmcs|
vmcs.deviceChange = VimArray.new("ArrayOfVirtualDeviceConfigSpec") do |vmcs_vca|
vmcs_vca << VimHash.new("VirtualDeviceConfigSpec") do |vdcs| vdcs.operation = "edit".freeze vdcs.device = VimHash.new("VirtualDisk") do |vDev| vDev.key = matchedDev["key"] vDev.controllerKey = matchedDev["controllerKey"] vDev.unitNumber = matchedDev["unitNumber"] vDev.backing = matchedDev["backing"] vDev.capacityInKB = new_disk_size_in_kb end end end end $log.info("resize_disk: attempting to reconfigure vm with spec: \'#{vmConfigSpec}\'") vimVm.send(:reconfig, vmConfigSpec) end end') ems.object_send('resize_disk', vm_base, disk_number, new_disk_size_in_kb) end def automate_retry(seconds, reason) $evm.root['ae_result'] = 'retry' $evm.root['ae_retry_interval'] = "#{seconds.to_i}.seconds" $evm.root['ae_reason'] = reason log(:info, "Retrying #{@method} after #{seconds} seconds, because '#{reason}'") exit MIQ_OK end # Dump all root object attributes automate_retry(30, "$evm.root not yet ready.") if $evm.root.nil? # Get dialog_disk_number variable from root hash if nil convert to zero DISK_NUMBER = $evm.root['dialog_diskindex'].to_i log(:info,"DISK_NUMBER: '#{DISK_NUMBER}'") vm = $evm.root['vm'] raise "VM object not found" if vm.nil? # This method only works with VMware VMs currently raise "Invalid vendor: #{vm.vendor}" unless vm.vendor.downcase == 'vmware' sizeGB = $evm.root['dialog_disksize'].to_i log(:info,"Detected VM:'#{vm.name}' vendor:'#{vm.vendor}' DISK_NUMBER:'#{DISK_NUMBER}' sizeGB:'#{sizeGB}'") log(:info, "Expanding disk to #{sizeGB}GB") new_disk_size_in_kb = (sizeGB * 1024**2) begin resizeDisk(vm, DISK_NUMBER, new_disk_size_in_kb) rescue => e
if e.message =~ /VimFault/
log(:warn, "Encountered VimFault: #{e.inspect}")
automate_retry(30, "Encountered VimFault #{e.inspect}")
end

log(:error, "e: #{e}")
log(:error, "e.inspect: #{e.inspect}")
log(:error,"[#{e}]\n#{e.backtrace.join("\n")}")
log(:error, "e.message: #{e.message}")
end

log(:info,"EVM Automate Method Ended")
exit MIQ_OK

#
# Set Ruby rescue behavior
#
rescue => err
$evm.log("error","[#{err}]\n#{err.backtrace.join("\n")}")
exit MIQ_ABORT
end

Search

Categories