414 lines
17 KiB
PowerShell
414 lines
17 KiB
PowerShell
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|