Change vCloud vApp/VM Storage Profile with PowerCLI

VMware has done a lot to open up the APIs for vCloud with the 5.1 release, however it still leaves much to be desired. One of the nicer things is the ability to change a storage profile for a VM. However, you need to know the HREF for the storage profile that you want to change to. This wasn’t so easy to get (I would love to be able to use a “get-storageProfile” PowerCLI cmd-let), but thankfully, Jake Robinson (@jakerobinson) and the VMware Community to the rescue:

http://communities.vmware.com/message/2163559#2163559

This script uses PowerCLI for Tenants (which cannot be installed on the same box running the ‘regular’ PowerCli). Taking his prompt to build an XML file from an HTTP GET to a vCloud HREF, we can retrieve storage profiles from any OrgvDC you have rights to. From this XML, we can assign a storage profile to a VM (or in this case, every VM in a vApp) based on it’s name and the Org you’re logged into. I modified his script a little bit, because if we pass an Org to the function, we don’t get the storage profiles, but if we pass an OrgvDC HREF, we automatically get the storage profiles (because storage profiles are assigned to Org vDCs and not globally to an Org). This reduces the number of function calls needed.

All this script needs is your vApp name and desired Storage Profile name.

What this also addresses is the ability to migrate all vCloud VMs off of the “*Any” Storage Profile.

# This function does a HTTP GET against the vCloud 5.1 API using our current API session.
# It accepts any vCloud HREF.
function Get-vCloud51($href)
{
 $request = [System.Net.HttpWebRequest]::Create($href)
 $request.Accept = "application/*+xml;version=5.1"
 $request.Headers.add("x-vcloud-authorization",$global:DefaultCIServers[0].SessionId)
 $response = $request.GetResponse()
 $streamReader = new-object System.IO.StreamReader($response.getResponseStream())
 $xmldata = $streamreader.ReadToEnd()
 $streamReader.close()
 $response.close()
 return $xmldata
}

# This function gets an OrgVdc via 1.5 API, then 5.1 API.
# It then returns the HREF for the storage profile based on the $profilename and

function Get-storageHref($orgVdc,$profileName)
{
 $orgVdc51 = Get-vCloud51 $orgVdc.Href
 $storageProfileHref = $orgVdc51.vdc.VdcStorageProfiles.VdcStorageProfile | Where-Object{$_.name -eq "$profileName"} | foreach {$_.href}
 return $storageProfileHref
}

# Get vApp, Storage Profile and OrgvDC names

$vappName = read-host "vApp name"
$profileName = read-host "Storage Profile"
$orgVdcName = read-host "Org vDC Name"

$orgVdc = get-orgvdc $orgVdcName

#Get storage profile HREF

$profileHref = Get-storageHref $orgVdc $profileName

# Change each VM's Storage Profile in the vApp

$CIvApp = Get-CIVApp $vappName
Foreach ($CIVM in ($CIvApp | Get-CIVM)) {
 $newSettings = $CIVM.extensiondata
 $newSettings.storageprofile.name = "$profileName"
 $newSettings.storageprofile.Href = "$profileHref"
 Write-Host "Changing the storage profile for $CIVM.name to $profileName"
 $newSettings.UpdateServerData()
}

6 thoughts on “Change vCloud vApp/VM Storage Profile with PowerCLI

  1. I spent 2 hours trying to figure this out last week!!! I knew the “UpdateServerData()” part at the end but couldn’t figure out how to get the Href of the storage profile I wanted to go to. I dug through the extensiondata but missed this area. Thanks for the post.

  2. Hi, I’ve seen your script for changing the storage profile on VM’s. But for me it’s not working.

    $newSettings.storageprofile.name = “$profileName” and
    $newSettings.storageprofile.Href = “$profileHref” give me the error (Property ‘name’ cannot be found on this object;)

    With get-member I don’t see storageprofile property on the object:
    TypeName: VMware.VimAutomation.Cloud.Impl.V1.CIVMImpl

    Name MemberType Definition
    —- ———- ———-
    ConvertToVersion Method T ConvertToVersion[T](), T Ver
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetType Method type GetType()
    IsConvertableTo Method bool IsConvertableTo(type toTy
    ToString Method string ToString()
    ToVirtualMachine Method System.Collections.Generic.IEn
    Client Property VMware.VimAutomation.Cloud.Int
    CpuCount Property int CpuCount {get;}
    Deleted Property bool Deleted {get;}
    Description Property string Description {get;}
    ExtensionData Property System.Object ExtensionData {g
    GuestOsFullName Property string GuestOsFullName {get;}
    Href Property string Href {get;}
    Id Property string Id {get;}
    MemoryGB Property decimal MemoryGB {get;}
    MemoryMB Property decimal MemoryMB {get;}
    Name Property string Name {get;}
    Org Property VMware.VimAutomation.Cloud.Typ
    OrgVdc Property VMware.VimAutomation.Cloud.Typ
    Status Property VMware.VimAutomation.Cloud.Typ
    Uid Property string Uid {get;}
    VApp Property VMware.VimAutomation.Cloud.Typ
    VMVersion Property VMware.VimAutomation.ViCore.Ty

  3. It seems this is broken with vCloud 5.5 ? i got the error:

    Exception calling “UpdateServerData” with “0” argument(s): “The reference
    cannot be parsed correctly. Reason: no server authority”
    At ….CENSORED….
    + $newSettings.UpdateServerData()
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  4. I had the same issue as Andres and after looking through the script I got it to work by changing line 19 to the following.

    $storageProfileHref = $orgVdc51.adminvdc.VdcStorageProfiles.VdcStorageProfile | Where-Object{$_.name -eq “$profileName”} | foreach {$_.href}

Leave a Reply