Live import VMs to vCloud Director

Tom Fojta wrote a great blog post about the new capability in vCloud Director 8.10 to import running VMs into vCloud Director. This is a huge asset in migration scenarios where customers can’t afford outages when being migrated into the vCD environment. Unfortunately the API syntax to actually initiate the import is a little convoluted and not the easiest process to manage.

I set about writing a PowerShell script to significantly simplify the process of initiating a live-import operation. The script itself is available from github at the following link: https://github.com/jondwaite/vcdliveimport.

The liveimport.ps1 script contained in this repository does the following:

  • Prompts for a credential to be used to connect to both vCloud Director (System context) and vCenter – if you have different usernames/passwords for each you’ll need to adjust this.
  • Enumerates the available vCenter instances registered as Provider Virtual Datacenters (PVDCs) in vCloud Director and allows one to be selected as the source vCenter for the migration.
  • Lists the available VMs in the selected vCenter instance, filters this list based on selectable criteria (e.g. don’t offer to import ‘Guest Introspection’ VMs) and allows the source VM to be selected.
  • Lists available destination Virtual Datacenters (VDCs) in the vCloud Director environment and allows the destination VDC to be selected.
  • Displays the appropriate POST request information to be submitted to vCloud Director to initiate the live-import of this VM.
  • Optionally – Submits the REST API request directly to the vCloud Director environment to actually initiate the import process.

An example transcript of this process is show below. Hopefully this helps someone else out and helps to make it easier for you to live-import running VMs into vCloud Director.

Jon.

Example Session Transcript:

PowerCLI C:\> liveimport.ps1
Connected to vCloud Director OK
vCenter(s) Found:
-----------------
vc01 (https://vcd01.dev.local/api/admin/extension/vimServer/158f73ec-a999-4332-8250-f4dd5e6c4971)

Selecting vc01 as only pVDC vCenter found.
vCenter vc01 selected.
Connected to vCenter Server vc01 OK

Evaluating vCenter VMs as migration candidates.............
Available candidate VMs:
------------------------
testvm01

Enter VM name to live-migrate to vCloud (or 'quit' to exit): testvm01
Selected VM testvm01 for live import to vCloud.

Available VDCs:
---------------
Lab VDC
Enter Destination VDC Name (or quit to exit): Lab VDC
VDC 'Lab VDC' selected.

URI for POST operation:
https://vcd01.dev.local/api/admin/extension/vimServer/158f73ec-a999-4332-8250-f4dd5e6c4971/importVmAsVApp

XML Document Body:
<?xml version="1.0" encoding="UTF-8"?>
<ImportVmAsVAppParams xmlns="http://www.vmware.com/vcloud/extension/v1.5" name="testvm01" sourceMove="true">
 <VmMoRef>vm-111</VmMoRef>
 <Vdc href="https://vcd01.dev.local/api/admin/vdc/b21c92fa-1a6f-42a9-8c1e-ef0947c7be76" />
</ImportVmAsVAppParams>

Content-Type: application/vnd.vmware.admin.importVmAsVAppParams+xml

Would you like to submit this API request to live import this VM? (y or n) (or quit to exit): y
Making request to live import VM testvm01...
Response was:
<?xml version="1.0" encoding="UTF-8"?>
<VApp xmlns="http://www.vmware.com/vcloud/v1.5" ovfDescriptorUploaded="true" deployed="false" status="0" name="testvm01" id="urn:vcloud:vapp:ff1a9021-2c21-4378-99c7-b77bdaf3e9e6" href="https://vcd01.ndev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6" type="application/vnd.vmware.vcloud.vApp+xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcd01.dev.local/api/v1.5/schema/master.xsd">
 <Link rel="down" href="https://vcd01.dev.local/api/network/251f72a8-19b5-4e7d-94ba-0523ee919cd9" name="VM Network" type="application/vnd.vmware.vcloud.vAppNetwork+xml" />
 <Link rel="down" href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6/controlAccess/" type="application/vnd.vmware.vcloud.controlAccess+xml" />
 <Link rel="up" href="https://vcd01.dev.local/api/vdc/b21c92fa-1a6f-42a9-8c1e-ef0947c7be76" type="application/vnd.vmware.vcloud.vdc+xml" />
 <Link rel="down" href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6/owner" type="application/vnd.vmware.vcloud.owner+xml" />
 <Link rel="down" href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6/metadata" type="application/vnd.vmware.vcloud.metadata+xml" />
 <Link rel="ovf" href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6/ovf" type="text/xml" />
 <Link rel="down" href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6/productSections/" type="application/vnd.vmware.vcloud.productSections+xml" />
 <Tasks>
 <Task cancelRequested="false" expiryTime="2016-10-31T11:27:25.312+13:00" operation="Importing Virtual Application testvm01(ff1a9021-2c21-4378-99c7-b77bdaf3e9e6)" 
operationName="importSingletonVapp" serviceNamespace="com.vmware.vcloud" startTime="2016-08-02T11:27:25.312+12:00" status="queued" name="task" id="urn:vcloud:task:37576f8c-0d39-444c-8842-81436ddb421e" href="https://vcd01.dev.local/api/task/37576f8c-0d39-444c-8842-81436ddb421e" type="application/vnd.vmware.vcloud.task+xml">
 <Owner href="https://vcd01.dev.local/api/vApp/vapp-ff1a9021-2c21-4378-99c7-b77bdaf3e9e6" name="testvm01" type="application/vnd.vmware.vcloud.vApp+xml" />
 <User href="https://vcd01.dev.local/api/admin/user/fa7fb40e-648c-4787-ad0f-711dcc315261" name="system" type="application/vnd.vmware.admin.user+xml" />
<Organization href="https://vcd01.dev.local/api/org/3f46b162-f794-4d9e-8fa1-6ca1ee7b6377" name="Lab" type="application/vnd.vmware.vcloud.org+xml" />
 <Progress>1</Progress>
 <Details />
 </Task>
 </Tasks>
 <DateCreated>2016-08-02T11:27:25.079+12:00</DateCreated>
 <Owner type="application/vnd.vmware.vcloud.owner+xml">
 <User href="https://vcd01.dev.local/api/admin/user/1545cb33-9151-43e2-a156-9d20e3b966c0" name="system" type="application/vnd.vmware.admin.user+xml" />
 </Owner>
 <InMaintenanceMode>false</InMaintenanceMode>
</VApp>

 

Tagged , , , , , . Bookmark the permalink.

10 Responses to Live import VMs to vCloud Director

  1. nick ellermann says:

    Thanks for this info. We are running 8.10 and the important button in the UI only lists powered of VMs as per previous versions of vCD. Is vCenter 6+ required as well or some other requirement?
    Features have been soo slow to come out in vCD. the portal is more of a pain than it is worth most of the time. We only put customers into it that require console access to a VM!

    • Jon Waite says:

      I’m not aware of any restriction that would prevent this from working on previous versions of vCenter (provided they are registered in vCloud Director and compatible they should work). Be interested to know if you test this and can confirm/deny.

  2. Riaan says:

    Hi Jon, thanks you for putting this together.

    Everything is running fine until the last step. I am getting the following error when trying to live import a vm:

    Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
    At \liveimport.ps1:199 char:21
    + … $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Pos …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    I am using Powershell v5, PowerCLI v6.5, vCloud Director for Service Providers 8.10, vSphere 6

    I have been scratching around however not able to find the root cause of the problem. Do you know where I can try and make a change or 2 to get this working? I have potentially 600VM’s that I need to live import into VCD.

    Thanks again!

    • Adrian says:

      Riaan, you’ve probably sorted this by now, but you can get the full error messages by submitting the API request via cURL. One thing to check for is that the VM you are migrating in is connected to the right portgroup, i.e. one that is backing an organisation network in the vDC it’s going into.

  3. Wayne Silvia says:

    I am trying to put metadata value into a way to export to csv….although I am able to put the “value” out using something like….
    $testmetadata = get-civm WADDC03 | get-cimetadata | Where { $_.key -eq “Class of Service”} | select ciobject, key, value

    write-host $testmetadata.value

    produces only the value…called Prod
    which is what I want..

    but if I try to use something like this to extract the value and try to use add-member I end up getting the result of @{Value=Prod}

    get-civm |
    Add-Member -Name “Class of Service” -Value { get-cimetadata $this | Where { $_.key -eq “Class of Service”} | select value } -MemberType ScriptProperty -Passthru -Force |

    select name, status, “Class of Service”

    I get this…

    Name Status Class of Service
    —- —— —————-
    CLOUDTest01 PoweredOn @{Value=Test}
    CLOUDTest04 PoweredOn @{Value=Test}
    Testvmserver1 PoweredOn
    ProdVMserver1 PoweredOn @{Value=Prod}
    ProdVMserver2 PoweredOn @{Value=Prod}

    Is there anyway to just get the value to show?

  4. Adrian says:

    Hi Jon, awesome script – like it! We’ve got several hundred VMs coming into a vCD 8.10 rig and this is going to help us immensely. Thank you!

  5. Gary says:

    Hi Jon,
    I seem to be getting a duplicate entry when it reads the vCenter info. Output from script is:
    Connected to vCloud Director OK
    vCenter(s) Found:
    —————–
    vCenter.domain.com vCenter.domain.com (https://vcd.domain.com/api/admin/extension/vimServer/13f8fbb7-88c3-4ae6-9b9c-af75633d2d8c https://vcd.domain.com/api/admin/extension/vimServer/13
    f8fbb7-88c3-4ae6-9b9c-af75633d2d8c)
    Selecting vCenter.domain.com vCenter.domain.com as only pVDC vCenter found.
    vCenter System.Object[] selected.
    WARNING: Invalid URI: The hostname could not be parsed.
    Could not connect to vCenter System.Object[] (credentials correct?), exiting.

    TO get around this I added 2 variables of $vcenter = “vCenter.domain.com” and vimserver[0]=”vcd.domain.com/api/admin/extension/vimServer/13f8fbb7-88c3-4ae6-9b9c-af75633d2d8c”

    It now gets to the Accept header and fails with the error:
    Invoke-RestMethod : The ‘Accept’ header must be modified using the appropriate property or method.
    Parameter name: name

    Any ideas?

    • Riaan says:

      Hi Gary,

      Not sure if you figured it out yet but here is the fix for what you are experiencing.

      I had the same and changed the following the section # Find all of our Provider Virtual Datacenters (pVDCs) and add to a hash to the following:

      Write-Host “PVDCName: $($pvdc.ExtensionData.VimServer.Name) URL: $($pvdc.ExtensionData.VimServer.Href)”
      $pvdcs.Add($pvdc.ExtensionData.VimServer.Name, $pvdc.ExtensionData.VimServer.Href)

      In the script that is downloaded it is $($pvdcobjs. instead of $($pvdc.

  6. Riaan says:

    Hi Jon

    Thanks for the script, it is working great!

    I have changed the Invoke-RestMethod to the following to give me more detail about any error that may occur instead of just the Powershell exception telling me that the method failed with a 400 Bad Request error:

    try
    {
    $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Post -Body $xml -ContentType “application/vnd.vmware.admin.importVmAsVAppParams+xml”
    } catch
    {
    $Result = $_.Exception.Response.GetResponseStream()
    $Reader = New-Object System.IO.StreamReader($Result)
    $ResponseBody = $Reader.ReadToEnd();
    Write-Host “There was an error processing the request!” -ForegroundColor Red
    Write-Host “Status Code: ” $_.Exception.Response.StatusCode.value__ -ForegroundColor DarkYellow
    Write-Host “Status Description” $_.Exception.Response.StatusDescription -ForegroundColor DarkYellow
    Write-Host “Full message from the server: ” $ResponseBody -ForegroundColor DarkYellow
    }

    So this brings me to a question that I am not sure how to get around, the above tells me that the method failed due to the following reason: ” majorErrorCode=”400″ message=”[ af6aa7aa-1e4a-4d32-bf06-5eb64b7a9d10 ] Cannot import VM VMName(vm-458). Changing datastores is not support while importing a powered on VM.” minorErrorCode=”BAD_REQUEST” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.vmware.com/vcloud
    /v1.5 http://VCDServer/api/v1.5/schema/master.xsd“>

    Any idea how I can get around this error?

    Thanks much in advance!

  7. Nice script Jon, thanks for the share!

Leave a Reply to Adrian Cancel reply

Your email address will not be published. Required fields are marked *

twenty − 16 =