Chapter 3
Automating Networking

In this chapter, you will learn to:

Set Up the Network 76
  • Standard and Distributed vSwitches
  • Moving Multiple VMs to a New Port Group
  • VMware NSX

Networking is another critical component of a virtual environment. You need networking to provide vSphere hosts with management, possibly for IP storage functionality, and to connect VMs to one another and sometimes to the outside world. Whether you’re deploying a new cluster with new networking or maintaining and upgrading existing networking, automation can come to your rescue to help you save time and maintain consistency of configuration. We’ll also take a look at automating VMware’s software-defined networking product, NSX.

Set Up the Network

Networking is at the heart of vSphere configuration. After the physical network cables have been patched into your ESXi hosts, you will need to create vSwitches and port groups in order to make management connections to manage your hosts, VMkernel ports to connect to iSCSI and NFS storage (and for vMotion), and virtual machine port groups so that your VMs can communicate with other servers—both in the virtual and physical worlds.

Standard and Distributed vSwitches

First, you need to create at least one switch. You have two possible options: a standard vSwitch or a distributed vSwitch. A standard vSwitch extends only to the boundary of an individual host; a distributed vSwitch can extend across that boundary and can be accessed by multiple hosts. This relaxes the requirement that individual standard vSwitches be configured exactly the same across hosts. By definition, a distributed vSwitch appears the same to each host. Toward the end of this chapter, we will demonstrate how to migrate VMs from a standard to a distributed vSwitch.

Standard Switches

Let’s take a look at configuring standard vSwitches (VSS) and some of the options you have when working with them. Standard vSwitches must be configured identically across all hosts in a cluster to ensure that technologies like vMotion work correctly. Consequently, PowerCLI is a great choice for this job because you can easily make each vSwitch consistent.

Apart from those switches that VMware refers to as internal (switches that are isolated from the physical network), each switch you create must be assigned to at least one network card. So, before creating your vSwitches, it’s a good idea to know what network adapters are present in your host. You can use the Get-VMHostNetworkAdapter cmdlet to examine this information (Listing 3-1).

Listing 3-1: Examining VMHost network adapters

Get-VMHost vesxi05* | Get-VMHostNetworkAdapter |
  Format-Table Name,Mac,BitRatePerSec,PortGroupname,vMotionEnabled -AutoSize

This code will give you output similar to the following example. The information provided should be sufficient for you to identify which network cards should map to each of the vSwitches you have to create.

Name   Mac               BitRatePerSec PortGroupname      vMotionEnabled
----   ---               ------------- -------------      --------------
vmnic0 00:50:56:8a:77:43          1000
vmnic1 00:50:56:8a:b1:54          1000
vmnic2 00:50:56:8a:ca:87          1000
vmnic3 00:50:56:8a:36:e3          1000
vmnic4 00:50:56:8a:3a:65          1000
vmnic5 00:50:56:8a:dd:51          1000
vmk0   00:50:56:8a:77:43               Management Network False

Sometimes further information is required, particularly if you need to liaise with a dedicated network team that manages the physical switches. It is possible to extract Cisco Discovery Protocol information from the ESXi host and pass it on to the network team, who can then help you assign the right NICs to the right vSwitches. The Get-VMHostDetailedNetworkInfo function retrieves this information for an individual host or all hosts in a cluster (Listing 3-2).

Listing 3-2: Retrieving ESXi host networking information

function Get-VMHostDetailedNetworkInfo {
    <#
    .SYNOPSIS
        Retrieve ESXi Host Networking Info.
    .DESCRIPTION
        Retrieve ESXi Host Networking Info using CDP.
    .PARAMETER VMHost
        Name of Host to Query
    .PARAMETER Cluster
        Name of Cluster to Query
    .EXAMPLE
        Get-VMHostDetailedNetworkInfo -VMHost VMHost01 -Verbose
    .EXAMPLE
        Get-VMHostDetailedNetworkInfo -Cluster Cluster01 |
         Sort-Object Host,PNic |
         Export-Csv C:ScriptsCDP.csv -NoTypeInformation
    #>
[CmdletBinding(DefaultParametersetName="VMHost")]
    param(
        [Parameter(Mandatory=$true,ParameterSetName="VMHost",
        Position=0)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $VMHost,

        [Parameter(Mandatory=$true,ParameterSetName="Cluster",
        Position=0)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Cluster
    )


Write-Verbose "Gathering VMHost objects"

$arrHostSystemPropertiesToGet = "Name","ConfigManager.NetworkSystem", `
"Config.Network"

if ($Cluster){
     $vmhosts = Get-Cluster $Cluster | Get-VMHost |
     Where-Object {"Connected", "Maintenance" -contains $_.ConnectionState} | `
       Get-View -Property $arrHostSystemPropertiesToGet
    }
else {
    $vmhosts = Get-VMHost $VMHost -State Connected, Maintenance | `
       Get-View -Property $arrHostSystemPropertiesToGet
    }

$MyCol = @()
foreach ($vmwarehost in $vmhosts){
 $ESXHost = $vmwarehost.Name
 Write-Verbose "Collating information for $ESXHost"
 $networkSystem =
   Get-View $vmwarehost.ConfigManager.NetworkSystem
 foreach($pnic in $networkSystem.NetworkConfig.Pnic){
     $pnicInfo = $networkSystem.QueryNetworkHint($pnic.Device)
     foreach($Hint in $pnicInfo){
         $NetworkInfo = "" |
           Select-Object Host, PNic, Speed, MAC, DeviceID,
            PortID, Observed, VLAN
         $NetworkInfo.Host = $vmwarehost.Name
         $NetworkInfo.PNic = $Hint.Device
         $NetworkInfo.DeviceID = $Hint.connectedSwitchPort.DevId
         $NetworkInfo.PortID = $Hint.connectedSwitchPort.PortId
         $record = 0
         Do{
   If ($Hint.Device -eq
   $vmwarehost.Config.Network.Pnic[$record].Device){

   $NetworkInfo.Speed =
    $vmwarehost.Config.Network.Pnic[$record].LinkSpeed.SpeedMb
   $NetworkInfo.MAC =
    $vmwarehost.Config.Network.Pnic[$record].Mac
             }
             $record ++
         }
   Until ($record -eq ($vmwarehost.Config.Network.Pnic.Length))
         foreach ($obs in $Hint.Subnet){
             $NetworkInfo.Observed += $obs.IpSubnet + " "
             Foreach ($VLAN in $obs.VlanId){
                 if ($VLAN -eq $null){
                 }
                 else {
                     $strVLAN = $VLAN.ToString()
                     $NetworkInfo.VLAN += $strVLAN + " "
                 }
             }
         }
         $MyCol += $NetworkInfo
     }
 }
}
Write-Output $Mycol

}

Figure 3-1 shows the typical output when you pipe the result of Get-VMHostDetailedNetworkInfo to Export-Csv.

c03f001.tif

Figure 3-1: Host detailed network information

Now that you know which of your physical NICs should be allocated to which vSwitch, it’s time to start creating the switches. By default, an install of ESXi creates a virtual machine port group on the same vSwitch as the management NIC. Since you will want to have NICs dedicated to virtual machine traffic, let’s remove it. Use the Get-VirtualSwitch cmdlet to retrieve the default vSwitch0, the Get-VirtualPortGroup cmdlet to identify the default VM network port group, and finally the Remove-VirtualPortGroup to remove it (Listing 3-3).

Listing 3-3: Removing the default VM network port group

Get-VirtualSwitch -VMHost vesxi05* -Name vSwitch0 |
  Get-VirtualPortGroup -Name "VM Network" |
  Remove-VirtualPortGroup -Confirm:$false

Now let’s create a new vSwitch to serve virtual machines. In Listing 3-4, we assigned the switches to vmnic4 and vmnic5 that we earlier identified as being allocated for this vSwitch.

Listing 3-4: Creating a new standard vSwitch

$vSwitch = New-VirtualSwitch -VMHost vesxi05* -Name "vSwitch2" -Nic vmnic4,vmnic5

We stored the result of the command to create the new switch in the $vSwitch variable so that it can be instantly reused in the next command to create a port group for that vSwitch (Listing 3-5).

Listing 3-5: Creating a new port group

New-VirtualPortGroup -VirtualSwitch $vSwitch -Name VM220 -VLanId 220

Adding VMkernel Port Groups

In addition to creating vSwitches and port groups for virtual machines, it is also highly likely that you will need to create VMkernel port groups for use with technologies like vMotion or fault tolerance. As mentioned earlier, VMkernel port groups also are a requirement for iSCSI or NFS storage.

Let’s create a VMkernel port group for vMotion; we’ll create it as an additional port group for vSwitch0 (you’ll see why in the next section when we look at making switches and port groups resilient). In Listing 3-6, we retrieve vSwitch0 from the variable $vSwitch0. Next, we supply it to the New-VMHostNetworkAdapter to create the port group for vMotion by setting the VMotionEnabled parameter to $true.

Listing 3-6: Creating a VMKernel port group

$vSwitch0 = Get-VirtualSwitch -VMHost vesxi05* -Name "vSwitch0"
New-VMHostNetworkAdapter -VMHost vesxi05* `
  -PortGroup "vMotion" `
  -VirtualSwitch $vSwitch0 `
  -IP 192.168.1.10 `
  -SubnetMask 255.255.255.0 `
  -VMotionEnabled:$true

Hopefully in your environment, a separate VLAN will be used for vMotion network traffic. To configure the VLAN for the vMotion port group you just created, use the Set-VirtualPortGroup cmdlet (Listing 3-7).

Listing 3-7: Configuring the VLAN for a vMotion port group

$VMotionPG = Get-VirtualPortgroup -VMHost vesxi05* -Name vMotion
Set-VirtualPortGroup -VirtualPortGroup $VMotionPG -VLanId 101

The process for creating a VMkernel port group for IP-based storage is almost identical. Simply drop the -VMotionEnabled parameter from the command used to create the vMotion port group (Listing 3-8).

Listing 3-8: Creating a VMkernel port group for IP-based storage

$vSwitch1 = Get-VirtualSwitch -VMHost vesxi05* -Name "vSwitch1"
New-VMHostNetworkAdapter -VMHost vesxi05* `
  -PortGroup "iSCSI" `
  -VirtualSwitch $vSwitch1 `
  -IP 192.168.20.50 `
  -SubnetMask 255.255.255.0
$iSCSIPG = Get-VirtualPortgroup -VMHost vesxi05* -Name iSCSI
Set-VirtualPortGroup -VirtualPortGroup $iSCSIPG -VLanId 200

Making Your Switches and Port Groups Resilient

In the previous section, you created a vMotion port group. You added it to the existing vSwitch0, which already hosts the management network port group and has one NIC assigned, vmnic0. Obviously, as a good IT professional you need a plan for those times when things go wrong. So, allocating only one NIC to this configuration is not a very good idea. A better practice for this scenario is to add an additional NIC to the switch for resiliency. Better still, configure vmnic0 as the active adapter for the management network and standby adapter for the vMotion network, and vice versa for vmnic1.

The function Set-ManagementAndvMotionResilient takes the input of the host, the names of management and vMotion networks, and the NICs to use, and then sets the first NIC as the active adapter for the management network and standby adapter for the vMotion network, and vice versa for the second NIC (Listing 3-9).

Listing 3-9: Adding resiliency to the management and vMotion port groups

function Set-ManagementAndvMotionResilient {

<#
.SYNOPSIS
    Add resiliency to Management and vMotion Port Groups.
.DESCRIPTION
    Add resiliency to Management and vMotion Port Groups.
.PARAMETER VMHost
    Name of Host to configure
.PARAMETER Management
    Name of Management Network Port Group
.PARAMETER vMotion
    Name of vMotion Port Group
.PARAMETER NIC0
    Name of first NIC to use
.PARAMETER NIC1
    Name of second NIC to use
.EXAMPLE
    Set-ManagementAndvMotionResilient -VMhost Server01
      -Management 'Management Network'
      -vMotion vMotion -NIC0 vmnic0 -NIC1 vmnic4
.EXAMPLE
    Get-VMHost Server01,Server02 |
      Set-ManagementAndvMotionResilient
        -Management 'Management Network'
        -vMotion vMotion -NIC0 vmnic0 -NIC1 vmnic1
#>

[CmdletBinding()]
Param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true,
    HelpMessage='Name of Host to configure'
    )]
    [ValidateNotNullOrEmpty()]
    [PSObject[]]
    $VMHost,

    [ValidateNotNullOrEmpty()]
    [String]
    $Management = 'Management Network',

    [ValidateNotNullOrEmpty()]
    [String]
    $vMotion = 'vMotion',

    [ValidateNotNullOrEmpty()]
    [String]
    $NIC0 = 'vmnic0',

    [ValidateNotNullOrEmpty()]
    [String]
    $NIC1 = 'vmnic1'
)
begin {

}
process {

   try {

   foreach ($ESXiHost in $VMHost){

   if ($ESXiHost.GetType().Name -eq "string"){
   try {
     $ESXiHost = Get-VMHost $ESXiHost -ErrorAction Stop
   }
   catch [Exception]{
     Write-Warning "VMHost $ESXiHost does not exist"
     continue
   }
   }

   elseif ($ESXiHost -isnot
    [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]){
   Write-Warning "You did not pass a string or a VMHost object"
     continue
   }

   $ManagementNetworkPG = Get-VirtualPortgroup -VMHost $ESXiHost
     -Name $Management
   $VMotionPG = Get-VirtualPortgroup -VMHost $ESXiHost -Name $vMotion

   $oTmpOutput = $ManagementNetworkPG | Get-NicTeamingPolicy |
     Set-NicTeamingPolicy -MakeNicActive $NIC0
   $ManagementNetworkPG | Get-NicTeamingPolicy |
     Set-NicTeamingPolicy -MakeNicStandby $NIC1

   $oTmpOutput = $VMotionPG | Get-NicTeamingPolicy |
     Set-NicTeamingPolicy -MakeNicActive $NIC1
   $VMotionPG | Get-NicTeamingPolicy |
     Set-NicTeamingPolicy -MakeNicStandby $NIC0

   }
   }

   catch [Exception] {
     "Unable to set Management and vMotion Resilient"
   }
}
end {

}
}

Copying Networking Configuration from Another Host

When working with multiple ESXi hosts in a cluster, you must verify that the configuration of vSwitches and port groups is consistent and accurate across all hosts. This ensures that vMotion is possible for all virtual machines across all hosts in the cluster. If port groups are slightly misspelled across hosts, the wrong VLAN ID is entered for one port group, or maybe even a port group is missed, then you are going to have issues.

The larger the environment, the more likely it is that multiple vSwitches and port groups will be required per host. Configuration of these elements through the vSphere Client is laborious, tedious, and liable to lead to costly mistakes. vSphere 4 introduced host profiles to help with this configuration, but like the distributed vSwitch, the profiles are only available with Enterprise Plus licensing. So, the Copy-VMHostNetworking function enables you to specify source and target ESXi hosts. The vSwitches and port groups then are copied from the source host and created on the target host.

During the creation of each vSwitch we have assumed two vmnics per vSwitch and that the vmnics will be numbered identically across the two hosts; you can adjust this for your environment if necessary. Also we do not copy networking from vSwitch0; we are focusing on the VM port group configuration (Listing 3-10).

Listing 3-10: Copying switches and port groups from one host to another

function Copy-VMHostNetworking {

<#
.SYNOPSIS
    Copy Switches and Port Groups from one host to another.
.DESCRIPTION
    Copy Switches and Port Groups from one host to another.
.PARAMETER Source
    Name of Host to copy networking from
.PARAMETER Target
    Name of Host to copy networking to
.EXAMPLE
    Copy-VMHostNetworking -Source Server01 -Target Server02
#>

[CmdletBinding()]
Param(
    [parameter(Mandatory=$True,
    HelpMessage='Name of Host to copy networking from'
    )]
    [ValidateNotNullOrEmpty()]
    [String]
    $Source,

    [parameter(Mandatory=$True,
    HelpMessage='Name of Host to copy networking to'
    )]
    [ValidateNotNullOrEmpty()]
    [String]
    $Target
)

$SourceHost = Get-VMHost $Source
$TargetHost = Get-VMHost $Target

$SourceHost | Get-VirtualSwitch |
 Where-Object {$_.name -ne "vSwitch0"} | Foreach {
 $vSwitch = $_
 if (($TargetHost |
  Get-VirtualSwitch -Name $_.Name -ErrorAction SilentlyContinue) `
   -eq $null){

  Write-Verbose "Creating Virtual Switch $($_.Name)"
  $NewSwitch = $TargetHost |
    New-VirtualSwitch -Name $_.Name -Mtu $_.Mtu

    $FirstNIC = $vSwitch.Nic[0]
    $SecondNIC = $vSwitch.Nic[1]

`
      -VMHostPhysicalNic `
      (Get-VMHostNetworkAdapter -Name $FirstNIC,$SecondNIC -VMHost `
        $TargetHost) -Confirm:$false
 }
  $_ | Get-VirtualPortGroup | Foreach {

  if (($TargetHost |
   Get-VirtualPortGroup -Name $_.Name `
    -ErrorAction SilentlyContinue) -eq $null){
   Write-Verbose "Creating Portgroup $($_.Name)"
   $NewPortGroup = $TargetHost |
     Get-VirtualSwitch -Name $vSwitch.Name |
     New-VirtualPortGroup -Name $_.Name -VLanId $_.VLanID
   }
   }
}

}

Everything we have done so far has been for a single host. However, it is very straightforward to build on what you have learned and apply that knowledge to multiple hosts. You’ve seen how to extract networking information from a host, or create vSwitches and port groups and apply redundancy to them. All it would take would be a foreach loop with a list of servers to automate these tasks across multiple hosts.

Typically, a lot of the networking topics we have covered so far are carried out during the build of a host and not altered much during its lifetime. So, why not build up the networking cmdlets and functions into a sequence of tasks and add them to a script for postconfiguration tasks of a newly built host? That way, a lot of time can be saved in the deployment process and consistency of configuration can be guaranteed.

Distributed vSwitches

The previous section on standard vSwitches required a lot of additional effort around maintaining consistent configuration across hosts. In this section, we will look at the VMware vSphere distributed switch (VDS). The main feature of the VDS is the central point of management; you no longer need to create identical standard switches per vSphere host. VDS moves the configuration and control of the network to a top-level vCenter Server object. Because statistics are kept in the vCenter Server database and aren’t lost during a vMotion, you have the benefit of greater tracking and analysis.

If you’re accustomed to using a vSphere standard switch, the VDS can take a little getting used to. The biggest challenge is disassociating in your mind the network from the vSphere host. Previously, you had to work on a single host at a time. This process could be automated with PowerCLI, but still, the level and potential for mistakes made the VSS less than optimal. Let’s take a look at the two processes.

To configure a network using a VSS, follow these steps:

  1. Create a VSS.
  2. Add uplinks to the VSS.
  3. Create the port groups.
  4. Create the VMkernel ports.

With the new model using the VDS, the configuration now requires the following steps:

  1. Create a VDS.
  2. Configure the VDS uplink ports.
  3. Create the VDS port groups.
  4. Create the VMkernel ports.
  5. Add the vSphere hosts to the VDS binding your physical NIC (pNIC) to a VDS uplink port.

Wait a second! That’s even more steps. How is that easier?

Well, let’s compare the steps needed to add a new VM port group to an existing switch using VSS with the steps needed using VDS. For a VSS system, you must complete the following:

  1. Get the targeted VSS object.
  2. Create a new port group.
  3. Repeat steps 1 and 2 for each VMHost.

To add a VM port group to a VDS system, you need only complete two steps:

  1. Get the targeted VDS switch.
  2. Create the VDS port group.

All that and we removed one measly step? Yes, but the step we removed was the source of many unplanned outages over the years. By making the change once, you allow vCenter Server to ensure the VM port group is configured prior to binding a host. Making the change once ensures that you won’t accidentally vMotion a VM to a host with a mistyped VLAN ID. This may sound like a small thing—you saw earlier in this chapter how to use PowerCLI to automate certain steps and avoid those shortcomings—but take our word for it, this is a huge addition!

Now that we’ve briefly covered one small advantage a VDS offers, let’s build one. The VDS functionality is provided via a PowerShell module in PowerCLI v6 and adds to the standard PowerCLI functionality contained in the Core module. Use the Import-Module cmdlet to load the VDS module:

Import-Module VMware.VimAutomation.Vds

With the VDS PowerCLI module loaded, the code in Listing 3-11 produces a new DS built to the following specifications:

  • Datacenter: PROD01
  • Number of ports: 64
  • Uplink ports: 4

Listing 3-11: Creating a new vDS

$Datacenter = Get-Datacenter -Name 'PROD01'
$VDSwitch = New-VDSwitch -Name 'PROD01-vDS01'
  -Location $Datacenter -NumUplinkPorts 4

So far, so good. Next, add a distributed virtual port group (DVPG) to the VDS you created in Listing 3-11. Listing 3-12 will create the following DVPG:

  • Name: dvPG01
  • Number of ports: 256
  • VLAN: 42

Listing 3-12: Creating a new DVPG

New-VDPortgroup -Name 'dvPG01' -VDSwitch $VDSwitch -NumPorts 256 -VLanId 42

You could configure additional information on the VDS and DVPG, but let’s skip to the end and reveal the true power here. The code in Listing 3-13 will create a complete VDS that consists of the following:

PROD01-VDS02

  • Prod01 datacenter
  • 6 uplinks
  • Cisco Discovery Protocol (CDP) enabled, and set to Both
  • Administrator: Joe Bloggs
  • Administrator Contact: [email protected]
  • Network I/O control enabled
  • Virtual port groups
    • VDS02-VLAN22
      • 256 ports
      • VLAN: 22
      • Enable Promiscuous mode, MAC Address changes, and forged transmits
      • Uplink ports Active 2, 4; Standby 3
    • VDS02-Trunk01
      • 128 ports
      • VLANs: 7, 19, 25 – 28
      • Uplink ports Active 2, 4; Standby 3
    • VDS02-10.10.10.0
      • 128 ports
      • Private VLAN 108
      • Uplink ports Active 1

Listing 3-13: Provisioning a complete vDS

# Create and configure our new VDS
$Datacenter = Get-Datacenter -Name 'PROD01'
$VDSwitch02 = New-VDSwitch -Name 'PROD01-VDS02'
  -Location $Datacenter -NumUplinkPorts 6
  -LinkDiscoveryProtocol CDP -LinkDiscoveryProtocolOperation Both
  -ContactName 'Joe Bloggs'
  -ContactDetails '[email protected]'
  -Notes 'Production VDS02'
$VDSwitch02.ExtensionData.EnableNetworkResourceManagement($true)


# A regular DVPG
$VDPGRegular = $VDSwitch02 |
  New-VDPortgroup -Name 'VDS02-VLAN22' -NumPorts 256 -VLanId 22
$VDPGRegular | Get-VDSecurityPolicy | Set-VDSecurityPolicy
  -AllowPromiscuous $true -MacChanges $true
  -ForgedTransmits $true
$VDPGRegular | Get-VDUplinkTeamingPolicy |
  Set-VDUplinkTeamingPolicy
    -ActiveUplinkPort 'dvUplink2','dvUplink4'
    -StandbyUplinkPort 'dvUplink3'
    -UnusedUplinkPort 'dvUplink1','dvUplink5','dvUplink6'

# A Trunked DVPG
$VDPTrunk = $VDSwitch02 | New-VDPortgroup -Name 'VDS02-Trunk01'
  -VlanTrunkRange '7,19,25-28'
$VDPTrunk | Get-VDUplinkTeamingPolicy |
  Set-VDUplinkTeamingPolicy
    -ActiveUplinkPort 'dvUplink2','dvUplink4'
    -StandbyUplinkPort 'dvUplink3'
    -UnusedUplinkPort 'dvUplink1','dvUplink5','dvUplink6'


# A Private VLAN
$VDSwitch02 | New-VDSwitchPrivateVlan -PrimaryVlanId 108
  -SecondaryVlanId 108 -PrivateVlanType Promiscuous
$VDPPrivate = $VDSwitch02 |
  New-VDPortgroup -Name 'VDS02-10.10.10.0'
$VDPPrivate | Set-VDVlanConfiguration -PrivateVlanId 108
$VDPPrivate | Get-VDUplinkTeamingPolicy |
  Set-VDUplinkTeamingPolicy -ActiveUplinkPort 'dvUplink1'
    -UnusedUplinkPort 'dvUplink2','dvUplink3','dvUplink4',
    'dvUplink5','dvUplink6'

The only thing left is to assign hosts to the DVUplink ports and you’re ready to host VMs. To do this, first test a given host for compatibility. To assist in this task, you can enlist the Get-DistributedSwitchCandidate function, which was originally included in the previously mentioned distributed switch module created for the first edition of this book. Since this functionality is not included in the official PowerCLI VDS module, it is included in Listing 3-14 for your convenience.

Listing 3-14: Testing hosts for VDS compatibility

function Get-DistributedSwitchCandidate {
<#
.SYNOPSIS
    Find VMHosts compatible with the given Distributed Switch.
.DESCRIPTION
    Find VMHosts compatible with the given Distributed Switch.
.PARAMETER VIObject
    Inventory object to query for compatible VMHosts.
    Supported types of objects for this parameter are Datacenter
    , ComputeResource and Folder
.PARAMETER DistributedSwitch
    The vDS to test against. Note: this parameter supports regular
    expressions, not traditional wildcards
.PARAMETER Recurse
    Recursively search for compatible hosts.
.EXAMPLE
    Get-DistributedSwitchCandidate -VIObject
    (Get-Cluster Cluster01) -DistributedSwitch vDS01
.EXAMPLE
    Get-Datacenter Prod01 | Get-DistributedSwitchCandidate
    -DistributedSwitch vDS01 -Recurse
#>
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,
    ValueFromPipeline=$true)]
    [ValidateNotNullOrEmpty()]
    [VMware.VimAutomation.Sdk.Types.V1.VIObject]
    $VIObject,

    [Parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [ValidateNotNullOrEmpty()]
    [String]
    $DistributedSwitch,

    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [Switch]
    $Recurse
)
begin
{
    $dvSwitchManager =
     Get-View (Get-View ServiceInstance).content.dvSwitchManager
}
process
{
    $vds = Get-View -ViewType "VmwareDistributedVirtualSwitch" `
        -Filter @{'Name'=$DistributedSwitch}
    if (-Not $vds)
    {
        Write-Warning "$Name not found!"
        continue;
    }
    if ($Recurse){$r = $True}else{$r = $False}

    $Moref = $VIObject | Get-View |
      Select-Object -ExpandProperty MoRef

    try
    {
        Get-VIObjectByVIView `
         $dvSwitchManager.QueryCompatibleHostForExistingDvs($Moref, `
           $r, $Vds.MoRef)
    }
    catch
    {
        Write-Warning "No compatible host found in $($VIObject.name)"
    }
}
}

For the next exercise, we’re interested in identifying any VMHost in the Prod01 production datacenter that is capable of being added to our new VDS (Listing 3-15).

Listing 3-15: Finding vDS VMHost candidates

Get-Datacenter PROD01 | Get-DistributedSwitchCandidate
  -DistributedSwitch 'PROD01-VDS02' -Recurse


Name                 ConnectionState PowerState
----                 --------------- ----------
vesxi05.sunnydale... Connected       PoweredOn
vesxi06.sunnydale... Connected       PoweredOn

The code in Listing 3-15 successfully located two vSphere hosts that can be added to our new VDS. Next, identify the pNIC that will bind to the VDS uplinks. Remember, you can use the Get-VMHostDetailedNetworkInfo function from Listing 3-2 to help identify the correct pNICs to assign to the right places.

Now you’re ready to add your hosts. To accomplish this task, use the code shown in Listing 3-16 to add the following:

  • VMHost: vesxi06
  • pNIC: vmnic2, vmnic3, vminc4, vmnic5
  • vDS: PROD01-VDS02

Listing 3-16: Adding a VMHost to a vDS

$VMHost = Get-VMHost 'vesxi06*'
$NetworkAdapters = $VMHost |
  Get-VMHostNetworkAdapter `
    -Name vmnic2,vmnic3,vmnic4,vmnic5 -Physical
$VDSwitch02 = Get-VDSwitch -Name 'PROD01-VDS02'
Add-VDSwitchVMHost -VDSwitch $VDSwitch02 -VMHost $VMHost
Add-VDSwitchPhysicalNetworkAdapter `
  -DistributedSwitch $VDSWitch02 `
  -VMHostPhysicalNic $NetworkAdapters -Confirm:$false

There you have it—from nothing to a VDS ready to host VMs. Now, if you’re thinking, “I bet that could all be combined into one step,” you’d be right! Take what you learned from the VDS listings and combine the steps into a single script.

If you wish to modify the pNIC mappings after the fact, you’ll need to use the Remove-VDSwitchPhysicalNetworkAdapter cmdlet, as shown in Listing 3-17.

Listing 3-17: Modifying an existing vDS-to-VMHost pNIC mapping

# Remove Adapters vmnic4 and vmnic5
$VMHost | Get-VMHostNetworkAdapter -Name vmnic4,vmnic5 -Physical |
  Remove-VDSwitchPhysicalNetworkAdapter -Confirm:$false

If you need to remove a host completely, you can do so with the Remove-VDSwitchVMHost cmdlet (Listing 3-18). You can remove a host (in our example, vesxi06) completely from the distributed switch (PROD01-VDS02). This cmdlet is especially handy if you’re trying to remove a vSphere host from vCenter Server.

Listing 3-18: Removing a VMHost from a VDS

$VMHost = Get-VMHost 'vesxi06*'
$VDSwitch02 = Get-VDSwitch -Name 'PROD01-VDS02'
$VDSwitch02 | Remove-VDSwitchVMHost -VMHost $VMHost -Confirm:$false

So, what about VMkernel network adapters in a DVPG? While a little more complicated than their VSS cousins, not only can they be used, they can also be automated using PowerCLI. In Listing 3-19, we’re creating a new VDS network adapter that meets the following specifications:

  • VDS: PROD-VDS02
  • DVPG: vMotion, VLAN 853
  • vSphere host: vesxi06
  • IP: 192.168.2.40/24
  • vMotion enabled

Listing 3-19: Creating network adapters on a DVPG

$VMHost = Get-VMHost 'vesxi06*'
$VDSwitch02 = Get-VDSwitch -Name 'PROD01-VDS02'
$vMotionDVPG = $VDSwitch02 | New-VDPortgroup -Name 'vMotion'
  -VlanId 853
$vmk = New-VMHostNetworkAdapter -VMHost $VMHost
  -PortGroup $vMotionDVPG -VirtualSwitch $VDSwitch02
  -IP 192.168.2.40 -SubnetMask 255.255.255.0
$vmk | Set-VMHostNetworkAdapter -VMotionEnabled:$true
  -Confirm:$false

Follow-on management is straightforward with the Set-VMHostNetworkAdapter cmdlet for updating settings and Remove-VMHostNetworkAdapter for removing an adapter.

You will quickly realize the power these functions provide when you have to do something such as enable fault tolerance (FT) logging on a VMkernel network adapter across an entire cluster. As shown in Listing 3-20, even this task is a snap in PowerCLI.

Listing 3-20: Enabling FT logging across a cluster

[System.Collections.ArrayList]$IPAddresses = '192.168.5.10', '192.168.5.11'
$VDSwitch02 = Get-VDSwitch -Name 'PROD01-VDS02'
$FTDVPG = $VDSwitch02 | New-VDPortgroup -Name 'FT' -VlanId 700
foreach ($VMHost in (Get-Cluster Cluster01 | Get-VMHost)){

  $vmkFT = New-VMHostNetworkAdapter -VMHost $VMHost `
    -PortGroup $FTDVPG -VirtualSwitch $VDSwitch02 `
    -IP $IPAddresses[0] -SubnetMask 255.255.255.0
  $vmkFT | Set-VMHostNetworkAdapter `
    -FaultToleranceLoggingEnabled:$true -Confirm:$false
  $IPAddresses.RemoveAt(0)

}

Creating a Copy of a Distributed Switch

If there is a requirement to deploy a new distributed switch, it might require configuration consistent with those already existing in your vCenter for items such as the Discovery Protocol and the Administrator Contact details. The VDS module contains a method to do this via the New-VDSwitch cmdlet. Listing 3-21 demonstrates how to copy the configuration from the PROD01-VDS02 VDS to create a new one. Use the -WithoutPortGroups parameter if the port groups do not have to be copied.

Listing 3-21: Creating a Copy of a VDS

$Datacenter = Get-Datacenter -Name 'PROD01'
$VDSwitch02 = Get-VDSwitch -Name 'PROD01-VDS02'
$VDSwitch02 | New-VDSwitch -Name 'PROD01-VDS03' `
  -WithoutPortGroups -Location $Datacenter

Back Up and Restore a Distributed Switch

More functionality included with the VDS module is the possibility to back up the configuration of a VDS and its port groups to a locally stored file, and to later take that file and restore the VDS to vCenter.

Listing 3-22 creates a backup of the PROD01-VDS02 VDS.

Listing 3-22: Backing up a distributed switch

Get-VDSwitch -Name 'PROD01-VDS02' | Export-VDSwitch `
  -Description "PROD01-VDS02 Switch Config" `
  -Destination "C:ScriptsPROD01-VDS02SwitchConfig.zip"

Listing 3-23 restores the PROD01-VDS02 VDS from the backup file created in Listing 3-22.

Listing 3-23: Restoring a distributed switch

New-VDSwitch -Name 'PROD01-VDS02' -Location $Datacenter `
  -BackupPath "C:ScriptsPROD01-VDS02SwitchConfig.zip"

Moving Multiple VMs to a New Port Group

A common admin task is moving VMs from one port group to another. Maybe there are behind-the-scenes networking changes that involve a redesign of the network, a change to VLANs, or possibly a migration from standard to distributed switches. The Move-VMToNewPortGroup function takes source and target port groups as input, finds each VM in the source port group, and moves them to the new port group (Listing 3-24).

Listing 3-24: Moving VMs from one port group to another

function Move-VMToNewPortGroup {

<#
.SYNOPSIS
    Move VMs from one Port Group to another.
.DESCRIPTION
    Move VMs from one Port Group to another.
.PARAMETER Source
    Name of Port Group to move from
.PARAMETER Target
    Name of Port Group to move to
.PARAMETER Cluster
    Name of Cluster containing VMs
.EXAMPLE
    Move-VMToNewPortGroup -Source PortGroup01
     -Target PortGroup02 -Cluster Cluster01
#>
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
    [parameter(Mandatory=$true,
    HelpMessage='Name of Port Group to move from'
    )]
    [ValidateNotNullOrEmpty()]
    [String]
    $Source,

    [parameter(Mandatory=$true,
    HelpMessage='Name of Port Group to move to'
    )]
    [ValidateNotNullOrEmpty()]
    [String]
    $Target,

    [ValidateNotNullOrEmpty()]
    [String]
    $Cluster
)

    try {
        if ($Cluster){

        Get-Cluster $Cluster | Get-VM | Get-NetworkAdapter |
         Where-Object {$_.NetworkName -eq $Source } |
          Set-NetworkAdapter -Portgroup $Target -Confirm:$false
        }
        else {

        Get-VM | Get-NetworkAdapter |
         Where-Object {$_.NetworkName -eq $Source } |
          Set-NetworkAdapter -Portgroup $Target -Confirm:$false
        }
    }
    catch [Exception]{
      throw "Unable to move VMs from source to target Port Group"
    }
}

A similar admin task is to rename a port group. If you carry out this task on a standard vSwitch in the vSphere client, then any VM with a connection to that port group will appear to be disconnected from the vSwitch. This will have no immediate impact on a running VM; however, upon restart of the VM its NIC will be disconnected and consequently it will not be able to communicate on the network. But now that the Move-VMToNewPortGroup function is available, you can be smart and also use this function to rename a port group, albeit indirectly. All you need to do is create a new port group with the new name for the port group, and then move the VMs from the old to the new port group.

You can also use the Move-VMToNewPortGroup function to migrate VMs from a standard vSwitch to a new distributed vSwitch. In fact, it is no different than moving them between two standard vSwitches (Listing 3-25).

Listing 3-25: Migrating VMs from a standard to a distributed port group

Move-VMToNewPortGroup -Source StandardPortGroup01 -Target
  DistributedPortGroup01 -Cluster Cluster01

VMware NSX

Now that we have discussed ways to configure and administer both standard and distributed switches, we will briefly discuss another aspect of virtual networking. NSX, VMware’s product for software-defined networking (SDN) has a number of advanced features that allow for even more control and configuration of the networking aspect of your virtual environment.

To cover NSX in its entirety would require a whole book dedicated to descriptions of the features and how to configure them. To remain in the confines of this networking chapter, we will briefly discuss the steps to deploy NSX and configure its prerequisites. For information about features and configuration beyond this, see the NSX API Guide (the API guide for NSX 6.2 can be found here: http://vmw.re/1LhfO6B) or other sources. The requirements for NSX also are outside the scope of this book. However, before deploying and using NSX, you must ensure that all requirements for the product have been satisfied.

Deploying NSX

As of PowerCLI 5.8r1, you can now deploy virtual appliances with a set configuration, using the Get-OvfConfiguration and Import-VApp cmdlets. As of this writing, PowerCLI must be connected to a vCenter Server to accomplish this task. Once connected to vCenter Server, a variable is created with the Get-OvfConfiguration cmdlet, creating a configuration object. Once the object has been populated with the desired configuration, it is imported using the Import-VApp cmdlet. Listing 3-26 shows how this is done.

Listing 3-26: Deploying NSX with a configuration

$ovfconfig = Get-OvfConfiguration -Ovf Z:NSXVMware-NSX-Manager-6.1.2-2318232.ova

$ovfconfig.common.vsm_cli_en_passwd_0.value = "VMware1!"
$ovfconfig.common.vsm_cli_passwd_0.value = "VMware1!"
$ovfconfig.Common.vsm_hostname.value = "NSX.MyDomain.local"
$ovfconfig.Common.vsm_ip_0.value = "10.144.99.21"
$ovfconfig.Common.vsm_netmask_0.Value = "255.255.255.0"
$ovfconfig.Common.vsm_gateway_0.value = "10.144.99.1"
$ovfconfig.Common.vsm_dns1_0.value = "10.144.99.5"
$ovfconfig.Common.vsm_isSSHEnabled.value = $true

Import-VApp -Source Z:NSXVMware-NSX-Manager-6.1.2-2318232.ova `
-OvfConfiguration $ovfconfig -Name "MGMT-NSX" `
-Datastore "ISCSI-SSD-900GB" -DiskStorageFormat thin `
-VMhost (Get-Cluster "Main-CL" | Get-VMHost | where `
{$_.ConnectionState -eq "Connected" -and $_.PowerState `
-eq "PoweredOn"} | Get-Random)

Get-VM "MGMT-NSX" | Start-VM

Once NSX is up and running, you can communicate with it via a REST-based API. If this is your first time using REST, this may seem a little daunting. However, once you have the basic properties set up for the REST call, you’ll notice it’s much easier than it looks. There are plenty of helpful tutorials online as well as a section on REST in Chapter 21, “vRealize Orchestrator.”

Once your NSX Manager has been deployed and powered on, you can connect it to vCenter. This could be done by logging into the NSX Manager Configuration page and navigating through the GUI. Since this book is about automating tasks, we’ll bypass the GUI and go straight for the code. Listing 3-27 demonstrates how this is accomplished.

Listing 3-27: Connecting vCenter Server to NSX Manager

function Connect-vCenter {
<#
.SYNOPSIS
    Connect vCenter Server to NSX Manager
.DESCRIPTION
    Connect vCenter Server to NSX Manager
.PARAMETER NSXIP
    NSX IP Address
.PARAMETER vCIP
    vCenter FQDN or IP Address
.PARAMETER NSXPassword
    The NSX Admin password given during deploy
.PARAMETER Credential
    PS Credential Object
.EXAMPLE
    $Credential = Get-Credential
    Connect-vCenter -NSXIP 10.144.99.22 -NSXPassword VMware1! `
 -vCIP 10.144.99.15 -Credential $Credential
#>
    Param (
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXPassword,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$vCIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [PSCredential]$Credential
    )

try {

    # --- Get vCenter Thumbprint
    [System.Net.ServicePointManager]::`
    ServerCertificateValidationCallback = {$true}
    $vCenter = [System.Net.Webrequest]::`
    Create("https://$vCIP")
    $vCenter.GetResponse()
    $Thumb = $vCenter.ServicePoint.Certificate.GetCertHashString()
    $Thumb = $Thumb -replace '(..(?!$))','$1:'
    $Thumb
    # --- Convert Credential Object to Username and Password

    $vcuser = $Credential.UserName
    $vcpass = $Credential.GetNetworkCredential().Password
    # --- Deal with certificate issues
    # --- Note: this will cause the cert handling behavior for the current
    # --- PowerShell session to trust all certs whether they are valid,
    # --- self-signed, invalid, etc
    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

   # --- Create REST Headers
   $Auth = "admin" + ':' + $NSXPassword
   $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
   $EncodedPassword = [System.Convert]::ToBase64String($Encoded)
   $Headers = @{"Authorization"="Basic $($EncodedPassword)";}

    # --- Send REST call and process results

    $uri = "https://$NSXIP/api/2.0/services/vcconfig"
    $body = "<vcInfo><ipAddress>$vCIP</ipAddress>"
    $body += "<userName>$vcuser</userName><password>"
    $body += "$vcpass</password><certificateThumbprint>"
    $body += "$thumb</certificateThumbprint>"
    $body += "<assignRoleToUser>true</assignRoleToUser>"
    $body += "</vcInfo>"

    $ConnectVC = Invoke-RestMethod -Method Put -Uri $uri `
    -Headers $Headers -ContentType "application/xml" -body $body

    $QueryVC = Invoke-RestMethod -Method Get -Uri $uri `
    -Headers $Headers -ContentType "application/xml"
    if($QueryVC) { Write-host "NSX Manager Connected"}
}
catch [Exception]{

     throw "Unable to connect NSX with vCenter"
}
}

Adding an IP Pool for NSX Controllers

The NSX controller is the mechanism that stores information on and controls the logical networks created in NSX. A deep dive on the NSX technology and its functions is outside the scope of this book—just know that NSX controllers must exist in order for NSX to work. Before you can deploy an NSX controller, you must add an IP pool for the NSX controllers, Virtual Extensible LANs (VXLANs), and VXLAN Tunnel Endpoints (VTEPs) to pull from. These IP pools are not the same as IP pools found within vCenter Server. Listing 3-28 is a function that creates an NSX IP pool.

Listing 3-28: Creating an IP pool for NSX controller consumption

function New-IPPool {
<#
.SYNOPSIS
    Add IP Pool for NSX Controller Consumption
.DESCRIPTION
    Add IP Pool for NSX Controller Consumption
.PARAMETER NSXIP
    NSX IP Address
.PARAMETER NSXPassword
    The NSX Admin password given during deploy
.PARAMETER IPPool
    Name of IP Pool being created
.PARAMETER Prefix
    Network Prefix
.PARAMETER gateway
    Network gateway
.PARAMETER dnssuffix
    dns suffix of network
.PARAMETER dns1
    DNS Server
.PARAMETER IPStart
    Starting IP address for IP Pool
.PARAMETER IPEnd
    Ending IP address for IP Pool

.EXAMPLE
    New-IPPool -NSXIP 10.144.99.22 -NSXPassword VMware1! `
 -IPPool rest-ippool-01 -Prefix 24 -gateway 10.144.99.1 `
 -dnssuffix "lab.local" -dns1 10.144.99.5 -IPStart `
10.144.99.31 -IPEnd 10.144.99.36
#>
    Param (
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXPassword,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$IPPool,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$prefix,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$gateway,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$dnssuffix,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$dns1,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$IPStart,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$IPEnd
)

try {

    # --- Deal with certificate issues
    # --- Note: this will cause the cert handling behavior for the current
    # --- PowerShell session to trust all certs whether they are valid,
    # --- self-signed, invalid, etc
    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

   # --- Create REST Headers
   $Auth = "admin" + ':' + $NSXPassword
   $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
   $EncodedPassword = [System.Convert]::ToBase64String($Encoded)
   $Headers = @{"Authorization"="Basic $($EncodedPassword)";}

    # --- Send REST call and process results
    $address = "https://$NSXIP/api/"
    $path = "2.0/services/ipam/pools/scope/globalroot-0"
    $uri = "$address$path"
    $body = "<ipamAddressPool><name>$IPPool</name>"
    $body += "<prefixLength>$prefix</prefixLength>"
    $body += "<gateway>$gateway</gateway>"
    $body += "<dnsSuffix>$dnssuffix</dnsSuffix>"
    $body += "<dnsServer1>$dns1</dnsServer1>"
    $body += "<ipRanges><ipRangeDto><startAddress>"
    $body += "$IPStart</startAddress><endAddress>"
    $body += "$IPEnd</endAddress></ipRangeDto>"
    $body += "</ipRanges></ipamAddressPool>"

    $CreatePool = Invoke-RestMethod -Method Post -Uri $uri `
    -Headers $Headers -ContentType "application/xml" -body $body

    $queryPool = Invoke-RestMethod -Method Get -Uri $uri `
    -Headers $Headers -ContentType "application/xml"
    $Pool = $queryPool.ipamAddressPools.ChildNodes | where `
    {$_.Name -eq "$IPPool"}
    $Pool
}
catch [Exception]{

    throw "Error occurred while trying to create IPPool"
}
}

Adding NSX Controllers

Now that you’ve satisfied the requirements to create an NSX controller, you can add one to the environment. Check the most up-to-date documentation from VMware to determine the recommended number of NSX controllers for your environment. Listing 3-29 details how to add an NSX controller.

Listing 3-29: Adding an NSX controller to your environment

function New-NSXController {
<#
.SYNOPSIS
    Add NSX Controller
.DESCRIPTION
    Add NSX Controller
.PARAMETER NSXIP
    NSX IP Address
.PARAMETER NSXPassword
    The NSX Admin password given during deploy
.PARAMETER IPPoolName
    Name of IP Pool being used
.PARAMETER ControllerName
    New Name for the Controller
.PARAMETER DESCRIPTION
    Description of the controller
.PARAMETER Cluster
    Name of Cluster being deployed to
.PARAMETER Datastore
    Name of Datastore being deployed to
.PARAMETER Network
    Name of Network being deployed to
.PARAMETER Size
    small, medium, or large
.PARAMETER Password
    must be at least 12 characters and strong

.EXAMPLE
   New-NSXController -NSXIP 10.144.99.22 -NSXPassword VMware1! `
   -IPPoolName "REST-IP-1" -controllername "Controller-01" `
   -Cluster "main-CL" -Datastore "iSCSI-SSD-900" `
   -Network "vDS-Main" -size small -password "VMware1!VMware1!"
#>
    Param (
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXPassword,

    [Parameter(Mandatory=$true,HelpMessage="Name of IP Pool")]
    [ValidateNotNullOrEmpty()]
    [String]$IPPoolName,

    [Parameter(Mandatory=$true,HelpMessage="Controller Name")]
    [ValidateNotNullOrEmpty()]
    [String]$ControllerName,

    [parameter(Mandatory=$false)]
    [ValidateNotNullOrEmpty()]
    [String]$Description,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$Cluster,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$Datastore,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$PortGroup,

[Parameter(Mandatory=$true,HelpMessage="small,medium,large")]
    [ValidateNotNullOrEmpty()]
    [String]$Size,

    [Parameter(Mandatory=$true,HelpMessage=" > 12 characters ")]
    [ValidateNotNullOrEmpty()]
    [String]$Password
)
try {
    # --- Deal with certificate issues
    # --- Note: this will cause the cert handling behavior for the current
    # --- PowerShell session to trust all certs whether they are valid,
    # --- self-signed, invalid, etc
    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

   # --- Create REST Headers
   $Auth = "admin" + ':' + $NSXPassword
   $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
   $EncodedPassword = [System.Convert]::ToBase64String($Encoded)
   $Headers = @{"Authorization"="Basic $($EncodedPassword)";}
   $ClusterID = Get-Cluster $cluster | Get-View -Property Name
   $DSID = Get-Datastore $datastore | Get-View -Property Name
   $NetworkID = Get-VDPortgroup $PortGroup | Get-View -Property Name

    # --- Send REST call and process results
    $address = "https://$NSXIP/api"
    $path = "/2.0/services/ipam/pools/scope/globalroot-0"
    $GETuri = "$address$path"
    $Scope = Invoke-RestMethod -Method get -Uri $GETuri `
    -Headers $Headers -ContentType "application/xml"
    $id = $scope.ipamAddressPools.ipamAddressPool | `
    where {$_.name -eq $IPPoolName}

    $uri = "https://$NSXIP/api/2.0/vdn/controller"
    $body = "<controllerSpec><name>$controllername</name>"
    $body += "<description>$description</description>"
    $body += "<ipPoolId>$($id.objectId)</ipPoolId>"
    $body += "<resourcePoolId>$($ClusterID.MoRef.Value)"
    $body += "</resourcePoolId><datastoreId>"
    $body += "$($DSID.MoRef.Value)</datastoreId>"
    $body += "<deployType>$size</deployType>"
    $body += "<networkId>$($NetworkID.MoRef.value)"
    $body += "</networkId><password>$password"
    $body += "</password></controllerSpec>"

    $Controller = Invoke-RestMethod -Method Post -Uri $uri `
    -Headers $Headers -ContentType "application/xml" -body $body

    $QueryController = Invoke-RestMethod -Method Get -Uri $uri `
    -Headers $Headers -ContentType "application/xml"
    if ($QueryController) {Write-Host "Deploying"}
    }
catch [Exception]{

     throw "Error occurred while trying to add Controller"
}
}

Install Network Virtualization Components

Once you’ve added your NSX controllers, you can prepare the hosts in your selected cluster for NSX. Each host in the target cluster must be prepared by installing additional software on the host to handle the network traffic. You can complete this process by clicking Installation ⇒ Host Preparation ⇒ Install in the vSphere Web Client; the software will be installed on all hosts in the target cluster. You can perform this function using the REST-based API, as shown in Listing 3-30.

Listing 3-30: Performing host preparation tasks for NSX

function Set-NSXHostPrep {
<#
.SYNOPSIS
    Perform Host Preparation tasks
.DESCRIPTION
    Perform Host Preparation tasks
.PARAMETER NSXIP
    NSX IP Address
.PARAMETER NSXPassword
    The NSX Admin password given during deploy
.PARAMETER Cluster
    Name of the target cluster

.EXAMPLE
   Set-NSXHostPrep -NSXIP 10.144.99.22 -NSXPassword VMware1! `
    -Cluster "Main-CL"
#>
    Param (
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXPassword,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$Cluster,
    )

try {
    # --- Deal with certificate issues
    # --- Note: this will cause the cert handling behavior for the current
    # --- PowerShell session to trust all certs whether they are valid,
    # --- self-signed, invalid, etc
    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

   # --- Create REST Headers
   $Auth = "admin" + ':' + $NSXPassword
   $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
   $EncodedPassword = [System.Convert]::ToBase64String($Encoded)
   $Headers = @{"Authorization"="Basic $($EncodedPassword)";}
   $ClustID = Get-Cluster $cluster | Get-View -Property Name

    # --- Send REST call and process results

    $uri = "https://$NSXIP/api/2.0/nwfabric/configure"
    $body = "<nwFabricFeatureConfig><resourceConfig>"
    $body += "<resourceId>$($ClustID.MoRef.Value)</resourceId>"
    $body += "</resourceConfig></nwFabricFeatureConfig>"

    $PrepHosts = Invoke-RestMethod -Method Post -Uri $uri `
    -Headers $Headers -ContentType "application/xml" -body $body

	Write-host "Host Preparation initiated"
    }
catch [Exception]{

    throw "Error occurred while trying to prepare hosts"
}
}

Install and Configure VXLAN

Now that your hosts have been prepared, the only thing left to do in preparation for creating your logical networks and logical switches is to install and configure VXLAN on these hosts. VXLAN enables the creation of a Layer 2 network on top of Layer 3; see Listing 3-31.

Listing 3-31: Installing and configuring VXLAN

function Install-VXLAN {
<#
.SYNOPSIS
    Install VXLAN on Cluster
.DESCRIPTION
    Install VXLAN on Cluster
.PARAMETER NSXIP
    NSX IP Address
.PARAMETER NSXPassword
    The NSX Admin password given during deploy
.PARAMETER Cluster
    Name of the target cluster
.PARAMETER DVS
    Name of Distributed Switch

.EXAMPLE
   Install-VXLAN -NSXIP 10.144.99.22 -NSXPassword VMware1! `
    -Cluster "Main-CL" -DVS "vDS-Main"
#>
    Param (
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXIP,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$NSXPassword,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$Cluster,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$DVS
    )

try {
    # --- Deal with certificate issues
    # --- Note: this will cause the cert handling behavior for the current
    # --- PowerShell session to trust all certs whether they are valid,
    # --- self-signed, invalid, etc
    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

    # --- Create REST Headers
    $Auth = "admin" + ':' + $NSXPassword
    $Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
    $EncodedPassword = [System.Convert]::ToBase64String($Encoded)
    $Headers = @{"Authorization"="Basic $($EncodedPassword)";}
    $ClID = Get-Cluster $cluster | Get-View -Property Name
    $NetID = Get-VDSwitch $DVS | Get-View -Property Name

    # --- Send REST call and process results

    $uri = "https://$NSXIP/api/2.0/nwfabric/configure"
    $body = "<nwFabricFeatureConfig><featureId>"
    $body += "com.vmware.vshield.nsxmgr.vxlan</featureId>"
    $body += "<resourceConfig><resourceId>$($ClID.MoRef.Value)"
    $body += "</resourceId>"
    $body += "<configSpec class=`"clusterMappingSpec`">"
    $body +="<switch><objectId>$($NetID.MoRef.value)</objectId>"
    $body +="</switch><vlanId>0</vlanId>"
    $body +="<vmknicCount>1</vmknicCount>"
    $body +="</configSpec></resourceConfig><resourceConfig>"
    $body +="<resourceId>$($NetID.MoRef.value)</resourceId>"
    $body +="<configSpec class=`"vdsContext`">"
    $body +="<switch><objectId>$($NetID.MoRef.value)</objectId>"
    $body +="</switch><mtu>1600</mtu><teaming>"
    $body +="FAILOVER_ORDER</teaming></configSpec>"
    $body +="</resourceConfig></nwFabricFeatureConfig>"

    $VXLAN = Invoke-RestMethod -Method Post -Uri $uri `
    -Headers $Headers -ContentType "application/xml" -body $body
    }
catch [Exception]{

    throw "Error occurred while trying to install VXLAN"
}
}

Further Configuration and Administration of NSX

You have now used a number of examples of REST calls via PowerShell to configure NSX. Once VXLAN is configured on all the hosts in the cluster, you are ready to finalize the logical network settings, begin creating logical networks, and benefit from all of the capabilities and functionality of NSX. To continue creating REST calls to configure NSX, you can refer to VMware’s NSX API Guide. The guide for NSX 6.2, for example, can be found here: http://vmw.re/1LhfO6B.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset