Skip to content

Instantly share code, notes, and snippets.

@mczerniawski
Created October 19, 2018 09:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mczerniawski/66f8f6d9cc38ed5d5ab2a7561cda8704 to your computer and use it in GitHub Desktop.
Save mczerniawski/66f8f6d9cc38ed5d5ab2a7561cda8704 to your computer and use it in GitHub Desktop.
function Set-ClusterVMAntiAffinity {
<#
.SYNOPSIS
Will configure Preferred Owners for Virtual Machine running on Failover Cluster
.DESCRIPTION
Uses Invoke-Command to allow for PSCredential
If Preferred Owner is provided will verify if it matches cluster Owner Nodes.
If yes - will set Preferred Owners for given VMs.
If no - will abort.
If $null, or '' is provided will reset Preferred Owners to defaults for given VM
.PARAMETER Cluster
Cluster Name
.PARAMETER Credential
Optional PSCredential used to connect to cluster
.PARAMETER VMName
Virtual Machine Name or array of names to process
.PARAMETER AntiAffinityGroupName
AntiAffinity Group name to configure VM with.
.PARAMETER Append
Switch option whether group should be added to current set.
.EXAMPLE
Set two VMs 'windows2016' and 'windows2016core' with AntiAffinity Group named 'templates'
Set-ClusterVMAntiAffinity -Cluster 'cluster0' -VMName 'windows2016','windows2016core' -AntiAffinityGroupName 'Templates' -Verbose
VERBOSE: Processing with default credentials of user {mczerniawski_admin}
VERBOSE: Processing VM {windows2016}
VERBOSE: VM {windows2016} current AntiAffinity Groups: {}
VERBOSE: Setting Anti Affinity: {Templates} for VM {windows2016}
VERBOSE: Processing VM {windows2016core}
VERBOSE: VM {windows2016core} current AntiAffinity Groups: {Template}
VERBOSE: Setting Anti Affinity: {Templates} for VM {windows2016core}
Cluster VMName AntiAffinityGroupName
------- ------ ---------------------
cluster0 windows2016 Templates
cluster0 windows2016core Templates
.EXAMPLE
Add AntiAffinity Group named 'templates2' to two VMs 'windows2016' and 'windows2016core'
Set-ClusterVMAntiAffinity -Cluster 'cluster0' -VMName 'windows2016','windows2016core' -AntiAffinityGroupName 'Templates2' -Verbose -Append
VERBOSE: Processing with default credentials of user {mczerniawski_admin}
VERBOSE: Processing VM {windows2016}
VERBOSE: VM {windows2016} current AntiAffinity Groups: {Templates}
VERBOSE: Append selected. Preparing new object for AntiAffinity Group name for VM {windows2016}.
VERBOSE: Setting Anti Affinity: {Templates2} for VM {windows2016}
VERBOSE: Processing VM {windows2016core}
VERBOSE: VM {windows2016core} current AntiAffinity Groups: {Templates}
VERBOSE: Append selected. Preparing new object for AntiAffinity Group name for VM {windows2016core}.
VERBOSE: Setting Anti Affinity: {Templates2} for VM {windows2016core}
Cluster VMName AntiAffinityGroupName
------- ------ ---------------------
cluster0 windows2016 {Templates, Templates2}
cluster0 windows2016core {Templates, Templates2}
.EXAMPLE
Clear any Anti Affinity Group name on 'windows2016' VM
Set-ClusterVMAntiAffinity -Cluster 'cluster0' -VMName 'windows2016' -AntiAffinityGroupName $null -Verbose
VERBOSE: Processing with default credentials of user {mczerniawski_admin}
VERBOSE: Provided no AntiAffinity Group Name. Will reset to default setting
VERBOSE: Processing VM {windows2016}
VERBOSE: VM {windows2016} current AntiAffinity Groups: {}
VERBOSE: Setting Anti Affinity: {} for VM {windows2016}
Cluster VMName AntiAffinityGroupName
------- ------ ---------------------
cluster0 windows2016
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, HelpMessage = 'Provide Cluster Name',
ValueFromPipeline, ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[System.String]
$Cluster,
[Parameter(Mandatory = $false, HelpMessage = 'Provide Credentials for Cluster',
ValueFromPipeline, ValueFromPipelineByPropertyName)]
[System.Management.Automation.PSCredential]
$Credential,
[Parameter(Mandatory, HelpMessage = 'Provide VMName',
ValueFromPipeline, ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$VMName,
[Parameter(Mandatory = $false, HelpMessage = 'Provide Preferred Owners Nodes to restrict VM to failover to',
ValueFromPipeline, ValueFromPipelineByPropertyName)]
[System.String[]]
$AntiAffinityGroupName,
[Parameter(Mandatory = $false, HelpMessage = 'Append AntiAffinity group to current set',
ValueFromPipeline, ValueFromPipelineByPropertyName)]
[switch]
$Append
)
begin {
#region PSSession parameters
$connectionParams = @{
ComputerName = $Cluster
}
if ($PSBoundParameters.ContainsKey('Credential')) {
$connectionParams.Credential = $Credential
Write-Verbose -Message "Processing with provided credentials {$($Credential.UserName)}"
}
else {
Write-Verbose -Message "Processing with default credentials of user {$($env:USERNAME)}"
}
$ClusterSession = New-PSSession @connectionParams -ErrorAction Stop
#endregion
#null or empty string - reset to defaults
if (-not $AntiAffinityGroupName) {
Write-Verbose -Message "Provided no AntiAffinity Group Name. Will reset to default setting"
$AntiAffinityGroupName = ''
}
}
process {
foreach ($VM in $VMName) {
Write-Verbose -Message "Processing VM {$VM}"
$ClusterVM = Invoke-Command -Session $ClusterSession -ScriptBlock {
Get-ClusterGroup -Name $USING:VM -ErrorAction SilentlyContinue
}
if (-not $ClusterVM) {
Write-Error -Message "VM {$VM} not found on cluster {$Cluster}"
}
else {
Write-Verbose -Message "VM {$VM} current AntiAffinity Groups: {$($ClusterVM.AntiAffinityClassNames)}"
#set to defaults
if ($Append) {
Write-Verbose -Message "Append selected. Preparing new object for AntiAffinity Group name for VM {$VM}."
$finalAntiAffinityGroupName = @($ClusterVM.AntiAffinityClassNames) + @($AntiAffinityGroupName)
}
else {
$finalAntiAffinityGroupName = @($AntiAffinityGroupName)
}
Write-Verbose -Message "Setting Anti Affinity: {$AntiAffinityGroupName} for VM {$VM} "
$finalVMAntiAffinity = Invoke-Command -Session $ClusterSession -ScriptBlock {
(Get-ClusterGroup -Name $USING:VM).AntiAffinityClassNames = @($USING:finalAntiAffinityGroupName)
(Get-ClusterGroup -Name $USING:VM).AntiAffinityClassNames
}
[pscustomobject]@{
Cluster = $Cluster
VMName = $VM
AntiAffinityGroupName = $finalVMAntiAffinity
}
}
}
}
end {
$ClusterSession | Remove-PSSession -ErrorAction SilentlyContinue
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment