Azure VMware Solutions REST API - part 2: az rest


After a discovery of Azure VMware Solution REST API through the Postman collection in part 1, we will use some of the fundamentals API calls through az rest, a useful subset of the Azure Command-Line Interface.

Compared to Postman, I consider az rest an easier way to discover Azure REST API in a blog post as it doesn't require to post screenshots or long code samples to narrate the exploration. But of course, you could use the AVS Postman collection to achieve the same purpose or any other REST client tool (httpie, curl etc.): this is the great power of REST APIs.


A big benefit of using az rest to manage an Azure product, like Azure VMware Solution, through its REST API is that the tool already manages the authentication or provide a simple way to connect to your tenant and to execute request without manually providing authentication tokens.


If you have not already logged-in to your tenant, you can follow the next steps:

1az login
3# Or, if you manage multiple tenants, you can add the --tenant parameter to login to it:
4az login --tenant

By default, this command will open a web browser asking you to connect to your azure tenant. Once logged-in your browser, you can close the tab and the CLI will successfully be connected.

If your terminal session cannot connect to a web browser (if you use a remote session like SSH for example), you can use:

1az login --use-device-code
2# To sign in, use a web browser to open the page and enter the code ********** to authenticate.

After opening the provided link and used the token, your CLI should be connected.

You can check your connection information with:

1az account show --output table
3EnvironmentName    HomeTenantId                          IsDefault    Name                          State    TenantId
4-----------------  ------------------------------------  -----------  ----------------------------  -------  ------------------------------------
5AzureCloud         ********-****-****-****-************  True         Azure VMware Solutions Tests  Enabled  ********-****-****-****-************


If you use multiple subscriptions (it is recommended!), you can select to one hosting your AVS:

1# List available subscriptions
2az account subscription list --output table
4# Select one subscription
5az account set --subscription ********-****-****-****-************


To achieve quick and successfully REST requests on a specific resource, it could be useful to get its base URI and to store it in an environment variable.

For an AVS resource, this base URI is built like:${SUBSCRIPTION_ID}/resourceGroups/${RESOURCEGROUP_NAME}/providers/Microsoft.AVS/privateClouds/${SDDC_NAME}

With the following components:

  • The Azure REST API domain endpoint
  • /subscriptions/${SUBSCRIPTION_ID}
  • resourceGroups/${RESOURCEGROUP_NAME}
  • /providers/Microsoft.AVS: A pointer to the AVS resources provider
  • /privateClouds/${SDDC_NAME}

With the following commands, you can easily populate an AVS base URI:

1export SUBSCRIPTION_ID="********-****-****-****-************"
2export RESOURCEGROUP_NAME="resourceGroupName"
3export SDDC_NAME="AVS-Tests"
4export SDDC_BASE_URI="${SUBSCRIPTION_ID}/resourceGroups/${RESOURCEGROUP_NAME}/providers/Microsoft.AVS/privateClouds/${SDDC_NAME}"

API version

When using Azure API, you need to specify the API version you want to use. For AVS, I currently use version 2021-12-01 (the last version currently available):

1export API_VERSION="api-version=2021-12-01"

AVS endpoints and credentials management

When you need to connect to an AVS system, you need two mandatory information:

  • The endpoints name
  • The credentials to use

The endpoints can be retrieved from (Doc.):

 1# The global information about the AVS deployment:
 2az rest -m get -u "${SDDC_BASE_URI}?${API_VERSION}"
 4# A filtered result from the previous request:
 5az rest -m get -u "${SDDC_BASE_URI}?${API_VERSION}" | jq ".properties.endpoints"
 7  "hcxCloudManager": "",
 8  "nsxtManager": "",
 9  "vcsa": ""

And credentials (Doc.):

1az rest -m post -u "${SDDC_BASE_URI}/listAdminCredentials?${API_VERSION}"
3  "nsxtPassword": "***************",
4  "nsxtUsername": "admin",
5  "vcenterPassword": "***************",
6  "vcenterUsername": "cloudadmin@vsphere.local"

Please note that you must use the post HTTP method to get credentials.

With this information, you can now connect to your AVS instance.

AVS network management

Some parts of an AVS workload management can be made through the Azure API and portal (in replacement or addition to the VMware products API or UI).

NSX-T Tier1 gateway

When dealing with NSX-T based networks, the Tier1 gateway (T1 GW) is an important element to consider.

In a vast majority of scenarios (including the AVS deployment model), the T1 GW is considered the first router component, accessible from a workload to communicate with network items out of its subnet.

By default, a first T1 GW is deployed with AVS and you can retrieve details about it by using (Doc.):

1az rest -m get -u "${SDDC_BASE_URI}/workloadNetworks/default/gateways?${API_VERSION}"

Note: Only a get method is available as you cannot Create, Update or Delete T1 gateways through the Azure API/UI: actions on T1 GW are only available from NSX-T itself (including creating new GWs).

DHCP service

It is possible to rely on the T1 GW to provide DHCP leases within network segment. The DHCP service can run as a server or a relay from another server.

The simpliest role to configure is the server one:

 1# Prepare data for the request
 3body=$(cat <<EOF
 5  "properties": {
 6    "displayName": "${DHCPServer}",
 7    "revision": 0,
 8    "dhcpType": "SERVER",
 9    "serverAddress": "",
10    "leaseTime":null
11  }
16# Create the DHCP service
17az rest -m put -u "${SDDC_BASE_URI}/workloadNetworks/default/dhcpConfigurations/${DHCPServer}?${API_VERSION}" --body "${body}"

NSX-T Segments

For example, you can Create, Read, Update or Delete (C.R.U.D.) NSX-T segments with the Azure API:

 1# Prepare data for the request
 2segment_name="VM-tests-109" # Name of segment to create
 3t1_gw_name="TNTXX-T1" # T1 GW name
 4body=$(cat <<EOF
 6  "properties": {
 7    "displayName": "${segment_name}",
 8    "connectedGateway": "${t1_gw_name}",
 9    "subnet": {
10      "dhcpRanges": [
11        ""
12      ],
13      "gatewayAddress": ""
14    },
15    "revision": 0
16  }
21# Create segment
22az rest -m put -u "${SDDC_BASE_URI}/workloadNetworks/default/segments/${segment_name}?${API_VERSION}" --body "${body}"
24# Get the new segment
25az rest -m get -u "${SDDC_BASE_URI}/workloadNetworks/default/segments/${segment_name}?${API_VERSION}"
27# Output
29  "id": "/subscriptions/********-****-****-****-************/resourceGroups/resourceGroupName/providers/Microsoft.AVS/privateClouds/AVS-Tests/workloadNetworks/default/segments/VM-tests-109",
30  "name": "VM-tests-109",
31  "properties": {
32    "connectedGateway": "TNTXX-T1",
33    "displayName": "VM-tests-109",
34    "provisioningState": "Fulfilled",
35    "revision": 0,
36    "status": "IN_PROGRESS",
37    "subnet": {
38      "dhcpRanges": [
39        ""
40      ],
41      "gatewayAddress": ""
42    }
43  },
44  "resourceGroup": "resourceGroupName",
45  "type": "Microsoft.AVS/privateClouds/workloadNetworks/segments"

AVS interconnectivity management

When your AVS instance is deployed, you will certainly need to connect it with external components like other Azure Resources, jump servers, on-premises resources etc.

I will not cover all the available AVS interconnectivity solutions in this post but here is a list of supported ones:

In this post, we will see how-to setup an ExpressRoute circuit.


The first information to collect is the ExpressRoute ID or Circuit ID:

1az rest -m get -u "${SDDC_BASE_URI}?${API_VERSION}" | jq ".properties.circuit"
3# Output
5  "expressRouteID": "/subscriptions/********-****-****-****-************/resourceGroups/resourceGroupName/providers/Microsoft.Network/expressRouteCircuits/tntxx-cust-p02-westeurope-er",
6  "expressRoutePrivatePeeringID": "/subscriptions/********-****-****-****-************/resourceGroups/resourceGroupName/providers/Microsoft.Network/expressRouteCircuits/tntxx-cust-p02-westeurope-er/peerings/AzurePrivatePeering",
7  "primarySubnet": "",
8  "secondarySubnet": ""

We keep only the expressRouteID information to create a new ExpressRoute authorization key:

 1connection_name="expressroute-test" # name the future authorization key
 2sddc_er_id=$(az rest -m get -u "${SDDC_BASE_URI}?${API_VERSION}" | jq ".properties.circuit.expressRouteID") # store the expressRouteID
 3body=$(cat <<EOF
 5  "properties": {
 6    "expressRouteId": ${sddc_er_id}
 7  }
12az rest -m put -u "${SDDC_BASE_URI}/authorizations/${connection_name}?${API_VERSION}" --body "${body}"
14# Output
16  "id": "/subscriptions/********-****-****-****-************/resourceGroups/resourceGroupName/providers/Microsoft.AVS/privateClouds/AVS-CSU-FR-LRI/authorizations/expressroute-test",
17  "name": "expressroute-test",
18  "properties": {
19    "expressRouteAuthorizationId": "/subscriptions/********-****-****-****-************/resourceGroups/tntxx-cust-p02-westeurope/providers/Microsoft.Network/expressRouteCircuits/tntxx-cust-p02-westeurope-er/authorizations/avs_resource_expressroute-test",
20    "expressRouteAuthorizationKey": "d502f9cb-91a2-4069-a474-7363e723bccc",
21    "expressRouteId": "/subscriptions/********-****-****-****-************/resourceGroups/tntxx-cust-p02-westeurope/providers/Microsoft.Network/expressRouteCircuits/tntxx-cust-p02-westeurope-er",
22    "provisioningState": "Succeeded"
23  },
24  "resourceGroup": "AVS-CSU-FR-LRI",
25  "type": "Microsoft.AVS/privateClouds/authorizations"

AVS ExpressRoute authorization from the Azure portal

This will provide you with an authorization key: expressRouteAuthorizationKey to be used to create a new connection from an expressRoute compatible component, like a Virtual network gateway:

Create an ExpressRoute connection to your AVS


As you may understand from the AVS API reference or the AVS Postman collection, this post is not a complete coverage of the AVS REST API capabilities but an example of what you can do with it and the az rest CLI tool.

To simplify the above commands, I did not mention any header like Accept or Content-Type as we used the default type of data when dealing with requests and answers: application/json.

Using API with az rest is a very easy way to manage automation of an AVS deployed instance with an imperative approach. A declarative approach may be preferred to managed large AVS workloads with production and self-remediation requirements and I will try to cover it in a future (not-yet-planned) post.


Title photo by Joshua Reddekopp on Unsplash