How can I resize a VMWare Disk


#1

I am trying to reconfigure a VMWare VM, it has options for Memory and Processors; however, I don’t see anything for disks. Is there a way to resize a VMWare disk from the portal?


Resize VMWare Disk During Provisioning (w/ Fat Template)
#2

Hi,

You can do this, by creating a custom button with a custom method.
This feature is not built-in by default, for I mean.


#3

Would you have an example or a document you can point me to? I am fairly new to the environment and still learning. Thanks.


#4

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

#5

This is great!! Any of you genius out there able to add a check for if the VM has a snapshot? If it does email the requestor stating the machine has a snapshot and this will need to be removed before expanding?!


#6

This worked beautifully! Thank you!


#7

Hi,
I am trying the have a vmware vm reconfigure option in service dialogue to change the CPU, Memory or Add additinal disk in end user selfservice portal. Any clue how can i achieve that.


#8

@hyclak,

I took this wonderful work and I tweaked it a bit and put it here, https://github.com/rhtconsulting/miq-Utilities/blob/master/Automate/RedHatConsulting_Utilities/Infrastructure/VM/Provisioning/StateMachines/Methods.class/methods/resize_disk.rb.

Thanks for the great work.

Blue skies,
Ian


#9

Any chance you know how to do the same for RHV?


#10

Unfortunately, no. We’ve only been focused on VMware implementations thus far so we haven’t looked at other providers.


#11

``I couldn’t find a windows module for this, but I did put together some powershell to resize the partition and read a value sent over from cloudforms to let ansible know if the step is needed or not. (but I put some powershell logic in to check if there’s space left just in case)

---
    # Written by Alex Mayberry, Red Hat (March, 2018)
    #
    # This role is designed to read the resize_p_drive = [true|false] from cloudforms
    # if resize_p_drive == true, we need to log in and extend the p drive partition/filesystem to 100% of available space 
    # 
    # No Modules Were Harmed During the Creation of This Role
    # Module Docs:
    # http://docs.ansible.com/ansible/latest/win_command_module.html
    #

  - name: 'Resize partition and filesystem of P: to 100% of available space, if needed.'
    win_shell: |
      $cur_size = $(Get-Partition -driveletter p).size
      $max_size = $(get-partitionsupportedsize -driveletter P).sizemax
      if ( $cur_size -lt $max_size ) {
         Resize-Partition -DriveLetter P -Size $max_size
      }
    when: resize_p_drive