NSX Undocumented Requirement…..Maybe???

Ran into an interesting issue in one of our labs today. While preparing a cluster to install the NSX vib one of our techs noticed the install kept failing. Logs indicated the problem was due to a callback to VMware Update Manager failing which seemed odd.

The NSX manager is what is actually pushing out the NSX vib so why is VUM involved? After checking the virtual center I noticed the tech had disabled the VUM plugin in the virtual center. After enabling it, the install process for NSX proceeded without issue.

To further test this I deployed another lab and 10 minutes later uninstalled VUM. Same result, NSX would not prepare a cluster of new hosts. Once I installed VUM I was once again able to prepare the cluster.

So moral of the story is, make sure your VUM instance is installed and functioning properly before trying to prepare a NSX cluster.

Create Random Password

Not taking credit for this function but it’s something I’ve used quite a bit lately. For the life of me I cannot track down who originally wrote it but it’s very handy to have. If someone knows the original author please let me know so I can properly credit them. Fairly simple code that will randomly generate a password of $length including Letters, numbers and Characters.

function random-password {
    $punc = 46..46
    $digits = 48..57
    $letters = 65..90 + 97..122
    $length = 15
    $password = get-random -count $length -input ($punc + $digits + $letters) | % -begin { $aa = $null } -process {$aa += [char]$_} -end {$aa}
    return $password
}

API Gotcha Deploying NSX Edge

Was beating my head against a wall over several days to track down why I could Inject a fully configured Edge into the NSX Manager but had no way to actually Deploy it via API. This was requiring me to log into the WebClient UI and right click the undeployed edge and click deploy, annoying to say the least.

After opening a support ticket with VMware and digging into the API a bit more we tracked down the mistake I was making. When injecting the Edge into the NSX manager you needed to specify the Edge to be deployed in 3 locations, not just the 2 I was thinking.

Initially I was specifying that each appliance was in a ‘Deployed’ state by setting the deployed variable to true. But it turns out theres another entry just below the Appliances section of API that’s required in order for deployment to actually occur when you create the Edge.

<deployAppliances>true</deployAppliances>

If you leave that statement as false, you’ll get an error every time you attempt to run this code against the NSX manager. To deploy the Edge at the time of creation, set all 3 entries to ‘true’

<appliances>
		<applianceSize>compact</applianceSize>
		<appliance>
			<highAvailabilityIndex>0</highAvailabilityIndex>
			<resourcePoolId>resgroup-8546</resourcePoolId>
			<resourcePoolName>System vDC (6a53b23b-8b07-47b2-9947-d7d53e399ec1)</resourcePoolName>
			<datastoreId>datastore-74</datastoreId>
			<datastoreName>584442-san-fc-hlu0-Silver</datastoreName>
			<hostId>host-2031</hostId>
			<hostName>354985-hyp28.ord1.rvi.local</hostName>
            <vmFolderId>group-v4168</vmFolderId>
			<vmFolderName>Service VMs</vmFolderName>
			<vmHostname>$EdgeName-0</vmHostname>
			<vmName>$EdgeName-0</vmName>
			<deployed>true</deployed>
			<edgeId>edge-100</edgeId>
		</appliance>
		<appliance>
			<highAvailabilityIndex>1</highAvailabilityIndex>
			<resourcePoolId>resgroup-8546</resourcePoolId>
			<resourcePoolName>System vDC (6a53b23b-8b07-47b2-9947-d7d53e399ec1)</resourcePoolName>
			<datastoreId>datastore-74</datastoreId>
			<datastoreName>584442-san-fc-hlu0-Silver</datastoreName>
			<hostId>host-4128</hostId>
			<hostName>354984-hyp27.ord1.rvi.local</hostName>
            <vmFolderId>group-v4168</vmFolderId>
			<vmFolderName>Service VMs</vmFolderName>
			<vmHostname>$EdgeName-1</vmHostname>
			<vmName>$EdgeName-1</vmName>
			<deployed>true</deployed>
			<edgeId>edge-100</edgeId>
		</appliance>
		<deployAppliances>true</deployAppliances>
	</appliances>

Create NSX One-Arm Load Balancer

As part of our lab automation we needed a way to load balance a pair of nested vCloud Director Cells. Given the way Edges work, we would have to have the IP’s of the Nested vCD instance sub-allocated to an Edge to handle the load balancing but this wasn’t going to be possible due to the way vCD works. The way to solve this, while unorthodox was to deploy a One-arm Load Balancing Edge outside the scope of vCD using NSX. Taking a cue from this great blog: Tom Fojta I was able to piece together the steps needed to create a one-arm load balancer via PowerCLI. Now what made this a little complex is I needed to deploy the Edge Load Balancer to a vxlan virtual wire after it had been created earlier in a deployment script.

The way I solved this was to query for the connected vxlan networks our nested vApp was connected to, once I had that it was simple to modify the body of a Rest call to have the proper configuration for our one-Arm Load Balancer. Be warned, the code for the body is very long as I fully configured the Edge prior to deployment. This included Load Balancer, Firewall, Nat and routing setup.

$NSXManager = Read-Host "Please provide the URL of the NSX Manager"
$NSXUserName = "administrator@vsphere.local"
$NSXPassword = Read-Host "Provide SSO Password" -AsSecureString
$NSXPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($NSXPassword))
$EdgeName = "$OrgName-One-Arm-LB"

### Ignore TLS/SSL errors
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
  
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUserName + ":" + $NSXPassword))
$head = @{"Authorization"="Basic $auth"}
$Request = "https://$NSXManager/api/4.0/edges"

$Response = Invoke-WebRequest -Uri $Request -Method 'Get' -Headers $head -ContentType "application/xml"
if ($Response.StatusCode -eq "200")
{
    $rxml = $Response.Content
    foreach ($edgeSummary in $rxml.pagedEdgeList.edgePage.edgeSummary) {
        $edge = @{} | select Name,id
        if ($edgeSummary.Name -like "*$OrgName*") {
            $edge.Name = $edgeSummary.Name
            $edge.ID = $edgeSummary.ID
            $requestedID = $edge.ID
            $Request = "https://$NSXManager/api/4.0/edges/$requestedID"
            $Response = Invoke-WebRequest -Uri $Request -Method 'Get' -Headers $head -ContentType "application/xml"
                if ($Response.StatusCode -eq "200") {
                    $rxml = $Response.Content
                    foreach ($vnic in $rxml.edge.vnics.vnic) {
                        $interface =  @{} | select portgroupId,portgroupName
                        if ($vnic.portgroupName -like '*ExNet-Inside*') {
                        $interface.portgroupId = $vnic.portgroupId
                        $portgroupID = $interface.portgroupId
                        $interface.portgroupName = $vnic.portgroupName
                        $portgroupname = $interface.portgroupName
                        }
                    }
                }
            
            }
        
        }
}

$body = "
<edge>
	<version>16</version>
	<status>undeployed</status>
	<datacenterMoid>datacenter-21</datacenterMoid>
	<datacenterName>1000112</datacenterName>
	<tenant>default</tenant>
	<name>$EdgeName</name>
	<fqdn>$EdgeName</fqdn>
	<enableAesni>true</enableAesni>
	<enableFips>false</enableFips>
	<vseLogLevel>emergency</vseLogLevel>
	<vnics>
		<vnic>
			<label>vNic_0</label>
			<name>vCloud-Https</name>
			<addressGroups>
				<addressGroup>
					<primaryAddress>192.168.100.119</primaryAddress>
					<secondaryAddresses>
						<ipAddress>192.168.100.120</ipAddress>
					</secondaryAddresses>
					<subnetMask>255.255.255.0</subnetMask>
					<subnetPrefixLength>24</subnetPrefixLength>
				</addressGroup>
			</addressGroups>
			<mtu>1500</mtu>
			<type>uplink</type>
			<isConnected>true</isConnected>
			<index>0</index>
            <portgroupId>$portgroupID</portgroupId>
            <portgroupName>
                $portgroupname
            </portgroupName>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_1</label>
			<name>vnic1</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>1</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_2</label>
			<name>vnic2</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>2</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_3</label>
			<name>vnic3</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>3</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_4</label>
			<name>vnic4</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>4</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_5</label>
			<name>vnic5</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>5</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_6</label>
			<name>vnic6</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>6</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_7</label>
			<name>vnic7</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>7</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_8</label>
			<name>vnic8</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>8</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
		<vnic>
			<label>vNic_9</label>
			<name>vnic9</name>
			<addressGroups/>
			<mtu>1500</mtu>
			<type>internal</type>
			<isConnected>false</isConnected>
			<index>9</index>
			<enableProxyArp>false</enableProxyArp>
			<enableSendRedirects>true</enableSendRedirects>
		</vnic>
	</vnics>
	<appliances>
		<applianceSize>compact</applianceSize>
		<appliance>
			<highAvailabilityIndex>0</highAvailabilityIndex>
			<resourcePoolId>resgroup-8546</resourcePoolId>
			<resourcePoolName>System vDC (6a53b23b-8b07-47b2-9947-d7d53e399ec1)</resourcePoolName>
			<datastoreId>datastore-74</datastoreId>
			<datastoreName>584442-san-fc-hlu0-Silver</datastoreName>
			<hostId>host-2031</hostId>
			<hostName>354985-hyp28.ord1.rvi.local</hostName>
            <vmFolderId>group-v4168</vmFolderId>
			<vmFolderName>Service VMs</vmFolderName>
			<vmHostname>$EdgeName-0</vmHostname>
			<vmName>$EdgeName-0</vmName>
			<deployed>true</deployed>
			<edgeId>edge-100</edgeId>
		</appliance>
		<appliance>
			<highAvailabilityIndex>1</highAvailabilityIndex>
			<resourcePoolId>resgroup-8546</resourcePoolId>
			<resourcePoolName>System vDC (6a53b23b-8b07-47b2-9947-d7d53e399ec1)</resourcePoolName>
			<datastoreId>datastore-74</datastoreId>
			<datastoreName>584442-san-fc-hlu0-Silver</datastoreName>
			<hostId>host-4128</hostId>
			<hostName>354984-hyp27.ord1.rvi.local</hostName>
            <vmFolderId>group-v4168</vmFolderId>
			<vmFolderName>Service VMs</vmFolderName>
			<vmHostname>$EdgeName-1</vmHostname>
			<vmName>$EdgeName-1</vmName>
			<deployed>true</deployed>
			<edgeId>edge-100</edgeId>
		</appliance>
		<deployAppliances>true</deployAppliances>
	</appliances>
	<features>
		<l2Vpn>
			<version>6</version>
			<enabled>false</enabled>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
		</l2Vpn>
		<featureConfig/>
		<firewall>
			<version>2</version>
			<enabled>true</enabled>
			<globalConfig>
				<tcpPickOngoingConnections>false</tcpPickOngoingConnections>
				<tcpAllowOutOfWindowPackets>false</tcpAllowOutOfWindowPackets>
				<tcpSendResetForClosedVsePorts>true</tcpSendResetForClosedVsePorts>
				<dropInvalidTraffic>true</dropInvalidTraffic>
				<logInvalidTraffic>false</logInvalidTraffic>
				<tcpTimeoutOpen>30</tcpTimeoutOpen>
				<tcpTimeoutEstablished>3600</tcpTimeoutEstablished>
				<tcpTimeoutClose>30</tcpTimeoutClose>
				<udpTimeout>60</udpTimeout>
				<icmpTimeout>10</icmpTimeout>
				<icmp6Timeout>10</icmp6Timeout>
				<ipGenericTimeout>120</ipGenericTimeout>
			</globalConfig>
			<defaultPolicy>
				<action>accept</action>
				<loggingEnabled>false</loggingEnabled>
			</defaultPolicy>
			<firewallRules>
				<firewallRule>
					<id>131074</id>
					<ruleTag>131074</ruleTag>
					<name>firewall</name>
					<ruleType>internal_high</ruleType>
					<enabled>true</enabled>
					<loggingEnabled>false</loggingEnabled>
					<description>firewall</description>
					<action>accept</action>
					<source>
						<exclude>false</exclude>
						<vnicGroupId>vse</vnicGroupId>
					</source>
				</firewallRule>
				<firewallRule>
					<id>131073</id>
					<ruleTag>131073</ruleTag>
					<name>default rule for ingress traffic</name>
					<ruleType>default_policy</ruleType>
					<enabled>true</enabled>
					<loggingEnabled>false</loggingEnabled>
					<description>default rule for ingress traffic</description>
					<action>accept</action>
				</firewallRule>
			</firewallRules>
		</firewall>
		<sslvpnConfig>
			<version>6</version>
			<enabled>false</enabled>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
			<advancedConfig>
				<enableCompression>false</enableCompression>
				<forceVirtualKeyboard>false</forceVirtualKeyboard>
				<randomizeVirtualkeys>false</randomizeVirtualkeys>
				<preventMultipleLogon>false</preventMultipleLogon>
				<clientNotification/>
				<enablePublicUrlAccess>false</enablePublicUrlAccess>
				<timeout>
					<forcedTimeout>0</forcedTimeout>
					<sessionIdleTimeout>10</sessionIdleTimeout>
				</timeout>
			</advancedConfig>
			<clientConfiguration>
				<autoReconnect>true</autoReconnect>
				<upgradeNotification>false</upgradeNotification>
			</clientConfiguration>
			<layoutConfiguration>
				<portalTitle>VMware</portalTitle>
				<companyName>VMware</companyName>
				<logoExtention>jpg</logoExtention>
				<logoUri>/api/4.0/edges/edge-100/sslvpn/config/layout/images/portallogo</logoUri>
				<logoBackgroundColor>FFFFFF</logoBackgroundColor>
				<titleColor>996600</titleColor>
				<topFrameColor>000000</topFrameColor>
				<menuBarColor>999999</menuBarColor>
				<rowAlternativeColor>FFFFFF</rowAlternativeColor>
				<bodyColor>FFFFFF</bodyColor>
				<rowColor>F5F5F5</rowColor>
			</layoutConfiguration>
			<authenticationConfiguration>
				<passwordAuthentication>
					<authenticationTimeout>1</authenticationTimeout>
					<primaryAuthServers/>
					<secondaryAuthServer/>
				</passwordAuthentication>
			</authenticationConfiguration>
		</sslvpnConfig>
		<dns>
			<version>6</version>
			<enabled>false</enabled>
			<cacheSize>16</cacheSize>
			<listeners>
				<vnic>any</vnic>
			</listeners>
			<dnsViews>
				<dnsView>
					<viewId>view-0</viewId>
					<name>vsm-default-view</name>
					<enabled>true</enabled>
					<viewMatch>
						<ipAddress>any</ipAddress>
						<vnic>any</vnic>
					</viewMatch>
					<recursion>false</recursion>
				</dnsView>
			</dnsViews>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
		</dns>
		<routing>
			<version>6</version>
			<enabled>true</enabled>
			<routingGlobalConfig>
				<ecmp>false</ecmp>
				<logging>
					<enable>false</enable>
					<logLevel>info</logLevel>
				</logging>
			</routingGlobalConfig>
			<staticRouting>
				<defaultRoute>
					<vnic>0</vnic>
					<mtu>1500</mtu>
					<gatewayAddress>192.168.100.1</gatewayAddress>
				</defaultRoute>
				<staticRoutes/>
			</staticRouting>
			<ospf>
				<enabled>false</enabled>
				<ospfAreas>
					<ospfArea>
						<areaId>51</areaId>
						<type>nssa</type>
						<authentication>
							<type>none</type>
						</authentication>
					</ospfArea>
					<ospfArea>
						<areaId>0</areaId>
						<type>normal</type>
						<authentication>
							<type>none</type>
						</authentication>
					</ospfArea>
				</ospfAreas>
				<ospfInterfaces/>
				<redistribution>
					<enabled>false</enabled>
					<rules/>
				</redistribution>
				<gracefulRestart>true</gracefulRestart>
				<defaultOriginate>false</defaultOriginate>
			</ospf>
		</routing>
		<highAvailability>
			<version>6</version>
			<enabled>true</enabled>
			<vnic>any</vnic>
			<ipAddresses>
				<ipAddress>169.254.10.1/30</ipAddress>
				<ipAddress>169.254.10.2/30</ipAddress>
			</ipAddresses>
			<declareDeadTime>15</declareDeadTime>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
			<security>
				<enabled>false</enabled>
			</security>
		</highAvailability>
		<syslog>
			<version>1</version>
			<enabled>false</enabled>
		</syslog>
		<featureConfig/>
		<loadBalancer>
			<version>10</version>
			<enabled>true</enabled>
			<enableServiceInsertion>false</enableServiceInsertion>
			<accelerationEnabled>false</accelerationEnabled>
			<virtualServer>
				<virtualServerId>virtualServer-1</virtualServerId>
				<name>vCloud-HTTPS-VIP</name>
				<enabled>true</enabled>
				<ipAddress>192.168.100.119</ipAddress>
				<protocol>https</protocol>
				<port>443</port>
				<connectionLimit>0</connectionLimit>
				<connectionRateLimit>0</connectionRateLimit>
				<defaultPoolId>pool-1</defaultPoolId>
				<applicationProfileId>applicationProfile-1</applicationProfileId>
				<enableServiceInsertion>false</enableServiceInsertion>
				<accelerationEnabled>false</accelerationEnabled>
			</virtualServer>
			<virtualServer>
				<virtualServerId>virtualServer-2</virtualServerId>
				<name>vCloud-Console-VIP</name>
				<enabled>true</enabled>
				<ipAddress>192.168.100.120</ipAddress>
				<protocol>https</protocol>
				<port>443</port>
				<connectionLimit>0</connectionLimit>
				<connectionRateLimit>0</connectionRateLimit>
				<defaultPoolId>pool-2</defaultPoolId>
				<applicationProfileId>applicationProfile-1</applicationProfileId>
				<enableServiceInsertion>false</enableServiceInsertion>
				<accelerationEnabled>false</accelerationEnabled>
			</virtualServer>
			<pool>
				<poolId>pool-1</poolId>
				<name>vCloud-HTTPS-Pool</name>
				<algorithm>leastconn</algorithm>
				<transparent>false</transparent>
				<monitorId>monitor-4</monitorId>
				<member>
					<memberId>member-1</memberId>
					<ipAddress>192.168.100.101</ipAddress>
					<weight>1</weight>
					<monitorPort>443</monitorPort>
					<port>443</port>
					<maxConn>0</maxConn>
					<minConn>0</minConn>
					<condition>enabled</condition>
					<name>vCloud-CellA-Https</name>
				</member>
				<member>
					<memberId>member-2</memberId>
					<ipAddress>192.168.100.104</ipAddress>
					<weight>1</weight>
					<monitorPort>443</monitorPort>
					<port>443</port>
					<maxConn>0</maxConn>
					<minConn>0</minConn>
					<condition>enabled</condition>
					<name>vCloud-CellB-Https</name>
				</member>
			</pool>
			<pool>
				<poolId>pool-2</poolId>
				<name>vCloud-Console-Pool</name>
				<algorithm>leastconn</algorithm>
				<transparent>false</transparent>
				<monitorId>monitor-3</monitorId>
				<member>
					<memberId>member-3</memberId>
					<ipAddress>192.168.100.103</ipAddress>
					<weight>1</weight>
					<monitorPort>443</monitorPort>
					<port>443</port>
					<maxConn>0</maxConn>
					<minConn>0</minConn>
					<condition>enabled</condition>
					<name>vCloud-Console-CellA</name>
				</member>
				<member>
					<memberId>member-4</memberId>
					<ipAddress>192.168.100.107</ipAddress>
					<weight>1</weight>
					<monitorPort>443</monitorPort>
					<port>443</port>
					<maxConn>0</maxConn>
					<minConn>0</minConn>
					<condition>enabled</condition>
					<name>vCloud-CellB-Console</name>
				</member>
			</pool>
			<applicationProfile>
				<applicationProfileId>applicationProfile-1</applicationProfileId>
				<name>vCloud-Https</name>
				<insertXForwardedFor>false</insertXForwardedFor>
				<sslPassthrough>true</sslPassthrough>
				<template>HTTPS</template>
				<serverSslEnabled>false</serverSslEnabled>
			</applicationProfile>
			<monitor>
				<monitorId>monitor-1</monitorId>
				<type>tcp</type>
				<interval>5</interval>
				<timeout>15</timeout>
				<maxRetries>3</maxRetries>
				<name>default_tcp_monitor</name>
			</monitor>
			<monitor>
				<monitorId>monitor-2</monitorId>
				<type>http</type>
				<interval>5</interval>
				<timeout>15</timeout>
				<maxRetries>3</maxRetries>
				<method>GET</method>
				<url>/</url>
				<name>default_http_monitor</name>
			</monitor>
			<monitor>
				<monitorId>monitor-3</monitorId>
				<type>https</type>
				<interval>5</interval>
				<timeout>15</timeout>
				<maxRetries>3</maxRetries>
				<method>GET</method>
				<url>/</url>
				<name>default_https_monitor</name>
			</monitor>
			<monitor>
				<monitorId>monitor-4</monitorId>
				<type>http</type>
				<interval>10</interval>
				<timeout>15</timeout>
				<maxRetries>3</maxRetries>
				<method>GET</method>
				<url>/cloud/server_status</url>
				<name>vCloud HTTPS Monitor</name>
			</monitor>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
		</loadBalancer>
		<gslb>
			<version>1</version>
			<enabled>false</enabled>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
		</gslb>
		<ipsec>
			<version>1</version>
			<enabled>false</enabled>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
			<sites/>
			<global>
				<psk>******</psk>
				<caCertificates/>
				<crlCertificates/>
			</global>
		</ipsec>
		<dhcp>
			<version>6</version>
			<enabled>false</enabled>
			<staticBindings/>
			<ipPools/>
			<logging>
				<enable>false</enable>
				<logLevel>info</logLevel>
			</logging>
		</dhcp>
		<bridges>
			<version>6</version>
			<enabled>false</enabled>
		</bridges>
		<nat>
			<version>7</version>
			<enabled>true</enabled>
			<natRules>
				<natRule>
					<ruleId>196611</ruleId>
					<ruleTag>196611</ruleTag>
					<ruleType>internal_high</ruleType>
					<action>dnat</action>
					<vnic>0</vnic>
					<originalAddress>192.168.100.120</originalAddress>
					<translatedAddress>192.168.100.120</translatedAddress>
					<loggingEnabled>false</loggingEnabled>
					<enabled>true</enabled>
					<description>loadBalancer</description>
					<protocol>tcp</protocol>
					<originalPort>443</originalPort>
					<translatedPort>443</translatedPort>
				</natRule>
				<natRule>
					<ruleId>196610</ruleId>
					<ruleTag>196610</ruleTag>
					<ruleType>internal_high</ruleType>
					<action>dnat</action>
					<vnic>0</vnic>
					<originalAddress>192.168.100.119</originalAddress>
					<translatedAddress>192.168.100.119</translatedAddress>
					<loggingEnabled>false</loggingEnabled>
					<enabled>true</enabled>
					<description>loadBalancer</description>
					<protocol>tcp</protocol>
					<originalPort>443</originalPort>
					<translatedPort>443</translatedPort>
				</natRule>
			</natRules>
		</nat>
		<featureConfig/>
		<featureConfig/>
	</features>
	<autoConfiguration>
		<enabled>true</enabled>
		<rulePriority>high</rulePriority>
	</autoConfiguration>
	<type>gatewayServices</type>
	<hypervisorAssist>false</hypervisorAssist>
	<edgeAssistId>0</edgeAssistId>
	<queryDaemon>
		<enabled>false</enabled>
		<port>5666</port>
	</queryDaemon>
</edge>"

$Request = "https://$NSXManager/api/4.0/edges"
$Response = Invoke-WebRequest -Uri $Request -Method 'Post' -Headers $head -ContentType "application/xml" -Body $body
if ($Response.StatusCode -eq "201")
{
    Write-Host "One Armed LB $EdgeName was properly created"
}


Create Third Party Catalog for vCloud Director

Was browsing some blogs today and ran across this entry by William Lam: virtuallyghetto.com. Ironically I had written something similar to this back in early May for us in our own internal vCloud Director lab. We’re currently hosting it on a Netapp for customers to subscribe to and manual creation of the catalog was a serious time sink. Quick PowerCLI script and we were off to the races.

We have a staging vCloud Director instance that we do all our Image testing on. Once the catalog there has been verified and shown to be working, we run this script to export and create the proper file structure for upload to the Netapp.

# Add vcloud cmdlets
if( -not (Get-PSSnapin VMware.VimAutomation.Core) )
{
    Add-PSSnapin VMware.VimAutomation.Core
}
if( -not (Get-PSSnapin VMware.VimAutomation.Cloud) )
{
    Add-PSSnapin VMware.VimAutomation.Cloud
}
try {
    Connect-CIServer "vcd01-2848638.mv.rackspace.com"
     
    } Catch {
        throw "Unable to connect to VCD Server"
    }
New-Item -ItemType directory -Path 's:/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/items' -Force
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
 
#downloading and creating descriptor.json file
$url = 'https://vcd01-2848638.mv.rackspace.com/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/'
$descriptor = (Invoke-RestMethod $url)
$descriptor.itemsHref = 'items.json'
$descriptor | Add-Member -PassThru NoteProperty maintenanceMessage "This catalog is currently in maintenance mode"
$descriptor | ConvertTo-Json -depth 999 | Out-File 's:/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/descriptor.json'
#downloading and creating items.json file
$url = 'https://vcd01-2848638.mv.rackspace.com/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/items'
$items = (Invoke-RestMethod $url)
 
#Creating Folder Structure and Downloading files
for ($i=0;$i -lt $Items.items.count; $i++) {
    $Items.items[$i].selfHref = $Items.items[$i].selfHref + 'item.json'
    $ovfPath = 'https://vcd01-2848638.mv.rackspace.com' + $Items.items[$i].files[0].hrefs
    $mfPath =  'https://vcd01-2848638.mv.rackspace.com' + $Items.items[$i].files[1].hrefs
    $vmdkPath = 'https://vcd01-2848638.mv.rackspace.com' + $Items.items[$i].files[2].hrefs
    $path = 's:/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/items/' + $Items.items[$i].selfHref.Split("/")[5] + '/file/'
    $url = 'https://vcd01-2848638.mv.rackspace.com/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/item/' + $Items.items[$i].selfHref.Split("/")[5]
    New-Item -ItemType directory -Path $path -Force
    $item = (Invoke-RestMethod $url)
    $outputURL = 's:/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/items/' + $Items.items[$i].selfHref.Split("/")[5] + '/item.json'
    $item | ConvertTo-Json -depth 999 | Out-File "$outputURL"
    #downloading .ovf .mf and .vmdk files
    $webclient = New-Object System.Net.WebClient
    $ovfFile = $item.files[0].name
    $mfFile = $item.files[1].name
    $vmdkFile = $item.files[2].name
    $webclient.DownloadFile($ovfPath,$path+$ovfFile)
    $webclient.DownloadFile($mfPath,$path+$mfFile)
    $webclient.DownloadFile($vmdkPath,$Path+$vmdkFile)
     
}
$items | ConvertTo-Json -depth 999 | Out-File 's:/vcsp/lib/1cf1823b-4321-4e66-b49d-16e2d78b744f/items.json'
#Disconnect-CIServer -server * -Force:$true -confirm:$false

PowerCLI Create Routed OrgVDC Networks

Creating Routed OrgVDC networks is fairly painless and straight forward when working with vCloud Director. But it does take some time, especially if you need to create 50-60 of them a day for customers. Luckily we can easily script this with PowerCLI

$edgeGateway = Search-Cloud -QueryType EdgeGateway -Name $orgName | Get-CIView | where {$_.name -like "$orgName*"}
$ExNetnetwork = New-Object VMware.VimAutomation.Cloud.Views.OrgVdcNetwork
$ExNetnetwork.EdgeGateway = $edgeGateway.Id
$ExNetnetwork.isShared = $false
$ExNetnetwork.Configuration = New-Object VMware.VimAutomation.Cloud.Views.NetworkConfiguration
$ExNetnetwork.Name = "ExNet-Inside"
$ExNetnetwork.Configuration.IpScopes = New-Object VMware.VimAutomation.Cloud.Views.IpScopes
$ExNetnetwork.Configuration.FenceMode = "natRouted"

$IpScope = New-Object VMware.VimAutomation.Cloud.Views.IpScope
$IpScope.Gateway = $ExNetinternalGateway
$IpScope.Netmask = $ExNetinternalNetmask
$IpScope.Dns1 = $ExNetinternalGateway
$IpScope.IpRanges = New-Object VMware.VimAutomation.Cloud.Views.IpRanges
$IpScope.IpRanges.IpRange = New-Object VMware.VimAutomation.Cloud.Views.IpRange
$IpScope.IpRanges.IpRange[0].StartAddress = $ExNetfirstInternalIP
$IpScope.IpRanges.IpRange[0].EndAddress = $ExNetlastInternalIP

$ExNetnetwork.Configuration.IpScopes.IpScope += $IpScope
 
$orgVdc.ExtensionData.CreateNetwork($ExNetnetwork)

PowerCLI Create OrgVDC Bug

I was looking over my code earlier and noticed a strange bug that kept popping up. When I deploy a lab for customers or vendors I specify the vCPU speed to match the physical CPU speed. Additionally I set the CPU and Memory guarantees at 5% as this is non-production and we don’t want folks getting greedy.

But what I was noticing was that depending on the order some code was executed, one code would effectively reverse the previous codes command.

If for example I set the CPU and Memory guarantees with the following code first…

#Set Org VDC CPU and Memory guarantees
Get-OrgVdc $orgvDCName | Set-OrgVdc -CpuGuaranteedPercent 5
Get-OrgVdc $orgvDCName | Set-OrgVdc -MemoryGuaranteedPercent 5

and follow it up by setting the vCPU Core Speed…

#Set the vCPU Core Speed
$orgVdc.ExtensionData.VCpuInMhz = '2400'
$orgVdc.ExtensionData.UpdateServerData()

Something Strange would occur. Namely the Memory guarantee would shoot up to 100% despite just setting it a few lines above to 5% (and seeing it take effect in vCloud and in the logs.)

The fix for this ultimately was to just switch the order of code execution and set the vCPU Core speed first and then set the reservation but for the life of me I cannot see why setting the vCPU code speed would affect memory reservation.

PowerCLI Create vCloud Organization

Creating vCloud Organizations was always a bit tedious in my opinion, if you are a service provider you choose the same options over and over for each customer. So as always, why not spend a bit of time and do it programmatically via powercli and save yourself some clicks.

[String]$OrgName = Read-Host "Enter the Customer Core Account Number (to be used for creating the URL)"
[String]$OrgFullName = Read-Host "Enter the Customer Core Account Name"
[String]$OrgDescription = Read-Host "Enter the Organization Description" 

try {
    $NewOrg = New-Org -Name $OrgName -FullName $OrgFullName -Description $OrgDescription

    $org = Get-Org -Name $OrgName
 
    # Configure Org to use the system LDAP
    $org.ExtensionData.Settings.OrgLdapSettings.OrgLdapMode = "SYSTEM"
    $org.ExtensionData.UpdateServerData()
    $org.ExtensionData.UpdateViewData()
 
    # Allow sharing of catalogs to other organizations
    $org.ExtensionData.Settings.OrgGeneralSettings.CanPublishCatalogs = $True
    $org.ExtensionData.Settings.OrgGeneralSettings.CanPublishExternally = $True
    $org.ExtensionData.Settings.OrgGeneralSettings.CanSubscribe = $True
    $org.ExtensionData.UpdateServerData()
    $org.ExtensionData.UpdateViewData()
 
    # Set vApp lease times
    $leases = $org.ExtensionData.Settings.GetVAppLeaseSettings()
    $leases.DeploymentLeaseSeconds = 0
    $leases.StorageLeaseSeconds = 0
    $leases.DeleteOnStorageLeaseExpiration = $False
    $leases.UpdateServerData()
 
    # Set vApp template lease times
    $templateleases = $org.ExtensionData.Settings.GetVAppTemplateLeaseSettings()
    $templateleases.StorageLeaseSeconds = 0
       $templateleases.DeleteOnStorageLeaseExpiration = $False
    $templateleases.UpdateServerData()
 
    # Set Org operations limits
    $limits = $org.ExtensionData.Settings.GetOperationLimitsSettings()
    $limits.OperationsPerUser = "3"
    $limits.OperationsPerOrg = "6"
    $limits.UpdateServerData()

    # Set Password Policy Limits
    $PasswordLimits = $org.ExtensionData.Settings.OrgPasswordPolicySettings
    $PasswordLimits.AccountLockoutEnabled = $True
    $PasswordLimits.UpdateServerData()

    } catch {
        $removeOrg = Search-Cloud Organization -name $OrgName
        if ($removeOrg -eq $null) {
            Write-Host "The Org was never created, closing down Program"
            DisconnectServers
            Exit
        } else {
            RemoveOrg
            Exit
            }
    }

PowerCLI create Load Balancer

Been a few days since my last post but wanted to come back and post the code to create a Load Balancer in vCloud via Powercli.

This took a very long time to finally get right and frankly the amount of code that needs to be entered is just silly. Creating a Load Balancer in NSX is so much easier compared to this so I cannot wait until NSX gets full integration with vCloud so we can skip this mess.

The use case here was to create a Edge Load Balancer for 2 vCloud cells to use. This would require HTTP/S as well as Console Load Balancing over 2 networks (ExNet and VMNet.) Feel free to hit me up with any questions regarding this. I’ll post how much simpler it is with NSX in the near future.

#Configuring the LB on the Edge
$edgegateway = Search-Cloud -QueryType EdgeGateway -name $orgName | Get-CIView

#Enable LB Service
$LoadBalancer = New-Object VMware.VimAutomation.Cloud.Views.LoadBalancerService
$LoadBalancer.IsEnabled = $true

#Creation of HTTP/S IP Pool Object
$LoadBalancer.Pool = New-Object VMware.VimAutomation.Cloud.Views.LoadBalancerPool
$LoadBalancer.Pool += New-Object VMware.VimAutomation.Cloud.Views.LoadBalancerPool
$LoadBalancer.Pool[0].Name = "vCloud-HTTP-Pool"
$LoadBalancer.Pool[0].Description = "vCloud HTTP Pool of IPs"
$LoadBalancer.Pool[0].Id = "1"

#Creation of Console IP Pool Object
$LoadBalancer.Pool[1].Name = "vCloud-Console-Pool"
$LoadBalancer.Pool[1].Description = "vCloud Console Pool of IPs"
$LoadBalancer.Pool[1].Id = "2"

#Create HTTPS Health Check for Pool
$LoadBalancer.Pool[0].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].ServicePort += New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].ServicePort[0].Port = "443"
$LoadBalancer.Pool[0].ServicePort[0].IsEnabled = $true
$LoadBalancer.Pool[0].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[0].ServicePort[0].Protocol = "HTTPS"
$LoadBalancer.Pool[0].ServicePort[0].Algorithm = "ROUND_ROBIN"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck = New-Object VMware.VimAutomation.Cloud.Views.LBPoolHealthCheck
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].Mode = "SSL"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].Interval = "10"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].Timeout = "15"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].HealthThreshold = "2"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].UnHealthThreshold = "3"
$LoadBalancer.Pool[0].ServicePort[0].HealthCheck[0].Uri = "/cloud/server_status"

#Create HTTP Health Check for Pool
$LoadBalancer.Pool[0].ServicePort[1].Port = "80"
$LoadBalancer.Pool[0].ServicePort[1].IsEnabled = $true
$LoadBalancer.Pool[0].ServicePort[1].HealthCheckPort = "80"
$LoadBalancer.Pool[0].ServicePort[1].Protocol = "HTTP"
$LoadBalancer.Pool[0].ServicePort[1].Algorithm = "ROUND_ROBIN"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck = New-Object VMware.VimAutomation.Cloud.Views.LBPoolHealthCheck
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].Mode = "HTTP"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].Interval = "10"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].Timeout = "15"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].HealthThreshold = "2"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].UnHealthThreshold = "3"
$LoadBalancer.Pool[0].ServicePort[1].HealthCheck[0].Uri = "/cloud/server_status"

#Create Console Health Check for Pool
$LoadBalancer.Pool[1].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[1].ServicePort[0].Port = "443"
$LoadBalancer.Pool[1].ServicePort[0].IsEnabled = $true
$LoadBalancer.Pool[1].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[1].ServicePort[0].Protocol = "TCP"
$LoadBalancer.Pool[1].ServicePort[0].Algorithm = "ROUND_ROBIN"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck = New-Object VMware.VimAutomation.Cloud.Views.LBPoolHealthCheck
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].Mode = "TCP"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].Interval = "10"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].Timeout = "15"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].HealthThreshold = "2"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].UnHealthThreshold = "3"
$LoadBalancer.Pool[1].ServicePort[0].HealthCheck[0].Uri = "/"

#Create HTTP/S Pool Member #1
$LoadBalancer.Pool[0].Member = New-Object VMware.VimAutomation.Cloud.Views.LBPoolMember
$LoadBalancer.Pool[0].Member += New-Object VMware.VimAutomation.Cloud.Views.LBPoolMember
$LoadBalancer.Pool[0].Member[0].IpAddress = $vCloud_CellA_HTTP
$LoadBalancer.Pool[0].Member[0].Weight = 1
$LoadBalancer.Pool[0].Member[0].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].Member[0].ServicePort += New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].Member[0].ServicePort[0].Port = "443"
$LoadBalancer.Pool[0].Member[0].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[0].Member[0].ServicePort[0].Protocol = "HTTPS"
$LoadBalancer.Pool[0].Member[0].ServicePort[1].Port = "80"
$LoadBalancer.Pool[0].Member[0].ServicePort[1].HealthCheckPort = "80"
$LoadBalancer.Pool[0].Member[0].ServicePort[1].Protocol = "HTTP"

#Create HTTP/S Pool Member #2
$LoadBalancer.Pool[0].Member[1].IpAddress = $vCloud_CellB_HTTP
$LoadBalancer.Pool[0].Member[1].Weight = 1
$LoadBalancer.Pool[0].Member[1].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].Member[1].ServicePort += New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[0].Member[1].ServicePort[0].Port = "443"
$LoadBalancer.Pool[0].Member[1].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[0].Member[1].ServicePort[0].Protocol = "HTTPS"
$LoadBalancer.Pool[0].Member[1].ServicePort[1].Port = "80"
$LoadBalancer.Pool[0].Member[1].ServicePort[1].HealthCheckPort = "80"
$LoadBalancer.Pool[0].Member[1].ServicePort[1].Protocol = "HTTP"

#Create Console Pool Member #1
$LoadBalancer.Pool[1].Member = New-Object VMware.VimAutomation.Cloud.Views.LBPoolMember
$LoadBalancer.Pool[1].Member += New-Object VMware.VimAutomation.Cloud.Views.LBPoolMember
$LoadBalancer.Pool[1].Member[0].IpAddress = $vCloud_CellA_Console
$LoadBalancer.Pool[1].Member[0].Weight = 1
$LoadBalancer.Pool[1].Member[0].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[1].Member[0].ServicePort[0].Port = "443"
$LoadBalancer.Pool[1].Member[0].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[1].Member[0].ServicePort[0].Protocol = "TCP"

#Create Console Pool Member #2
$LoadBalancer.Pool[1].Member[1].IpAddress = $vCloud_CellB_Console
$LoadBalancer.Pool[1].Member[1].Weight = 1
$LoadBalancer.Pool[1].Member[1].ServicePort = New-Object VMware.VimAutomation.Cloud.Views.LBPoolServicePort
$LoadBalancer.Pool[1].Member[1].ServicePort[0].Port = "443"
$LoadBalancer.Pool[1].Member[1].ServicePort[0].HealthCheckPort = "443"
$LoadBalancer.Pool[1].Member[1].ServicePort[0].Protocol = "TCP"

#Instantiate the Virtual Server Object Array
$LoadBalancer.VirtualServer = New-Object VMware.VimAutomation.Cloud.Views.LoadBalancerVirtualServer
$LoadBalancer.VirtualServer += New-Object VMware.VimAutomation.Cloud.Views.LoadBalancerVirtualServer

#Create Virtual Server #1 for HTTP/S
$LoadBalancer.VirtualServer[0].Name = "vCloud-HTTPS-VIP"
$LoadBalancer.VirtualServer[0].IsEnabled = $true
$LoadBalancer.VirtualServer[0].IPAddress = $VMNetExTernalBlock[1]
$LoadBalancer.VirtualServer[0].Interface = $VMNetExternalNetwork.href
$LoadBalancer.VirtualServer[0].Description = "Virtual IP connecting VMNet to vCloud Web Client"
$LoadBalancer.VirtualServer[0].ServiceProfile = New-Object VMware.VimAutomation.Cloud.Views.LBVirtualServerServiceProfile
$LoadBalancer.VirtualServer[0].ServiceProfile[0].isEnabled = $true
$LoadBalancer.VirtualServer[0].ServiceProfile[0].Protocol = "HTTPS"
$LoadBalancer.VirtualServer[0].ServiceProfile[0].Port = "443"
$LoadBalancer.VirtualServer[0].ServiceProfile[0].Persistence = New-Object VMware.VimAutomation.Cloud.Views.LBPersistence
$LoadBalancer.VirtualServer[0].ServiceProfile[0].Persistence.Method = "SSL_SESSION_ID"
$LoadBalancer.VirtualServer[0].Logging = $true
$LoadBalancer.VirtualServer[0].Pool = "vCloud-HTTP-Pool"

#Create Virtual Server #2 for Console
$LoadBalancer.VirtualServer[1].Name = "vCloud-Console-VIP"
$LoadBalancer.VirtualServer[1].IsEnabled = $true
$LoadBalancer.VirtualServer[1].IPAddress = $VMNetExTernalBlock[2]
$LoadBalancer.VirtualServer[1].Interface = $VMNetExternalNetwork.href
$LoadBalancer.VirtualServer[1].Description = "Virtual IP connecting VMNet to vCloud Console"
$LoadBalancer.VirtualServer[1].ServiceProfile = New-Object VMware.VimAutomation.Cloud.Views.LBVirtualServerServiceProfile
$LoadBalancer.VirtualServer[1].ServiceProfile[0].isEnabled = $true
$LoadBalancer.VirtualServer[1].ServiceProfile[0].Protocol = "TCP"
$LoadBalancer.VirtualServer[1].ServiceProfile[0].Port = "443"
$LoadBalancer.VirtualServer[1].ServiceProfile[0].Persistence = New-Object VMware.VimAutomation.Cloud.Views.LBPersistence
$LoadBalancer.VirtualServer[1].ServiceProfile[0].Persistence.Method = $null
$LoadBalancer.VirtualServer[1].Logging = $true
$LoadBalancer.VirtualServer[1].Pool = "vCloud-Console-Pool"


$edgegateway.ConfigureServices($LoadBalancer)

PowerCLI Create Edge Firewall

In our labs I had need to be able to create Edge Firewalls via PowerCLI in order to speed along deployment for various vendors and customers. Using the UI was cumbersome and often lead to mistakes so time to do this all via powerCLI. This will deploy an Edge with the following variables:

 

  • HA Edge
  • DNS Relay Enabled
  • Compact Size
  • 2 External Interfaces called ExNet and VMNet
    • The Interface IP’s are also sub-allocated to the Edge allowing for later SNAT outbound connectivity
# Create Edge Firewall
$firewall = New-Object VMware.VimAutomation.Cloud.Views.Gateway
$firewall.Name = $orgName
$firewall.Configuration = New-Object VMware.VimAutomation.Cloud.Views.GatewayConfiguration
$firewall.Configuration.BackwardCompatibilityMode = $false
$firewall.Configuration.GatewayBackingConfig = "compact"
$firewall.Configuration.UseDefaultRouteForDnsRelay = $true
$firewall.Configuration.HaEnabled = $true

$firewall.Configuration.EdgeGatewayServiceConfiguration = New-Object VMware.VimAutomation.Cloud.Views.GatewayFeatures
$firewall.Configuration.GatewayInterfaces = New-Object VMware.VimAutomation.Cloud.Views.GatewayInterfaces

$firewall.Configuration.GatewayInterfaces.GatewayInterface = New-Object VMware.VimAutomation.Cloud.Views.GatewayInterface
$firewall.Configuration.GatewayInterfaces.GatewayInterface += New-Object VMware.VimAutomation.Cloud.Views.GatewayInterface
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].DisplayName = "ExNet"
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].Network = $ExNetExternalNetwork.Href
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].InterfaceType = "uplink"
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].UseForDefaultRoute = $true
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].ApplyRateLimit = $false
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].DisplayName = "VMNet"
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].Network = $VMNetExternalNetwork.Href
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].InterfaceType = "uplink"
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].UseForDefaultRoute = $false
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].ApplyRateLimit = $false
$ExNetexternalSubnet = New-Object VMware.VimAutomation.Cloud.Views.SubnetParticipation
$ExNetexternalSubnet.Gateway = $ExNetExternalNetwork.Gateway
$ExNetexternalSubnet.Netmask = $ExNetExternalNetwork.Netmask
$ExNetexternalSubnet.IpAddress = $ExNetExternalBlock[0]
$ExNetexternalSubnet.IpRanges = New-Object VMware.VimAutomation.Cloud.Views.IpRanges
$ExNetexternalSubnet.IpRanges.IpRange = New-Object VMware.VimAutomation.Cloud.Views.IpRange
$ExNetexternalSubnet.IpRanges.IpRange[0].StartAddress = $ExNetexternalSubnet.IpAddress # ### $firstExternalIP
$ExNetexternalSubnet.IpRanges.IpRange[0].EndAddress = $ExNetexternalSubnet.IpAddress # ### $lastExternalIP

$VMNetexternalSubnet = New-Object VMware.VimAutomation.Cloud.Views.SubnetParticipation
$VMNetexternalSubnet.Gateway = $VMNetExternalNetwork.Gateway
$VMNetexternalSubnet.Netmask = $VMNetExternalNetwork.Netmask
$VMNetexternalSubnet.IpAddress = $VMNetExTernalBlock[0]
$VMNetexternalSubnet.IpRanges = New-Object VMware.VimAutomation.Cloud.Views.IpRanges
$VMNetexternalSubnet.IpRanges.IpRange = New-Object VMware.VimAutomation.Cloud.Views.IpRange
$VMNetexternalSubnet.IpRanges.IpRange += New-Object VMware.VimAutomation.Cloud.Views.IpRange
$VMNetexternalSubnet.IpRanges.IpRange += New-Object VMware.VimAutomation.Cloud.Views.IpRange
$VMNetexternalSubnet.IpRanges.IpRange[0].StartAddress = $VMNetexternalSubnet.IpAddress # ### $firstExternalIP
$VMNetexternalSubnet.IpRanges.IpRange[0].EndAddress = $VMNetexternalSubnet.IpAddress # ### $firstExternalIP
$VMNetexternalSubnet.IpRanges.IpRange[1].StartAddress = $VMNetExTernalBlock[1] # ### $SecondExternalIP
$VMNetexternalSubnet.IpRanges.IpRange[1].EndAddress = $VMNetExTernalBlock[1] # ### $SecondExternalIP
$VMNetexternalSubnet.IpRanges.IpRange[2].StartAddress = $VMNetExTernalBlock[2] # ### $ThirdExternalIP
$VMNetexternalSubnet.IpRanges.IpRange[2].EndAddress = $VMNetExTernalBlock[2] # ### $ThirdExternalIP
$firewall.Configuration.GatewayInterfaces.GatewayInterface[0].SubnetParticipation = $ExNetexternalSubnet
$firewall.Configuration.GatewayInterfaces.GatewayInterface[1].SubnetParticipation = $VMNetexternalSubnet
$orgVdc.ExtensionData.CreateEdgeGateway($firewall)

If you’re looking for reference code on how to deploy Load Balancers, Add Routed Networks, create NAT and Firewall rules stay tuned, I’ll be posting those in the next few days.