VMware {code} Community
rsanheim
Contributor
Contributor

How to expand disk size of a single disk using VIJava (or the plain Java SDK) ?

Dear VMWare Friends and Family

We are trying to expand the disk on an existing VM using VIJava. More specifically, we want to resize a 10 GB disk to 30 GB on a powered-off VM without losing any data on the disk. We've tried a few different approaches, and so far none of them have worked:

1) We tried using VirtualDiskManager#extendVirtualDisk, which is listed as “experimental” in vCenter 2.5. Unfortunatley getVirtualDiskManager() on ServiceContent returns nil, so we weren’t able to go further to test this option. We are guessing this may be turned off on the vCenter level.

2) We tried taking various samples and posts on the community site, converting them to JRuby, and applying those to an existing VM with 10 gigs of space. We have the latest code below, which raises an exception: "com.vmware.vim25.InvalidDeviceSpec: null". We've also seen the task return successfully but no change happen at the vCenter level in the disk space.

We are using vCenter 2.5, VIJava (the latest release), Java 6, JRuby 1.2, and Redhat-based VMs.

Below is the relevant code sample. (It's JRuby, so all method names are lower-cased and underscored versions of the Java methods. JRuby does this translation automatically).

    # retrieve the VM object for a specified name
    vm = find_by_name

    # pull back all devices, find the SCSI Controller, and get the controller key
    devices = vm.managed_object.config.hardware.device
    current_controller = devices.find {|d| d.device_info.label == "SCSI Controller 0"}
    controller_key = current_controller.controller_key

    # determine the next unit_number
    unit_number = devices.length + 1;

    # create a new backing file for the expanded disk
    disk_backing_info = VirtualDiskFlatVer2BackingInfo.new
    disk_backing_info.disk_mode = "persistent"
    disk_backing_info.file_name = "#{datastore_name} #{vm_name}/#{vm_name}.vmdk"

    # assemble the VirtualDisk, 30 gigs in size
    disk = VirtualDisk.new
    disk.backing = disk_backing_info
    disk.key = -1 # specifying a negative key makes it unique
    disk.controller_key = 1000
    disk.unit_number = unit_number
    disk.capacity_in_kb = 30 * 1024 * 1024

    # assemble spec telling vCenter to edit the existing disk and replace it
    device_config_spec = VirtualDeviceConfigSpec.new
    device_config_spec.operation = VirtualDeviceConfigSpecOperation.edit
    device_config_spec.file_operation = VirtualDeviceConfigSpecFileOperation.replace
    device_config_spec.device = disk

    # go from Ruby Array to Java Array of VirtualDeviceConfigSpec, and set it on the config spec
    device_config_spec_array = [device_config_spec].to_java(VirtualDeviceConfigSpec)
    vm_config_spec = VirtualMachineConfigSpec.new
    vm_config_spec.device_change = device_config_spec_array

    # finally kick off the reconfig task with the config spec
    task = vm.managed_object.reconfigVM_Task(vm_config_spec);
    task.waitForMe      

Can you think of anything that might be causing this issue? Any insight or suggestions you can offer are much appreciated.

Thanks,

Rob

0 Kudos
3 Replies
admin
Immortal
Immortal

ReconfigVM_Task is the correct API to perform the task. The error you reported implies that there is some wrong value assigned to one of the attributes of your DeviceSpec. Please check the key of your existing "SCSI Controller", is that value is '1000'? You have specified the value for controllerKey attribute of your VirtualDisk as '1000' while it should be a key of a valid SCSI Controller Device. Also check if the unitNumber value exceeds 14. UnitNumber is a unique number of a device on its controller and as a single Controller supports only 15 devices on it. Incase value of unitNumber assigned exceeds 14, it gave an error. Hope you this information might resolve the issue at your end.

You can also refer the Java SDK sample "VMReconfig.java" shipped with VI SDK for reference.

rsanheim
Contributor
Contributor

Thanks, Seemankij. That was a big help.

We have now successfully resized a disk for an existing VM. Here's a summary of the changes we had to make:

  • Instead of using the key, controller_key, and unit_number for the SCSI Controller, we had to use the key, controller_key, and unit_number for the Hard Disk. (And that makes sense, of course, since we're resizing the disk, not the SCSI Controller).

  • We had to remove the code that set the VirtualDeviceConfigSpecFileOperation to VirtualDeviceConfigSpecFileOperation.replace. Instead of setting it to "replace", we don't set it at all.

With those two changes, we can successfully resize the disk for an existing VM.

Here's an updated code snippet:

      # create a new backing file for the expanded disk
      disk_backing_info = VirtualDiskFlatVer2BackingInfo.new
      disk_backing_info.disk_mode = "persistent"
      disk_backing_info.file_name = "#{datastore_name} #{vm_name}/#{vm_name}.vmdk"
      
      # assemble the VirtualDisk, 20 gigs in size
      disk = VirtualDisk.new
      disk.backing = disk_backing_info
      disk.key = 2000
      disk.controller_key = 1000
      disk.unit_number = 0
      disk.capacity_in_kb = 20 * 1024 * 1024
      
      # assemble spec telling vCenter to edit the existing disk and replace it
      device_config_spec = VirtualDeviceConfigSpec.new
      device_config_spec.operation = VirtualDeviceConfigSpecOperation.edit
      # device_config_spec.file_operation = VirtualDeviceConfigSpecFileOperation.replace
      device_config_spec.device = disk

      # go from Ruby Array to Java Array of VirtualDeviceConfigSpec, and set it on the config spec
      device_config_spec_array = [device_config_spec].to_java(VirtualDeviceConfigSpec)
      vm_config_spec = VirtualMachineConfigSpec.new
      vm_config_spec.device_change = device_config_spec_array
      
      # finally kick off the reconfig task with the config spec
      task = vm.managed_object.reconfigVM_Task(vm_config_spec);
      task.waitForMe      

After seeing the resize succeed in the vCenter, we ssh'ed into the VM and of course realized that Linux knew nothing about the expanded disk. Is there a standard pattern for how to do this resize and then update things at the OS level so it can see the new disk space?

Thanks,

Rob

0 Kudos
stumpr
Virtuoso
Virtuoso

Resizing a partition will depend on your OS and the filesystem. Nothing standard per say.

For Linux, assuming you are using ext2 or ext3 partition(s) resize2fs should be able to do an online resize if you expand the partition. I think the kernel has to support it as well, so you'll need Kernel 2.6. You'll have to take the partition offline to do a size decrease.

Reuben Stump | http://www.virtuin.com | @ReubenStump
0 Kudos