PowerVCF 2.0 Authentication Changes

One of the many major enhancements in VMware Cloud Foundation 4.0 is a switch from basic authentication to token based authentication for the VCF API.

Basic authentication is a header field in the form of Authorization: Basic <credentials>, where credentials is the base64 encoding of a username and password. The credentials are not encrypted, therefore Basic Authentication is not the industry standard for API authentication.

VCF 4.0 has moved to using token based authentication (JWT Tokens to be exact) for securing the API. The token implementation is as follows:

  1. An authorized user executes a POST API call to /v1/tokens
  2. The response contains an access token and a refresh token
    1. The access token is valid for 1 hour
      1. The access token is passed in every API call header in the form of Authorization: Bearer <access token>
    2. The refresh token is valid for 24 hours
      1. The refresh token is used to request a new access token once it has expired

PowerVCF 2.0 abstracts all of this in the following way:

  • An authorized user connects to SDDC Manager to request the tokens by running:

Connect-VCFManager -fqdn sfo-vcf01.sfo.rainpole.io -username svc-vcf-api@rainpole.io -password VMw@re1!

  • The access & refresh tokens are stored in memory and used when running subsequent API calls. As each API call is executed PowerVCF checks the expiry of the access token. If the access token is about to expire, it uses the refresh token to request a new access token and proceeds with the API call. So the user does not need to worry about token management.

We have also introduced roles that can be assigned to users. Initially we have ADMIN & OPERATOR, with more roles planned for a future release.

ADMIN = Full Administrator Access to all APIs

OPERATOR = All Access except Password Management, User Management, Backup Management

To request an API token you must have a user account that is assigned either the ADMIN or OPERATOR role in SDDC Manager. The default administrator@vsphere.local user is assigned the ADMIN role during bringup but it is advisable to add additional users for performing day to day tasks.

Once you have a user added you can then authenticate with SDDC Manager to retrieve your access & refresh tokens.

Tip: You can connect using the administrator@vsphere.local user to add new users using PowerVCF. You can use the New-VCFUser PowerVCF cmdlet to create the user and assign a role like so:


Connect-VCFManager -fqdn sfo-vcf01.sfo.rainpole.io -username administrator@vsphere.LOCAL -password VMw@re1!

New-VCFUser -user vcf-admin@rainpole.io -role ADMIN

Once your user is configured PowerVCF will do the rest when it comes to managing the API access tokens.

 

Announcing PowerVCF 2.0

I’m happy to announce the availability of PowerVCF 2.0. This version of PowerVCF is compatible with VMware Cloud Foundation 4.0 and above. Due to some API security enhancements in VCF 4.0 around the use of API tokens for authentication the module has been refactored to leverage access & refresh tokens (more on that here). For that reason if you would like to use PowerVCF for VCF 3.9.x you should continue to use PowerVCF 1.2 .

PowerVCF 2.0 is published to the PowerShell Gallery here https://www.powershellgallery.com/packages/PowerVCF/2.0.0

Whats new in PowerVCF 2.0

Along with a number of new or modified cmdlets the following enhancements have been made:

  • Grouped cmdlets based on order of API documentation
  • Code hygiene

The following table provides a detailed breakdown of all the changes for this release. Thanks to my colleague @GaryJBlake for doing most of the work on this release and for pulling this list together!

Category cmdlet Name Description Comment
Backup and Restore Start-VCFRestore Starts the restore process of SDDC Manager NEW
Backup and Restore Get-VCFRestoreTasks Gets the status of the restore process NEW
Connectivity Connect-VCFManager Create authentication header for SDDC Manager appliance UPDATED – Support the new token / bearer authentication model and basicAuth switch for restore process
Connectivity Connect-CloudBuilder Create authentication header for Cloud Builder appliance NEW
Certificates Get-VCFCertificateAuthority Get Certificate Authority information UPDATED – Added support for getting the details by id
Certificates Remove-VCFCertificateAuthority Deletes Certificate Authority configuration NEW
Certificates Get-VCFCertificate View certificate of all the resources in a domain UPDATED – Added support for get certificate details by resource
Credentials Get-VCFCredential Get the credentials UPDATED- Added support for getting the details by id
Credentials Stop-VCFCredentialTask Cancels a failed update or rotate passwords task RENAMED – From Cancel-VCFCredentialTask
Credentials Restart-VCFCredentialTask Retry a failed rotate/update passwords task RENAMED – From Retry-VCFCredentialTask
Hosts Commission-VCFHost Commissions a list of hosts UPDATED – Added support for validating the input spec for host operations (-validate switch)
NSX-T Edge Clusters Get-VCFEdgeCluster Get an Edge Cluster NEW
NSX-T Edge Clusters New-VCFEdgeCluster creates an NSX-T edge cluster NEW
Personalities Get-VCFPersonality Get the vSphere Lifecycle Manager Personalities NEW
SDDC (Cloud Builder) Get-CloudBuilderSDDC Retrieve all SDDCs NEW
SDDC (Cloud Builder) Start-CloudBuilderSDDC Create SDDC NEW
SDDC (Cloud Builder) Restart-CloudBuilderSDDC Retry failed SDDC creation NEW
SDDC (Cloud Builder) Get-CloudBuilderSDDCValidation Get all SDDC specification validations NEW
SDDC (Cloud Builder) Start-CloudBuilderSDDCValidation Validate SDDC specification before creation NEW
SDDC (Cloud Builder) Stop-CloudBuilderSDDCValidation Cancel SDDC specification validation NEW
SDDC (Cloud Builder) Restart-CloudBuilderSDDCValidation Retry SDDC validation NEW
System Prechecks Start-VCFSystemPrecheck Perform System Precheck RENAMED – From Start-PreCheckVCFSystem
System Prechecks Get-VCFSystemPrecheckTask Get System Precheck Task RENAMED – From Get-PreCheckVCFSystemTask
Tasks Restart-VCFTask Retry a previously failed task RENAMED – From Retry-VCFTask
Users Get-VCFRole Get all roles NEW
Users Get-VCFUser Get all Users NEW
Users New-VCFUser Adds a new user NEW
Users New-VCFServiceUser Adds a new service user NEW
Users Delete-User Deletes a user NEW
vRealize Suite Lifecycle Manager Reset-VCFvRSLCM Redeploy vRealize Suite Lifecycle Manager NEW
vRealize Suite Lifecycle Manager New-VCFvRSLCM Validate the input specification for vRealize Suite Lifecycle Manager deployment UPDATED – Added support for validating the json spec (-validate switch).

PowerShell Script to Configure an NSX-T Load Balancer for the vRealize Suite & Workspace ONE Access

As part of my role in the VMware Hyper-converged Business Unit (HCIBU) I spend a lot of time working with new product versions testing integrations for next-gen VMware Validated Designs and Cloud Foundation. A lot of my focus is on Cloud Operations and Automation (vROPs, vRLI, vRA etc) and consequently I regularly need to deploy environments to perform integration testing. I will typically leverage existing automation where possible and tend to create my own when i find gaps. Once such gap was the ability to use PowerShell to interact with the NSX-T API. For anyone who is familiar with setting up a load balancer for the vRealize Suite in NSX-T – there are a lot of manual clicks required. So i set about creating some PowerShell functions to make it a little less tedious and to speed up getting my environments setup so i could get to the testing faster.

There is comprehensive NSX-T API documentation posted on code.vmware .com that I used to decipher the various API endpoints required to complete the various tasks:

  • Create the Load Balancer
  • Create the Service Monitors
  • Create the Application Profiles
  • Create the Server Pools
  • Create the Virtual Servers

The result is a PowerShell module with a function for each of the above and a corresponding JSON file that is read in for the settings for each function. I have included a sample JSON file to get you started. Just substitute your values.

Note: You must have a Tier-1 & associated segments created. (I’ll add that functionality when i get a chance!)

PowerShell Module, Sample JSON & Script are posted to Github here

Create a multi pNIC VMware Cloud Foundation NSX-V Workload Domain with PowerVCF

Hopefully by now you’ve seen my earlier posts about the new PowerShell module for the VMware Cloud Foundation API. If not i’d suggest reviewing these before reading on

With the release of VMware Cloud Foundation 3.9.1 it is now supported, via the API only, to use more than 2 physical NICs (pNICs) per host. In fact the API now supports up to three vSphere Distributed switches and six physical NICs, providing more flexibility to support high performance use cases and physical traffic separation.

There is a tech note that goes into more detail on the use cases for more than 2 pNICs and it also shows how this works using PostMan but we can also achieve this using PowerVCF.

The workflow using PowerVCF is the same as my earlier example for creating a workload domain. The only difference is the content in the JSON file.

Note: There is a validation API to validate the JSON you are passing before making the submission. PowerVCF dynamically formats the validation JSON as the formatting is slightly different to what you submit to create the workload domain.

To get you started there is a sample JSON file with the required formatting. Here is a snapshot of what it looks like

{
  "domainName": "PowerVCF",  
  "vcenterSpec": {  
    "name": "sfo01w01vc01",  
    "networkDetailsSpec": {  
       "ipAddress": "172.16.225.64",  
       "dnsName": "sfo01w01vc01.sfo01.rainpole.local",  
       "gateway": "172.16.225.1",  
       "subnetMask": "255.255.255.0"
     },  
     "rootPassword": "VMw@re1!",  
     "datacenterName": "PowerVCF-DC"  
   },  
   "computeSpec": {  
      "clusterSpecs": [ {  
          "name": "Cluster1",  
          "hostSpecs": [ {  
              "id": "d0693b58-4012-4387-92ed-721cfa709e44",
              "license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
              "hostNetworkSpec": {  
                 "vmNics": [ {  
                     "id": "vmnic0",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, {  
                     "id": "vmnic1",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, { 
                     "id": "vmnic2",  
                     "vdsName": "SDDC-Dswitch-Private2" 
                  }, {  
                     "id": "vmnic3",  
                     "vdsName": "SDDC-Dswitch-Private2"  
                  } ]  
               }  
            }, {  
              "id": "7006bec4-fccb-49a0-bff6-fd56c807d26a",
              "license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
              "hostNetworkSpec": {  
                 "vmNics": [ {  
                     "id": "vmnic0",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, {  
                     "id": "vmnic1",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, { 
                     "id": "vmnic2",  
                     "vdsName": "SDDC-Dswitch-Private2" 
                  }, {  
                     "id": "vmnic3",  
                     "vdsName": "SDDC-Dswitch-Private2"  
                  } ]  
               }  
            }, {  
              "id": "cc257a80-e179-4297-bf7e-179a0944bbab",
              "license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
              "hostNetworkSpec": {  
                 "vmNics": [ {  
                     "id": "vmnic0",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, {  
                     "id": "vmnic1",  
                     "vdsName": "SDDC-Dswitch-Private1"  
                  }, { 
                     "id": "vmnic2",  
                     "vdsName": "SDDC-Dswitch-Private2" 
                  }, {  
                     "id": "vmnic3",  
                     "vdsName": "SDDC-Dswitch-Private2"  
                  } ] 
               } 
           } ],     
    "datastoreSpec": {  
        "vsanDatastoreSpec": {  
            "failuresToTolerate": 1,  
            "licenseKey": "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB",
            "datastoreName": "vSanDatastore" 
         }  
     },  
     "networkSpec": { 
         "vdsSpecs": [ { 
             "name": "SDDC-Dswitch-Private1", 
             "portGroupSpecs": [ {  
                 "name": "SDDC-DPortGroup-Mgmt", 
                 "transportType": "MANAGEMENT" 
             }, { 
                 "name": "SDDC-DPortGroup-VSAN",  
                 "transportType": "VSAN" 
             }, {  
                 "name": "SDDC-DPortGroup-vMotion", 
                 "transportType": "VMOTION" 
             } ] 
          },  
          {  
             "name": "SDDC-Dswitch-Private2", 
             "portGroupSpecs": [ { 
                "name": "SDDC-DPortGroup-Public", 
                "transportType": "PUBLIC"  } ] 
           } 
        ],  
        "nsxClusterSpec": { 
           "nsxVClusterSpec": {  
              "vlanId": 2237,  
              "vdsNameForVxlanConfig": "SDDC-Dswitch-Private1"  
            }  
          }  
        }  
      } ] 
   }, 
  "nsxVSpec" : {
    "nsxManagerSpec" : {
      "name" : "sfo01w01nsx01",
      "networkDetailsSpec" : {
        "ipAddress" : "172.16.225.66",
        "dnsName" : "sfo01w01nsx01.sfo01.rainpole.local",
        "gateway" : "172.16.225.1",
        "subnetMask" : "255.255.255.0"
      }
    },
    "nsxVControllerSpec" : {
      "nsxControllerIps" : [ "172.16.225.121", "172.16.225.122", "172.16.225.123" ],
      "nsxControllerPassword" : "VMw@re123456!",
      "nsxControllerGateway" : "172.16.225.1",
      "nsxControllerSubnetMask" : "255.255.255.0"
    },
    "licenseKey" : "CCCCC-CCCCC-CCCCC-CCCCC-CCCCC",
    "nsxManagerAdminPassword" : "VMw@re1!",
    "nsxManagerEnablePassword" : "VMw@re1!"
  }
}

You can see that the magic happens in the hostNetworkSpec section where you map each vmnic to a vdsName

<p>"hostNetworkSpec": { "vmNics": [ { "id": "vmnic0", "vdsName": "SDDC-Dswitch-Private1" }, { "id": "vmnic1", "vdsName": "SDDC-Dswitch-Private1" }, { "id": "vmnic2", "vdsName": "SDDC-Dswitch-Private2" }, { "id": "vmnic3", "vdsName": "SDDC-Dswitch-Private2" } ] }</p>

So please try it out and let us know how it goes!

Create a new VMware Cloud Foundation Workload Domain with PowerVCF

So now that we have a PowerShell module for the VMware Cloud Foundation API, just what can we do with it? Well in this example we will create an NSX-V backed VMware Cloud Foundation workload domain, all using PowerVCF to interact with the API. Now all of this could obviously be wrapped up in a single script but I’m going to show you each step, with some tips along the way.

I will be making the assumption that you are familiar with VMware Cloud Foundation Concepts. If not please review the documentation here.

So once you have the initial VCF bringup completed you need to add a workload domain(s) to service our workloads. In my example below I have a management domain only.

And i have only the 4 hosts that are part of the management domain in my inventory. So i need to add new hosts to my inventory before i can create a new workload domain.

The sequence of events is as follows:

  • Install the PowerVCF Module
  • Connect to SDDC Manager
  • Create a network pool
  • Commission hosts
  • Create Workload domain

Install the PowerVCF Module from the PowerShell Gallery

  • Open PowerShell
  • Run the following to install the module

Install-Module -Name PowerVCF

Connect to SDDC Manager

  • To establish a session with SDDC Manager run the following

Connect-VCFManager -fqdn sddc-manager.sfo01.rainpole.local -username admin -password VMw@re1!

Create a network pool

The first thing you need before you can commission new hosts is to create a new network pool, which will include the vSAN & vMotion network details for this workload domain cluster.

To create a new network pool do the following:

  • Before you can create a network pool you first need to create the json body that will be passed in.

TIP: The PowerVCF Module includes a folder of sample json files to get you started

Here is the json format required for creating a vSAN network pool (Please use the same json with the module rather than copying from here as formatting is probably messed up!)


{
"name": "sfo01w01-cl01",
"networks": [
{
"type": "VSAN",
"vlanId": 2240,
"mtu": 9000,
"subnet": "172.16.240.0",
"mask": "255.255.255.0",
"gateway": "172.16.240.253",
"ipPools": [
{
"start": "172.16.240.5",
"end": "172.16.240.100"
}
]
},
{
"type": "VMOTION",
"vlanId": 2236,
"mtu": 9000,
"subnet": "172.16.236.0",
"mask": "255.255.255.0",
"gateway": "172.16.236.253",
"ipPools": [
{
"start": "172.16.236.5",
"end": "172.16.236.100"
}
]
}
]
}

So first off lets get a list of current Network Pools. To do this run the following cmdlet:

Get-VCFNetworkPool

As expected this returns a single network pool.

So to create a new network pool using the json you created earlier run the following:

New-VCFNetworkPool -json .\SampleJSON\NetworkPool\addNetworkPoolSpec.json

Now running Get-VCFNetworkPool should display 2 Network Pools

Commission Hosts

Now that you have a network pool you can commission hosts and associate them with the network pool. For this you need the following json

TIP: For this json you need the network pool name & ID. These were returned when the pool was created and also by Get-VCFNetworkPool


[
{
"fqdn": "sfo01w01esx01.sfo01.rainpole.local",
"username": "root",
"storageType": "VSAN",
"password": "VMw@re1!",
"networkPoolName": "sfo01w01-cl01",
"networkPoolId": "afd314f6-f31d-4ad4-8943-0ecb35c044b9"
},
{
"fqdn": "sfo01w01esx02.sfo01.rainpole.local",
"username": "root",
"storageType": "VSAN",
"password": "VMw@re1!",
"networkPoolName": "sfo01w01-cl01",
"networkPoolId": "afd314f6-f31d-4ad4-8943-0ecb35c044b9"

},
{
"fqdn": "sfo01w01esx03.sfo01.rainpole.local",
"username": "root",
"storageType": "VSAN",
"password": "VMw@re1!",
"networkPoolName": "sfo01w01-cl01",
"networkPoolId": "afd314f6-f31d-4ad4-8943-0ecb35c044b9"
},
{
"fqdn": "sfo01w01esx04.sfo01.rainpole.local",
"username": "root",
"storageType": "VSAN",
"password": "VMw@re1!",
"networkPoolName": "sfo01w01-cl01",
"networkPoolId": "afd314f6-f31d-4ad4-8943-0ecb35c044b9"
}
]

So to commission the 4 new hosts into my VCF inventory i simply run

Commission-VCFHost -json .\SampleJSON\Host\commissionHosts.json

TIP: This returns a task id, which you can monitor by running the following until status=Successful:

Get-VCFTask -id b93e2bc7-627b-4f7c-980b-c12b3497c4ea

Create a Workload Domain

Once the commission hosts task is complete you can then create a workload domain using those hosts. Creating a workload domain also requires a json file. For this you need the id’s of the hosts that you want to use. In VCF hosts that are available to be used in a workload domain have a status of UNASSIGNED_USEABLE so to find the id’s of the hosts you want to add run the following

TIP: Filter the results by adding | select fqdn,id

Get-VCFHost -Status UNASSIGNED_USEABLE | select fqdn,id

This returns the ids you need for creating the workload domain. Here is the Workload domain json. (Replace ESXi licence (AAAAA), vSAN licence (BBBBB) & NSX-V licence (CCCCC) with your keys)


{
"domainName" : "PowerVCF",
"vcenterSpec" : {
"name" : "sfo01w01vc01",
"networkDetailsSpec" : {
"ipAddress" : "172.16.225.64",
"dnsName" : "sfo01w01vc01.sfo01.rainpole.local",
"gateway" : "172.16.225.1",
"subnetMask" : "255.255.255.0"
},
"rootPassword" : "VMw@re1!",
"datacenterName" : "PowerVCF-DC"
},
"computeSpec" : {
"clusterSpecs" : [ {
"name" : "Cluster1",
"hostSpecs" : [ {
"id" : "dd2ec05f-39e1-464e-83f1-1349a0dcf723",
"license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
"hostNetworkSpec" : {
"vmNics" : [ {
"id" : "vmnic0",
"vdsName" : "sfo01w01vds01"
}, {
"id" : "vmnic1",
"vdsName" : "sfo01w01vds01"
} ]
}
}, {
"id" : "809b25e8-1db6-464b-b310-97f581c56da5",
"license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
"hostNetworkSpec" : {
"vmNics" : [ {
"id" : "vmnic0",
"vdsName" : "sfo01w01vds01"
}, {
"id" : "vmnic1",
"vdsName" : "sfo01w01vds01"
} ]
}
}, {
"id" : "5d3eea32-6464-4ae6-9866-932fb926a5f1",
"license":"AAAAA-AAAAA-AAAAA-AAAAA-AAAAA",
"hostNetworkSpec" : {
"vmNics" : [ {
"id" : "vmnic0",
"vdsName" : "sfo01w01vds01"
}, {
"id" : "vmnic1",
"vdsName" : "sfo01w01vds01"
} ]
}
} ],
"datastoreSpec" : {
"vsanDatastoreSpec" : {
"failuresToTolerate" : 1,
"licenseKey" : "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB",
"datastoreName" : "sfo01w01vsan01"
}
},
"networkSpec" : {
"vdsSpecs" : [ {
"name" : "sfo01w01vds01",
"portGroupSpecs" : [ {
"name" : "sfo01w01vds01-Mgmt",
"transportType" : "MANAGEMENT"
}, {
"name" : "sfo01w01vds01-VSAN",
"transportType" : "VSAN"
}, {
"name" : "sfo01w01vds01-vMotion",
"transportType" : "VMOTION"
} ]
} ],
"nsxClusterSpec" : {
"nsxVClusterSpec" : {
"vlanId" : 2237,
"vdsNameForVxlanConfig" : "sfo01w01vds01"
}
}
}
} ]
},
"nsxVSpec" : {
"nsxManagerSpec" : {
"name" : "sfo01w01nsx01",
"networkDetailsSpec" : {
"ipAddress" : "172.16.225.66",
"dnsName" : "sfo01w01nsx01.sfo01.rainpole.local",
"gateway" : "172.16.225.1",
"subnetMask" : "255.255.255.0"
}
},
"nsxVControllerSpec" : {
"nsxControllerIps" : [ "172.16.235.121", "172.16.235.122", "172.16.235.123" ],
"nsxControllerPassword" : "VMw@re123456!",
"nsxControllerGateway" : "172.16.235.1",
"nsxControllerSubnetMask" : "255.255.255.0"
},
"licenseKey" : "CCCCC-CCCCC-CCCCC-CCCCC-CCCCC",
"nsxManagerAdminPassword" : "VMw@re1!",
"nsxManagerEnablePassword" : "VMw@re1!"
}
}

To create the workload domain run the following:

New-VCFWorkloadDomain -json .\SampleJSON\WorkloadDomain\workloadDomainSpec-NSX-V.json

This will return a Task ID. Monitor the workload domain creation by running the following

Get-VCFTask -id b93e2bc7-627b-4f7c-980b-c12b3497c4ea

And that should be it. If you’ve gotten all your json details correct you should have a fully functioning NSX-V workload domain without using the UI!

Introducing PowerVCF – A PowerShell Module for the VMware Cloud Foundation API

Its been a while since I’ve posted something so I thought it was about time! Since joining VMware a year ago I’ve been heads down drinking from the firehose, learning from a phenomenal team and generally keeping very busy. More recently I’ve been playing a lot with VMware Cloud Foundation (VCF). A recent release (3.8) introduced a public API and I started getting field questions on how to leverage it so I started digging. The API has been expanded in 3.9. It is based on the OpenAPI standard (formerly Swagger) and can be accessed through the developer center in the SDDC Manager UI or via code.vmware.com

Now I’m not a developer so I fell back on Postman to do some initial testing. I like Postman as it dumbs it down for us non-devs 🙂 but I wanted something a little easier to consume so i started a little side project called PowerVCF (hat-tip to the far superior PowerNSX, PowerVRA, PowerVRO)

Basically I wanted to provide a simple, efficient, PowerCLI style experience for consuming the VMware Cloud Foundation public API.

Solution?

I am delighted to unleash the first iteration of PowerVCF on the community! Creating this has been a great learning experience for me. In the process I’ve improved my PowerShell skills, learned Git, Markdown and have started looking into CI/CD workflows. It’s also my first submission to the PowerShell Gallery.

Automate your VMware Validated Design NSX-V Distributed Firewall Configuration

A few weeks back I mentioned on twitter that i was working on automating the VMware Validated Design NSX-V Distributed Firewall Configuration in my lab. (I admit it took longer than i had planned!) Currently this is a manual post deployment step once VMware Cloud Builder has completed the deployment. This will likely be picked up by Cloud Builder in a future release but for now its a manual, and somewhat tedious, but required, step!

Full details on the manual steps required for this configuration can be found here. Please take the time to understand what these rules are doing before implementing them.

So in an effort to make this post configuration step a little less painful i set out to automate it. I’ve played with the NSX-V API in the past and found it much easier to interact with by using PowerNSX, rather than leveraging PostMan and the API directly. PowerNSX is the unofficial, official automation tool for NSX. Hats off to VMware engineers Nick Bradford, Dale Coghlan & Anthony Burke for creating and documenting this tool. Anthony also published a FREE book on Automating NSX for vSphere with PowerNSX. More on that here.

Disclaimer: This script is not officially supported by VMware. Use at your own risk & test in a development/lab environment before using in production.

I’ve posted the script to GitHub here as its a bit lengthy! There may be a more efficient way to do some parts of it and if anyone wants to contribute please feel free!

As with a lot of the scripts i create it is menu based and has 2 main options:

  1. Create DFW exclusions, IP Sets & Security Groups
  2. Create DFW Rules

The reason i split it into 2 distinct operations is to allow you to inspect the exclusion list, IP Sets & Security Groups before creating the firewall rules. This will ensure that you dont lock yourself out of vCenter by creating an incorrect rule.

Required Software

  • PowerCli
    • The script will check for PowerCli and if not found will attempt to install the latest version from the PowerShell Gallery
    • Currently tested on Windows only
    • If you dont have internet access you can manually install PowerCli by opening a PowerShell console as administrator and running:
    • Find-Module -Name VMware.PowerCLI | Install-Module
  • PowerNSX
    • The script will check for PowerNSX and if not found will attempt to install the latest version from the PowerShell Gallery
    • Currently tested on Windows only
    • If you dont have internet access you can manually install PowerNSX by opening a PowerShell console as administrator and running:
    • Find-Module -Name PowerNSX | Install-Module

Required Variables

Before you can run the script you need to edit the User Variables to provide the following:

  • Target vCenter details
    • Required to establish a PowerCli Connection with vCenter Server. This is used when updating the DFW exclusion list
  • Target NSX Manager details
    • Required to establish a connection with NSX manager to configure the DFW
  • IP Addresses for the various SDDC components

Hopefully you will find this useful!

VMware Validated Design – Automated Deployment with Cloud Builder – Part 4: Generating SSL Certificates

This is part 4 of a series of posts on VMware Cloud Builder.

In this post I will cover generating the required SSL certificates for deploying this VMware Validated Design with VMware Cloud Builder.

Friendly warning: This is a long post so maybe get a coffee before reading!

Continue reading “VMware Validated Design – Automated Deployment with Cloud Builder – Part 4: Generating SSL Certificates”

Quick Fix: The trust relationship between this workstation and the primary domain failed…

We’ve all been there…attempt to open an RDP session to a VM you haven’t connected to in a while and you see the message above! Traditionally the fix for this was to log on as a local admin user, remove the VM from the AD domain (add to workgroup), reboot, log in again, add to AD domain, reboot….well here is a quicker way of resolving the issue with PowerShell.

Modify the username, password and domain controller FQDN and save the following as ResetDomainMembership.ps1 and run on the affected VM as a local administrator


$password = "Password123!" | ConvertTo-SecureString -asPlainText -Force
$username = "domain\administrator"
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
Reset-ComputerMachinePassword -Server dc01.domain.local -credential $credential
shutdown -r -t 0

Tip: If you dont want to include the password in the script as this is a security concern you can use a Read-Host command to prompt the user for the password


$password = Read-Host -asSecureString "Please enter the password"

Shutdown/Power up a vSAN cluster with PowerCli

I have been doing a lot of lab testing lately and using  vCloud Director is a great way to be able to run side by side tests (sometimes destructive!) against multiple environments without requiring multiple physical clusters. I wanted to emulate a Dell EMC VxRail appliance so I created a 4 node nested vSAN cluster with a vCenter appliance & external PSC running on the cluster, to use as a vCD template. When creating vCD templates it is preferable to power down the environment before adding to the vCD catalog. When it comes to powering down this environment, because the vCenter & PSC are running on the cluster, there is a chicken and egg scenario as you need to power down in this order:

  1. vCenter
  2. PSC
  3. Put ESXi hosts in maintenance mode (vSAN aware operation)
  4. Power down ESXi hosts

The inverse applies when powering up the environment.  So rather than connect to multiple different interfaces to execute the power down or power up operations I put together the following Menu based PowerCli script with the following Options

These options will call the following functions

Option 1. Shutdown vSAN Cluster & PSC/vCenter

  • ConnectViServer $vCenterFQDN $vCenterUser $vCenterPassword
    • Generic function to connect to a VIServer (ESXi or vCenter). Just pass the hostname, user & password. This instance connects to vCenter as we need to perform a DRS operation.
  • ChangeDRSLevel $PartiallyAutomated
    • The ChangeDRSLevel function takes an argument for the level to set it to. In this case it sets it to partially Automated to stop DRS from moving VMs around.
  • MoveVMs
    • This function will move the VMs defined in $VMList to the host defined in $VMHost. This ensures that we know where the VMs are when we come to power the cluster back up
  • ConnectViServer $VMHost $VMHostUser $VMHostPassword
    • Generic function to connect to a VIServer (ESXi or vCenter). Just pass the hostname, user & password. This instance connects to the host defined in the $VMHost variable
  • ShutdownVM
    • This function will gracefully shutdown the VMs in the order defined in $VMList. In this case it will shutdown the vCenter first & then the PSC. This list can be expanded to include other VMs or could be refactored to use a CSV for a large list of VMs
  • EnterMaintenanceMode
    • This function will put all hosts defined in $VMHosts into maintenance mode. As this is a vSAN cluster it passes the NoAction flag to prevent any data moment or rebuild
  • ShutdownESXiHosts
    • This function will shutdown all hosts in the cluster

Option 2. Startup vSAN Cluster & PSC/vCenter

  • ExitMaintenanceMode
    • This function will exit all hosts from maintenance mode
  • ConnectViServer $VMHost $VMHostUser $VMHostPassword
    • Generic function to connect to a VIServer (ESXi or vCenter). Just pass the hostname, user & password. This instance connects to the host defined in the $VMHost variable
  • StartVMs
    • This function will startup the VMs in the reverse order defined in $VMList. In this case it will startup the PSC first & then the vCenter.
  • PollvCenter
    • This function will Poll vCenter until it is up and available
  • ConnectViServer $vCenterFQDN $vCenterUser $vCenterPassword
    • Generic function to connect to a VIServer (ESXi or vCenter). Just pass the hostname, user & password. This instance connects to vCenter as we need to perform a DRS operation
  • ChangeDRSLevel $FullyAutomated
    • The ChangeDRSLevel function takes an argument for the level to set it to. In this case it sets it to Fully Automated as we are done with the maintenance.

The script is posted to Github here and is also posted below. This was written and tested against vSphere 6. I will update it in the coming weeks for vSphere 6.5 and hopefully leverage some of the new APIs

# Script to shutdown & startup a vSAN cluster when vCenter/PSC are running on the cluster
# Created by Brian O'Connell | Dell EMC
# Provided with zero warranty! Please test before using in anger!
# @LifeOfBrianOC
# https://lifeofbrianoc.com/

## User Variables ##
$vCenterFQDN = "vcs01.domain.local"
$vCenterUser = "VC_Admin@domain.local"
$vCenterPassword = "Password123!"
$Cluster = "MARVIN-Virtual-SAN-Cluster"
$VMList = @("VCS01", "PSC01")
$VMHosts = @("esxi04.domain.local", "esxi05.domain.local", "esxi06.domain.local", "esxi07.domain.local")
$VMHost = "esxi04.domain.local"
$VMHostUser = "root"
$VMHostPassword = "Password123!"

### DO NOT MODIFY ANYTHING BELOW THIS LINE ###

# Add Required PowerCli Modules
Get-Module -ListAvailable VM* | Import-Module

# Function to Connect to VI Host (vCenter or ESXi). Pass host, username & password to the function
Function ConnectVIServer ($VIHost, $User, $Password) {
    Write-Host " "
    Write-Host "Connecting to $VIHost..." -Foregroundcolor yellow
    Connect-VIServer $VIHost -User $User -Password $Password | Out-Null
	Write-Host "Connected to $VIHost..." -Foregroundcolor Green
    Write-Host "------------------------------------------------" -Foregroundcolor Green
}

# Define DRS Levels to stop Vms from moving away from the defined host
$PartiallyAutomated = "PartiallyAutomated"
$FullyAutomated = "FullyAutomated"

# Function to Change DRS Automation level						
Function ChangeDRSLevel ($Level) {						

    Write-Host " "
    Write-Host "Changing cluster DRS Automation Level to Partially Automated" -Foregroundcolor yellow
    Get-Cluster $cluster | Set-Cluster -DrsAutomation $Level -confirm:$false | Out-Null
    Write-Host "------------------------------------------------" -Foregroundcolor yellow
}
						
# Function to Move the Vms to a defined host so they can be easily found when starting back up
Function MoveVMs {

    Foreach ($VM in $VMList) {
        # Power down VM
        Write-Host " "
        Write-Host "Moving $VM to $VMHost" -Foregroundcolor yellow
        Get-VM $VM | Move-VM -Destination $VMHost -Confirm:$false | Out-Null
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
    }   
    Disconnect-VIServer $vCenterFQDN -confirm:$false | Out-Null
}

# Function to Shutdown VMs
Function ShutdownVM  {

    Foreach ($VM in $VMList) {
        # Power down VM
        Write-Host " "
        Write-Host "Shutting down $VM" -Foregroundcolor yellow
        Shutdown-VMGuest $VM -Confirm:$false | Out-Null
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "Waiting for $VM to be Shutdown" -Foregroundcolor yellow
        # Check VM powerstate and wait until it is powered off before proceeding with the next VM
        do {
            sleep 15
            $powerState = (get-vm $VM).PowerState
        }
        while ($powerState -eq "PoweredOn")
        Write-Host " "
        Write-Host "$VM Shutdown.." -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow	
    }
}

# Function to put all ESXi hosts into maintenance mode with the No Action flag for vSAN data rebuilds
Function EnterMaintenanceMode {

    Foreach ($VMHost in $VMHosts) {
        Connect-VIServer $VMHost -User root -Password $VMHostPassword | Out-Null
        # Put Host into Maintenance Mode
        Write-Host " "
        Write-Host "Putting $VMHost into Maintenance Mode" -Foregroundcolor yellow
        Get-View -ViewType HostSystem -Filter @{"Name" = $VMHost }|?{!$_.Runtime.InMaintenanceMode}|%{$_.EnterMaintenanceMode(0, $false, (new-object VMware.Vim.HostMaintenanceSpec -Property @{vsanMode=(new-object VMware.Vim.VsanHostDecommissionMode -Property @{objectAction=[VMware.Vim.VsanHostDecommissionModeObjectAction]::NoAction})}))}
        Disconnect-VIServer $VMHost -confirm:$false | Out-Null
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "$VMHost in maintenance mode.." -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow	
    }
}

# Function to Exit hosts from maintenance mode
Function ExitMaintenanceMode {

    Foreach ($VMHost in $VMHosts) {
        Connect-VIServer $VMHost -User root -Password $VMHostPassword | Out-Null
        # Exit Maintenance Mode
        Write-Host " "
        Write-Host "Exiting Maintenance Mode for $VMHost" -Foregroundcolor yellow
        Set-VMHost $VMHost -State "Connected" | Out-Null
        Disconnect-VIServer $VMHost -confirm:$false | Out-Null
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "$VMHost out of maintenance mode.." -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow	
    }
    Write-Host "Waiting for vSAN Cluster to be Online" -Foregroundcolor yellow	
	Sleep 60							
}

# Function to shutdown hosts
Function ShutdownESXiHosts {

    Foreach ($VMHost in $VMHosts) {
        # Exit Maintenance Mode
        Write-Host " "
        Write-Host "Shutting down ESXi Hosts" -Foregroundcolor yellow
        Connect-VIServer -Server $VMHost -User root -Password $VMHostPassword | %{
            Get-VMHost -Server $_ | %{
                $_.ExtensionData.ShutdownHost_Task($TRUE) | Out-Null
            }
        }
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "ESXi host $VMHost shutdown.." -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow	
    }
		Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "All ESXi Hosts shutdown.." -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
}

# Function to Start VMs in the reverse order they were powered down									
Function StartVMs {
    # Reverse the VM list to start in reverse order
    [array]::Reverse($VMList)

    Foreach ($VM in $VMList) {
        # Power on VM
        Write-Host " "
        Write-Host "Powering on $VM" -Foregroundcolor yellow
        Start-VM $VM -Confirm:$false | Out-Null
        Write-Host "------------------------------------------------" -Foregroundcolor yellow
        Write-Host " "
        Write-Host "Waiting for $VM to be Powered On" -Foregroundcolor yellow
        # Check VM powerstate and wait until it is powered on before proceeding with the next VM
        do {
            sleep 15
            $powerState = (get-vm $VM).PowerState
        }
        while ($VM -eq "PoweredOff")
        Write-Host " "
        Write-Host "$VM Powered On..proceeding with next VM" -Foregroundcolor green
        Write-Host "------------------------------------------------" -Foregroundcolor yellow	
    }

}

# Function to Poll the status of vCenter after starting up the VM
Function PollvCenter {

    do 
    {
        try 
        {
            Write-Host " "
            Write-Host "Polling vCenter $vCenterFQDN Availability...." -ForegroundColor Yellow
            Write-Host "------------------------------------------------" -Foregroundcolor yellow
            # Create Web Request
            [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
            $HTTP_Request = [System.Net.WebRequest]::Create("https://$($vCenterFQDN):9443")

            # Get a response
            $HTTP_Response = $HTTP_Request.GetResponse()

            # Get the HTTP code
            $HTTP_Status = [int]$HTTP_Response.StatusCode

            If ($HTTP_Status -eq 200) { 
                Write-Host " "
                Write-Host "vCenter $vCenterFQDN is Available!"  -ForegroundColor Green
                Write-Host "------------------------------------------------" -Foregroundcolor Green
                # Close HTTP request
                $HTTP_Response.Close()
            }
        }
        catch { 
            Write-Host " "
            Write-Host "vCenter $vCenterFQDN Not Available Yet...Retrying Poll..."  -ForegroundColor Cyan
            Write-Host "------------------------------------------------" -Foregroundcolor Cyan
    } }
    While ($HTTP_Status -ne 200)	
}

# Function to display the main menu 
Function Menu 
{
    Clear-Host         
    Do
    {
        Clear-Host                                                                        
        Write-Host -Object 'Please choose an option'
        Write-Host     -Object '**********************'	
        Write-Host -Object 'vCenter & vSAN Maintenance Options' -Foregroundcolor Yellow
        Write-Host     -Object '**********************'
        Write-Host -Object '1.  Shutdown vSAN Cluster & PSC/vCenter '
        Write-Host -Object ''
        Write-Host -Object '2.  Startup vSAN Cluster & PSC/vCenter '
        Write-Host -Object ''
        Write-Host -Object 'Q.  Exit'
        Write-Host -Object $errout
        $Menu = Read-Host -Prompt '(Enter 1 - 2 or Q to quit)'

        switch ($Menu) 
        {
            1 
            {
				ConnectVIServer $vCenterFQDN $vCenterUser $vCenterPassword
                ChangeDRSLevel $PartiallyAutomated
                MoveVMs
                ConnectVIServer $VMHost $VMHostUser $VMHostPassword
                ShutdownVM
                EnterMaintenanceMode
                ShutdownESXiHosts   
            }
            2 
            { 
				ExitMaintenanceMode
                ConnectVIServer $VMHost $VMHostUser $VMHostPassword
                StartVMs
				PollvCenter
                ConnectVIServer $vCenterFQDN $vCenterUser $vCenterPassword
                ChangeDRSLevel $FullyAutomated
            }
            Q 
            {
                Exit
            }	
            default 
            {
                $errout = 'Invalid option please try again........Try 1-2 or Q only'
            }

        }
    }
    until ($Menu -eq 'q')
}   

# Launch The Menu
Menu