Thursday, April 6, 2017

vCenter REST API and the Content Library

Untitled Document.md

Overview

In this post I will demonstrate the use of the REST API to place an ISO image within the content library of vCenter,
creating a new VM, and finally booting that VM from the ISO image.

I built these examples by following the documentation which is part of the REST SDK.

Getting Started

The examples assume the availability of a bash shell and curl, however, the tools themselves are not as
important as the actual process.

Set Environment Variables

Store the base URL of the vcenter host. Example:

VCENTER=https://vc1

Generate a unique client token for use later on.

CLIENT_TOKEN=$(uuidgen)

Authenticate

Post using http basic auth. Capture the session id which is returned.

curl -k -X POST -H 'Accept: application/json' \
--basic -u administrator@spinhirne.com:VMware1!  \
$VCENTER/rest/com/vmware/cis/session  | python -m json.tool

Store the session id within an environment variable. Example:

SESSION_ID=e37ebe2698fcf1b91af36cfbfcfd2acf

Creating a New Content Library

Get supported content library item types

Optional step, but informative.

vCenter has built in support for a couple of content types. Query the supported types. For this
guide we’ll make use of the “iso” type.

curl -k -X GET -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/com/vmware/content/type  | python -m json.tool

Get a list of datastore IDs

Datastore IDs are needed in order to define a backend for local content libraries. Capture the
ID (the “datastore” attribute of the returned json) of each datastore you wish to use.

curl -k -X GET -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/vcenter/datastore | python -m json.tool

Store the datastore IDs within an environment variable(s). Example:

DATASTORE0="datastore-12"

Create a new local library

Create a library and capture its UUID.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/com/vmware/content/local-library \
<<- JSON
{
    "client_token": "$CLIENT_TOKEN",
    "create_spec": {
        "description": "test lib",
        "name": "testLib1",
        "storage_backings": [
            {
                "datastore_id": "$DATASTORE0",
                "type": "DATASTORE"
            }
        ],
        "type": "LOCAL"
    }
}
JSON
) | python -m json.tool

Store the UUID within an environment variable. Example:

LIBRARY=d38b7d74-70c5-4fa5-b4b6-5cd9001457ba

Add an ISO item to the library

Locate an iso file and capture the file name as an environment variable. Example:

ISO_FILE=/tmp/test.iso

Capture its size and md5sum as well:

ISO_MD5=$(md5sum $ISO_FILE | gawk '{print $1}')
ISO_SIZE=$(ls -l $ISO_FILE | gawk '{print $5}')

Create a library item for this iso.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/com/vmware/content/library/item \
<<- JSON
{
        "client_token": "$CLIENT_TOKEN",
        "create_spec": {
                "description": "a custom iso",
                "library_id": "$LIBRARY",
                "name": "$(basename $ISO_FILE)",
                "type": "iso"
        }
}
JSON
) | python -m json.tool

Capture the library item within an environment variable. Example:

LIBRARY_ITEM=b568e170-4702-42d4-804a-93b35f678e30

Create an update session

An update session is needed in order to upload the actual iso file.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/com/vmware/content/library/item/update-session \
<<- JSON
{
        "client_token": "$CLIENT_TOKEN",
        "create_spec": {
            "library_item_id": "$LIBRARY_ITEM"
        }
}
JSON
) | python -m json.tool

Capture the update session within an environment variable. Example:

UPDATE_SESSION=39bf1ccb-d7b9-4aff-b250-83b3c6c3620a:8bed2a31-ce25-4d9d-b0e8-dc1a861ebc1e

Request URI for file upload

We’re going to use a PUSH session to push the file to vCenter. For this, vCenter will give us an
endpoint for the upload.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/com/vmware/content/library/item/updatesession/file/id:$UPDATE_SESSION?~action=add \
<<- JSON
{
    "file_spec": {
        "checksum_info": {
            "algorithm": "MD5",
            "checksum": "$ISO_MD5"
        },
        "name": "$(basename $ISO_FILE)",
        "size": $ISO_SIZE,
        "source_type": "PUSH"
    }
}
JSON
) | python -m json.tool

Capture the upload endpoint with an environment variable. Example:

UPLOAD_ENDPOINT=$VCENTER/cls/data/75be4d03-dcaa-451a-b946-1ba0aa38f947/dsl-4.4.10.iso

Upload the file

Upload the file using a PUT request with the file uploaded as multipart form data.

curl -v -k -X PUT \
-F "$(basename $ISO_FILE)=@$ISO_FILE" \
-H 'Accept: application/json' -H "vmware-api-session-id: $SESSION_ID" \
$UPLOAD_ENDPOINT

Validate the upload

Check for any upload errors.

curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/com/vmware/content/library/item/updatesession/file/id:$UPDATE_SESSION?~action=validate \
| python -m json.tool

Complete or fail the session

If there are any validation errors then fail the session:

curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d '{"client_error_message": "upload failed"}' \
-w "%{http_code}\n" \
$VCENTER/rest/com/vmware/content/library/item/update-session/id:$UPDATE_SESSION?~action=fail

Otherwise mark it as complete. Marking it complete causes the item to actually update with the uploaded content.

curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/com/vmware/content/library/item/update-session/id:$UPDATE_SESSION?~action=complete

Get the status of the update session

Optional step, but informative.

curl -k -X GET -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/com/vmware/content/library/item/update-session/id:$UPDATE_SESSION \
| python -m json.tool

Delete the update session

Clean up.

curl -k -X DELETE -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/com/vmware/content/library/item/update-session/id:$UPDATE_SESSION 

Creating a New VM

Get a list of folder IDs

We need to find a VM folder for our VM. Get a list of vm folders from the system and
capture the ID (the “folder” field) of one of them.

curl -k -X GET -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/vcenter/folder?filter.type=VIRTUAL_MACHINE | python -m json.tool

Store the folder id within an environment variable. Example:

VMFOLDER="group-v3"

Get a list of hosts

Get a list of hosts from the system and capture the ID (the “host” field) of one of them.

curl -k -X GET -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
$VCENTER/rest/vcenter/host | python -m json.tool

Store the host id within an environment variable. Example:

VCHOST="host-9"

Create a test VM

Now we’ll create a VM. We’ll deploy to the host/folder gathered previously and we’ll use the datastore
we used for our content library for its disk backing.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/vcenter/vm \
<<- JSON
{
    "spec": {
        "name": "testVM",
        "guest_OS": "OTHER_LINUX_64",
        "placement": {
            "host": "$VCHOST",
            "datastore": "$DATASTORE0",
            "folder":"$VMFOLDER"
        }
    }
}
JSON
) | python -m json.tool

Store the VM id within an environment variable. Example:

VM="vm-59"

Mount the iso from the library on the VM

Mounting the iso from the content library will create a new cdrom device on the VM which is backed
by the library item. The call will return the id of the newly created cdrom.

(curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-d @- \
$VCENTER/rest/com/vmware/vcenter/iso/image/id:$LIBRARY_ITEM?~action=mount \
<<- JSON
{
    "vm": "$VM"
}
JSON
) | python -m json.tool

Capture the id of the cdrom within an environment variable. Example:

VMCDROM=3000

Power on the VM

Power on the VM and then verify from the console that it has booted the iso image.

curl -k -X POST -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/vcenter/vm/$VM/power/start

Power off the VM

Optionally power off the VM if you’re finished with it.

curl -k -X POST -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/vcenter/vm/$VM/power/stop

Unmount the cdrom

curl -k -X POST \
-H 'Accept: application/json' -H "Content-Type: application/json" -H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
-d @- \
$VCENTER/rest/com/vmware/vcenter/iso/image/id:$VM?~action=unmount \
<<- JSON
{
    "cdrom": "$VMCDROM"
}
JSON

Final Clean Up

Delete the VM

curl -k -X DELETE -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/vcenter/vm/$VM

Delete the library item

curl -k -X DELETE -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/com/vmware/content/library/item/id:$LIBRARY_ITEM

Delete the library

curl -k -X DELETE -H 'Accept: application/json' \
-H "vmware-api-session-id: $SESSION_ID" \
-w "%{http_code}\n" \
$VCENTER/rest/com/vmware/content/local-library/id:$LIBRARY