Integrations

NSX Tagging

Applying NSX Tags with Python

2025-09-16

We use tags to generate dynamic groups in NSX and then target these groups in our distributed firewall rules. Tagging was a manual process when we brought NSX into our environment. Sometimes we'd forget about it and spend time troubleshooting connectivity issues before realizing we never tagged the system. We needed a way to apply tags during our provisioning process.

To accomplish this, requesters are prompted to select one or more tags when initiating a new system build. Selected tags are stored as parameters in the JSON data associated with the build, and then passed into a script by Ansible during the build process. The script assumes an nsx.json file is present with the following attributes:

{
    "nsx_host": "nsx.domain.com",
    "nsx_user": "nsxadmin",
    "nsx_pass": "supersecret"
}

The script takes a single tag and vm name. The vm name needs to match the NSX entry exactly.

#!/bin/python3
import requests
import json
import os
import sys
import argparse
from os.path import dirname,abspath
import urllib3

# Disable certificate warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

try:
    config_file_path = os.path.join(dirname(dirname(abspath(__file__))),"nsx.json")
    config = json.load(open(config_file_path))
except Exception as e:
    print(f"Failed to load config file from {config_file_path}.\r\nException: {e}")
    sys.exit(1)


# NSX-T Manager configuration
nsx_manager = f"https://{config['nsx_host']}"
username = config['nsx_user']
password = config['nsx_pass']


# Get the virtual machine ID by name
def get_vm_id_by_name(vm_name):
    vm_url = f"{nsx_manager}/api/v1/fabric/virtual-machines"
    headers = {
        "Accept": "application/json",
    }
    response = requests.get(vm_url, headers=headers, auth=(username,password), verify=False)
    if response.status_code == 200:
        vms = response.json()["results"]
        for vm in vms:
            if vm["display_name"].lower() == vm_name.lower():
                return vm["external_id"]
        raise Exception(f"Virtual machine '{vm_name}' not found.")
    else:
        raise Exception(f"Failed to retrieve virtual machines. Status code: {response.status_code}. Text: {response.text}")


# Function to add tags to a virtual machine
def add_tag_to_vm(vm_name, tag):
    try:
        vm_id = get_vm_id_by_name(vm_name)
    except Exception as e:
        raise e

    vm_url = f"{nsx_manager}/api/v1/fabric/virtual-machines/?action=add_tags"
    headers = {
        "Accept": "application/json",
    }
    body={
        "external_id": vm_id,
        "tags":[tag]
    }
    response = requests.post(vm_url, auth=(username,password), verify=False, headers=headers, json=body)
    if response.status_code == 204:
        return True
    else:
        raise Exception(f"Failed to retrieve virtual machine details. Status code: {response.status_code}. Text: {response.text}")


def main(args):

    # Add tag. On NSX-T 3.2+, the scope cannot be None. It has to be an empty string
    try:
        tag = {
            "scope": "",
            "tag": args.tag
        }
        if add_tag_to_vm(args.vm_name, tag):
            print(f'Added {args.tag} to {args.vm_name}')
            sys.exit(0)
        else:
            sys.exit(1)

    except Exception as e:
        print(f"Failed to add {args.tag} to {args.vm_name}. Exception: {e}")
        sys.exit(1)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Add a tag to a virtual machine in NSX-T")
    parser.add_argument("-v","--vm_name", type=str, help="Name of the virtual machine", required=True)
    parser.add_argument("-t", "--tag", type=str, help="Tag to add to the virtual machine", required=True)
    args = parser.parse_args()
    main(args)

Example

python3 nsx_add_tags.py --vm-name webserver1 --tag http