From 8201e075a47339cc23af9939f95ef6b7947dfec7 Mon Sep 17 00:00:00 2001 From: William Lam Date: Thu, 8 Dec 2016 05:43:04 -0800 Subject: [PATCH] Adding VCHA module --- Modules/VCHA.psm1 | 413 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 Modules/VCHA.psm1 diff --git a/Modules/VCHA.psm1 b/Modules/VCHA.psm1 new file mode 100644 index 0000000..160f0e7 --- /dev/null +++ b/Modules/VCHA.psm1 @@ -0,0 +1,413 @@ +Function Get-VCHAConfig { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: Nov 20, 2016 + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .SYNOPSIS + This function retrieves the VCHA Configuration which provides you with + the current state, mode as well as the IP Addresses of the Active, + Passive & Witness Node. This is only available on VCSA 6.5 (vSphere 6.5 or greater) + .DESCRIPTION + Function to return VCHA Configuration + .EXAMPLE + Get-VCHAConfig +#> + $vcHAClusterConfig = Get-View failoverClusterConfigurator + $vcHAConfig = $vcHAClusterConfig.getVchaConfig() + + $vcHAState = $vcHAConfig.State + switch($vcHAState) { + configured { + $activeIp = $vcHAConfig.FailoverNodeInfo1.ClusterIpSettings.Ip.IpAddress + $passiveIp = $vcHAConfig.FailoverNodeInfo2.ClusterIpSettings.Ip.IpAddress + $witnessIp = $vcHAConfig.WitnessNodeInfo.IpSettings.Ip.IpAddress + + $vcHAClusterManager = Get-View failoverClusterManager + $vcHAMode = $vcHAClusterManager.getClusterMode() + + Write-Host "" + Write-Host -NoNewline -ForegroundColor Green "VCHA State: " + Write-Host -ForegroundColor White "$vcHAState" + Write-Host -NoNewline -ForegroundColor Green " VCHA Mode: " + Write-Host -ForegroundColor White "$vcHAMode" + Write-Host -NoNewline -ForegroundColor Green " ActiveIP: " + Write-Host -ForegroundColor White "$activeIp" + Write-Host -NoNewline -ForegroundColor Green " PassiveIP: " + Write-Host -ForegroundColor White "$passiveIp" + Write-Host -NoNewline -ForegroundColor Green " WitnessIP: " + Write-Host -ForegroundColor White "$witnessIp`n" + ;break + } + invalid { Write-Host -ForegroundColor Red "VCHA State is in invalid state ...";break} + notConfigured { Write-Host "VCHA is not configured";break} + prepared { Write-Host "VCHA is being prepared, please try again in a little bit ...";break} + } +} + +Function Get-VCHAClusterHealth { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: Nov 20, 2016 + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .SYNOPSIS + This function retrieves the VCHA Cluster Health which provides more info + on each of the individual. This is only available on VCSA 6.5 (vSphere 6.5 or greater) + .DESCRIPTION + Function to return VCHA Cluster Health + .EXAMPLE + Get-VCHAClusterHealth +#> + $vcHAClusterConfig = Get-View failoverClusterConfigurator + $vcHAConfig = $vcHAClusterConfig.getVchaConfig() + $vcHAState = $vcHAConfig.State + + switch($vcHAState) { + invalid { Write-Host -ForegroundColor Red "VCHA State is in invalid state ...";break} + notConfigured { Write-Host "VCHA is not configured";break} + prepared { Write-Host "VCHA is being prepared ...";break} + configured { + $vcHAClusterManager = Get-View failoverClusterManager + $healthInfo = $vcHAClusterManager.GetVchaClusterHealth() + + $vcClusterState = $healthInfo.RuntimeInfo.ClusterState + $nodeState = $healthInfo.RuntimeInfo.NodeInfo + + Write-Host "" + Write-Host -NoNewline -ForegroundColor Green "VCHA Cluster State: " + Write-Host -ForegroundColor White "$vcClusterState" + Write-Host -NoNewline -ForegroundColor Green "VCHA Node Information: " + $nodeState | Select NodeIp, NodeRole, NodeState + ;break + } + } +} + +Function Set-VCHAClusterMode { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: Nov 20, 2016 + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .SYNOPSIS + This function allows you to set the mode of the VCHA Cluster whether + that is Enabled, Disabled or in Maintenance Mode. This is only available on VCSA 6.5 (vSphere 6.5 or greater) + .DESCRIPTION + Function to set VCHA Cluster Mode + .EXAMPLE + Set-VCHAClusterMode -Enabled $true + .EXAMPLE + Set-VCHAClusterMode -Disabled $true + .EXAMPLE + Set-VCHAClusterMode -Maintenance $true +#> + param( + [Switch]$Enabled, + [Switch]$Disabled, + [Switch]$Maintenance + ) + + $vcHAClusterManager = Get-View failoverClusterManager + + if($Enabled) { + Write-Host "Setting VCHA Cluster to Enabled ..." + $task = $vcHAClusterManager.setClusterMode_Task("enabled") + $task1 = Get-Task -Id ("Task-$($task.value)") + $task1 | Wait-Task + } elseIf($Maintenance) { + Write-Host "Setting VCHA Cluster to Maintenance ..." + $task = $vcHAClusterManager.setClusterMode_Task("maintenance") + $task1 = Get-Task -Id ("Task-$($task.value)") + $task1 | Wait-Task + } elseIf($Disabled) { + Write-Host "`nSetting VCHA Cluster to Disabled ...`n" + $task = $vcHAClusterManager.setClusterMode_Task("disabled") + $task1 = Get-Task -Id ("Task-$($task.value)") + $task1 | Wait-Task + } +} + +Function New-VCHABasicConfig { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: Nov 20, 2016 + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .SYNOPSIS + This function allows you create a new "Basic" VCHA Cluster, it does not + cover the "Advanced" use case. You will need to ensure that you have a + "Self Managed" vCenter Server before attempting this workflow. + This is only available on VCSA 6.5 (vSphere 6.5 or greater) + .DESCRIPTION + Function to create "Basic" VCHA Cluster + .PARAMETER VCSAVM + The name of the vCenter Server Appliance (VCSA) in which you wish to enable VCHA on (must be self-managed) + .PARAMETER HANetwork + The name of the Virtual Portgroup or Distributed Portgroup used for the HA Network + .PARAMETER ActiveHAIp + The IP Address for the Active VCSA node + .PARAMETER ActiveNetmask + The Netmask for the Active VCSA node + .PARAMETER PassiveHAIp + The IP Address for the Passive VCSA node + .PARAMETER PassiveNetmask + The Netmask for the Passive VCSA node + .PARAMETER WitnessHAIp + The IP Address for the Witness VCSA node + .PARAMETER WitnessNetmask + The Netmask for the Witness VCSA node + .PARAMETER PassiveDatastore + The name of the datastore to deploy the Passive node to + .PARAMETER WitnessDatastore + The name of the datastore to deploy the Witness node to + .PARAMETER VCUsername + The VCSA username (e.g. administrator@vghetto.local) + .PARAMETER VCPassword + The VCSA password + .EXAMPLE + New-VCHABasicConfig -VCSAVM "vcenter65-1" -HANetwork "DVPG-VCHA-Network" ` + -ActiveHAIp 192.168.1.70 ` + -ActiveNetmask 255.255.255.0 ` + -PassiveHAIp 192.168.1.71 ` + -PassiveNetmask 255.255.255.0 ` + -WitnessHAIp 192.168.1.72 ` + -WitnessNetmask 255.255.255.0 ` + -PassiveDatastore "vsanDatastore" ` + -WitnessDatastore "vsanDatastore" ` + -VCUsername "administrator@vghetto.local" ` + -VCPassword "VMware1!" +#> + param( + [Parameter( + Mandatory=$true, + ValueFromPipeline=$true, + ValueFromPipelineByPropertyName=$true) + ] + [String]$VCSAVM, + [String]$HANetwork, + [String]$ActiveHAIp, + [String]$ActiveNetmask, + [String]$PassiveHAIp, + [String]$PassiveNetmask, + [String]$PassiveDatastore, + [String]$WitnessHAIp, + [String]$WitnessNetmask, + [String]$WitnessDatastore, + # Crappy Implementation but need to research more into using PSH Credential + [String]$VCUsername, + [String]$VCPassword + ) + + $VCSAVMView = Get-View -ViewType VirtualMachine -Filter @{"name"=$VCSAVM} + if($VCSAVMView -eq $null) { + Write-Host -ForegroundColor Red "Error: Unable to find Virtual Machine $VCSAVM" + return + } + + $HANetworkView = Get-View -ViewType Network -Filter @{"name"=$HANetwork} + if($HANetworkView -eq $null) { + Write-Host -ForegroundColor Red "Error: Unable to find Network $HANetwork" + return + } + + $PassiveDatastoreView = Get-View -ViewType Datastore -Filter @{"name"=$PassiveDatastore} + if($PassiveDatastoreView -eq $null) { + Write-Host -ForegroundColor Red "Error: Unable to find Passive Datastore $PassiveDatastore" + return + } + + $WitnessDatastoreView = Get-View -ViewType Datastore -Filter @{"name"=$WitnessDatastore} + if($WitnessDatastoreView -eq $null) { + Write-Host -ForegroundColor Red "Error: Unable to find Witness Datastore $WitnessDatastore" + return + } + + $vcIP = $VCSAVMView.Guest.IpAddress + if($vcIP -eq $null) { + Write-Host -ForegroundColor Red "Error: Unable to automatically retrieve the IP Address of $VCSAVM which is needed to use this function" + return + } + + # Retrieve Source VC SSL Thumbprint + $vcurl = "https://$vcIP" +add-type @" + using System.Net; + using System.Security.Cryptography.X509Certificates; + + public class IDontCarePolicy : ICertificatePolicy { + public IDontCarePolicy() {} + public bool CheckValidationResult( + ServicePoint sPoint, X509Certificate cert, + WebRequest wRequest, int certProb) { + return true; + } + } +"@ + [System.Net.ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy + # Need to do simple GET connection for this method to work + Invoke-RestMethod -Uri $VCURL -Method Get | Out-Null + + $endpoint_request = [System.Net.Webrequest]::Create("$vcurl") + # Get Thumbprint + add colons for a valid Thumbprint + $vcSSLThumbprint = ($endpoint_request.ServicePoint.Certificate.GetCertHashString()) -replace '(..(?!$))','$1:' + + $vcHAClusterConfig = Get-View failoverClusterConfigurator + $spec = New-Object VMware.Vim.VchaClusterDeploymentSpec + + $activeNetworkConfig = New-Object VMware.Vim.ClusterNetworkConfigSpec + $activeNetworkConfig.NetworkPortGroup = $HANetworkView.MoRef + $ipSettings = New-Object Vmware.Vim.CustomizationIPSettings + $ipSettings.SubnetMask = $ActiveNetmask + $activeIpSpec = New-Object VMware.Vim.CustomizationFixedIp + $activeIpSpec.IpAddress = $ActiveHAIp + $ipSettings.Ip = $activeIpSpec + $activeNetworkConfig.IpSettings = $ipSettings + $spec.ActiveVcNetworkConfig = $activeNetworkConfig + + $activeVCConfig = New-Object Vmware.Vim.SourceNodeSpec + $activeVCConfig.ActiveVc = $VCSAVMView.MoRef + $serviceLocator = New-Object Vmware.Vim.ServiceLocator + $credential = New-Object VMware.Vim.ServiceLocatorNamePassword + $credential.username = $VCUsername + $credential.password = $VCPassword + $serviceLocator.Credential = $credential + $serviceLocator.InstanceUuid = $global:DefaultVIServer.InstanceUuid + $serviceLocator.Url = $vcurl + $serviceLocator.SslThumbprint = $vcSSLThumbprint + $activeVCConfig.ManagementVc = $serviceLocator + $spec.ActiveVcSpec = $activeVCConfig + + $passiveSpec = New-Object VMware.Vim.PassiveNodeDeploymentSpec + $passiveSpec.Folder = (Get-View (Get-Folder vm)).MoRef + $passiveIpSettings = New-object Vmware.Vim.CustomizationIPSettings + $passiveIpSettings.SubnetMask = $passiveNetmask + $passiveIpSpec = New-Object VMware.Vim.CustomizationFixedIp + $passiveIpSpec.IpAddress = $passiveHAIp + $passiveIpSettings.Ip = $passiveIpSpec + $passiveSpec.IpSettings = $passiveIpSettings + $passiveSpec.NodeName = $VCSAVMView.Name + "-Passive" + $passiveSpec.datastore = $PassiveDatastoreView.MoRef + $spec.PassiveDeploymentSpec = $passiveSpec + + $witnessSpec = New-Object VMware.Vim.NodeDeploymentSpec + $witnessSpec.Folder = (Get-View (Get-Folder vm)).MoRef + $witnessSpec.NodeName = $VCSAVMView.Name + "-Witness" + $witnessIpSettings = New-object Vmware.Vim.CustomizationIPSettings + $witnessIpSettings.SubnetMask = $witnessNetmask + $witnessIpSpec = New-Object VMware.Vim.CustomizationFixedIp + $witnessIpSpec.IpAddress = $witnessHAIp + $witnessIpSettings.Ip = $witnessIpSpec + $witnessSpec.IpSettings = $witnessIpSettings + $witnessSpec.datastore = $WitnessDatastoreView.MoRef + $spec.WitnessDeploymentSpec = $witnessSpec + + Write-Host "`nDeploying VCHA Cluster ...`n" + $task = $vcHAClusterConfig.deployVcha_Task($spec) + $task1 = Get-Task -Id ("Task-$($task.value)") + $task1 | Wait-Task -Verbose +} + +Function Remove-VCHAConfig { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: Nov 20, 2016 + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .SYNOPSIS + This function allows you destroy a VCHA Cluster. In addition, you have + the option to specify whether you would like both the Passive & Witness + Virtual Machines be deleted after the VCHA Cluster has been destroyed. + This is only available on VCSA 6.5 (vSphere 6.5 or greater) + .DESCRIPTION + Function to destroy a VCHA Cluster Mode + .EXAMPLE + Remove-VCHAConfig + .EXAMPLE + Remove-VCHAConfig -Confirm:$false + .EXAMPLE + Remove-VCHAConfig -DeleteVM $true -Confirm:$false + .NOTES + Before you can destroy a VCHA Cluster, you must make sure it is first + disabled. Run the Set-VCHAClusterMode -Disabled $true to do so +#> + param( + [Boolean]$Confirm=$true, + [Switch]$DeleteVM=$false + ) + + $Verified = $false + if($Confirm -eq $true) { + Write-Host -ForegroundColor Yellow "`nDo you want to destroy VCHA Cluster?" + $answer = Read-Host -Prompt "Do you accept (Y or N)" + if($answer -eq "Y" -or $answer -eq "y") { + $Verified = $true + } + } else { + $Verified = $true + } + + if($Verified) { + $vcHAClusterManager = Get-View failoverClusterManager + $vcHAMode = $vcHAClusterManager.getClusterMode() + + if($vcHAMode -ne "disabled") { + Write-Host -ForegroundColor Yellow "To destroy VCHA Cluster, you must first set the VCHA Cluster Mode to `"Disabled`"" + Exit + } + + # Query BIOS UUID of the Passive/Witness to be able to delete + if($DeleteVM) { + $vcHAClusterConfig = Get-View failoverClusterConfigurator + $vcHAConfig = $vcHAClusterConfig.getVchaConfig() + $passiveBiosUUID = $vcHAConfig.FailoverNodeInfo2.biosUuid + $witnessBiosUUID = $vcHAConfig.WitnessNodeInfo.biosUuid + } + + $vcHAClusterConfig = Get-View failoverClusterConfigurator + + Write-Host "Destroying VCHA Cluster ..." + $task = $vcHAClusterConfig.destroyVcha_Task() + $task1 = Get-Task -Id ("Task-$($task.value)") + $task1 | Wait-Task + + # After VCHA Cluster has been destroyed, we can now delete the VMs we had queried earlier + if($DeleteVM) { + if($passiveBiosUUID -ne $null -and $witnessBiosUUID -ne $null) { + $searchIndex = Get-View searchIndex + + $passiveVM = $searchIndex.FindByUuid($null,$passiveBiosUUID,$true,$null) + $witnessVM = $searchIndex.FindByUuid($null,$witnessBiosUUID,$true,$null) + + if($passiveVM -ne $null -and $witnessVM -ne $null) { + Write-Host "Powering off & deleting Passive VM ..." + Stop-VM -VM (Get-View $passiveVM).Name -Confirm:$false | Out-Null + Remove-VM (Get-View $passiveVM).Name -DeletePermanently -Confirm:$false + Write-Host "Powering off & deleting Witness VM ..." + Stop-VM -VM (Get-View $witnessVM).Name -Confirm:$false | Out-Null + Remove-VM (Get-View $witnessVM).Name -DeletePermanently -Confirm:$false + } + } + } + } +}