Getting started with automating NSX - PowerShell

Submitted by Robin van Altena on Thu, 06/16/2022 - 13:09
 
 
Follow your favourite author

Leave us your email address and be the first to receive a notification when Robin posts a new blog.

Getting started with automating NSX - PowerShell
Thu 16 Jun, 2022
Where do I start if I want to automate some tasks in NSX? Or what tool can I use best to automate the Distributed Firewall in NSX? These are some of the questions we receive when implementing NSX. It is one of the reasons I presented about this at the 2022 VMUGNL Usercon. This second part of the blog series focuses on automating NSX-T with PowerShell.
Textarea

The reason why I am writing and presenting about this topic, is to show you that starting is not that difficult. And of course, it is fun to automate or build things, especially if the tasks are click intensive or error prone. The first part of this blog series can be found here: Some basic introduction on API calls and Postman

So, before we dive into automating NSX with PowerShell. What do we need to know before we get started? Remember this is the getting started series.

PowerShell

By default, PowerShell is available on almost all windows OS'es, but PowerShell is also available for Linux and macOS. Although there are multiple versions available for download. I try to build my scripts, so they are compatible with version 5.1 because that version is available in most places.

Download PowerShell from Microsoft
Textarea

PowerShell needs modules and functions to be able to automate against NSX. For NSX-V PowerNSX has been created by the community and is the most widely used PowerShell module for automating or scripting against NSX-V. Unfortunately, for NSX-T there is no PowerNSX module available. For NSX-T there are two options. Either use direct API calls (RestMethod) from PowerShell or use the commands VMware has built into PowerCLI. Both options can do the same, but work in a different manner. It is up to you which you prefer.

Rest API method

The Rest API method in PowerShell has many similarities with running API calls in Postman. This is one of the main advantages of this method of working. See part one of this series.

As shown in the first part of this series we can look up the API call for creating a segment in NSX-T. And with the correct body in the API call to NSX-T, we can create a segment.

The way of working in PowerShell is very similar. First, we need to connect to NSX-T and verify (or ignore) the certificates. For this I have borrowed some code from my colleague Robert in his blog about retrieving information from NSX-T load-balancers. I just added some lines to set the NSXmanager, the NSXuser and request the password as secure string.

Code (new)

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

function createSession {
    $script:session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
    $script:headers = @{}

    $script:nsx_uri = "https://" + $nsxManager + "/"
    $uri = $nsx_uri + "api/session/create"

    $private:body = "j_username=$($nsxUsername)&j_password=$($nsxPassword)"

    try {
        $response = invoke-webrequest -contentType "application/x-www-form-urlencoded" -WebSession $session -uri $uri -Method 'POST' -Body $body -usebasicparsing -Erroraction Stop
        $xsrftoken = $response.headers["X-XSRF-TOKEN"]

        $response
        $script:loginSuccess = $true

        $script:headers.Add("X-XSRF-TOKEN", $xsrftoken)
        $script:headers.Add("Accept", "application/json")
        $script:headers.Add('Content-Type','application/json')
    }
    catch {
        Write-Host "Failed" -ForegroundColor Red
        Write-Host "$($_.Exception)" -ForegroundColor Red
        write-host "Error Details:" $_.ErrorDetails.Message -ForegroundColor Magenta
        $script:loginSuccess = $false
    }
}

$nsxManager = "192.168.136.20"
$nsxUsername = "admin"

$password = Read-Host -Prompt "Input the the NSXT $nsxUsername password" -AsSecureString
$nsxPassword =[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))

createSession

Textarea

If you execute this code in PowerShell, after you adjusted the address of the NSX manager, you should see the following output. This output is shown because in the code there is a $response that displays the response from the API call.

Image
Connecting to NSX with PowerShell using API call
Textarea

If you have mistyped the password for example, the code returns the error message. This is because a try-catch function is used if the API call fails, the catch part is triggered. The following code displays the returned error. These error messages can be very helpful in troubleshooting the code.

       write-Host "$($_.Exception)" -ForegroundColor Red
        write-host "Error Details:" $_.ErrorDetails.Message -ForegroundColor Magenta
        $script:loginSuccess = $false

The error looks like this:

Image
Displaying the error on a connection
Textarea

Once the connection has been successfully setup. It is time to create the segment.

We already know the API call for creating or updating the segment, since we already used it in the first part of this series. There we also used this JSON code in the body to create the segment.

Code (new)

  {
    "display_name":  "API-Test",
    "subnets":  [
      {
        "gateway_address":  "40.1.1.1/16"
      }
    ],
    "connectivity_path":  ""
  }

Textarea

The first step now is to create the same JSON code in PowerShell. Again, as always there are various methods, but this is one I can understand.

First, we need to give the segment a name or id $SegmentID = 'Powershell-API-Test'.
Then we can start to declare the body $body = @{}
We can add values to the base of the body with $body.Add("display_name",$SegmentID)
As shown in the JSON above, the value subnets is an array with multiple values. Here we will be working from the inside out.

To start, we create the value for the gateway_address
$GatewayAddr = @{"gateway_address"="30.1.1.1/16"}
Which is the same as:

$GatewayAddr = @{}
$GatewayAddr.add("gateway_address"="30.1.1.1/16")

But since it is only one value, we can make a one-liner out of it.

Next the value needs to be added to an array.
$Arrsubnets = New-Object System.Collections.ArrayList
$Arrsubnets.add($GatewayAddr)

And the array needs to be added to the body as a value for subnets.
$body.Add("subnets",$Arrsubnets)

Once all the information is present the body can be converted to JSON.
$body = $body | ConvertTo-Json -Depth 10
The -Depth parameter specifies how many levels are included in the JSON. This parameter is required because by default it is only 2. Although a warning is displayed if the number of levels is exceeded, it is better to have it present.

Another great troubleshooting feature is to use Out-File ".\body.json" to export the body to a JSON file. This JSON file can then be used to test it in Postman. That way you can validate if the code for creating the JSON is valid and that the JSON works.

All that is left in our code is to define our API call.
$patchSegmentURL = “https://$nsxmanager/policy/api/v1/infra/segments/$SegmentID”

And use a similar try-catch function which will result in the following code:

Code (new)

$SegmentID = 'Powershell-API-Test'
$patchSegmentURL = “https://$nsxmanager/policy/api/v1/infra/segments/$SegmentID”

$body = @{}
$body.Add("display_name",$SegmentID)
$body.Add("connectivity_path","")

$GatewayAddr = @{"gateway_address"="30.1.1.1/16"}

$Arrsubnets = New-Object System.Collections.ArrayList
$Arrsubnets.add($GatewayAddr)

$body.Add("subnets",$Arrsubnets)
$body = $body | ConvertTo-Json -Depth 10 #|Out-File ".\body.json"

try {
    $response = Invoke-restmethod -headers $global:headers -uri $patchSegmentURL -Method 'PATCH' -body $body -Erroraction Stop   
}
catch {
    Write-Host "Failed" -ForegroundColor Red
    Write-Host "$($_.Exception)" -ForegroundColor Red
    write-host "Error Details:" $_.ErrorDetails.Message -ForegroundColor Magenta
    break
}

Textarea

Saving both pieces of code to a file and running it will look like this:

Image
Creating a segment in NSX with PowerShell using an API call
Textarea

And of course, the segment is visible in NSX. I can show you a screenshot, but maybe it is better to try to alter the JSON file and test or play around with it yourself.

PowerCLI

The second option to script or automate against NSX-T is to use PowerCLI. In recent versions of PowerCLI there are a few functions available that can be used to automate against NSX-T.

To connect and disconnect Connect-NsxtServer and Disconnect-NsxtServer can be used. But the function you will use most is Get-NsxtPolicyService. This function functions as a proxy against the NSX-T API service.

The method of connecting to NSX-T is much simpler to setup, but takes a little longer to connect. This is because the PowerCLI function builds a list of services or commands that can be used against the specific installation of NSX-T. Therefore, the time it takes to connect to NSX-T is dependent on the resources available on the NSX-T manager and on the host where the PowerCLI function is started.

To connect to NSX-T simply run Connect-NsxtServer -Server <NSX-T manager> and enter the username and password.

Image
Connecting to NSX-T with PowerCLI
Textarea

Once a connection has been made. We can use Get-NsxtPolicyService to list the various services or commands. These are like the API calls listed in the NSX-T API guide.

Image
Listing the available services for Get-NsxtPolicyServce
Textarea

The list can be narrowed down by searching for a piece of the name Get-NsxtPolicyService -Name *segment*. But segment is in the name of a lot of API calls, so that does not help very much. In this case it is better to export the complete list to a text file and compare it with the API guide. Then you will see that com.vmware.nsx_policy.infra.segments is the service or command we need to use.

Running Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.segments will allow us to run the basic operations against NSX-T for that specific service. This is similar to the basic operations in the API call. But on its own, it's not very useful. If we put it in a string, we can make more use of it.

For example, we can retrieve the documentation from this service with:
$NewGegment = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.segments
$NewGegment.help

Image
Viewing the documentation for a service with NsxtPolicyService
Textarea

And with the Get-Member function we can retrieve the list of operations that we can perform with this service and the input that is required to perform these operations.

Image
Listing the operations for a service with NsxtPolicyService
Textarea

As you can see there is a list operation, we can use to list all the segments. That operation returns a result that contains all the segments. So, to view a list of all the segments we can use $NewSegment.list().results to view all the available information about the segments or we can use $NewSegment.list().results.display_name to only list the display name of all the segments.

Image
Listing the information about the segments
Textarea

Now that we can retrieve the information about the segments it is time to create one with this way of working. This can be done with a similar Patch operation. If we scroll a little bit back in this blog we can see the patch operation requires:
patch(string segment_id, com.vmware.nsx_policy.model.segment segment)
The segment id is a GUID or simply the name we give to the segment, but the second part needs to hold the information about the segment. Like the body in the API call.

In my VMUG presentation I created a VLAN backed segment, so I will be showing the same segment here.

To begin, we will define the id or name of the segment $Segmentid = "Powershell-Test"
To hold the specification about the segment we use
$NewSegmentSpec = $NewSegment.Help.patch.segment.Create()
And to the $NewSegmentSpec we add the settings we want the segment to use. In our case we want it to have VLAN 123 and a VLAN backed Segment must be part of a Transport zone. The setting for the Transportzone can be retrieved using the List() method, by looking at a Segment with the same Transportzone.

$VLANs = @('123')
$transportZone = "/infra/sites/default/enforcement-points/default/transport-zones/0350d3c5-6e7c-4dbf-abe8-c7852b50b2b3"

$NewSegmentSpec.id = $Segmentid
$NewSegmentSpec.vlan_ids = $VLANs
$NewSegmentSpec.transport_zone_path = $transportZone

And to create or update the segment we run $NewSegment.patch($Segmentid, $NewSegmentSpec)

Since this is a Patch method, we can simply adjust the VLAN array and run it again if required. 

Image
Creating a Segment with NsxtPolicyService
Textarea

Again, I can show you a screenshot of the segment I have created, but I think it is more fun and educational to try this yourself. In the next part of this series, I will explain some of the basics about Terraform and how to use it against NSX-T. Hopefully, you have enjoyed reading this blog. If you have any questions or remarks, please leave them at the bottom.

Questions, Remarks & Comments

If you have any questions and need more clarification, we are more than happy to dig deeper. Any comments are also appreciated. You can either post it online or send it directly to the author, it’s your choice.
Let us know  

 
 
Questions, Remarks & Comments

Message Robin directly, in order to receive a quick response.

More about RedLogic