Question

API - Modify subnet and Mac Address of VM

  • 8 June 2022
  • 7 replies
  • 552 views

Badge

Hi,

I want from PRISM API to modify the subnet and Mac Address of a VM.

Is it possible to do that by PRISM API ?

I tried something like this by this URL [https://PRISM_URL:9440/api/nutanix/v3/vms/c7956715-db3d-48ef-b9df-f2ffcd433a1c]

{
"spec":{
"name":"T0-SRV1"
},
"resources":{
"nic_list":[
{
"uuid":"d7684227-25a9-485b-a064-1789276617c3",
"mac_address":"50:6b:8d:ab:0e:dd",
"subnet_reference":{
"kind":"subnet",
"name":"TEST0-SUB",
"uuid":"c8c4ee2b-a39f-466b-9cc4-2ccce4ebea79"
}
}
]
},
"metadata":{
}
}

But i get this message :

{
"api_version": "3.1",
"code": 422,
"message_list": [
{
"details": {
"": [
"Additional properties are not allowed (u'resources' was unexpected)"
],
"metadata": [
"'kind' is a required property"
],
"spec": [
"'resources' is a required property"
]
},
"message": "Request could not be processed.",
"reason": "INVALID_REQUEST"
}
],
"state": "ERROR"
}

 

Thanks for your help,

 

Matt


7 replies

Badge

Hi,

 

With Nutanix Dev API reference i found the required parameter in JSON data.

 

Now my json data is :

{
"metadata":{
"kind":"vm"
},
"spec":{
"name":"T0-SRV1",
"resources":{
"power_state":"OFF",
"hardware_clock_timezone": "UTC",
"nic_list":[
{
"uuid":"d7684227-25a9-485b-a064-1789276617c3",
"mac_address":"50:6b:8d:ab:0e:dd",
"subnet_reference":{
"kind":"subnet",
"name":"TEST0-SUB",
"uuid":"c8c4ee2b-a39f-466b-9cc4-2ccce4ebea79"
}
}
]
}
}
}

 

A task was created :

{
"status": {
"state": "PENDING",
"execution_context": {
"task_uuid": "e5cc28b7-a056-4219-9d1d-61fb906d8006"
}
},
"spec": {
"name": "T0-SRV1",
"resources": {
"hardware_clock_timezone": "UTC",
"nic_list": [
{
"subnet_reference": {
"kind": "subnet",
"name": "TEST0-SUB",
"uuid": "c8c4ee2b-a39f-466b-9cc4-2ccce4ebea79"
},
"uuid": "d7684227-25a9-485b-a064-1789276617c3",
"mac_address": "50:6b:8d:ab:0e:dd"
}
],
"power_state": "OFF"
}
},
"api_version": "3.1",
"metadata": {
"use_categories_mapping": false,
"kind": "vm",
"spec_version": 1,
"uuid": "c7956715-db3d-48ef-b9df-f2ffcd433a1c"
}
}

 

But the task ended with failed status :


{
"status": "FAILED",
"last_update_time": "2022-06-08T12:08:49Z",
"error_detail": "INTERNAL_ERROR: Internal Server Error. ",
"logical_timestamp": 1,
"entity_reference_list": [
{
"kind": "vm",
"uuid": "c7956715-db3d-48ef-b9df-f2ffcd433a1c"
}
],
"start_time": "2022-06-08T12:08:49Z",
"creation_time": "2022-06-08T12:08:49Z",
"start_time_usecs": 1654690129734856,
"cluster_reference": {
"kind": "cluster",
"uuid": "22a30cff-e0e2-4623-a480-3858b41a31e5"
},
"subtask_reference_list": [],
"completion_time": "2022-06-08T12:08:49Z",
"creation_time_usecs": 1654690129626334,
"progress_message": "update_vm",
"operation_type": "update_vm_intentful",
"completion_time_usecs": 1654690129734856,
"error_code": "500",
"percentage_complete": 100,
"api_version": "3.1",
"uuid": "e5cc28b7-a056-4219-9d1d-61fb906d8006"
}

 

Do you know what is wrong in my JSON data ?

 

Thanks for your help,

 

Matt

Hello Matt

I didn’t tested your code but i noticed the following:

  • it seems that you don’t have spec_version in metadata. When you edit an entity from Nutanix APIv3, you have to first read the spec_version and add it.
  • Timezone format it’s wrong, see my example below.

The steps to edit a VM are: 

  1. read the entity with API
  2. get the current vm[‘metadata’][‘spec_version’]
  3. compose the edit query containing the spec version you read(sometimes increase by 1 or 2 than what is read) and submit the request to the api.

About increasing the spec_version, I can’t really tell when and why but sometimes I had to read the spec_version, increase it by 2 and then send the edit request. Try first without incrementing the spec_version.

 

An example which worked for me:

# I read spec_version: 2 and i didn’t modified it.

{
  "spec": {
    "name": "test_vm",
    "resources": {
      "power_state": "OFF",
      "hardware_clock_timezone": "Europe/Zurich",
      "num_sockets": 2
    }
  },
  "metadata": {
    "kind": "vm",
    "spec_version": 2
  }
}

 

Another example, more close to your situation on how to add a network adapter to a vm:

curl -X 'PUT' \
'https://<prism_central_url>:9440/api/nutanix/v3/vms/<vm_uuid>' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-Nutanix-Client-Type: ui' \
-d '{
"spec": {
"name": "<vm_name>",
"resources": {
"power_state": "OFF",
"hardware_clock_timezone": "Europe/Zurich",
"nic_list": [
{
"nic_type": "NORMAL_NIC",
"ip_endpoint_list": [
{
"ip_type": "DHCP"
}
],
"subnet_reference": {
"kind": "subnet",
"uuid": "<subnet/vlan_uuid>"
},
"is_connected": true
}
]
}
},
"metadata": {
"kind": "vm",
"spec_version": 1
}
}'

 

Userlevel 4
Badge +5

Spec_version is used to handle concurrency (race condition). Every time you update a resource, the spec_version changes. 

The safest way of updating a resource is to:

  1. Send a GET request to the resource UUID
  2. Remove the entire $.status key
  3. Update the $.spec key with your new values
  4. Send back the entire payload (no need to change the spec in $.metadata)
Userlevel 1
Badge +3

Hi @JoseNutanix , thanks for these details !

Just a quick question, i’m actually able to retrieve/select spec,api_version and metadata from the GET request (that i’ll use in another request in payload)

 

Do you know how it’s possible to “update” some property of the payload, i.e how do you add/remove a category property ? As retrieved data type is PSCustomObject, i don’t know if there any EASY method to work with payload data in powershell

 

Thanks :)

Userlevel 4
Badge +5

@gael01,

In this scenario, categories are part of the metadata. You’ll have to update this by adding/removing categories from the list/array. Look for $.metadata.categories_mapping and $.metadata.categories.

I’m not familiar with PoSH, you’ll have to make sure to get access to those JSON paths and update them accordingly. 

Here an example of the payload you’ll find (depending if categories exist or not)

 

"metadata": {

[...]

"categories_mapping": {
"OSType": [
"Linux"
],
"CalmService": [
"BasicLinux"
],
"CalmUsername": [
"admin"
],
"CalmApplication": [
"API Test 01"
]
},
"entity_version": "27",
"owner_reference": {
"kind": "user",
"name": "admin",
"uuid": "f0b701e7-163d-5358-abbc-2edb73b1a38c"
},
"categories": {
"OSType": "Linux",
"CalmService": "BasicLinux",
"CalmUsername": "admin",
"CalmApplication": "API Test 01"
}
}
Userlevel 1
Badge +3

Hey ! meanwhile i figured out on the same statement, and according to Nutanix official support all metadata + spec + api_version block should be send back in the PUT request.

It’s working when adding categories when categories were null, but it’s kind of complicated when it’s about to keep existing categories, + add a new one (currently working on that )

Userlevel 1
Badge +3

Hi ! finally found a solution to do what I need in Powershell

All explanation was made in my ServerFault post (question + solution) below :

https://serverfault.com/questions/1135179/update-json-payload-using-powershell-and-nutanix-api/1135270#1135270

Reply