python java go powershell

Protection Domain Tutorial (v2)

This REST API Python tutorial shows you how to: define cluster connection, authenticate to a cluster, get cluster information, create a protection domain, find unprotected VMs, and add the unprotected VMs to a protection domain.

Before you begin

Install Python library requests.

You can download the completed script at

You can download the sample response to this script at


  1. Import the modules for the Python code.
  2. Authenticate cluster connection by defining the following parameters.
  3. Get the cluster information.
  4. Find specific elements in a cluster.
  5. Create a protection domain.
  6. Find unprotected VMs.
  7. Add the unprotected VMs to a cluster.
  8. Add a specific VM to a protection domain.

CBT API Tutorial (v3)


This document is primarily intended for backup software providers to support backup and restore for virtual machines in a Nutanix cluster.

This document outlines functional workflows for using the V2 CBT APIs provided by Nutanix for backing up VMs on Nutanix clusters. These APIs enable backup software providers perform the following on a Nutanix cluster:

Nutanix and Backup Software Overview

Following is the basic backup and recovery workflow for backup software to integrate with Nutanix APIs.

  1. Connect and authenticate with the Nutanix cluster.
  2. Take backups by using the Nutanix VM management, snapshot management, and changed block tracking APIs.
  3. Index and catalog all backups on the backup media.
  4. Restore virtual machines or virtual machine files using various Nutanix APIs.

High-level Procedures

Making a Backup of a VM

  1. Authenticate to the management service running on the cluster.
  2. Get a list of VMs on the Nutanix cluster with the /vms API.
  3. Create either an application-consistent or a crash-consistent snapshot of a virtual machine with the /vm_snapshot API.
  4. Examine the contents of the created snapshot by doing a GET on the snapshot UUID.
  5. For every file included in the snapshot, if a full backup is desired, read the contents of the snapshotted file using NFS.
  6. If incremental or differential backup is desired, use the changed region tracking /data/changed_regions API to query the metadata about the regions that have changed between this snapshot and the reference snapshot. Read only the changed data using NFS.
  7. Maintain the snapshot taken in step 3.
    • If the snapshot is not needed any more, use the DELETE API to request deletion of the snapshot.
    • If the snapshot must be preserved for use later as a reference for an incremental or differential snapshot, set the snapshot expiry time to the desired value using the PUT API on the snapshot.

Restoring a VM from Backup

  1. Mount the storage container through NFS.
  2. Retrieve the backed up data into the storage container on the cluster.
    • If the snapshot is not present in the storage container, copy the entire entity from the backup device into the storage container.
    • If the snapshot is present in the storage container, clone the snapshot and apply diffs. This approach approach is faster and more efficient.
  3. Recreate the VM by using the create VM API with the configuration captured during backup.

Accessing a Storage Container through NFS

When restoring a file from backup, it is necessary to access a Nutanix storage container using NFS. Since a storage container is not a general-purpose NFS file share, specific steps are required to allow a computer to access it as an NFS client.

To whitelist a computer to access all storage containers on the Nutanix cluster:

PUT /cluster

To whitelist a computer to access a single storage container on the Nutanix cluster:

PUT /storge_containers/{uuid}

After the whitelisting, mount the storage container on the whitelisted computer:

$ sudo mount -t nfs external_ip_addr:/storage_container_name mount_dir

Backup and Restore APIs

The following APIs are needed to create and restore backups. See the V2 API reference for complete specifications of these APIs.

Snapshot ID Allocation

Description REST Endpoint HTTP Verb
Creates snapshot ID(s) for future snapshot requests. /idempotence_identifiers POST

Snapshot Creation

Description REST Endpoint HTTP Verb
Creates a snapshot containing the given VM with the snapshot ID obtained earlier. /vm_snapshot POST

Snapshot Retrieval

Description REST Endpoint HTTP Verb Notes
Fetches details of a snapshot and should be used to check the progress of a snapshot creation request. If the snapshot creation is successful, status/state moves to kComplete. If the snapshot creation is not successful, the status/state is set to kError. /vm_snapshots/{uuid} GET status in the response contains info of the created snapshot. It is the client’s responsibility to check the type of the snapshot created by inspecting status/snapshot_type. Only a crash-consistent snapshot may have been created when an application-consistent snapshot was requested. Today, the API doesn’t specify the reason why the application-consistent snapshot request failed. In case of an unrecoverable error, the status/state field will be set to kError and error detail will be set in status/message field.

Snapshot Deletion

Description REST Endpoint HTTP Verb
Deletes a snapshot. /vm_snapshots/{uuid} DELETE

Snapshot Listing

Description REST Endpoint HTTP Verb
Lists snapshots with basic filtering support. /vm_snapshots/list POST

Changed Regions Tracking

Description REST Endpoint HTTP Verb
Returns the metadata about the regions that have changed between any two snapshots of a file. It can be used for both incremental and differential backups. It is beneficial to use this API even for a full backup because it indicates the regions that are zeroes and hence helps avoid reading zeroes. /data/changed_regions POST

Networking Tutorial (v3)

Network Events Webhook Tutorial (v3)


This document demonstrates the approach to be followed in implementing webhooks. Webhooks subscribe to significant events in the lifecycle of a guest VM or service chain and then execute a networking configuration task on a third-party network product.

The use case covered in this tutorial is as follows: when a new web server virtual machine is powered on, add it to the load balancing pool on a virtual F5 load balancer appliance.


Below is a high-level representation of the basic steps for implementing a webhook.

  1. (Nutanix cluster) Get the list of all networking event notifications that you are interested for a particular entity.
  2. (Nutanix cluster) Register the webhook URL of the callback server to subscribe it to specific events for an entity.
  3. (Client) Parse, interpret, and transform the webhook metadata when the specified event occurs.
  4. (Client) Make a REST API or CLI end point call of the 3rd-party product using input from the webhook metadata sent to the client.

F5 Example

Choose event notifications (Nutanix cluster)

Each entity has a list of events for which it generates the notifications. The events POST API consolidates the events per kind plugin and generates the list.

POST https://<cluster_ip_addr>:9440/api/nutanix/v3/webhooks/events/list

For example, the vm kind generates these events:

    "target_kind": "vm",
    "events_list": [

Register URL of callback server (Nutanix cluster)

Obtain the webhook URL of the callback server and register it to subscribe it to specific networking events for an entity.

POST https://<cluster_ip_addr>:9440/api/nutanix/v3/webhooks

For example, to call the F5 whenever a VM is turned on or off:

{"spec": {
    "name": "string",
    "resources": {
        "url": "https://<f5_ip_addr>/mgmt/tm/ltm/pool/~Common~<pool_name>/members",
        "target_kind": "string",
        "events_list": [
    "description": "string"

Transform webhook metadata (Client)

When a specified event occurs, the client must parse, interpret, and transform the webhook metadata.

For example, the webhook metadata for vm_on has this structure:

{"event": {
    "event_type": "vm_on",
    "op_type": "user|system",
    "vm_name": "string",
    "vm_uuid": "string",
    "vm_ip_list": ["string"],
    "vm_mac_list": ["string"],
    "host_name": "string",
    "host_uuid": "string",
    "host_ip": "string",
    "category": ["string"],
    "label": ["string"]

Call endpoint (Client)

Based on the webhook metadata, make a REST API or CLI end point call to the 3rd-party product.


This JSON provides the parameters for creating a load balancing pool.

    "name": " <pool_member>:<service_port>",
    "address": " <ipaddress_pool_node>"

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import cgi
import json
import pprint
import requests
from SocketServer import ThreadingMixIn
import threading

F5_VM = <F5 ip>
F5_POOLTYPE = "~Common~"
F5_POOL = "%s%s" % (F5_POOLTYPE, <F5 pool>)
F5_USERNAME = <F5 username>
F5_PASSWORD = <F5 password>

class Handler(BaseHTTPRequestHandler):
    def _unplug_vnic_f5(self, vnic_ip):
        url = "https://%s/mgmt/tm/ltm/pool/%s/members/%s%s" % (
            F5_VM, F5_POOL, F5_POOLTYPE, self._get_f5_member_name(vnic_ip))
        auth = (F5_USERNAME, F5_PASSWORD)
        requests.delete(url, auth=auth, verify=False)

    def _plug_vnic_f5(self, vnic_ip):
        url = "https://%s/mgmt/tm/ltm/pool/%s/members" % (F5_VM, F5_POOL)
        data = json.dumps(
            {"name": self._get_f5_member_name(vnic_ip), "address": vnic_ip})
        auth = (F5_USERNAME, F5_PASSWORD)
        response =, auth=auth, verify=False, data=data)
        if response.status_code not in [200, 409]:
            raise Exception(
                "Cannot configure F5 Address pool: %s" % response.text)

    def _handle_vm_on(self, vnic_ip):
        print("VM_ON: %s" % vnic_ip)

    def _handle_vm_off(self, vnic_ip):
        print("VM_OFF: %s" % vnic_ip)

    def _handle_post(self, data):
        event_type = data.get("event_type")
        event_data = data.get("data", {}).get("metadata", {})
        ip_list = event_data.get("vm_ip_list", [])

        if event_type == "VM_ON":
            for ip in ip_list:
        elif event_type == "VM_OFF":
            for ip in ip_list:

    def do_POST(self):
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
        if ctype == "application/json":
            length = int(self.headers.getheader('content-length'))
            data =

        message =  threading.currentThread().getName()

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""
if __name__ == '__main__':
    server = ThreadedHTTPServer(('’, 8080), Handler)
    print 'Starting server, use <Ctrl-C> to stop'

This sample client-side Python code will parse, interpret, and transform webhooks notification metadata on a vm_on or vm_off event and then make a REST API call to F5 load balancer virtual appliance for network configuration. The network configuration will involve adding the webserver VM to the loadbalancer pool.