Using ETag and If-Match Headers with Nutanix v4 APIs

Nutanix.dev - Using eTag and If-Match Headers with Nutanix v4 APIs

Table of Contents

In our most recent article we covered Using Request ID Headers with Nutanix v4 APIs. This article is the second part in a mini series covering how the Nutanix v4 APIs implement better, standards-based approaches, particularly with regards to how users consume those APIs. Request IDs are generally accepted as standard practice when sending API requests; ETag and If-Match headers fall under the same category of standard practices.

How did this work in API v3?

When updating a resource using the Nutanix Prism Central v3 APIs, responses could fail with an error indicating a version mismatch. This situation could arise from a resource being read by the API consumer and, before the resource could be updated, that resource would change. The result is a mismatched specification that would prevent an API consumer from successfully completing a resource update request.

The Nutanix Prism Central v3 APIs did not implement ETag-based version matching and could not use them as a way of guaranteeing spec mismatches would never occur. That all changes in Nutanix Prism Central API v4.

Nutanix Prism Central API v4: ETag Implementation

The Mozilla developer network docs describe ETag as follows:

The ETag (or entity tag) HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed. Additionally, etags help to prevent simultaneous updates of a resource from overwriting each other (“mid-air collisions”).

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag

With a greater focus on standards-based implementations like ETag, previous issues with potential spec mismatches and mid-air collisions can be completely avoided.

Prepare Test Image

Note: This section can be skipped if you would like to update an existing image in your environment. In an upcoming step we will use the v4 APIs to obtain an image ext_id.

In today’s example, we’ll look at creating then updating a Prism Central image. Prism Central images are often used as base disks for virtual machines and can contain pre-configured operating sytem configurations, software packages (etc).

To create an image that can be used for testing, use Postman or your preferred API prototyping/test software to submit a request with the following settings.

Note: In all examples throughout this article, {{pc_ip}} refers to the IP address or FQDN of your Prism Central instance.

  • URL: https://{{pc_ip}}:9440/api/vmm/v4.0.a1/images
  • Method: POST
  • Headers
    • Content-Type: application/json
    • Ntnx-Request-Id: <UUID generated at https://www.uuidgenerator.net>
  • JSON payload: As shown below

Note: During testing, this request can be sent without the initialClusterLocations object.

{
  "name": "centos7minimal",
  "type": "DISK_IMAGE",
  "description": "CentOS 7 x86_64 Minimal from v4 APIs",
  "source": {
    "url": "{{centos7_url}}",
    "allowInsecure": false,
    "$objectType": "vmm.v4.images.UrlSource"
  },
  "initialClusterLocations": [
    {
      "extId": "{{cluster_uuid}}"
    }
  ]
}

Get Existing Image extId (with OData filters)

To update an image, we first need to obtain an existing image’s extId. This is a unique identifier for the image and will be used to ensure we are updating the correct image. The following settings can be used to list images visible to an existing Nutanix Prism Central instance; note that this request uses v4 API OData filters to find a specific image with a name starting with "centos7". Adjust this filter parameter if you are searching for a different image.

  • URL: https://{{pc_ip}}:9440/api/vmm/v4.0.a1/images?$filter=startswith(name, 'centos7')
  • Method: GET
  • Headers
    • Content-Type: application/json

In this demo’s test environment, this will return details of a single image named "centos7minimal", matching the name of the image created in the previous step. The screenshot below shows the image’s extId as fa90243c-c2bc-45b3-879b-c75f85559e75.

Nutanix Prism Central v4 API response to filter matching images

Get Existing Image Details

Now that we know the relevant image’s extId, we can get that image’s details, again using the v4 APIs. This is a simple request, as follows:

  • URL: https://{{pc_ip}}:9440/api/vmm/v4.0.a1/images/fa90243c-c2bc-45b3-879b-c75f85559e75
  • Method: GET

The response from this request includes a number of critical pieces of information. For this demo, we are specifically interested in the following:

  • The image’s current specification: data object. Within this object, we can see the image’s name is "centos7minimal".
  • The image resource’s “version”, identified in the response headers as "Etag". Below, we can see the ETag is YXBwbGljYXRpb24vanNvbg==:01.
Images API response, showing data.name as "centos7minimal"
Images API response, including Etag header as YXBwbGljYXRpb24vanNvbg==:01

Resource Update Without ETag

Before continuing with a real image update, we’ll take a quick look at what happens when an image update is requested, but without using the Etag header value to specify the resource version.

  • URL: https://{{pc_ip}}:9440/api/vmm/v4.0.a1/images/fa90243c-c2bc-45b3-879b-c75f85559e75
  • Method: PUT
  • Headers
    • Content-Type: application/json
    • Ntnx-Request-Id: <UUID generated from https://www.uuidgenerator.net>
  • JSON payload: As obtained from previous GET request’s data object.

When this request is submitted, the immediate response is HTTP 428 PRECONDITION REQUIRED. This tells us we have not included the resource’s Etag as the value of the If-Match header. This is required to verify the resource’s version.

Omitting the Etag header value when updating a Prism Central image

Resource Update With ETag and If-Match Header

To fix the error in the previous request, it is mandatory to include the Etag value as the If-Match header. In addition, there are two important notes to consider here:

  • Remember to provide a new Ntnx-Request-Id header value each time requests like this are sent
  • The resource’s Etag value will change after every update. If you make a change to any resource, you must get the resource’s new ETag via a new API GET request.

With these changes in mind, our request can be constructed as follows:

  • URL: https://{{pc_ip}}:9440/api/vmm/v4.0.a1/images/fa90243c-c2bc-45b3-879b-c75f85559e75
  • Method: PUT
  • Headers
    • Content-Type: application/json
    • Ntnx-Request-Id: <UUID generated from https://www.uuidgenerator.net>
    • If-Match: <Etag value>
API request updated to include new Ntnx-Request-Id and Etag value as If-Match header

Now, when this request is sent, the response is HTTP 202 ACCEPTED, indicating all prerequisites have been met and the request has been accepted successfully.

Image update request sent and accepted, after correctly specifying If-Match: <Etag value> header

Resource Update With Incorrect ETag

It is possible that a resource update request could be submitted without first obtaining the resource’s current ETag. This would be the case if a previous update request was submitted and accepted, without requesting the resource’s updated ETag. As mentioned previously, resource ETags will change after every update.

Despite the request being properly constructed and containing all the required data, an incorrect ETag will return a response similar to the example below.

Resource update request with incorrect ETag

Wrapping Up

The changes detailed here are conceptually quite simple and bring this part of the Nutanix v4 APIs in-line with accepted API best practices. Combining Ntnx-Request-Id and ETag will help ensure your requests are sent and accepted successfully.

For the first part in this series, remember to check out Using Request ID Headers with Nutanix v4 APIs.

Thanks for reading and have a great day! 🙂

Appendix A: Complete Image Update Payload

For the purposes of this demo, the image’s name has been updated from “centos7minimal” to “centos7minimal_updated”

{
        "sizeBytes": 8589934592,
        "$sourceItemDiscriminator": "vmm.v4.images.UrlSource",
        "source": {
            "url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2003.qcow2",
            "allowInsecure": false,
            "$reserved": {
                "$fqObjectType": "vmm.v4.r0.a1.images.UrlSource"
            },
            "$objectType": "vmm.v4.images.UrlSource"
        },
        "$reserved": {
            "$fqObjectType": "vmm.v4.r0.a1.images.Image"
        },
        "$objectType": "vmm.v4.images.Image",
        "extId": "fa90243c-c2bc-45b3-879b-c75f85559e75",
        "name": "centos7minimal_updated",
        "description": "CentOS 7 x86_64 Minimal from v4 APIs",
        "type": "DISK_IMAGE"
    }

© 2024 Nutanix, Inc. All rights reserved. Nutanix, the Nutanix logo and all Nutanix product, feature and service names mentioned herein are registered trademarks or trademarks of Nutanix, Inc. in the United States and other countries. Other brand names mentioned herein are for identification purposes only and may be the trademarks of their respective holder(s). This post may contain links to external websites that are not part of Nutanix.com. Nutanix does not control these sites and disclaims all responsibility for the content or accuracy of any external site. Our decision to link to an external site should not be considered an endorsement of any content on such a site. Certain information contained in this post may relate to or be based on studies, publications, surveys and other data obtained from third-party sources and our own internal estimates and research. While we believe these third-party studies, publications, surveys and other data are reliable as of the date of this post, they have not independently verified, and we make no representation as to the adequacy, fairness, accuracy, or completeness of any information obtained from third-party sources.