Home > PowerCLI, PowerShell, Thin Provisioning, vSphere > Thick to Thin with PowerCLI and the SDK

Thick to Thin with PowerCLI and the SDK

November 8th, 2009 LucD Leave a comment Go to comments

One of the interesting new features in vSPhere is vStorage Thin Provisioning. I’m not going to explain what Thin Provisioning is all about. For that you can consult several knowledgeable blogs (for example this entry on Virtual Geek) and/or books (for example Scott Lowe’s excellent Mastering VMware vSphere 4.0).

The problem I have with Thin Provisioning, is that there are a lot of existing guests and templates out there that were created with Thick VMDKs in the past. The only documented way I could find to convert these Thick VMDKs to Thin VMDKs was to use svMotion from the vSphere client.

Now that is not a solution I want to (or can) use in an automated environment.I could of course ‘emulate’ the svMotion process in a PowerShell script with the RelocateVM method, but that is in my opinion not really an ideal solution.

Luckily there is the VirtualDiskManager with some handy methods like the CopyVirtualDisk_Task method.

This method combined with the ReconfigVM_Task method ultimately gave me a working solution. With the following script I succeeded in converting a Thick VMDK into a Thin VMDK in place. My “in place” statement is of course relative, you have to have enough free space in the datastore to create a Thin version of the VMDK besides the Tick version of the VMDK. Once the reconfiguration is done you can safely remove the Thick VMDK file(s).

The guest has to be powered off for the following script to work !

$vmName = "guest-name"
$vCenter = "vCenter-hostname"
$esxAccount = "ESX-account"
$esxPasswd = "ESX-password"

$vcHost = Connect-VIServer -Server $vCenter
$vmImpl = Get-VM $vmName
if($vmImpl.PowerState -ne "PoweredOff"){
 Write-Host "Guest must be powered off to use this script !" -ForegroundColor red
 exit
}
$vm = $vmImpl | Get-View
$esxName = (Get-View $vm.Runtime.Host).Name

# For Virtual Disk Manager we need to connect to the ESX server
$esxHost = Connect-VIServer -Server $esxName -User $esxAccount -Password $esxPasswd

$vDiskMgr = Get-View -Id (Get-View ServiceInstance).Content.VirtualDiskManager
$firstHD = $true
$vm.Config.Hardware.Device | where {$_.GetType().Name -eq "VirtualDisk"} | % {
 if(!$_.Backing.ThinProvisioned){
 $dev = $_
 $srcName = $dev.Backing.FileName
 $dstName = $srcName.Replace("/","/thin_")
 $esx = Get-View $vm.Runtime.Host
 $srcDC = Get-Datacenter | Get-View
 $spec = New-Object VMware.Vim.VirtualDiskSpec
 $controller = $vm.Config.Hardware.Device | where {$_.Key -eq $dev.ControllerKey}
 switch($controller.GetType().Name){
 "VirtualBusLogicController" {$adapter = "busLogic"}
 "VirtualIDEController" {$adapter = "ide"}
 "VirtualLsiLogicController" {$adapter = "lsiLogic"}
 "VirtualLsiLogicSASController" {$adapter = "lsiLogic"}
 "ParaVirtualSCSIController" {$adapter = ""}
 "Default"{
 Write-Host "Unknown controller type"
 exit
 }
 }
 $spec.adapterType = $adapter
 $spec.diskType = "thin"

 $taskMoRef = $vDiskMgr.CopyVirtualDisk_Task($srcName, $srcDC.MoRef, $dstName, $srcDC.MoRef, $spec, $false)
 $task = Get-View $taskMoRef
 while("running","queued" -contains $task.Info.State){
 $task.UpdateViewData("Info")
 }

 if($firstHD){
 $specHD = New-Object VMware.Vim.VirtualMachineConfigSpec
 $firstHD = $false
 }
 $deviceMod = New-Object VMware.Vim.VirtualDeviceConfigSpec
 $deviceMod.device = $dev
 $deviceMod.device.Backing.FileName = $dstName
 $deviceMod.Operation = "edit"
 $specHD.deviceChange += $deviceMod
 }
}
Disconnect-VIServer -Server $esxHost -Confirm:$false

# For the reconfiguration of the VM we connect to the vCenter
Connect-VIServer -Server $vCenter
$taskMoRef = $vm.ReconfigVM_Task($specHD)
$task = Get-View $taskMoRef
while("running","queued" -contains $task.Info.State){
 $task.UpdateViewData("Info")
}

Annotation:

Line 3-4: provide an ESX account and password with root access on the ESX server

Line 8-11: the guest must be powered off for this script to work

Line 16: the VirtualDiskManager methods can only be used when connected to an ESX

Line 20: this loops through all devices and finds the Thick VMDKs

Line 24: the backing filename of the Thin VMDK is the same as the backing filename of the Thick VMDK with a “thin_” prefix

Line 29-39: this Switch construct provides the correct adapter name. Take note that the adapter names are case-sensitive

Line 41: the diskType property allows to specify what VMDK format the copy should have

Line 43: the CopyVirtualDisk_Task method creates a Thin copy of the Thick VMDK

Line 49-59: this construct creates the specification for the ReconfigVM_Task method

Line 64: the new Thin VMDKs are now connected (as backing file(s)) to the VM

Note that the script doesn’t remove the Thick VMDK files from the VM’s directory. This is a safety precaution should something go wrong with the conversion.

Note that this procedure was tested and tried in my environment and seems to work correctly. If you are going to use this script, first try it out in your test environment and make sure the guests with the Thin VMDKs are working correctly !

  1. August 10th, 2010 at 22:42 | #1

    Hi Luc,

    Did you ever have any luck with this? I’ve had a trawl through hte new version of the toolkit, but it doesn’t look like VMware have added a thin disk option.

    Cheers….

  2. Steve Ochry
    March 8th, 2010 at 16:35 | #2

    @LucD
    I was provided a workaround in C#. Essentially, the workaround is to create a propertyCollector and retrieve the properties on the httpNfcLeaseMor object. Looping through the properties, picking out the ones you need. Code pasted below in C#, for what it is worth.

    private void RetrieveHttpNfcLeaseProperties(ManagedObjectReference httpNfcLeaseMor,
    out HttpNfcLeaseInfo httpNfcLeaseInfo,
    out HttpNfcLeaseState httpNfcLeaseState,
    out int httpNfcLeaseInitializeProgress,
    out LocalizedMethodFault httpNfcLeaseError)
    {
    httpNfcLeaseInfo = null;
    httpNfcLeaseState = HttpNfcLeaseState.error;
    httpNfcLeaseInitializeProgress = 0;
    httpNfcLeaseError = null;

    PropertyCollector propertyCollector =
    new PropertyCollector(vimClient, vimClient.ServiceContent.PropertyCollector);

    ObjectContent[] objectContent = propertyCollector.RetrieveProperties(
    new[] {ViewBase.GetPropertyFilterSpec(httpNfcLeaseMor)});

    if ((objectContent != null) && (objectContent.Length > 0))
    {
    foreach (DynamicProperty property in objectContent[0].PropSet)
    {
    switch (property.Name)
    {
    case “info”:
    httpNfcLeaseInfo = (HttpNfcLeaseInfo) property.Val;
    break;

    case “state”:
    string state;

    if (property.Val is XmlNode[])
    {
    state = ((XmlNode[]) property.Val)[1].Value;
    }
    else
    {
    state = property.Val.ToString();
    }

    httpNfcLeaseState = (HttpNfcLeaseState)Enum.Parse(typeof(HttpNfcLeaseState), state);
    break;

    case “initializeProgress”:
    httpNfcLeaseInitializeProgress = (int) property.Val;
    break;

    case “error”:
    httpNfcLeaseError = (LocalizedMethodFault) property.Val;
    break;
    }
    }
    }
    }

    • March 8th, 2010 at 17:27 | #3

      Thanks for sharing that Steve.
      I’ll have a look if I can package that solution in a PowerShell script.

  3. Steve Ochry
    March 1st, 2010 at 22:43 | #4

    @LucD
    I am bumping into this very issue on the C# side of things. Did you ever get anywhere with a work around?

    • March 1st, 2010 at 23:00 | #5

      Hi Steve, no I’m afraid I didn’t find a workaround for this yet :-(
      But it’s still on my list of things to investigate further.

  4. January 31st, 2010 at 12:55 | #6

    Thanks for the update.

  5. January 31st, 2010 at 10:04 | #7

    Hi Luc,

    Any luck getting this to work?

    Al…….

    • January 31st, 2010 at 10:42 | #8

      I encountered a problem while testing this. The HttpNfcLease MoRef the ImportVApp method returns has a problem.
      One of the PowerCLI developers confirmed that there is a “…bug in xml deserialisation of NfcLeaseState object.”
      I’m still looking if there is a way around the problem.

  6. January 18th, 2010 at 22:11 | #9

    This would be useful for restoring VMs without the need of third party systems or using the DR Appliance. The only issue I’ve had is the network adapter which defaults to a standard vmxnet adapter, but as long as it’s removed and replaced with a vmxnet3 card before powering it on (which can easily be scripted), the VM boots up and picks up it’s original IP info and works perfectly.

  7. January 18th, 2010 at 17:20 | #10

    Hi Luc,

    Using the powershell toolkit, is there a way of importing an OVF and specifying the disk type as Thin? I’ve had a dig around in the kit and can only find the vApp cmdlet in the main toolkit. I assume that it will import an OVF, but there is no option for disk provisioning, however I did notive that the OVF Tool has those options.

    Any guidence will as always be much appreciated.

    Ali………

    • January 18th, 2010 at 20:48 | #11

      Very intriguing idea.
      A quick look at the VirtualApp methods in the SDK makes me think it should be possible.
      Let me play with the concept in my lab. Might even produce a new post when I get it to work.
      Luc.

  1. November 9th, 2009 at 01:25 | #1