How can I resize a VMWare Disk

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?

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.

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

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
2 Likes

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?!

This worked beautifully! Thank you!

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.

@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

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

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

``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

See also: VMware Resize Disk

pemcg