Design a site like this with WordPress.com
Get started

Add or remove Tags in NSX-T with PowerCLI

In this Blogpost I will explain how to add or remove a Tag in NSX-T.

If the VM is not tagged before it is very easy to set a new Tag, but if the VM has already been tagged and you don’t want to loose the existing Tags, it becomes more complicated, because the NSX API will overwrite all Tags if a new one will be set.

If you would like to learn how to use PowerCLI with NSX-T Policy API you can read my Blog: Creating Objects in NSX-T Policy API with VMware PowerCLI

Complete Script

This Script will add a “quarantine” Tag to a VM, with interactive User Input to define which VM should be tagged. The VM name is Case Sensitive and can be found in NSX Inventory -> Virtual Machines.

$display_name = Read-Host -Prompt 'VM Name'
$SecTag = "quarantine"
$secscope = ""
$vmdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.realized_state.enforcement_points.virtual_machines
$vmdatavmid = @([PSCustomObject]$vmdata.list("default").results | select-object -property display_name, external_id | select-string "display_name=$display_name")
$vmdatavmid = $vmdatavmid -replace ("@{display_name=$display_name; ") -replace ("}")
$vmdataid=$vmdatavmid|ConvertFrom-StringData
$vmdataentry = @([PSCustomObject]$vmdata.list("default").results | select-object -property display_name, tags | select-string "display_name=$display_name")
$vmdataentrytags=$vmdataentry-replace ("@{display_name=$display_name; tags=(\[)struct ") -replace'(\])'
$vmdataentrytags = $vmdataentrytags -replace ("struct ") -replace ("'") -replace ("}}"),("}") -replace (":"),("=") -replace (" ") -replace ("},"),("};")

#$vmdataentrytags = $vmdataentrytags -replace ("{scope=$secscope,tag=$SecTag};") -replace (";{scope=$secscope,tag=$SecTag}")
$vmdataentrytags = @($vmdataentrytags.split(";"))
$vmdataentrytags = $vmdataentrytags -replace ("{") -replace ("}")
$vmdataentrytags+="scope=$secscope,tag=$SecTag"
$vmdatacontent = $vmdata.Help.updatetags.virtual_machine_tags_update.Create()
$vmdatacontent.virtual_machine_id = $vmdataid.external_id
foreach ($item in $vmdataentrytags) {
$item=@($item.split(","))
$vmdatatags1=$item|ConvertFrom-StringData
$vmdatatags=$vmdata.Help.updatetags.virtual_machine_tags_update.tags.Element.Create()
$vmdatatags.tag=$vmdatatags1.tag
$vmdatatags.scope=$vmdatatags1.scope
$vmdatacontent.tags.Add($vmdatatags) |Out-Null
}
$vmdata.updatetags("default", $vmdatacontent)

Let dive into the script:

We will create a Variable, and with “Read-Host”, the Input can be tipped in after the “-Prompt” VM Name.

$display_name = Read-Host -Prompt 'VM Name'

In my example I will set a Tag with the Name “quarantine” and no Scope.

$SecTag = "quarantine"
$secscope = ""

We will store the Information from all VMs recognized in NSX to the Variable “$vmdata”.

$vmdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.realized_state.enforcement_points.virtual_machines

For each VM we will have now a lot of information.

In all examples I will use the Virtual Machine “DEV-DB”

$vmdata.list("default").results

—-output omitted—-
guest_info : struct {‘computer_name’: dev-db, ‘os_name’: Ubuntu Linux
(64-bit)}
compute_ids : {moIdOnHost:5, hostLocalId:5,
locationId:564d2f4a-05a3-3fc5-6afc-f839afad7dc1,
instanceUuid:52caf68c-335e-e4e9-18b3-221f5ffe0300…}
resource_type : VirtualMachine
external_id : 564d2f4a-05a3-3fc5-6afc-f839afad7dc1
source : struct {‘target_display_name’: esx2, ‘is_valid’: True,
‘target_type’: HostNode, ‘target_id’:
283c61ef-fcc0-481f-a881-027338e11654}
_last_sync_time : 1577041205593
type : REGULAR
display_name : DEV-DB
power_state : VM_RUNNING
host_id : 283c61ef-fcc0-481f-a881-027338e11654
local_id_on_host : 5
tags : {struct {‘scope’: 2, ‘tag’: dev}, struct {‘scope’: 1, ‘tag’:
internal}, struct {‘scope’: 3, ‘tag’: db}}
—-output omitted—-

To add a Tag to a Specific VM we need the external VM ID (VM UUID). We will store the VM Display Name and the ID in a Variable named “$vmdatavmid”

$vmdatavmid = @([PSCustomObject]$vmdata.list("default").results | select-object -property display_name, external_id | select-string "display_name=$display_name")

With select-string “display_name=$display_name” we will choose the right VM.

But the Information cannot be used without some modification, because we only need the ID.

This will be the output from $vmdatavmid

@{display_name=DEV-DB; external_id=564d2f4a-05a3-3fc5-6afc-f839afad7dc1}
So we need to remove “@{display_name=DEV-DB; ” and “}”

$vmdatavmid = $vmdatavmid -replace ("@{display_name=$display_name; ") -replace ("}")

Let us check the output again

$vmdatavmid
external_id=564d2f4a-05a3-3fc5-6afc-f839afad7dc1

The Information is still in the wrong format so we will convert the information into a table:

$vmdataid=$vmdatavmid|ConvertFrom-StringData

Let us check the output from “$vmdataid”

Name                Value
—-                      —–
external_id      564d2f4a-05a3-3fc5-6afc-f839afad7dc1  

We will now retrieve the existing Tags and Scope from the VM and store the Information in $vmdataentry.

$vmdataentry = @([PSCustomObject]$vmdata.list("default").results | select-object -property display_name, tags | select-string "display_name=$display_name")

This is the Output from “$vmdataentry” and we need to remove a lot of information…

@{display_name=DEV-DB; tags=[struct {‘scope’: 2, ‘tag’: dev}, struct {‘scope’: 1, ‘tag’: internal}, struct {‘scope’: 3, ‘tag’: db}]}

You can remove/replace everything in one line but I make smaller portions to understand what happen with the string. So I will remove now “@{display_name=DEV-DB; tags=[struct ” and the Bracket “]” at the end. Brackets will be interpreted by PowerShell and must be isolated with (\]).

$vmdataentrytags=$vmdataentry-replace ("@{display_name=$display_name; tags=(\[)struct ") -replace'(\])'

In the next Step we will remove and replace all other information

$vmdataentrytags = $vmdataentrytags -replace ("struct ") -replace ("'") -replace ("}}"),("}") -replace (":"),("=") -replace (" ") -replace ("},"),("};")

Let’s check the Variable “$vmdataentrytags”:

{scope=2,tag=dev};{scope=1,tag=internal};{scope=3,tag=db}

If you would like to remove a Tag/Scope, you need to insert here the following Line:

$vmdataentrytags = $vmdataentrytags -replace (“{scope=$secscope,tag=$SecTag};”) -replace (“;{scope=$secscope,tag=$SecTag}”)

We will split the String now. The Identifier is “;”

$vmdataentrytags = @($vmdataentrytags.split(";"))

…and remove also the curly brackets.

$vmdataentrytags = $vmdataentrytags -replace ("{") -replace ("}")

The output from “$vmdataentrytags” should look like the following output.

scope=2,tag=dev
scope=1,tag=internal
scope=3,tag=db

We will add now our additional Tag/Scope we defined on the Top of the script.

If you would like to remove the Tag/Scope you need to comment out this line.

$vmdataentrytags+="scope=$secscope,tag=$SecTag"

The output from “$vmdataentrytags” will have now the additional Tag.

scope=2,tag=dev
scope=1,tag=internal
scope=3,tag=db
scope=,tag=quarantine

The next Variable for NSX-T will apply later the Tags/Scope to a VM.

$vmdatacontent = $vmdata.Help.updatetags.virtual_machine_tags_update.Create()

We will add the Virtual Machine ID (UUID)

$vmdatacontent.virtual_machine_id = $vmdataid.external_id

The API Structure for VM Tags is as follows:

Unfortunately the Tags are not placed in a list so each scope/tag combination must be added as a single entry. We will create a loop (foreach) to attach all Tags.

foreach ($item in $vmdataentrytags) {

We will split now each “$vmdataentrytags” in scope and tag. The identifier is “,”.

$item = @($item.split(","))

…and create a List

$vmdatatags1=$item|ConvertFrom-StringData

We will add now for each entry the Tag/Scope to “$vmdatacontent” and close the loop.

$vmdatatags = $vmdata.Help.updatetags.virtual_machine_tags_update.tags.Element.Create()

$vmdatatags.tag=$vmdatatags1.tag

$vmdatatags.scope=$vmdatatags1.scope
$vmdatacontent.tags.Add($vmdatatags) | Out-Null

}

The Last step will add the Tags to the VM.

$vmdata.updatetags("default", $vmdatacontent)
Advertisement

PowerCLI for NSX-T Policy API

About VMware PowerCLI

VMware PowerCLI is a command-line and scripting tool built on Windows PowerShell, and provides more than 700 cmdlets for managing and automating vSphere, vCloud, vRealize Operations Manager, vSAN, NSX-T, VMware Cloud on AWS, VMware HCX, VMware Site Recovery Manager, and VMware Horizon environments.

If you would like to learn more about VMware PowerCLI visit VMware {code}.

About NSX-T Policy API

Policy API is a new API introduced in NSX-T 2.4 and belongs to the simplified UI for an easier way to manage the Objects.

It is different from the old API (aka NSX -T Management Plane API) that belongs to the Advanced Networking & Security UI.

Most of the external Systems (like vRA, Kubernetes, etc.) can use both APIs and it is a question of Time when the Old API will be deprecated.

About SDK Toolkit and PowerCLI

VMware NSX-T generate the CMDLETS with the SDK Toolkit and if a new Version of NSX-T will be available also a new PowerCLI Version will be available with all new functions from NSX-T.

Disclaimer

If you would like to start with PowerCLI you will find a lot of Blogs how you can install PowerCLI on Windows, MAC and Linux. So this will not be Part of this Blog.

If you would like to use PowerCLI for NSX-T in you Production Enviroment, please contact you VMware Representative to clarify the Support Options!

Let’s start with PowerCLI for NSX-T

General Information

You will find four Commandlets if you are searching for NSX-T.

Get-Module "VMware.VimAutomation.Nsx*" -ListAvailable

Connect-NsxtServer
Disconnect-NsxtServer
Get-NsxtPolicyService
Get-NsxtService

But with this four Modules you can modify all Objects in your NSX Manager. If you know how to do it;-)

We would like to create Objects in the Policy API and need the CMDLET “Get-NsxtPolicyService”.

Login to NSX Manager and get Modules

To get all possible Modules from NSX-T we need to login to our NSX Manager.

Connect-NsxtServer -Server IP-Address/DNS-Name -User Username -Password password

After the connection was successful you should see following output:

Now we can can  list all Modules. This could take some Time to get all Modules (In the Moment while I am writing, we have 286 Modules). I stored this Modules in a Text File to have them available for later configuration Tasks.

Get-NsxtPolicyService

Create a T1 Router

This Script will create a T1 Router and connect it to a T0 Router:

#Variables for NSX Manager Connection 
$nsxmanagerip = "IP_OR_DNS_NAME" 
$nsxuser = "USERNAME" 
$nsxpasswd = "PASSWORD" 
#General Variables 
$description = "Created with VMware PowerCLI" 
$tag = "powercli" 
#Variables for T1 Router 
$t1routerid = "NAME_OF_NEW_T1_ROUTER" 
$t1routerpath_to_t0_rtr = "/infra/tier-0s/NAME_OF_NEW_T0_ROUTER" 
$t1routeradvertisement = @("TIER1_IPSEC_LOCAL_ENDPOINT","TIER1_CONNECTED") 
#Connect to NSX Manager Connect-NsxtServer -Server 
$nsxmanagerip -User $nsxuser -Password $nsxpasswd 
#Retrieve Router Information 
$t1routerdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.tier1s 
#Set Variables 
$t1routerspecification = $t1routerdata.Help.patch.tier1.Create() 
$t1routerspecification.description = $description 
$t1routerspecification.id = $t1routerid 
$t1routerspecification.display_name = $t1routerid 
$t1routerspecification.tier0_path = $t1routerpath_to_t0_rtr 
$t1routerspecification.route_advertisement_types = $t1routeradvertisement 
#Add Tag to the Router 
$t1routertag = $t1routerdata.Help.patch.tier1.tags.Element.Create() 
$t1routertag.tag = $tag 
$t1routerspecification.tags.Add($t1routertag) | Out-Null 
#Create T1 Router 
$t1routerdata.patch($t1routerspecification.id, $t1routerspecification)

Each Line beginning with “$” will be recognized from PowerShell as a Variable. For single Variables you need to put the content in Quotes. “content”.

If you need to set a list of Variables you will need to set the Variables in brackets starting with the @ symbol. @(“content1″,”content2”)

Set the Variables for the NSX Manager:

$nsxmanagerip = "IP_OR_DNS_NAME" 
$nsxuser = "USERNAME" 
$nsxpasswd = "PASSWORD"

Now we create some Variables to find the Objects created by PowerCLI easier.

$description = "Created with VMware PowerCLI" 
$tag = "powercli"

To create the T1 Router and connect the T1 Router to an existing T0 Router we need the following Variables.

$t1routerid = "NAME_OF_NEW_T1_ROUTER" 
$t1routerpath_to_t0_rtr = "/infra/tier-0s/NAME_OF_NEW_T0_ROUTER" 
$t1routeradvertisement = @("TIER1_IPSEC_LOCAL_ENDPOINT","TIER1_CONNECTED")

If not done yet, connect now to the NSX Manager. Otherwise comment this line out.

Connect-NsxtServer -Server $nsxmanagerip -User $nsxuser -Password

The next command will retrieve the Information about the existing T1 Routers , will learn the structure for the input variables and set the Variable to create in the last step the T1 Router.

$t1routerdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.tier1s

Now we can display all T1 Routers and the underlying Information to understand the Structure and the needed Information.

$t1routerdata.list().results

Example Output:

You can also ask for the mandatory Objects.

$t1routerdata | Get-Member

The important one is “patch”. You can see that you will need the tier1_id and the tier1 information to update or create a T1 router.

We need to create a Variable to store the Router Specifications.

$t1routerspecification = $t1routerdata.Help.patch.tier1.Create()

After we executed this command we can check what kind of Inputs are available to create the T1 Router.

$t1routerspecification

You can see all Input Parameter and also the expected Structure.

“String” means single input, “List<string>” means single or multiple inputs and “boolean” means yes or no.

Input Parameter  with “com.vmware.” are child or nested objects and need to be set in a different way. We will do this if we add the TAG to the T1 Router.

We will set the Router Variables:

$t1routerspecification.description = $description
$t1routerspecification.id = $t1routerid
$t1routerspecification.display_name = $t1routerid
$t1routerspecification.tier0_path = $t1routerpath_to_t0_rtr
$t1routerspecification.route_advertisement_types = $t1routeradvertisement

Now let’s come to the Child/Nested objects. The command looks similar to the command where we  created a Variable to store the Router Specifications, but we drill one step deeper in the structure and define the input with Element.

$t1routertag = $t1routerdata.Help.patch.tier1.tags.Element.Create()

And now we can set also the Tag.

$t1routertag.tag = $tag

The next Variable will attach the Child Variables to the Router Specifications.  “| Out-Null” will suppress the Output “0” if I run the script.

$t1routerspecification.tags.Add($t1routertag) | Out-Null

Let’s check if we see all Variables before we create the T1 Router.

$t1routerspecification

Now we are ready to create the Router.

$t1routerdata.patch($t1routerspecification.id, $t1routerspecification)

If the command runs without any error message, your input was correct and you created a new T1 Router. But let us check if this is true;-)…. Login to your NSX Manager and type in the search bar “powercli”.

You should see some results like this:

Create a Logical Segment

This Script will create a Logical Segment:

#Variables for NSX Manager Connection 
$nsxmanagerip = "IP_OR_DNS_NAME" 
$nsxuser = "USERNAME" 
$nsxpasswd = "PASSWORD" 
#General Variables 
$description = "Created with VMware PowerCLI" 
$tag = "powercli" 
#Variables for Segment 
$segmentid = "SEGMENTNAME" 
$transportzone = "/infra/sites/default/enforcement-points/default/transport-zones/TRANSPORTZONEID" 
$path_to_t1_rtr = "/infra/tier-1s/T1ROUTERNAME" 
$defaultgateway = "IP-ADDRESS/MASK" 
#Connect to NSX Manager Connect-NsxtServer -Server 
$nsxmanagerip -User 
$nsxuser -Password 
$nsxpasswd 
#Retrieve Segment Information 
$segmentdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.segments 
#Set Variables 
$segmentdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.segments 
$segmentspecification = $segmentdata.Help.patch.segment.Create() 
$segmentspecification.description = $description 
$segmentspecification.id = $segmentid 
$segmentspecification.transport_zone_path = $transportzone 
$segmentspecification.connectivity_path = $path_to_t1_rtr 
#Set Default Gateway Variables 
$subnetSpec = $segmentdata.help.patch.segment.subnets.Element.Create() 
$subnetSpec.gateway_address = $defaultgateway 
$segmentspecification.subnets.Add($subnetSpec) | Out-Null 
#Add Tag to the Segment 
$segmenttag = $segmentdata.help.patch.segment.tags.Element.Create() 
$segmenttag.tag = $tag 
$segmentspecification.tags.Add($segmenttag) | Out-Null #Create Segment 
$segmentdata.patch($segmentid, $segmentspecification)

I will only explain the Details for the Segment. To create the Segment we need the following Variables.

$segmentid = "SEGMENTNAME"
$transportzone = "/infra/sites/default/enforcement-points/default/transport-zones/TRANSPORTZONEID"

To find out the Transport Zone UUID you can check this in your NSX Manager: System->Fabric->Transport Zones

The Routername can be the T1 Router you created earlier and the Defaultgateway Address will be used for the VMs connected to this segment.

$path_to_t1_rtr = "/infra/tier-1s/T1ROUTERNAME"
$defaultgateway = "IP-ADDRESS/MASK"

If not already connected you need to connect to your  NSX Manager. Otherwise you should comment this line out.

Connect-NsxtServer -Server $nsxmanagerip -User $nsxuser -Password $nsxpasswd

The next command will retrieve the Information about the existing Segments, will learn the structure for the input variables and set the Variable to createthe Segment in the last step.

$segmentdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.segments

Now we can use following commands to get more Information regarding the Structure.

$segmentdata.list().results
$segmentdata | Get-Member

We will now create the Variables needed for the Segment.

$segmentspecification = $segmentdata.Help.patch.segment.Create()
$segmentspecification.description = $description
$segmentspecification.id = $segmentid
$segmentspecification.transport_zone_path = $transportzone
$segmentspecification.connectivity_path = $path_to_t1_rtr

To set the Default Gateway Information we drill one step deeper in the structure and define the input with Element.

$subnetSpec = $segmentdata.help.patch.segment.subnets.Element.Create()
$subnetSpec.gateway_address = $defaultgateway
$segmentspecification.subnets.Add($subnetSpec) | Out-Null

We will do the same for the Segment Tag.

$segmenttag = $segmentdata.help.patch.segment.tags.Element.Create()
$segmenttag.tag = $tag
$segmentspecification.tags.Add($segmenttag) | Out-Null

The Last step will create the new Segment.

$segmentdata.patch($segmentid, $segmentspecification)

Let’s check if the script was successful!

Create Groups

This Script will create a Group and using Group Member Attributes:

#Variables for NSX Manager Connection 
$nsxmanagerip = "IP_OR_DNS_NAME" 
$nsxuser = "USERNAME" 
$nsxpasswd = "PASSWORD" 
#General Variables 
$description = "Created with VMware PowerCLI" 
$tag = "powercli" 
#Variables for Groups 
$groupdomain = "default" 
$groupid = "GROUP_NAME" 
$groupmember = "SCOPE_NAME|TAG_NAME" 
$groupmember_type = "VirtualMachine" 
#Connect to NSX Manager 
Connect-NsxtServer -Server $nsxmanagerip -User $nsxuser -Password $nsxpasswd 
#Retrieve Group Information 
$groupdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.domains.groups 
#Set Group Variables 
$groupspecification = $groupdata.Help.patch.group.Create() 
$groupspecification.display_name = $groupid 
$groupspecification.description = $description 
#Add Group Member Variables 
$groupexpspecification = $groupdata.Help.patch.group.expression.Element.condition.Create() $groupexpspecification.member_type = $groupmember_type 
$groupexpspecification.value = $groupmember 
$groupexpspecification.key="Tag" 
$groupexpspecification.operator = "EQUALS" 
$groupspecification.expression.Add($groupexpspecification) | Out-Null 
#Add TAG to Group 
$grouptag = $groupdata.Help.patch.group.tags.Element.Create() 
$grouptag.tag = $tag 
$groupspecification.tags.Add($grouptag) | Out-Null 
#Create Group 
$groupdata.patch($groupdomain, $groupid, $groupspecification)

To create the group we need the following Variables. The Domain should be “default” and will be inserted the URL String . Please be aware that domain and Membertype are Case Sensitive.

$groupdomain = "default"
$groupid = "GROUP_NAME"
$groupmember = "SCOPE_NAME|TAG_NAME"
$groupmember_type = "VirtualMachine"

The next command will retrieve the Information about the existing Groups, will learn the structure for the input variables and create the Variable to create the Segment in the last step

$groupdata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.domains.groups

We will now create the Variables for the Group.

$groupspecification = $groupdata.Help.patch.group.Create()
$groupspecification.display_name = $groupid
$groupspecification.description = $description

Define the Group Criterias.

$groupexpspecification = $groupdata.Help.patch.group.expression.Element.condition.Create()
$groupexpspecification.member_type = $groupmember_type
$groupexpspecification.value = $groupmember
$groupexpspecification.key="Tag"
$groupexpspecification.operator = "EQUALS"
$groupspecification.expression.Add($groupexpspecification) | Out-Null

Again we will tag the Group with the Word “powercli”.

$grouptag = $groupdata.Help.patch.group.tags.Element.Create()
$grouptag.tag = $tag
$groupspecification.tags.Add($grouptag) | Out-Null

And create the Group with the additional Variable $groupdomain for the URL String.

$groupdata.patch($groupdomain, $groupid, $groupspecification)

Create a Firewall Section and Rule

This Script will create a Firewall Section and a Rule:

#Variables for NSX Manager Connection 
$nsxmanagerip = "IP_OR_DNS_NAME" 
$nsxuser = "USERNAME" 
$nsxpasswd = "PASSWORD" 
#General Variables 
$description = "Created with VMware PowerCLI" 
$tag = "powercli" 
#Variables for Firewallentries 
$secdomain = "default" 
$policysectionid = "FW_SECTION_NAME" 
$rulename = "FW_RULE_NAME" 
$source = "/infra/domains/default/groups/GROUPNAME" 
$destination = "any" 
$service = "any" 
$action = "ALLOW" 
#Connect to NSX Manager 
Connect-NsxtServer -Server $nsxmanagerip -User $nsxuser -Password $nsxpasswd 
#Retrieve Firewall Section and Rule Information 
$secpolicydata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.domains.security_policies 
#Set Firewall Variables 
$secpolicyspecification = $secpolicydata.Help.patch.security_policy.Create() 
$secpolicyspecification.description = $description 
$secpolicyspecification.display_name = $policysectionid 
#Set Rule Variables 
$secpolicyrule = $secpolicydata.Help.patch.security_policy.rules.Element.Create() 
$secpolicyrule.description = $description 
$secpolicyrule.display_name = $rulename 
$secpolicyrule.source_groups = @($source) 
$secpolicyrule.destination_groups = @($destination) 
$secpolicyrule.services = @($service) 
$secpolicyrule.action = $action 
$secpolicyspecification.rules.Add($secpolicyrule) | Out-Null 
#Add TAG to Firewall Section 
$secpolicytag = $secpolicydata.Help.patch.security_policy.tags.Element.Create() 
$secpolicytag.tag = $tag 
$secpolicyspecification.tags.Add($secpolicytag) | Out-Null 
#Create Firewall Section and Rule 
$secpolicydata.patch($secdomain, $policysectionid, $secpolicyspecification)

We will create a Firewall Section and in the Section the Firewall Rule.

$secdomain = "default"
$policysectionid = "FW_SECTION_NAME"
$rulename = "FW_RULE_NAME"
$source = "/infra/domains/default/groups/GROUPNAME"
$destination = "any"
$service = "any"
$action = "ALLOW"

Retrieve Firewall Information

$secpolicydata = Get-NsxtPolicyService -Name com.vmware.nsx_policy.infra.domains.security_policies

Set Variables for the Firewall Section

$secpolicyspecification = $secpolicydata.Help.patch.security_policy.Create()
$secpolicyspecification.description = $description
$secpolicyspecification.display_name = $policysectionid

Set Variables for the Firewall Rule

$secpolicyrule = $secpolicydata.Help.patch.security_policy.rules.Element.Create()
$secpolicyrule.description = $description $secpolicyrule.display_name = $rulename
$secpolicyrule.source_groups = @($source)
$secpolicyrule.destination_groups = @($destination)
$secpolicyrule.services = @($service)
$secpolicyrule.action = $action
$secpolicyspecification.rules.Add($secpolicyrule) | Out-Null

Tag the Firewall Section

$secpolicytag = $secpolicydata.Help.patch.security_policy.tags.Element.Create()
$secpolicytag.tag = $tag
$secpolicyspecification.tags.Add($secpolicytag) | Out-Null

Create the Firewall Section and the Rule

$secpolicydata.patch($secdomain, $policysectionid, $secpolicyspecification)

I hope this will help you to start with VMware PowerCLI and NSX-T