NSX-T Data Center - Using Powershell/PowerCLI to copy/migrate NSX-V IPSets to NSX-T Groups
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:
- Manually create them in our NSX-T setup
- Use existing 3rd party tools, as an example ReSTNSX - NSX-T Migration Made Easy (MAT)
- Script/develop something to leverage NSX-V and NSX-T APIs
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
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.
-
To get all the existing NSX-T Groups we can use:
GET https://<nsx-t manager>/policy/api/v1/infra/domains/default/groups/
-
Once we know what are our groups we can check their structure:
GET https://<nsx-t manager>/policy/api/v1/infra/domains/default/groups/<group_id>
Some NSX-T Groups examples created:
NSXT-IPGROUP-01 | |
---|---|
NSXT-IPGROUP-02 | |
---|---|
NSXT-IPGROUP-03 | |
---|---|
NSXT-IPGROUP-04 | |
---|---|
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 |
---|---|
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 |
---|---|
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:
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: 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
And the result from NSX-V and NSX-T Manager
Our NSX-V IPSets | Our brand new NSX-T Groups |
---|---|
Detail of some of them
NSX-V IPSets Details | NSX-T New Groups Details |
---|---|
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.