SDServers.psm1
Function Set-SDIMCBootOrder { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $imcip ) $result = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body "<aaaLogin inName='admin' inPassword='12qwaszx!@QWASZX'></aaaLogin>" $cookie = $result.aaaLogin.outCookie $getstatus = '<configResolveClass cookie="' + $cookie + '" inHierarchical="false" classId="computeRackUnit"/>' $getStatusResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getstatus # Remove any existing advanced boot order # Define clear text string for username and password [string]$userName = 'admin' [string]$userPassword = '12qwaszx!@QWASZX' # Convert to SecureString [securestring]$secStringPassword = ConvertTo-SecureString $userPassword -AsPlainText -Force [pscredential]$imccred = New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword) Import-module Cisco.IMC Connect-IMC $imcip -Credential $imccred Get-ImcLsbootDevPrecision -Hierarchy | Where-Object { $_.order } | Remove-ImcManagedObject -force Disconnect-IMC #Get the MAC of the MLOM port 1 $getLAN1Mac = '<configResolveClass cookie="' + $cookie + '" inHierarchical="true" classId="networkAdapterEthIf"/>' $getLAN1MacResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getLAN1Mac $mac1 = $getLAN1MacResults.configResolveClass.outConfigs.networkAdapterEthIf | Where-Object -Property Dn -Match "^sys/rack-unit-1/network-adapter-L/eth-1" | Select-Object -ExpandProperty Mac #SET new Boot order $request1 = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1/boot-precision/hdd-VMware_ESXi"> <inConfig> <lsbootHdd dn="sys/rack-unit-1/boot-precision/hdd-VMware_ESXi" name="VMware_ESXi" type="LOCALHDD" slot="MSTOR-RAID" order="1" state="Enabled"/> </inConfig> </configConfMo>' $request2 = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1/boot-precision/http-cobp1"> <inConfig> <lsbootHttp dn="sys/rack-unit-1/boot-precision/http-cobp1" type="HTTP" macAddress="' + $mac1 + '" iptype="IPv4" slot="L" port="1" order="2" state="Enabled" ipConfigType="DHCP"/> </inConfig> </configConfMo>' Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $request1 Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $request2 $getstatus = '<configResolveClass cookie="' + $cookie + '" inHierarchical="false" classId="computeRackUnit"/>' $getStatusResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getstatus $powerState = $getStatusResults.configResolveClass.outConfigs.computeRackUnit.operPower if ($powerState -eq "off") { $poweron = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1" ><inConfig><computeRackUnit adminPower="up" dn="sys/rack-unit-1"/></inConfig></configConfMo>' Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $poweron } elseif ($powerState -eq "on") { $powerCycle = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1" ><inConfig><computeRackUnit adminPower="hard-reset-immediate" dn="sys/rack-unit-1"/></inConfig></configConfMo>' Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $powerCycle } } Function Set-SDIMCInterface { #Change the Cisco IMC from Dedicated to Shared_LOM and set redundancy to active active Get-ImcMgmtIf -Imc $imchandle | Set-ImcMgmtIf -NicMode shared_lom -NicRedundancy active-active -VlanEnable yes -VlanId 997 -Xml -Force Start-Sleep -Seconds 120 } Function Set-SDIMCSetup { [CmdletBinding()] param ( #ESXi IP [Parameter(Mandatory = $true)] [String] $imcip ) Write-Host "Attempting to Access IMC API at $imcip" $result = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body "<aaaLogin inName='admin' inPassword='password'></aaaLogin>" if ($result.aaaLogin.response -eq "yes") { Write-Host "Login Sucessful at $imcip" $cookie = $result.aaaLogin.outCookie } #Changeing password Write-Host "Changing password" $passwordChange = "<configConfMo cookie='$cookie' inHierarchical='false' dn='sys/user-ext/user-1'><inConfig><aaaUser id='1' name='admin' priv='admin' pwd='12qwaszx!@QWASZX' dn='sys/user-ext/user-1'/></inConfig></configConfMo>" $passwordChangeResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $passwordChange Write-Host "Attempting to Access IMC API at $imcip with new password" $result = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body "<aaaLogin inName='admin' inPassword='12qwaszx!@QWASZX'></aaaLogin>" if ($result.aaaLogin.response -eq "yes") { Write-Host "Login Sucessful at $imcip" $cookie = $result.aaaLogin.outCookie } #Power on Server for Boot $getstatus = '<configResolveClass cookie="' + $cookie + '" inHierarchical="false" classId="computeRackUnit"/>' $getStatusResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getstatus if ($getStatusResults.configResolveClass.outConfigs.computeRackUnit.operPower -eq "off") { Write-Host "Powering on $imcip" $poweron = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1" ><inConfig><computeRackUnit adminPower="up" dn="sys/rack-unit-1"/></inConfig></configConfMo>' $poweronResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $poweron if ($poweronResults.configConfMo.outConfig.computeRackUnit.status -eq "modified") { Write-Host "Powering on of server $imcip Sucessful" } } # Start loop to check if server is booted do { Write-Host "Waiting for server to complete BIOS Post" Write-Host "Sleeping for 30 seconds" Start-Sleep -Seconds 30 $getStatusResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getstatus $biosPostState = $getStatusResults.configResolveClass.outConfigs.computeRackUnit.biosPostState }until ($biosPostState -match "complete") Write-Host "BIOS Post complete" #Wait 30 Seconds Start-Sleep -Seconds 15 Write-Host "Getting Local Drives through API for RAID Array" #Get Local Disks that are in the M2 Slot $getLocalHdd = '<configResolveClass cookie="' + $cookie + '" inHierarchical="false" classId="pidCatalogHdd"/>' $localHddResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $getLocalHdd $localHdd = $localHddResults.configResolveClass.outConfigs.pidCatalogHdd $localDisks = @() foreach ($hdd in $localHdd) { $localDisks += $hdd | Where-Object -Property "pid" -like "UCS-M2-240GB" | Select-Object -ExpandProperty disk } Write-Host "Creating Virtual Drive Group for Raid Array and creating Raid Array" #Set Var for Virtual Disk Creation $driveGroup = "[" + $localDisks[0] + "," + $localDisks[1] + "]" $driveCreate = '<configConfMo cookie="' + $cookie + '" inHierarchical="false" dn="sys/rack-unit-1/board/storage-MSTOR-RAID/virtual-drive-create"><inConfig><storageVirtualDriveCreatorUsingUnusedPhysicalDrive virtualDriveName="VD_BOOT" raidLevel="1" driveGroup="' + $driveGroup + '" stripSize="64k" adminState="trigger"/></inConfig></configConfMo>' #Create Raid array for the VMware ESXi $driveCreateResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $driveCreate if ( $driveCreateResults.configConfMo.outConfig.storageVirtualDriveCreatorUsingUnusedPhysicalDrive.status -eq "modified") { Write-Host "Sucessfully created RAID Array on $imcip" } Write-Host "Enableing Secure Boot on $imcip" #API Request for Enabling Secureboot $secureBootEnable = "<configConfMo cookie='$cookie' inHierarchical='true'><inConfig><lsbootBootSecurity dn='sys/rack-unit-1/boot-policy/boot-security' secureBoot='enable'/></inConfig></configConfMo>" $secureBootEnableResults = Invoke-RestMethod -Method Post -SkipCertificateCheck -Uri "https://$imcip/nuova" -Body $secureBootEnable if ($secureBootEnableResults.configConfMo.outConfig.lsbootBootSecurity.status -eq "modified") { Write-Host "Enableing Secure Boot on $imcip : Successful" } } Function Set-SDVCenterSettings { $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) #Connect to vCenter Server for Site Connect-VIServer -Server "10.$siteNumberIP.4.200" -User 'administrator@vsphere.local' -Password '12qwaszx!@QWASZX' -Force #Get datacenter form vCenter $VMDataCenter = Get-Datacenter -Name "$site" #Create new Virtual Distributed Switch New-VDSwitch -Name "$site-VDS-001" -Location $VMDataCenter -LinkDiscoveryProtocol "LLDP" -LinkDiscoveryProtocolOperation "Both" -MaxPorts 256 -NumUplinkPorts 2 -Mtu 9000 #Create VLANS on VDS-001 switch Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v30.$site`-usr-tr" -NumPorts 8 -VLanId 30 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v31.$site`-srv-tr" -NumPorts 8 -VLanId 31 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v32.$site`-net-mgt" -NumPorts 8 -VLanId 32 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v33.$site`-pawt0-tr" -NumPorts 8 -VLanId 33 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v34.$site`-pawt1-tr" -NumPorts 8 -VLanId 34 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v40.$site`-ia-tr" -NumPorts 8 -VLanId 40 Get-VDSwitch -Name "$site-VDS-001" | New-VDPortgroup -Name "v998.$site`-net-mgt" -NumPorts 8 -VLanId 998 Get-VDSwitch -Name "$site-VDS-002" | New-VDPortgroup -Name "v3001.$site`-vsan-tr" -NumPorts 8 -VLanId 3001 Get-VDSwitch -Name "$site-VDS-002" | New-VDPortgroup -Name "v3002.$site`-vmotion-tr" -NumPorts 8 -VLanId 3002 } Function Add-SDVMHost { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $esxiip, [Parameter(Mandatory = $true)] [Bollean] $witnessHost ) <# This Function connects to the vcenter server and then added the host to thew vSAN cluster if it is not a witness. Following this it then Adds the disks for vSAN into a disk group #> $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) #Connect to vCenter Server for Site Connect-VIServer -Server "10.$siteNumberIP.4.200" -User 'administrator@vsphere.local' -Password '12qwaszx!@QWASZX' -Force if ($witnessHost -eq $false) { $vmcluster = Get-Cluster Add-VMHost -Location $vmcluster -Name $esxiip -User root -Password '12qwaszx!@QWASZX' -Force Disconnect-VIServer * -Confirm:$false Connect-VIServer -Server $esxiIP -Protocol https -User root -Password '12qwaszx!@QWASZX' -Force $capacityDisks = Get-VMHost | Get-ScsiLun | Where-Object -Property Model -EQ "INTEL SSDPF2KX03" | Select-Object -ExpandProperty CanonicalName $cacheDisks = Get-VMHost | Get-ScsiLun | Where-Object -Property Model -EQ "INTEL SSDPF2KX01" | Select-Object -ExpandProperty CanonicalName Disconnect-VIServer * -Confirm:$false Connect-VIServer -Server "10.$siteNumberIP.4.200" -Protocol https -User "Administrator@vsphere.local"-Password '12qwaszx!@QWASZX' -Force New-VsanDiskGroup -VMHost $esxiip -SsdCanonicalName $cacheDisks -DataDiskCanonicalName $capacityDisks Disconnect-VIServer * -Confirm:$false } elseif ($witnessHost -eq $true) { $dc = Get-Datacenter Add-VMHost -Location $dc -Name $esxiip -User root -Password '12qwaszx!@QWASZX' -Force Disconnect-VIServer * -Confirm:$false } } Function Set-SDVMHSettings { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $esxiip ) $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) #Connect to vCenter Server for Site Connect-VIServer -Server "10.$siteNumberIP.4.200" -User 'administrator@vsphere.local' -Password '12qwaszx!@QWASZX' -Force #Get NICs for VDS-001 $vmhostNetworkAdapter1 = Get-VMHost $esxiip | Get-VMHostNetworkAdapter -Physical -Name vmnic2 $vmhostNetworkAdapter2 = Get-VMHost $esxiip | Get-VMHostNetworkAdapter -Physical -Name vmnic3 $vmhostNetworkAdapter3 = Get-VMHost $esxiip | Get-VMHostNetworkAdapter -Physical -Name vmnic4 $vmhostNetworkAdapter4 = Get-VMHost $esxiip | Get-VMHostNetworkAdapter -Physical -Name vmnic5 #Add Host to VDS-001 Get-VDSwitch -Name "$site-VDS-001" | Add-VDSwitchVMHost -VMHost $esxiip -confirm:$False #Add Nics from the servers to the VDS-001 Get-VDSwitch "$site-VDS-001" | Add-VDSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmhostNetworkAdapter1 -confirm:$False Get-VDSwitch "$site-VDS-001" | Add-VDSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmhostNetworkAdapter2 -confirm:$False Get-VDSwitch "$site-VDS-001" | Add-VDSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmhostNetworkAdapter3 -confirm:$False Get-VDSwitch "$site-VDS-001" | Add-VDSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmhostNetworkAdapter4 -confirm:$False $esxiip -match ".\d+$" $esxiipLastOctect = $Matches[0] $esxiipLastOctect = $esxiipLastOctect.Replace(".", "") #Create VMDK for vmotion on VDS-001 $vds = Get-VDSwitch -Name "$site-VDS-001" New-VMHostNetworkAdapter -VirtualSwitch $vds -PortGroup "v3002.$site`-vmotion-tr" -IP "10.$siteNumberIP.6.$esxiipLastOctect" -SubnetMask "255.255.255.0" -mtu 9000 -VMotionEnabled $true -vmhost $esxiip #Create VMDK for vSAN on VDS-001 New-VMHostNetworkAdapter -VirtualSwitch $vds -PortGroup "v3001.$site`-vsan-tr" -IP "10.$siteNumberIP.5.$esxiipLastOctect" -SubnetMask "255.255.255.0" -mtu 9000 -VsanTrafficEnabled $true -VMHost $esxiip Disconnect-VIServer * -Confirm:$false } Function New-SDVMwareConfig { [CmdletBinding()] param ( #VMware IP address [Parameter(Mandatory = $True)] [String] $vmwareIP, #Domain Name [Parameter(Mandatory = $True)] [String] $domainName, #Hostname for Virtual Machine Host [Parameter(Mandatory = $True)] [String] $hostname, #Site Number in IP Format [Parameter(Mandatory = $True)] [String] $siteNumberIP, #Root Password VMware [Parameter(Mandatory = $True)] [String] $rootPw, #On Board Port 1 MAC [Parameter(Mandatory = $True)] [String] $hypenMAC ) $siteNumberIP = (Set-SiteIPFormat -site $siteNumberIP) [string[]]$vmkickstartconfig = Get-Content $PSScriptRoot\Templates\vmkickstart.txt $vmkickstartconfig[3] = $vmkickstartconfig[3].Replace('$vmwareIP', $vmwareIP) $vmkickstartconfig[3] = $vmkickstartconfig[3].Replace('$siteNumberIP', $siteNumberIP) $vmkickstartconfig[3] = $vmkickstartconfig[3].Replace('$hostname', $hostname) $vmkickstartconfig[3] = $vmkickstartconfig[3].Replace('$domainName', $domainName) $vmkickstartconfig[4] = $vmkickstartconfig[4].Replace('$rootpw', $rootpw) $vmkickstartconfig[23] = $vmkickstartconfig[23].Replace('$siteNumberIP', $siteNumberIP) $kickstart = "vmaccepteula install --firstdisk --overwritevmfs network --bootproto=static --ip=$vmwareIP --netmask=255.255.255.0 --gateway=10.$siteNumberIP.4.1 --hostname=$hostname.$domainName --nameserver=10.$siteNumberIP.8.82,10.$siteNumberIP.8.83 --vlanid=3000 rootpw $rootPw keyboard 'US Default' reboot %firstboot --interpreter=busybox # enable & start SSH vim-cmd hostsvc/enable_ssh vim-cmd hostsvc/start_ssh # enable & start ESXi Shell vim-cmd hostsvc/enable_esx_shell vim-cmd hostsvc/start_esx_shell # Suppress ESXi Shell warning esxcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1 # NTP esxcli system ntp set -s 172.30.0.$siteNumberIP esxcli system ntp set -e 1 " if (!(Test-Path C:\HTTP_Boot\esxi\01-$hypenMAC)) { New-Item -Name 01-$hypenMAC -Path C:\HTTP_Boot\esxi\ -ItemType Directory } $kickstart | Out-File C:\HTTP_Boot\esxi\01-$hypenMAC\$hypenMAC-ks.cfg $ksPath = "http://$global:deployserverIP/esxi/01-$hypenMAC/$hypenMAC-ks.cfg" $bootCFG = "bootstate=0 title=Loading ESXi installer timeout=5 prefix=http://$global:deployserverIP/esxi/7.0.3 kernel=b.b00 kernelopt=ks=$ksPath runweasel modules=jumpstrt.gz --- useropts.gz --- features.gz --- k.b00 --- uc_intel.b00 --- uc_amd.b00 --- uc_hygon.b00 --- procfs.b00 --- vmx.v00 --- vim.v00 --- tpm.v00 --- sb.v00 --- s.v00 --- ucstoole.v00 --- nenicens.v00 --- nenic.v00 --- nfnic.v00 --- i40en.v00 --- igbn.v00 --- ixgben.v00 --- nmlx5cor.v00 --- nmlx5rdm.v00 --- qcnic.v00 --- qedentv.v00 --- qedf.v00 --- qedi.v00 --- qedrntv.v00 --- qfle3.v00 --- qfle3f.v00 --- qfle3i.v00 --- atlantic.v00 --- bnxtnet.v00 --- bnxtroce.v00 --- brcmfcoe.v00 --- elxiscsi.v00 --- elxnet.v00 --- iavmd.v00 --- icen.v00 --- ionic_en.v00 --- irdman.v00 --- iser.v00 --- lpfc.v00 --- lpnic.v00 --- lsi_mr3.v00 --- lsi_msgp.v00 --- lsi_msgp.v01 --- lsi_msgp.v02 --- mtip32xx.v00 --- ne1000.v00 --- nhpsa.v00 --- nmlx4_co.v00 --- nmlx4_en.v00 --- nmlx4_rd.v00 --- ntg3.v00 --- nvme_pci.v00 --- nvmerdma.v00 --- nvmetcp.v00 --- nvmxnet3.v00 --- nvmxnet3.v01 --- pvscsi.v00 --- qflge.v00 --- rste.v00 --- sfvmk.v00 --- smartpqi.v00 --- vmkata.v00 --- vmkfcoe.v00 --- vmkusb.v00 --- vmw_ahci.v00 --- bmcal.v00 --- crx.v00 --- elx_esx_.v00 --- btldr.v00 --- esx_dvfi.v00 --- esx_ui.v00 --- esxupdt.v00 --- tpmesxup.v00 --- weaselin.v00 --- esxio_co.v00 --- loadesx.v00 --- lsuv2_hp.v00 --- lsuv2_in.v00 --- lsuv2_ls.v00 --- lsuv2_nv.v00 --- lsuv2_oe.v00 --- lsuv2_oe.v01 --- lsuv2_oe.v02 --- lsuv2_sm.v00 --- native_m.v00 --- qlnative.v00 --- trx.v00 --- vdfs.v00 --- vmware_e.v00 --- vsan.v00 --- vsanheal.v00 --- vsanmgmt.v00 --- tools.t00 --- xorg.v00 --- gc.v00 --- imgdb.tgz --- basemisc.tgz --- resvibs.tgz --- imgpayld.tgz build=7.0.3-0.20.19193900 updated=0" $BootCFG | Out-File C:\HTTP_Boot\esxi\01-$hypenMAC\boot.cfg } Function New-SDVsanStretchedClusterWitness { <# .SYNOPSIS This function will deploy a Witness for a 2 Node or Stretched vSAN Cluster .DESCRIPTION This function will deploy a Witness for a 2 Node or Stretched vSAN Cluster .PARAMETER Cluster Specifies the name of the Cluster you want to set the vSAN Witness Host for. .PARAMETER Datastore Specifies the name of the datastore to use. .PARAMETER OVAPath Full path and OVA filename for the vSAN Witness Appliance .PARAMETER Name The Virtual Machine Name of the vSAN Witness Appliance .PARAMETER Pass The root password of the vSAN Witness Appliance .PARAMETER Size The deployment size of the vSAN Witness Appliance .PARAMETER PG1 The port group name for the vSAN Witness Appliance management network .PARAMETER PG2 The port group name for the vSAN Witness Appliance WitnessPg network .EXAMPLE PS C:\> New-VsanStretchedClusterWitness -Cluster <Cluster Name> -Datastrre <Datastore name> -OVAPath <c:\path\witness-xxx.ova> -Name <Witness VM Name> -Pass <password for witness> -Size <tiny/normal/large> -PG1 <port group name for Management network> -PG2 <port group name for Witness Network> #> $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) $Cluster = $site + "-vSAN" # Grab a random host in the cluster to deploy to $TargetHost = Get-Cluster $Cluster | Get-VMHost | Where-Object { $_.PowerState -eq "PoweredOn" -and $_.ConnectionState -eq "Connected" } | Get-Random # Grab a random datastore $TargetDatastore = Get-Datastore -Host $TargetHost | Where-Object -Property Name -Match "^datastore" # Grab the OVA properties from the vSAN Witness Appliance OVA $OVARoot = "C:\StackDeploy\" $OVAPath = Get-ChildItem C:\StackDeploy\ | Where-Object -Property Name -Match "^VMware-Virtual" | Select-Object -ExpandProperty Name $OVAFile = $OVARoot + $OVAPath $ovfConfig = Get-OvfConfiguration -Ovf $OVAFile # Set the Network Port Groups to use, the deployment size, and the root password for the vSAN Witness Appliance $ovfconfig.NetworkMapping.Management_Network.Value = "v3000." + $site + "-vmware-mgt" $ovfconfig.NetworkMapping.Secondary_Network.Value = "v3001." + $site + "-vsan-tr" $ovfconfig.DeploymentOption.Value = "normal" $ovfconfig.Common.guestinfo.passwd = "12qwaszx!@QWASZX" $ovfconfig.Common.guestinfo.ipaddress0 = "10.$siteNumberIP.4.201" $ovfconfig.Common.guestinfo.netmask0 = "255.255.255.0" $ovfconfig.Common.guestinfo.gateway0 = "10.$siteNumberIP.4.1" $ovfconfig.Common.guestinfo.dnsDomain = $config.config.DomainName $ovfconfig.Common.guestinfo.hostname = $site + "-VSANW-001v" $ovfconfig.Common.guestinfo.dns = "10.$siteNumberIP.8.82" $ovfconfig.Common.guestinfo.ipaddress1 = "10.$siteNumberIP.5.201" $ovfconfig.Common.guestinfo.netmask1 = "255.255.255.0" $ovfconfig.Common.guestinfo.gateway1 = "10.$siteNumberIP.5.1" # Import the vSAN Witness Appliance Import-VApp -Source $OVAFile -OvfConfiguration $ovfConfig -Name $ovfconfig.Common.guestinfo.hostname -VMHost $TargetHost -Datastore $TargetDatastore -DiskStorageFormat Thin } Function New-SDVsanStretchedClusterWitnessLarge { <# .SYNOPSIS This function will deploy a Witness for a 6 Node or Stretched vSAN Cluster .DESCRIPTION This function will deploy a Witness for a 6 Node or Stretched vSAN Cluster .PARAMETER Cluster Specifies the name of the Cluster you want to set the vSAN Witness Host for. .PARAMETER Datastore Specifies the name of the datastore to use. .PARAMETER OVAPath Full path and OVA filename for the vSAN Witness Appliance .PARAMETER Name The Virtual Machine Name of the vSAN Witness Appliance .PARAMETER Pass The root password of the vSAN Witness Appliance .PARAMETER Size The deployment size of the vSAN Witness Appliance .PARAMETER PG1 The port group name for the vSAN Witness Appliance management network .PARAMETER PG2 The port group name for the vSAN Witness Appliance WitnessPg network .EXAMPLE PS C:\> New-VsanStretchedClusterWitness -Cluster <Cluster Name> -Datastrre <Datastore name> -OVAPath <c:\path\witness-xxx.ova> -Name <Witness VM Name> -Pass <password for witness> -Size <tiny/normal/large> -PG1 <port group name for Management network> -PG2 <port group name for Witness Network> #> $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) # Grab a random host in the cluster to deploy to $TargetHost = Get-VMHost -Name "10.$siteNumberIP.4.10" # Grab a random datastore $TargetDatastore = Get-Datastore -Host $TargetHost | Where-Object -Property Name -Match "^datastore" # Grab the OVA properties from the vSAN Witness Appliance OVA $OVARoot = "C:\StackDeploy\" $OVAPath = Get-ChildItem C:\StackDeploy\ | Where-Object -Property Name -Match "^VMware-Virtual" | Select-Object -ExpandProperty Name $OVAFile = $OVARoot + $OVAPath $ovfConfig = Get-OvfConfiguration -Ovf $OVAFile # Set the Network Port Groups to use, the deployment size, and the root password for the vSAN Witness Appliance $ovfconfig.NetworkMapping.Management_Network.Value = "v3000." + $site + "-vmware-mgt" $ovfconfig.NetworkMapping.Secondary_Network.Value = "v3001." + $site + "-vsan-tr" $ovfconfig.DeploymentOption.Value = "normal" $ovfconfig.Common.guestinfo.passwd = "12qwaszx!@QWASZX" $ovfconfig.Common.guestinfo.ipaddress0 = "10.$siteNumberIP.4.201" $ovfconfig.Common.guestinfo.netmask0 = "255.255.255.0" $ovfconfig.Common.guestinfo.gateway0 = "10.$siteNumberIP.4.1" $ovfconfig.Common.guestinfo.dnsDomain = $config.config.DomainName $ovfconfig.Common.guestinfo.hostname = $site + "-VSANW-001v" $ovfconfig.Common.guestinfo.dns = "10.$siteNumberIP.8.82" $ovfconfig.Common.guestinfo.ipaddress1 = "10.$siteNumberIP.5.201" $ovfconfig.Common.guestinfo.netmask1 = "255.255.255.0" $ovfconfig.Common.guestinfo.gateway1 = "10.$siteNumberIP.5.1" # Import the vSAN Witness Appliance Import-VApp -Source $OVAFile -OvfConfiguration $ovfConfig -Name $ovfconfig.Common.guestinfo.hostname -VMHost $TargetHost -Datastore $TargetDatastore -DiskStorageFormat Thin } Function New-SDVCenterConfig { [CmdletBinding()] param ( #ESXi IP [Parameter(Mandatory = $true)] [String] $esxiIP ) $site = $config.config.SiteNumber $siteNumberIP = (Set-SiteIPFormat -site $site) Connect-VIServer -Server $esxiIP -Protocol https -User root -Password '12qwaszx!@QWASZX' -Force $capacityDisks = Get-VMHost | Get-ScsiLun | Where-Object -Property Model -EQ "INTEL SSDPF2KX03" | Select-Object -ExpandProperty CanonicalName $cachDisks = Get-VMHost | Get-ScsiLun | Where-Object -Property Model -EQ "INTEL SSDPF2KX01" | Select-Object -ExpandProperty CanonicalName $vcenterTemplate = Get-content C:\StackDeploy\vCenter-Template.json -Raw | ConvertFrom-Json $vcenterTemplate.new_vcsa.esxi.hostname = $esxiIP $vcenterTemplate.new_vcsa.esxi.password = "12qwaszx!@QWASZX" $vcenterTemplate.new_vcsa.esxi.password = "12qwaszx!@QWASZX" $vcenterTemplate.new_vcsa.esxi.VCSA_Cluster.datacenter = $site $vcenterTemplate.new_vcsa.esxi.VCSA_Cluster.cluster = $site + "-vSAN" $vcenterTemplate.new_vcsa.esxi.VCSA_Cluster.deduplication_and_compression = $true $vcenterTemplate.new_vcsa.esxi.VCSA_cluster.disks_for_vsan.capacity_disk = @($capacitydisks) $vcenterTemplate.new_vcsa.esxi.VCSA_cluster.disks_for_vsan.cache_disk = @($cachDisks) $vcenterTemplate.new_vcsa.esxi.VCSA_cluster.enable_vlcm = $false $vcenterTemplate.new_vcsa.appliance.name = $site + "-VCSA-001v" $vcenterTemplate.new_vcsa.network.ip = "10." + $siteNumberIP + ".4.200" $vcenterTemplate.new_vcsa.network.prefix = "24" $vcenterTemplate.new_vcsa.network.gateway = "10." + $siteNumberIP + ".4.1" $vcenterTemplate.new_vcsa.network.system_name = "10." + $siteNumberIP + ".4.200" $vcenterTemplate.new_vcsa.network.dns_servers = @("10.$siteNumberIP.8.82", "10.$siteNumberIP.8.83") $vcenterTemplate.new_vcsa.os.password = "12qwaszx!@QWASZX" $vcenterTemplate.new_vcsa.os.ssh_enable = $true $vcenterTemplate.new_vcsa.os.time_tools_sync = $true $vcenterTemplate.new_vcsa.sso.password = "12qwaszx!@QWASZX" $vcenterTemplate | ConvertTo-Json -Depth 32 | Out-File C:\StackDeploy\vcenter-$site.json Disconnect-VIServer -Confirm:$false } Function Install-SDVCenterServer { if (!(Test-Path C:\StackDeploy\vcenter-logs)) { New-Item -Name vcenter-logs -ItemType Directory -Path C:\StackDeploy } #Get ISO for vCenter $vcsaiso = "C:\StackDeploy\" + (Get-ChildItem C:\StackDeploy | Where-Object -Property Name -Match "^VMware-VCSA" | Select-Object -ExpandProperty Name) $site = $config.config.SiteNumber $mountResult = Mount-DiskImage $vcsaiso -PassThru $mountResult | Get-Volume $driveLetter = (($mountResult | Get-Volume).DriveLetter) $process = (Start-Process "$driveLetter`:\vcsa-cli-installer\win32\vcsa-deploy.exe" -ArgumentList "install C:\StackDeploy\vcenter-$site.json --accept-eula --no-esx-ssl-verify --no-ssl-certificate-verification --verbose --log-dir C:\StackDeploy\vcenter-logs\" -Wait -PassThru) $process.ExitCode if ($process.ExitCode -eq 0) { Dismount-DiskImage -ImagePath $vcsaiso Write-Host "Sucessully deployed vCenter" return $process.ExitCode } elseif ($process.ExitCode -ne 0) { Write-Host $process.ExitCode Write-Host "An error has occured please consult the vcsa-cli-installer.log log files in C:\StackDeploy\vcenter-logs" return $process.ExitCode } } Function New-SDVsanStretchedCluster { <# .SYNOPSIS This function will create a 2 Node or Stretched vSAN Cluster .DESCRIPTION This function will create a 2 Node or Stretched vSAN Cluster .PARAMETER Witness Specifies the name of the new vSAN Witness Host want to use. .EXAMPLE PS C:\> New-VsanStretchedCluster -ClusterName <Cluster Name> -Witness <Witness> .NOTES Author : Jase McCarty Version : 0.1 ==========Tested Against Environment========== VMware vSphere Hypervisor(ESXi) Version : 6.5 VMware vCenter Server Version : 6.5 PowerCLI Version : PowerCLI 6.5.4 PowerShell Version : 3.0 #> # Set our Parameters [CmdletBinding()]Param( [Parameter(Mandatory = $true)] [String] $Witness ) $site = $global:config.config.SiteNumber # Check to see the cluster exists Try { # Check to make sure the New Witness Host has already been added to vCenter $Cluster = Get-Cluster -Name "$site-vSAN" -ErrorAction Stop } Catch [VMware.VimAutomation.Sdk.Types.V1.ErrorHandling.VimException.VimException] { Write-Host "The cluster, $ClusterName, was not found. " -foregroundcolor red -backgroundcolor white Write-Host "Please enter a valid cluster name and rerun this script." -foregroundcolor black -backgroundcolor white Exit } # Determine whether this is a 2 Node or Stretched Cluster $HostCount = $Cluster | Select-Object @{n = "count"; e = { ($_ | Get-VMHost).Count } } Switch ($HostCount.count) { "2" { $SCTYPE = "2 Node" } default { $SCTYPE = "Stretched" } } # Get the vSAN Cluster's Configuration $VsanConfig = Get-VsanClusterConfiguration -Cluster $Cluster # If we're dealing with a Stretched Cluster architecture, then we can proceed If (-Not $VsanConfig.StretchedClusterEnabled) { # Create Fault Domains for 2 Node vSAN $Cluster | Set-Cluster -VsanEnabled:$true -Confirm:$false -ErrorAction SilentlyContinue $VsanHosts = $Cluster | Get-VMHost $PFD = Get-VsanFaultDomain -Name "Preferred" -ErrorAction SilentlyContinue If (-Not $PFD) { $PFD = New-VsanFaultDomain -VMHost $VsanHosts[0] -Name "Preferred" -Confirm:$false } $SFD = Get-VsanFaultDomain -Name "Secondary" -ErrorAction SilentlyContinue If (-Not $SFD) { $SFD = New-VsanFaultDomain -VMHost $VsanHosts[1] -Name "Secondary" -Confirm:$false } # Get the Witness Host $WitnessHost = Get-VMHost -Name $Witness -ErrorAction Stop # See if it is the VMware vSAN Witness Appliance $IsVsanWitnessAppliance = Get-AdvancedSetting -Entity $WitnessHost -Name Misc.vsanWitnessVirtualAppliance # If it is the VMware vSAN Witness Appliance, then proceed If ($IsVsanWitnessAppliance.Value -eq "1") { Write-Host "$Witness is a vSAN Witness Appliance." -foregroundcolor black -backgroundcolor green # Check to make sure a VMKernel port is tagged for vSAN Traffic, otherwise exit. Could possibly tag a VMkernel next time If ( Get-VMHost $Witness | Get-VMHostNetworkAdapter | Where-Object { $_.VsanTrafficEnabled }) { Write-Host "$Witness has a VMKernel port setup for vSAN Traffic. Proceeding." -foregroundcolor black -backgroundcolor green } else { Write-Host "$Witness does not have a VMKernel port setup for vSAN Traffic. Exiting" -foregroundcolor red -backgroundcolor white Exit } } else { # The Witness isn't a vSAN Witness Appliance, so exit Write-Host "$Witness is not a vSAN Witness Appliance, stopping" -foregroundcolor red -backgroundcolor white Write-Host "This script only supports using the vSAN Witness Appliance" -foregroundcolor red -backgroundcolor white Exit } $VsanWitnessHostDisks = Get-VMHost -Name $Witness | Get-VMHostHba | Get-ScsiLun | Where-Object { $_.VsanStatus -eq "Eligible" } # There must be at least 2 disks # Need to add a check to make sure at least 1 flash and 1 capacity (flash or spinning) If ($VsanWitnessHostDisks.Count -gt 1) { $CacheDisks = @() $CapacityDisks = @() # Enumerate through each of the disks. Foreach ($VsanDisk in $VsanHostDisks) { # If the device is tagged as SSD and is less than the max size, denote it as a cache device If ($VsanDisk.IsSsd -eq $true -and $VsanDisk.CapacityGB -lt "80") { $CacheDisks += $VsanDisk } else { # Add the disk to the CapacityDisks array $CapacityDisks += $VsanDisk } } # Set the cluster configuration to Stretched/2 Node, with the witness and the preferred fault domain Write-Host "Adding Witness $Witness and enabling the $SCTYPE Cluster" -foregroundcolor black -backgroundcolor white Set-VsanClusterConfiguration -Configuration $Cluster -StretchedClusterEnabled $True -PreferredFaultDomain $PFD -WitnessHost $Witness -WitnessHostCacheDisk $CacheDisks -WitnessHostCapacityDisk $CapacityDisks } } } #Export Function Memembers Export-ModuleMember -Function Set-SDIMCBootOrder Export-ModuleMember -Function Set-SDIMCInterface Export-ModuleMember -Function Set-SDIMCSetup Export-ModuleMember -Function Set-SDVCenterSettings Export-ModuleMember -Function Add-SDVMHost Export-ModuleMember -Function Set-SDVMHSettings Export-ModuleMember -Function New-SDVMwareConfig Export-ModuleMember -Function New-SDVsanStretchedClusterWitness Export-ModuleMember -Function New-SDVsanStretchedClusterWitnessLarge Export-ModuleMember -Function New-SDVCenterConfig Export-ModuleMember -Function Install-SDVCenterServer Export-ModuleMember -Function New-SDVsanStretchedCluster |