10 minute read

When moving from NSX-V to NSX-T there is the option of using the NSX-T Migration Coordinator, however sometimes our NSX-V configuration cannot fit the ones supported by the migration coordinator. With this in mind there are a couple of options to migrate/copy our customized NSX-V objects to NSX-T:

In my case, since I had a decent amount of objects to copy and 1st and 2nd option were not an option, I end up scripting the process using Powershell/PowerCLI.

This particular post will focus in copy/migrate all our NSX-V IPSets objects, and more specific in the interaction with the NSX-T API side, since for NSX-V we will leverage PowerNSX Powershell module.

In this post we are assuming Greenfield from NSX-T point of view, hence there is no validation if we are overwriting any potential existing groups.

Retrieving NSX-V IPSets

We need to get the NSX-V IPSets from our NSX-V environment.

As we mentioned we will leverage PowerNSX module to interact with our NSX-V Manager.

Get-NSXIpSet

Get-NSXIpSet

At this point we can export the result to a csv file or just use the result to proceed with the creation of the NSX-T Groups.

Running some GET calls using Postman REST Client to check the NSX-T Group object

The easy way to check the structure would be to create a couple of NSX-T Groups with the content that we would have.

On this post we are only focused in the NSX-T Groups that contain IP, IP Ranges and IP Networks, since our focus is to copy/migrate our NSX-V IPSets to NSX-T Groups.

We can use Powershell to query NSX-T API, but to check the object we will just use Postman REST Client.

Some NSX-T Groups examples created:

NSXT-IPGROUP-01  
NSXT-IPGROUP-01 - NSX-T NSXT-IPGROUP-01 - JSON
NSXT-IPGROUP-02  
NSXT-IPGROUP-02 - NSX-T NSXT-IPGROUP-02 - JSON
NSXT-IPGROUP-03  
NSXT-IPGROUP-03 - NSX-T NSXT-IPGROUP-03 - JSON
NSXT-IPGROUP-04  
NSXT-IPGROUP-04 - NSX-T NSXT-IPGROUP-04 - JSON

From the JSON output it seems that for our object the important fields would be:

  • expression - will have our object content
  • display_name - how it will appear in UI
  • id - our object id to use for our API calls
NSXT-IPGROUP-03 NSXT-IPGROUP-04
NSXT-IPGROUP-03 - Relevant Fields NSXT-IPGROUP-04 - Relevant Fields

Building our foundation for our script

How can we get the list of all existing NSX-T Groups

To retrieve all the configured groups we will use the following API Call as mentioned previously:

GET https://<nsx-t manager>/policy/api/v1/infra/domains/default/groups/

$urlGetGroups = "https://$nsxtManager/policy/api/v1/infra/domains/default/groups/"

$nsxtGroups = Invoke-RestMethod -Uri $urlGetGroups `
  -Authentication Basic -Credential $nsxtManagerCredentials `
  -Method Get -ContentType "application/json" `
  -SkipCertificateCheck

This will give us the list of all the existing NSX-T Groups:

$nsxtGroups.results.display_name

  NSXT-IPGROUP-01
  NSXT-IPGROUP-02
  NSXT-IPGROUP-03
  NSXT-IPGROUP-04

How can we get a specific NSX-T Group using the Group Name

As we show before there are two (2) ids for the same object in NSX-T:

  • display name - Name that shows up in the NSX-T Manager UI, this ID do not need to be unique, hence you can have two (2) objects with the same name
  • id - unique object ID, hence the preferred ID to use in API calls

A quick example:

NSX-T Manager UI ID NSX-T Object ID
NSX-T Manager Duplicate ID NSX-T API Unique ID

Quick tip: if you need to get the API url for the object you can get it from NSX-T Manager UI by right clicking in the Group Object elipses: Getting API Object URL

Let us check the result:

GET https://<nsx-t manager>/policy/api/v1/infra/domains/default/groups/<GroupObject ID>

$groupObjectID = "NSXT-IPGROUP-04"
$urlGetGroup = "https://$nsxtManager/policy/api/v1/infra/domains/default/groups/$groupObjectID"

$nsxtGroup = Invoke-RestMethod -Uri $urlGetGroup `
  -Authentication Basic -Credential $nsxtManagerCredentials `
  -Method Get -ContentType "application/json" `
  -SkipCertificateCheck

Let us check our NSX-T Group details:

> $nsxtGroup

  expression          : {@{ip_addresses=System.Object[]; resource_type=IPAddressExpression; marked_for_delete=False; _protection=NOT_PROTECTED}}
  resource_type       : Group
  id                  : NSXT-IPGROUP-04
  display_name        : NSXT-IPGROUP-04
  path                : /infra/domains/default/groups/NSXT-IPGROUP-04
  relative_path       : NSXT-IPGROUP-04
  parent_path         : /infra/domains/default
  marked_for_delete   : False
  _create_user        : admin
  _create_time        : 1601038849793
  _last_modified_user : admin
  _last_modified_time : 1601038849793
  _system_owned       : False
  _protection         : NOT_PROTECTED
  _revision           : 0

> $nsxtGroup.expression

  ip_addresses                                                     resource_type       marked_for_delete _protection
  ------------                                                     -------------       ----------------- -----------
  {100.100.104.1, 100.100.104.0/24, 100.100.104.10-100.100.104.15} IPAddressExpression             False NOT_PROTECTED

How to check if the NSX-T Group that we want to create already exists to avoid duplicates

At this point we have two (2) alternatives:

  • We create our new NSX-T Groups without checking, either because we know that they do not exist or just because we do not mind to have duplicates
  • We create. update or replace the NSX-T Groups depending on their existence or not in the target environment

We will follow the second approach, since we want to keep our environment tidy and because it will add an extra challenge.

Since the Object IDs will be different for sure, since we are copying our NSX-V IPSets, we will need to use the IPSet Object Name as our common ID between our two (2) environments.

Hence, our search in the current NSX-T Groups list will be done using the display_name instead of its unique id and once we get our NSX-T Group we can get our unique id to use in our API calls:

> $nsxtGroup = $nsxtGroups.results | Where-Object { $_.display_name -eq "NSXT-IPGROUP-04" }

  expression          : {@{ip_addresses=System.Object[]; resource_type=IPAddressExpression; marked_for_delete=False; _protection=NOT_PROTECTED}}
  resource_type       : Group
  id                  : NSXT-IPGROUP-04
  display_name        : NSXT-IPGROUP-04
  path                : /infra/domains/default/groups/NSXT-IPGROUP-04
  relative_path       : NSXT-IPGROUP-04
  parent_path         : /infra/domains/default
  marked_for_delete   : False
  _create_user        : admin
  _create_time        : 1601038849793
  _last_modified_user : admin
  _last_modified_time : 1601038849793
  _system_owned       : False
  _protection         : NOT_PROTECTED
  _revision           : 0

> $nsxtGroup.id

  NSXT-IPGROUP-04

How to create a new NSX-T Group

When we use the NSX-T Policy API we can either use PUT or PATCH depending if you are creating an object or updating an existing object.

PUT /policy/api/v1/infra/domains/<domain-id>/groups/<group-id>

PATCH /policy/api/v1/infra/domains/<domain-id>/groups/<group-id>

A quick reference to a VMware blog post with a nice table explaining the available HTTP “Verbs”/Methods in )NSX-T Policy API: HTTP Verbs from How to Navigate NSX-T Policy APIs for Network Automation

When updating an existing object PUT and PATCH have a small difference related to concurrency control that is described in a bit more detail in NSX-T API Guide in Optimistic Concurrency Control and the _revision property.

We will use PATCH, since it will work to create and update our objects and would make it easier to script the process.

It is time to test the creation of a new NSX-T Group.

Creating a new NSX-T Group

From the API Guide and from the examples that we got above we know that our JSON payload would be something similar to:

{
  "expression": [
    {
      "ip_addresses": "<IPs>",
      "resource_type": "IPAddressExpression"
    }
  ],
  "display_name": "<nsxtGroupDisplayName>",
  "description": "<nsxtGroupDescription>"
}
$groupObjectID = "NSXT-newGroup"
$groupObjectDisplayName = "NSXT-newGroup01"
$groupObjectDescription = "New NSX-T Group Created using API"

#  The function ConvertTo-JSON flattens out any array with
# single element which breaks the expected format, since
# NSX-T removes duplicates we can duplicate our single object
$groupObjectIPS = @()
$groupObjectIPs += "10.10.10.10"
$groupObjectIPs += "10.10.10.10"

$urlPatchGroup = "https://$nsxtManager/policy/api/v1/infra/domains/default/groups/$groupObjectID"

$newGroupObjectJSON = @{
  "expression" = @(
    @{
      "ip_addresses" = $groupObjectIPs;
      "resource_type" = "IPAddressExpression"
    }
  );
  "display_name" = $groupObjectDisplayName;
  "description" = $groupObjectDescription
}

$jsonPayload = ConvertTo-Json -InputObject $newGroupObjectJSON -depth 10 -compress

$httpResponse = Invoke-RestMethod -Uri $urlPatchGroup `
  -Authentication Basic -Credential $nsxtManagerCredentials `
  -Method Patch -ContentType "application/json" `
  -Body $jsonPayload `
  -SkipCertificateCheck

Now putting all together and create a quick Powershell snippet to copy our NSX-V IPSets

We will use PowerNSX Powershell module cmdlet Get-NSXIPSet, instead of developing something on purpose for it.

> Get-NsxIPset | Select Name

  name
  ----
  NSXV-IPSet01
  NSXV-IPSet02
  NSXV-IPSet03
  NSXV-IPSet04
  NSXV-IPSet05

To create our NSX-T Groups we will need the following properties from our NSX-V IPSets:

  • name - We will use this property as our display_name and as our ID for object creation
  • description - Will keep the same description
  • value - Our IPSet values
> Get-NsxIPset | Select name, description, value

  name         description              value
  ----         -----------              -----
  NSXV-IPSet01 NSXV-IPSet01 description 100.100.104.1
  NSXV-IPSet02                          100.100.100.3,100.100.100.2
  NSXV-IPSet03                          100.100.200.1-100.100.200.10
  NSXV-IPSet04                          100.100.150.0/24
  NSXV-IPSet05 NSXV-IPSet05 description 100.100.160.1-100.100.160.10,100.100.150.1,100.100.165.10/24

Let us create a quick loop to go through our NSX-V IPSets and create the equivalent NSX-T Groups

$nsxtManager = "nsxt manager fqdn"
$nsxtManagerCredentials = Get-Credential

$nsxvIPSets = Get-NSXIPSet
$totalNumberIPSets = $nsxvIPSets.Count
$counter = 1

foreach ($nsxvIPSetItem in $nsxvIPSets) {
  Write-Host "-> ($counter/$totalNumberIPSets) Copy NSX-V IPSet" -Foreground Blue
  Write-Host "--> Name - $($nsxvIPSetItem.name)`t`t- Description: $($nsxvIPSetItem.description)" -Foreground Yellow
  Write-Host "--> Value: $($nsxvIPSetItem.Value)" -Foreground Yellow

  #  The function ConvertTo-JSON flattens out any array with
  # single element which breaks the expected format, since
  # NSX-T removes duplicates we can duplicate our single object
  $groupIPs = @()
  $nsxvIPSetIPs = ($nsxvIPSetItem.Value).Split(",")
  if ($nsxvIPSetIPs.Count -eq 1) {
    $groupIPs += $nsxvIPSetIPs
    $groupIPs += $nsxvIPSetIPs
  } else {
    $groupIPs = $nsxvIPSetIPs
  }
  
  $urlPatchGroup = "https://$nsxtManager/policy/api/v1/infra/domains/default/groups/$(($nsxvIPSetItem.name).Replace(" ","_"))"

  $newGroup = @{
    "expression" = @(
      @{
        "ip_addresses" = $groupIPs;
        "resource_type" = "IPAddressExpression"
      }
    );
    "display_name" = $nsxvIPSetItem.name;
    "description" = $nsxvIPSetItem.description
  }

  $jsonPayload = ConvertTo-Json -InputObject $newGroup -depth 10 -compress

  $httpResponse = Invoke-RestMethod -Uri $urlPatchGroup `
    -Authentication Basic -Credential $nsxtManagerCredentials `
    -Method Patch -ContentType "application/json" `
    -Body $jsonPayload `
    -SkipCertificateCheck

  $counter++
}

Testing our code

We are not covering the NSX-V Server connection in the post, so we assume that it is established and ready to go, will add to post a tidier and clean script later

Running it

Snippet run

And the result from NSX-V and NSX-T Manager

Our NSX-V IPSets Our brand new NSX-T Groups
NSX-V IPsets New NSX-T Groups

Detail of some of them

NSX-V IPSets Details NSX-T New Groups Details
NSX-V IPSet01 Source New NSX-T Groups NSXV-IPSET01
NSX-V IPSet05 Source New NSX-T Groups NSXV-IPSET01

Considerations:

  • Since we are using PATCH method, groups will be either created if brand new unique id is used, or will be upgraded with the new values in case of an existing unique id.
  • A more developed script will be added to the post at a later stage.