DRSRule.psm1
<# .Description
Retrieves the DRS VM groups. It returns DRS VM groups that correspond to the filter criteria provided by the cmdlet parameters. The default return type holds more information than the "raw" DRS object that vSphere uses. There is also a switch to allow for just returning said raw DRS object, quite useful for consumption by other cmdlets in this module. .Synopsis This cmdlet retrieves the DRS VM groups .Example Get-DrsVMGroup -Name '*VM Group 1*' Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 1 Cluster1 True {VM1,VM2} VM Group 12 Cluster1 True {VM3} New VM Group 100 Cluster2 True {VM4,VM5,VM6} Returns all DRS VM groups with name like '*VM Group 1*' .Example Get-DrsVMGroup -Cluster Cluster1 -Name 'VM Group 1' Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 1 Cluster1 True {VM1,VM2} The DRS VM group with the exact name 'VM Group 1' from Cluster1 will be returned .Example Get-Cluster Cluster2 | Get-DrsVMGroup Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 5 Cluster2 True {VM101,VM102} testVMGroup Cluster2 True {VM0,VM1001,VM1002} Returns all DRS VM groups in cluster "Cluster2" .Example Get-VM DrsRuleTest1 | Get-DrsVMGroup Name Cluster UserCreated VM ---- ------- ----------- -- TestVMGroup1 myClus0 True {DrsRuleTest1, DrsRuleTest0} Gets a DRS VMGroup by the related VM object. Returns the VMGroup(s) of which a VM is a part, if any .Outputs If corrsponding DRS VMGroup(s) found, either DRSRule.VMGroup in "normal" mode, or VMware.Vim.ClusterVmGroup in "-ReturnRaw" mode. Else, $null .Link https://github.com/PowerCLIGoodies/DRSRule New-DrsVMGroup Remove-DrsVMGroup Set-DrsVMGroup #> function Get-DrsVMGroup { [CmdletBinding(DefaultParameterSetName = "ByName")] [OutputType([DRSRule.VMGroup],[VMware.Vim.ClusterVmGroup])] param( ## Name of DRS VM Group to get (or, all if no name specified) [Parameter(Position = 0, ParameterSetName="ByName")] [string]${Name} = '*', ## Cluster from which to get DRS VM group (or, all clusters if no name specified) [Parameter(Position = 1, ParameterSetName="ByName", ValueFromPipeline=$True)] [PSObject[]]${Cluster}, ## Virtual Machine for which to get the corresponding DRS VMGroup(s), if any [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByRelatedObject")] [VMware.VimAutomation.Types.VirtualMachine]$VM, ## Switch: return "raw" VMware.Vim.ClusterVmGroup object (contains less info, but useful to other functions that can consume this raw object) [switch]$ReturnRawGroup ) Process { ## is this invocation getting item by related object? $bByRelatedObject = $PSCmdlet.ParameterSetName -eq "ByRelatedObject" ## get cluster object(s) from the Cluster param (if no value was specified -- gets all clusters) $arrClustersToCheck = if ($bByRelatedObject) {$VM.VMHost.Parent} else {Get-ClusterObjFromClusterParam -Cluster $Cluster} ## for the cluster(s) to check, try to get the pertinent VMGroups $arrClustersToCheck | ForEach-Object -Process { $oThisCluster = $_ ## update the View data, in case it was stale $oThisCluster.ExtensionData.UpdateViewData("ConfigurationEx") ## foreach ClusterVmGroup item, return something $oThisCluster.ExtensionData.ConfigurationEx.Group | Where-Object -FilterScript { ## where it's the given type, and, if ByRelatedObject, it contains the MoRef of this realted object -- else, if the name is like the specified name ($_ -is [VMware.Vim.ClusterVmGroup]) -and $(if ($bByRelatedObject) {$_.VM -contains $VM.Id} else {$_.Name -like ${Name}}) } | ForEach-Object -Process { if ($true -eq $ReturnRawGroup) {return $_} else { New-Object -TypeName DRSRule.VMGroup -Property @{ Name = $_.Name ## updated to use $oThisCluster, instead of $Cluster, which would get all cluster names if more than one cluster Cluster = $oThisCluster.Name VM = $( if($_.Vm) {Get-View $_.Vm -Property Name | Select-Object -ExpandProperty Name} else {$null} ) VMId = $_.Vm UserCreated = [Boolean]$_.UserCreated Type = $_.GetType().Name } } } } } } <# .Description This cmdlet retrieves the DRS VM groups. It returns DRS VM groups that correspond to the filter criteria provided by the cmdlet parameters. The default return type holds more information than the "raw" DRS object that vSphere uses. There is also a switch to allow for just returning said raw DRS object, quite useful for consumption by other cmdlets in this module. .Synopsis Retrieves the DRS VMHost groups .Example Get-DRSVMHostGroup -Name '*VMHost Group 1*' Name Cluster UserCreated VMHost ---- ------- ----------- ------ VMHost Group 1 Cluster1 True {esx1,esx2} VMHost Group 12 Cluster1 True {esx3} New VMHost Group 1 Cluster2 True {esx4,esx5,esx6} Returns all DRS VMHost groups with name like '*VMHost Group 1*' .Example Get-DRSVMHostGroup -Cluster Cluster1 -Name 'VMHost Group 1' Name Cluster UserCreated VMHost ---- ------- ----------- ------ VMHost Group 1 Cluster1 True {esx1,esx2} The DRS VMHost group with the exact name 'VMHost Group 1' from Cluster1 will be returned .Example Get-Cluster Cluster2 | Get-DrsVMHostGroup Name Cluster UserCreated VMHost ---- ------- ----------- ------ oldVMHostGroup Cluster2 True {esx11,esx12} VMHost Group DR Cluster2 True {esx13} New VMHost Grp 3 Cluster2 True {esx14,esx15,esx16} Returns all DRS VMHost groups in cluster "Cluster2" .Example Get-VMHost esx11 | Get-DrsVMHostGroup Name Cluster UserCreated VMHost ---- ------- ----------- ------ oldVMHostGroup Cluster2 True {esx11,esx12} Gets a DRS VMHostGroup by the related VMHost object. Returns the VMHostGroup(s) of which a VMHost is a part, if any .Outputs If corrsponding DRS VMHostGroup(s) found, either DRSRule.VMHostGroup in "normal" mode, or VMware.Vim.ClusterHostGroup in "-ReturnRaw" mode. Else, $null .Link https://github.com/PowerCLIGoodies/DRSRule New-DrsVMHostGroup Remove-DrsVMHostGroup Set-DrsVMHostGroup #> function Get-DrsVMHostGroup { [CmdletBinding(DefaultParameterSetName = "ByName")] [OutputType([DRSRule.VMHostGroup],[VMware.Vim.ClusterHostGroup])] param( ## Name of DRS VMHost Group to get (or, all if no name specified) [Parameter(Position = 0, ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]${Name} = '*', ## Cluster from which to get DRS VMHost group (or, all clusters if no name specified) [Parameter(Position = 1, ParameterSetName="ByName", ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [PSObject[]]${Cluster}, ## VMHost for which to get the corresponding DRS VMHostGroup(s), if any [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByRelatedObject")] [VMware.VimAutomation.Types.VMHost]$VMHost, ## Switch: return "raw" VMware.Vim.ClusterHostGroup object (contains less info, but useful to other functions that can consume this raw object) [switch]$ReturnRawGroup ) Process{ ## is this invocation getting item by related object? $bByRelatedObject = $PSCmdlet.ParameterSetName -eq "ByRelatedObject" ## get cluster object(s) from the Cluster param (if no value was specified -- gets all clusters) $arrClustersToCheck = if ($bByRelatedObject) {$VMHost.Parent} else {Get-ClusterObjFromClusterParam -Cluster $Cluster} ## for the cluster(s) to check, try to get the pertinent VMHostGroups $arrClustersToCheck | ForEach-Object -Process { $oThisCluster = $_ ## update the View data, in case it was stale $oThisCluster.ExtensionData.UpdateViewData("ConfigurationEx") ## foreach ClusterVmGroup item, return something $oThisCluster.ExtensionData.ConfigurationEx.Group | Where-Object -FilterScript { ($_ -is [VMware.Vim.ClusterHostGroup]) -and $(if ($bByRelatedObject) {$_.Host -contains $VMHost.Id} else {$_.Name -like ${Name}}) } | ForEach-Object -Process { if ($true -eq $ReturnRawGroup) {return $_} else { New-Object DRSRule.VMHostGroup -Property @{ Name = $_.Name Cluster = $oThisCluster.Name VMHost = $( if($_.Host) {Get-View $_.Host -Property Name | Select-Object -ExpandProperty Name} else {$null} ) VMHostId = $_.Host UserCreated = [Boolean]$_.UserCreated Type = $_.GetType().Name } } } } } } <# .Description This cmdlet retrieves the DRS VM to VM rules. It returns DRS VM to VM rules that correspond to the filter criteria provided by the cmdlet parameters. The VM to VM rules can be either affinity- or anti-affinity rules. The default return type holds more information than the "raw" DRS object that vSphere uses. There is also a switch to allow for just returning said raw DRS object, quite useful for consumption by other cmdlets in this module. .Synopsis Retrieves the DRS VM to VM rules .Example Get-DrsVMToVMRule -Name 'Rule 1*' Name Cluster Enabled KeepTogether Mandatory VM ---- ------- ------- ------------ --------- -- Rule 1 Cluster1 False False False {VM1, VM2} Rule 12 Cluster2 True True True {VM3, VM4} Returns all DRS VM to VM rules with name like 'Rule 1*' .Example Get-Cluster Cluster2 | Get-DrsVMtoVMRule Name Cluster Enabled KeepTogether Mandatory VM ---- ------- ------- ------------ --------- -- Rule 0 Cluster2 False False False {VM101, VM102} Rule 11 Cluster2 True True True {VM103, VM014} Rule_old Cluster2 False True True {VM110, VM111} Returns all DRS VM to VM rules in Cluster2 .Example Get-VM VM3 | Get-DrsVMToVMRule Name Cluster Enabled KeepTogether Mandatory VM ---- ------- ------- ------------ --------- -- Rule 12 Cluster2 True True True {VM3, VM4} Returns all DRS VM to VM rules involving the specified VM, "VM3" .Outputs DRSRule.VMToVMRule object with information about the given DRS VM to VM rule, or a raw vSphere object of on of the types VMware.Vim.ClusterAffinityRuleSpec or VMware.Vim.ClusterAntiAffinityRuleSpec, depending on if the rule is affinity or anti-affinity .Link https://github.com/PowerCLIGoodies/DRSRule New-DrsVMToVMRule Remove-DrsVMToVMRule Set-DrsVMToVMRule #> function Get-DrsVMToVMRule { [CmdletBinding(DefaultParameterSetName = "ByName")] [OutputType([DRSRule.VMToVMRule],[VMware.Vim.ClusterAffinityRuleSpec],[VMware.Vim.ClusterAntiAffinityRuleSpec])] param( ## Name of DRS VM-to-VMHost rule to get (or, all if no name specified) [Parameter(Position = 0, ParameterSetName="ByName")] [string]${Name} = '*', ## Cluster from which to get DRS VM-to-VM rule (or, all clusters if no name specified) [Parameter(Position = 1, ParameterSetName="ByName", ValueFromPipeline = $True)] [PSObject[]]${Cluster}, ## Virtual Machine for which to get the corresponding VM-to-VM DRS rule(s), if any [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByRelatedObject")] [VMware.VimAutomation.Types.VirtualMachine]$VM, ## Switch: return DRS VM to VM rule as "raw" VMware.Vim.ClusterAffinityRuleSpec or VMware.Vim.ClusterAntiAffinityRuleSpec object (contains less info, but useful to other functions that can consume this raw object) [switch]$ReturnRawRule ) Process { ## is this invocation getting item by related object? $bByRelatedObject = $PSCmdlet.ParameterSetName -eq "ByRelatedObject" ## get cluster object(s) from the Cluster param (if no value was specified -- gets all clusters) $arrClustersToCheck = if ($bByRelatedObject) {$VM.VMHost.Parent} else {Get-ClusterObjFromClusterParam -Cluster $Cluster} ## for the cluster(s) to check, try to get the pertinent VM-to-VM rules $arrClustersToCheck | ForEach-Object -Process { $oThisCluster = $_ ## update the View data, in case it was stale $oThisCluster.ExtensionData.UpdateViewData("ConfigurationEx") ## foreach rule item, return something $oThisCluster.ExtensionData.ConfigurationEx.Rule | Where-Object -FilterScript { ($_ -is [VMware.Vim.ClusterAffinityRuleSpec] -or $_ -is [VMware.Vim.ClusterAntiAffinityRuleSpec]) -and $(if ($bByRelatedObject) {$_.VM -contains $VM.Id} else {$_.Name -like ${Name}}) } | ForEach-Object -Process { if ($ReturnRawRule) {$_} else{ New-Object DRSRule.VMToVMRule -Property @{ Name = $_.Name Cluster = $oThisCluster.Name ClusterId = $oThisCluster.Id Enabled = [Boolean]$_.Enabled KeepTogether = $($_ -is [VMware.Vim.ClusterAffinityRuleSpec]) VM = $( if($_.VM) {Get-View $_.VM -Property Name | Select-Object -ExpandProperty Name} else {$null} ) VMId = $_.VM UserCreated = [Boolean]$_.UserCreated Type = $_.GetType().Name # Mandatory = [Boolean]$_.Mandatory } } } } } } <# .Description This cmdlet retrieves the DRS VM to VMHost rules. It returns a number of DRS VM to VMHost rules that correspond to the filter criteria provided by the cmdlet parameters. The default return type holds more information than the "raw" DRS object that vSphere uses. There is also a switch to allow for just returning said raw DRS object, quite useful for consumption by other cmdlets in this module. .Synopsis Retrieve the DRS VM to VMHost rules .Example Get-DrsVMToVMHostRule -Name 'Rule 1*' Name Cluster Enabled Mandatory VMGroupName ---- ------- ------- --------- ----------- Rule 1 Cluster1 False False VM Group 1 Rule 11 Cluster2 True True All VM Returns all DRS VM to VMHost rules with name like 'Rule 1*' .Example Get-DrsVMtoVMHostRule -Cluster Cluster[12] Name Cluster Enabled Mandatory VMGroupName ---- ------- ------- --------- ----------- Rule 0 Cluster1 True False VM Group 1 Rule 1 Cluster1 False False VM Group 12 Rule 2 Cluster1 False False VM Group 31 Rule 11 Cluster2 True True All VM Rule_bak Cluster2 True False testVMGroup Rule_toDel Cluster2 False True VM Group 5 Returns all DRS VM to VMHost rules in clusters named "Cluster1" and "Cluster2" .Example Get-VM myVM0 | Get-DrsVMtoVMHostRule Name Cluster Enabled Mandatory VMGroupName ---- ------- ------- --------- ----------- Rule 2 Cluster1 False False VM Group 31 Returns all DRS VM to VMHost rules in the cluster in which "myVM0" resides that involve a DRS VMGroup of which "myVM0" is a member .Example Get-VMHost myhost0.dom.com | Get-DrsVMtoVMHostRule Name Cluster Enabled Mandatory VMGroupName ---- ------- ------- --------- ----------- Rule_toDel Cluster2 False True VM Group 5 Returns all DRS VM to VMHost rules in the cluster of which VMHost "myhost0.dom.com" is a part, and that involve a DRS VMHostGroup of which "myhost0.dom.com" is a member (either as the Affine or AntiAffine VMHost group) .Outputs DRSRule.VMToVMHostRule bject with information about the given DRS VM to VMHost rule, or a "raw" VMware.Vim.ClusterVmHostRuleInfo vSphere object .Link https://github.com/PowerCLIGoodies/DRSRule New-DrsVMToVMHostRule Remove-DrsVMToVMHostRule Set-DrsVMToVMHostRule #> function Get-DrsVMToVMHostRule { [CmdletBinding(DefaultParameterSetName = "ByName")] [OutputType([DRSRule.VMToVMHostRule],[VMware.Vim.ClusterVmHostRuleInfo])] param( ## Name of DRS VM affinity/antiaffinity rule to get (or, all if no name specified) [Parameter(Position = 0, ParameterSetName="ByName")] [ValidateNotNullOrEmpty()] [string]${Name} = '*', ## Cluster from which to get DRS VM-to-VMhost rule (or, all clusters if no name specified) [Parameter(Position = 1, ParameterSetName="ByName", ValueFromPipeline = $True)] [PSObject[]]${Cluster}, ## Virtual Machine for which to get the corresponding VM-to-VMHost DRS rule(s), if any [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByRelatedVM")] [VMware.VimAutomation.Types.VirtualMachine]$VM, ## VMHost for which to get the corresponding VM-to-VMHost DRS rule(s), if any [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByRelatedVMHost")] [VMware.VimAutomation.Types.VMHost]$VMHost, ## Switch: return DRS VM to VMHost rule as "raw" VMware.Vim.ClusterVmHostRuleInfo object (contains less info, but useful to other functions that can consume this raw object) [switch]$ReturnRawRule ) Process { ## is this invocation getting item by related object? $bByRelatedObject = "ByRelatedVM", "ByRelatedVMHost" -contains $PSCmdlet.ParameterSetName ## get cluster object(s) from the Cluster param (if no value was specified -- gets all clusters), and the FilterScript scriptblock to use for the Where-Object call later, for "filtering" rules $arrClustersToCheck, $sbFilterScript = if ($bByRelatedObject) { if ($PSCmdlet.ParameterSetName -eq "ByRelatedVM") { ## the cluster in which the VM resides, and, a scriptblock that checks if the list of names of DRS VMGroups of which this VM is a part contains the VMGroupName property's value in the given VMToVMHost rule $VM.VMHost.Parent, {($VM | Get-DrsVMGroup -ReturnRaw).Name -contains $_.VmGroupName} } else { $arrNamesOfVMHostGroups_thisVMHost = ($VMHost | Get-DrsVMHostGroup -ReturnRaw).Name ## the cluster in which the VMHost resides, and, a scriptblock that checks if the list of names of DRS VMHostGroups of which this VMHost is a part contains either the AffineHostGroupName or AffineHostGroupName property's value in the given VMToVMHost rule # good way to do it using Compare-Object, but possibly more confusing to read -- checks to see if there is more than zero "equal" items in the two arrays # $VMHost.Parent, {(Compare-Object -ReferenceObject $arrNamesOfVMHostGroups_thisVMHost -DifferenceObject @($_.AffineHostGroupName, $_.AntiAffineHostGroupName) -IncludeEqual -ExcludeDifferent | Measure-Object).Count -gt 0} $VMHost.Parent, {$arrNamesOfVMHostGroups_thisVMHost -contains $_.AffineHostGroupName -or ($arrNamesOfVMHostGroups_thisVMHost -contains $_.AntiAffineHostGroupName)} } ## end else } else {(Get-ClusterObjFromClusterParam -Cluster $Cluster), {$_.Name -like $Name}} ## for the cluster(s) to check, try to get the pertinent VM-to-VMHost rules $arrClustersToCheck | ForEach-Object -Process { $oThisCluster = $_ ## update the View data, in case it was stale $oThisCluster.ExtensionData.UpdateViewData("ConfigurationEx") ## foreach rule item, return something $oThisCluster.ExtensionData.ConfigurationEx.Rule | Where-Object -FilterScript {$_ -is [VMware.Vim.ClusterVmHostRuleInfo]} | ## filter by the VmGroupName, the VMHostGroupName, or by the rule name, depending on the parameters supplied to this cmdlet call Where-Object -FilterScript $sbFilterScript | ForEach-Object -Process { if ($ReturnRawRule) {$_} else { New-Object DRSRule.VMToVMHostRule -Property @{ Name = $_.Name Cluster = $oThisCluster.Name ClusterId = $oThisCluster.Id Enabled = [Boolean]$_.Enabled Mandatory = [Boolean]$_.Mandatory VMGroupName = $_.vmGroupName AffineHostGroupName = $_.affineHostGroupName AntiAffineHostGroupName = $_.antiAffineHostGroupName UserCreated = [Boolean]$_.UserCreated Type = $_.GetType().Name } } } } } } #.ExternalHelp DRSRule.Help.xml Function New-DrsVMGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMGroup])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [Parameter(Mandatory = $True, Position = 2, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a VM obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) })] [PSObject[]]${VM}, [Switch]$Force ) Process{ Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## check if group of this name already exists in this cluster; removed the -ReturnRaw, as the actual group is what is needed for removal action later (if appropriate) $oExistingVmGroup = Get-DrsVMGroup -Cluster $oThisCluster -Name $Name if ($oExistingVmGroup -and !$Force) { Throw "DRS VM group named '$Name' already exists in cluster '$($oThisCluster.Name)'" } elseif($oExistingVmGroup -and $Force) { ## changed to use item returned from Get-DrsVMGroup, instead of "$_", which was the cluster object $oExistingVmGroup | Remove-DrsVMGroup } else { Write-Verbose "Good -- no DRS group of name '$Name' found in cluster '$($oThisCluster.Name)'" } $VM = $VM | Foreach-Object { $oThisVmItem = $_ if($oThisVmItem -is [System.String]) { try { ## limit scope to this cluster $oThisCluster | Get-VM -Name $oThisVmItem -ErrorAction:Stop } catch {Write-Warning "No VM of name '$oThisVmItem' found in cluster '$($oThisCluster.Name)'. Valid VM name?"; Throw $_} } else { $oThisVmItem } } if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Create DRS VM group '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $newGroup = New-Object VMware.Vim.ClusterVmGroup $newGroup.Name = ${Name} $newGroup.UserCreated = $True ## changed to use .Id instead of .ExtensionData.MoRef, for speed's sake (doesn't need to populate VM objects' .ExtensionData) $newGroup.VM = ${VM} | ForEach-Object -Process {$_.Id} $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::Add $groupSpec.Info = $newGroup $spec.GroupSpec += $groupSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMGroup -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function New-DrsVMHostGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMHostGroup])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [Parameter(Mandatory = $True, Position = 2, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a VMHost obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) })] [PSObject[]]${VMHost}, [Switch]$Force ) Process{ Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## check if group of this name already exists in this cluster $oExistingVMHostGroup = Get-DrsVMHostGroup -Cluster $oThisCluster -Name $Name if ($oExistingVMHostGroup -and !$Force) { Throw "DRS VMHost group named '$Name' already exists in cluster '$($oThisCluster.Name)'" } elseif($oExistingVMHostGroup -and $Force) { $oExistingVMHostGroup | Remove-DrsVMHostGroup } else { Write-Verbose "Good -- no DRS group of name '$Name' found in cluster '$($oThisCluster.Name)'" } $VMHost = $VMHost | Foreach-Object { $oThisVMHostItem = $_ if($oThisVMHostItem -is [System.String]) { try { ## limit scope to this cluster $oThisCluster | Get-VMHost -Name $oThisVMHostItem -ErrorAction:Stop } catch {Write-Warning "No VMHost of name '$oThisVMHostItem' found in cluster '$($oThisCluster.Name)'. Valid VMHost name?"; Throw $_} } else { $oThisVMHostItem } } if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Create DRS VMHost group '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $newGroup = New-Object VMware.Vim.ClusterHostGroup $newGroup.Name = ${Name} $newGroup.UserCreated = $True $newGroup.Host = ${VMHost} | ForEach-Object -Process {$_.Id} $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::Add $groupSpec.Info = $newGroup $spec.GroupSpec += $groupSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMHostGroup -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function New-DrsVMToVMHostRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMToVMHostRule])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [Parameter(ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [switch]${Enabled}, [Parameter(ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [switch]${Mandatory}, [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [String]${VMGroupName}, [Parameter(ValueFromPipelineByPropertyName=$True)] [String]${AffineHostGroupName}, [Parameter(ValueFromPipelineByPropertyName=$True)] [String]${AntiAffineHostGroupName}, [Switch]$Force ) Process { Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## check if rule of this name already exists in this cluster $oExistingRule = Get-DrsVMtoVMHostRule -Cluster $oThisCluster -Name $Name if ($oExistingRule -and !$Force) { Throw "DRS rule named '$Name' already exists in cluster '$($oThisCluster.Name)'" } elseif($oExistingRule -and $Force) { $oExistingRule | Remove-DrsVMToVMHostRule } else { Write-Verbose "Good -- no DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'" } ## check if VMGroupName and AffineHostGroupName/AntiAffineHostGroupName (the one specified) are valid groups in this cluster if ($null -eq (Get-DrsVMGroup -Cluster $oThisCluster -Name $VMGroupName)) {Throw "No DrsVmGroup named '$VMGroupName' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVmGroup '$VMGroupName' found in cluster '$($oThisCluster.Name)'"} $strDrsVMHostGroupNameToCheck = ${AffineHostGroupName},${AntiAffineHostGroupName} | Where-Object {-not [String]::IsNullOrEmpty($_)} if(!$strDrsVMHostGroupNameToCheck) { Throw "No VMHostGroup specified for new rule on cluster $($oThisCluster.Name)" } if ($null -eq (Get-DrsVMHostGroup -Cluster $oThisCluster -Name $strDrsVMHostGroupNameToCheck)) {Throw "No DrsVMHostGroup named '$strDrsVMHostGroupNameToCheck' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVMHostGroup '$strDrsVMHostGroupNameToCheck' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Create $(if ([String]::IsNullOrEmpty(${AffineHostGroupName})) {'AntiAffineVMToVMHost'} else {'AffineVMToVMHost'}) DRS rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $newRule = New-Object VMware.Vim.ClusterVmHostRuleInfo $newRule.Name = ${Name} $newRule.Mandatory = ${Mandatory} $newRule.Enabled = ${Enabled} $newRule.UserCreated = $True $newRule.VmGroupName = ${VMGroupName} $newRule.AffineHostGroupName = ${AffineHostGroupName} $newRule.AntiAffineHostGroupName = ${AntiAffineHostGroupName} $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Info = $newRule $spec.RulesSpec += $ruleSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMtoVMHostRule -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function New-DrsVMToVMRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMToVMRule])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [Parameter(ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [switch]${Enabled}, # [Parameter(ValueFromPipelineByPropertyName=$True)] # [ValidateNotNullOrEmpty()] # [switch]${Mandatory}, [Parameter(ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [switch]${KeepTogether}, [Parameter(ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a VM obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) })] [PSObject[]]${VM}, [Switch]$Force ) Process { Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## check if rule of this name already exists in this cluster $oExistingRule = Get-DrsVMtoVMRule -Cluster $oThisCluster -Name $Name if ($oExistingRule -and !$Force) { Throw "DRS rule named '$Name' already exists in cluster '$($oThisCluster.Name)'" } elseif($oExistingRule -and $Force) { $oExistingRule | Remove-DrsVMToVMRule } else { Write-Verbose "Good -- no DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'" } $VM = $VM | Foreach-Object { $oThisVmItem = $_ if($oThisVmItem -is [System.String]) { try { ## limit scope to this cluster $oThisCluster | Get-VM -Name $oThisVmItem -ErrorAction:Stop } catch {Write-Warning "No VM of name '$oThisVmItem' found in cluster '$($oThisCluster.Name)'. Valid VM name?"; Throw $_} } else { $oThisVmItem } } if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Create DRS VM $(if (${KeepTogether}) {'KeepTogether'} else {'KeepApart'}) rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $newRule = $( if(${KeepTogether}) {New-Object VMware.Vim.ClusterAffinityRuleSpec} else {New-Object VMware.Vim.ClusterAntiAffinityRuleSpec} ) $newRule.Name = ${Name} $newRule.Enabled = [Boolean]${Enabled} # $newRule.Mandatory = [Boolean]${Mandatory} $newRule.UserCreated = $True $newRule.Vm = $VM | Foreach-Object {$_.Id} $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Info = $newRule $spec.RulesSpec += $ruleSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMtoVMRule -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function Remove-DrsVMGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::High)] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster} ) Process { Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## check that VMGroup exists $target = @(Get-DrsVMGroup -Cluster $oThisCluster -Name $Name -ReturnRawGroup) if ($null -eq $target) {Throw "No DrsVmGroup named '$Name' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVmGroup '$Name' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Remove DRS VM group '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $target | Foreach-Object { $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::remove $groupSpec.RemoveKey = $_.Name $groupSpec.Info = $_ $spec.GroupSpec += $groupSpec } $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) } } } } #.ExternalHelp DRSRule.Help.xml Function Remove-DrsVMHostGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::High)] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster} ) Process{ Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## check that VMHostGroup exists $target = @(Get-DrsVMHostGroup -Cluster $oThisCluster -Name $Name -ReturnRawGroup) if ($null -eq $target) {Throw "No DrsVMHostGroup named '$Name' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVMHostGroup '$Name' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Remove DRS Host group '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $target | Foreach-Object { $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::remove $groupSpec.RemoveKey = $_.Name $groupSpec.Info = $_ $spec.GroupSpec += $groupSpec } $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) } } } } #.ExternalHelp DRSRule.Help.xml Function Remove-DrsVMToVMHostRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::High)] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster} ) Process { Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## verify that rule of this name exists in this cluster $target = @(Get-DrsVMtoVMHostRule -Cluster $oThisCluster -Name ${Name} -ReturnRawRule) if ($null -eq $target) {Throw "No DRS rule named '$Name' exists in cluster '$($oThisCluster.Name)'"} else {Write-Verbose "Good -- DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Remove DRS rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $target | Foreach-Object { $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Info = $_ $ruleSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::remove ## this RemoveKey needs the .Key property of the rule object, not the .Name property in other RemoveKey examples $ruleSpec.RemoveKey = $_.Key $spec.RulesSpec += $ruleSpec } $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) } } } } #.ExternalHelp DRSRule.Help.xml Function Remove-DrsVMToVMRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::High)] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster} ) Process { Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## verify that rule of this name exists in this cluster $target = @(Get-DrsVMtoVMRule -Cluster $oThisCluster -Name ${Name} -ReturnRawRule) if ($null -eq $target) {Throw "No DRS rule named '$Name' exists in cluster '$($oThisCluster.Name)'"} else {Write-Verbose "Good -- DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Remove DRS rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $target | ForEach-Object { $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Info = $_ $ruleSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::remove ## this RemoveKey needs the .Key property of the rule object, not the .Name property in other RemoveKey examples $ruleSpec.RemoveKey = $_.Key $spec.RulesSpec += $ruleSpec } $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) } } } } <# .Description This cmdlet changes settings of the DRS VM group with the provided parameters .Synopsis Cmdlet to change a DRS VM group .Example Get-DrsVMGroup -Name 'VM Group 1' -Cluster Cluster1 | Set-DrsVMGroup -AddVM vm3 Add the given virtual machine to DRS VM group 'VM Group 1' on cluster 'Cluster1' Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 1 Cluster1 False {VM1,VM2,VM3} .Example Set-DrsVMGroup -Name 'VM Group 1' -Append -VM vm4 -Cluster Cluster1 Add the given virtual machine to DRS VM group 'VM Group 1' on cluster 'Cluster1'. This is the same functionality as provided by the more recently added -AddVM parameter, but is being kept in place in order to remain backwards compatible with existing scripts out there. Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 1 Cluster1 False {VM1,VM2,VM3,VM4} .Example Get-DrsVMGroup -Name 'VM Group 1' -Cluster Cluster1 | Set-DrsVMGroup -RemoveVM vm[1-2] Remove the given virtual machines from DRS VM group 'VM Group 1' on cluster 'Cluster1' Name Cluster UserCreated VM ---- ------- ----------- -- VM Group 1 Cluster1 False {VM3,VM4} .Outputs DRSRule.VMGroup object with information about the updated DRS VM group .Link https://github.com/PowerCLIGoodies/DRSRule Get-DrsVMGroup New-DrsVMGroup Remove-DrsVMGroup #> function Set-DrsVMGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium, DefaultParameterSetName = "ByVMParam")] [OutputType([DRSRule.VMGroup])] param ( ## The name of the DRS VM group to modify [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]$Name, ## Cluster in which the DRS VM group resides [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]$Cluster, ## VM(s) to add to the DRS VM group. The VMs can be specified as strings (their names) or as VirtualMachine objects. [parameter(Mandatory = $True, ParameterSetName="AddVM")] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) })]$AddVM, ## VM(s) to remove from the DRS VM group. The VMs can be specified as strings (their names) or as VirtualMachine objects. [parameter(Mandatory = $True, ParameterSetName="RemoveVM")] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) })]$RemoveVM, ## The VM that shall be in the DRS VM group. The VMs can be specified as strings (their names) or as VirtualMachine objects. Without the -Append parameter, this -VM parameter essentially overwrites the existing list of VMGroup members with the VMs specified. # ## The -VM parameter, when used with the -Append parameter, provides the same functionality as the more recently added -AddVM parameter. The -VM and -Append parameters are being kept as-is so as to maintain backwards compatibility with existing scripts. [parameter(ValueFromPipeline=$true, ParameterSetName="ByVMParam")] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) })] [PSObject[]]$VM, ## Switch: append the given VM(s) as members of the DRS VM group ($true), or set them as the only members of the group ($false or not specified)? Not used with -AddVM or -RemoveVM parameters. [parameter(ParameterSetName="ByVMParam")][Switch]$Append ) ## end param Process { Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## the VM names/object to consider when setting this DRS VM group, based on the parameter set in play $arrVMInputToConsider = Switch ($PsCmdlet.ParameterSetName) { "ByVMParam" {$VM; break} "AddVM" {$AddVM; break} "RemoveVM" {$RemoveVM} } ## end switch ## the actual VM objects to use for the VMGroup update $arrVMsForGroupUpdate = $arrVMInputToConsider | Foreach-Object { $oThisVmItem = $_ if ($_ -is [System.String]) { try { ## limit scope to this cluster $oThisCluster | Get-VM -Name $oThisVmItem -ErrorAction:Stop } catch {Write-Warning "No VM of name '$oThisVmItem' found in cluster '$($oThisCluster.Name)'. Valid VM name?"; Throw $_} } else { $oThisVmItem } } ## end foreach-object ## check that VMGroup exists $target = Get-DrsVMGroup -Cluster $oThisCluster -Name $Name -ReturnRawGroup if ($null -eq $target) {Throw "No DrsVmGroup named '$Name' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVmGroup '$Name' found in cluster '$($oThisCluster.Name)'"} if ($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Set DRS VM group '$Name'")) { ## the IDs of the VMs of interest for this group update (will be added to-, removed from-, or will replace the existing VMGroup members) $arrMembersIdsOfInterest = $arrVMsForGroupUpdate | ForEach-Object -Process {$_.Id} ## new cluster config spec $spec = New-Object VMware.Vim.ClusterConfigSpecEx $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::edit ## original VM IDs that were in the VMGroup (for later comparison) $arrOriginalVMIDsInTarget = $target.VM $groupSpec.Info = $target ## set the members of the group according to the parameterset Switch ($PsCmdlet.ParameterSetName) { "ByVMParam" { if ($Append) {$groupSpec.Info.VM += $arrMembersIdsOfInterest | Where-Object {$groupSpec.Info.VM -notcontains $_}} else {$groupSpec.Info.VM = $arrMembersIdsOfInterest} break } ## end case ## just add the given VM IDs (same as -Append param with -VM param, which were kept for backwards compatibility) "AddVM" {$groupSpec.Info.VM += $arrMembersIdsOfInterest | Where-Object {$groupSpec.Info.VM -notcontains $_}; break} ## remove the given VM IDs from the spec "RemoveVM" { ## if the none of the specified VMs are already a part of the group, write a verbose message to that effect if ((Compare-Object -ReferenceObject $groupSpec.Info.VM -DifferenceObject $arrMembersIdsOfInterest -IncludeEqual -ExcludeDifferent | Measure-Object).Count -eq 0) { Write-Verbose "None of the VMs specified are in VMGroup '$($target.Name)' -- no VMs will be removed from group" } ## end if ## else, just "keep" the VM IDs that were not specified to be removed else {$groupSpec.Info.VM = $groupSpec.Info.VM | Where-Object {$arrMembersIdsOfInterest -notcontains $_}} } ## end case } ## end switch ## if all VMs were specified to be remove from the group (if the $groupSpec.Info.VM value is $null), write warning and take no further action (may not be supported by vSphere API, seemingly; trying to do so via GUI returns message to the effect of, "Cannot remove all members of group") if ($null -eq $groupSpec.Info.VM) {Write-Warning "Removing all VMs from VMGroup not supported. Taking no action"} ## if the VMGroup had any VMs in it already, and the VM list is the same between the existing VMGroup and the new ClusterGroupSpec, do not bother calling ReconfigureComputeResource() method elseif (($null -ne $arrOriginalVMIDsInTarget) -and $null -eq (Compare-Object -ReferenceObject $arrOriginalVMIDsInTarget -DifferenceObject $groupSpec.Info.VM)) { Write-Verbose "Not changing VMGroup (no new members added, and no members to remove)" } ## end if else { $spec.GroupSpec += $groupSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) ## return the updated object Get-DrsVMGroup -Cluster $Cluster -Name $Name } ## end else } ## end if shouldprocess } ## end foreach-object } ## end process } ## end fn <# .Description This cmdlet changes settings of the DRS VMHost group with the provided parameters .Synopsis Changes a DRS VMHost group .Example Get-DrsVMHostGroup -Name 'My ESX' -Cluster Cluster1 | Set-DrsVMHostGroup -AddVMHost esx3 Name Cluster UserCreated VM ---- ------- ----------- -- My ESX Cluster1 True {esx1,esx2,esx3} .Example Set-DrsVMHostGroup -Name 'My ESX' -Append -VMHost esx4 -Cluster Cluster1 Name Cluster UserCreated VM ---- ------- ----------- -- My ESX Cluster1 True {esx1,esx2,esx3,esx4} .Example Get-DrsVMHostGroup -Name 'My ESX' -Cluster Cluster1 | Set-DrsVMHostGroup -RemoveVMHost esx[1-2] Name Cluster UserCreated VM ---- ------- ----------- -- My ESX Cluster1 True {esx3,esx4} .Outputs DRSRule.VMHostGroup object with information about the updated DRS VMHost group .Link https://github.com/PowerCLIGoodies/DRSRule Get-DrsVMHostGroup New-DrsVMHostGroup Remove-DrsVMHostGroup #> function Set-DrsVMHostGroup { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium, DefaultParameterSetName = "ByVMHostParam")] [OutputType([DRSRule.VMHostGroup])] param ( ## The name of the DRS VMHost group to modify [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]$Name, ## Cluster in which the DRS VMHost group resides [Parameter(Mandatory = $True, Position = 1, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]$Cluster, ## VMHost(s) to add to the DRS VMHost group. The VMHosts can be specified as strings (their names) or as VMHost objects. [parameter(Mandatory = $True, ParameterSetName="AddVMHost")] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) })]$AddVMHost, ## VMHost(s) to remove from the DRS VMHost group. The VMHosts can be specified as strings (their names) or as VMHost objects. [parameter(ValueFromPipeline=$true, ParameterSetName="RemoveVMHost")] [ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) })]$RemoveVMHost, ## The VMHost that shall be in the DRS VMHost group. The VMHost can be given as strings (names) or as VMHost objects. Without the -Append parameter, this -VMHost parameter essentially overwrites the existing list of VMHostGroup members with the VMHosts specified. # ## The -VMHost parameter, when used with the -Append parameter, provides the same functionality as the more recently added -AddVMHost parameter. The -VMHost and -Append parameters are being kept as-is so as to maintain backwards compatibility with existing scripts. [parameter(Mandatory=$true, ParameterSetName="ByVMHostParam")][ValidateNotNullOrEmpty()][ValidateScript({ _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) })] [PSObject[]]$VMHost, ## Switch: append the given VMHosts(s) as members of the DRS VMHost group ($true), or set them as the only members of the group ($false or not specified)? Not used with -AddVMHost or -RemoveVMHost parameters. [parameter(ParameterSetName="ByVMHostParam")][Switch]$Append ) ## end param process { Get-ClusterObjFromClusterParam -Cluster $Cluster | ForEach-Object -Process { $oThisCluster = $_ ## the VM names/object to consider when setting this DRS VM group, based on the parameter set in play $arrVMHostInputToConsider = Switch ($PsCmdlet.ParameterSetName) { "ByVMHostParam" {$VMHost; break} "AddVMHost" {$AddVMHost; break} "RemoveVMHost" {$RemoveVMHost} } ## end switch ## the actual VMHost objects to use for the VMHostGroup update $arrVMHostsForGroupUpdate = $arrVMHostInputToConsider | Foreach-Object { $oThisVMHostItem = $_ if ($_ -is [System.String]) { try { ## limit scope to this cluster $oThisCluster | Get-VMHost -Name $oThisVMHostItem -ErrorAction:Stop } catch {Write-Warning "No VMHost of name '$oThisVMHostItem' found in cluster '$($oThisCluster.Name)'. Valid VMHost name?"; Throw $_} } else { $oThisVMHostItem } } ## end foreach-object ## if no matching VMHosts found in cluster if ($null -eq $arrVMHostsForGroupUpdate) {Write-Warning "No matching VMHosts found in cluster for group update. Valid VMHost? ('$($arrVMHostInputToConsider -join ', ')')"} else { ## check that VMHostGroup exists $target = Get-DrsVMHostGroup -Cluster $oThisCluster -Name $Name -ReturnRawGroup if ($null -eq $target) {Throw "No DrsVMHostGroup named '$Name' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVMHostGroup '$Name' found in cluster '$($oThisCluster.Name)'"} if ($PsCmdlet.ShouldProcess("$($oThisCluster.Name)","Set DRS Host group '$Name'")) { ## the IDs of the VMHosts of interest for this group update (will be added to-, removed from-, or will replace the existing VMGroup members) $arrMembersIdsOfInterest = $arrVMHostsForGroupUpdate | ForEach-Object -Process {$_.Id} ## new cluster config spec $spec = New-Object VMware.Vim.ClusterConfigSpecEx $groupSpec = New-Object VMware.Vim.ClusterGroupSpec $groupSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::edit ## original VM IDs that were in the VMGroup (for later comparison) $arrOriginalVMHostIDsInTarget = $target.Host $groupSpec.Info = $target ## set the members of the group according to the parameterset Switch ($PsCmdlet.ParameterSetName) { "ByVMHostParam" { if ($Append) {$groupSpec.Info.Host += $arrMembersIdsOfInterest | Where-Object {$groupSpec.Info.Host -notcontains $_}} else {$groupSpec.Info.Host = $arrMembersIdsOfInterest} break } ## end case ## just add the given VMHost IDs (same as -Append param with -VMHost param, which were kept for backwards compatibility) "AddVMHost" {$groupSpec.Info.Host += $arrMembersIdsOfInterest | Where-Object {$groupSpec.Info.Host -notcontains $_}; break} ## remove the given VMHost IDs from the spec "RemoveVMHost" { ## if the none of the specified VMHosts are already a part of the group, write a verbose message to that effect if ((Compare-Object -ReferenceObject $groupSpec.Info.Host -DifferenceObject $arrMembersIdsOfInterest -IncludeEqual -ExcludeDifferent | Measure-Object).Count -eq 0) { Write-Verbose "None of the VMHosts specified are in VMHostGroup '$($target.Name)' -- no VMHosts will be removed from group" } ## end if ## else, just "keep" the VMHost IDs that were not specified to be removed else {$groupSpec.Info.Host = $groupSpec.Info.Host | Where-Object {$arrMembersIdsOfInterest -notcontains $_}} } ## end case } ## end switch ## if all hosts were specified to be remove from the group (if the $groupSpec.Info.Host value is $null), write warning and take no further action (may not be supported by vSphere API, seemingly; trying to do so via GUI returns message to the effect of, "Cannot remove all members of group") if ($null -eq $groupSpec.Info.Host) {Write-Warning "Removing all VMHosts from VMHostGroup not supported. Taking no action"} ## if there were hosts in the group to start, and the VMHost list is the same between the existing VMHostGroup and the new ClusterGroupSpec, do not bother calling ReconfigureComputeResource() method elseif (($null -ne $arrOriginalVMHostIDsInTarget) -and ($null -eq (Compare-Object -ReferenceObject $arrOriginalVMHostIDsInTarget -DifferenceObject $groupSpec.Info.Host))) { Write-Verbose "Not changing VMHostGroup (no new members added, and no members to remove)" } ## end if else { $spec.GroupSpec += $groupSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) ## return the updated object Get-DrsVMHostGroup -Cluster $Cluster -Name $Name } ## end else } ## end if shouldprocess } ## end foreach-object } ## end else } ## end process } ## end fn #.ExternalHelp DRSRule.Help.xml Function Set-DrsVMToVMHostRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMToVMHostRule])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [switch]${Enabled}, [PSObject]${VMGroup}, [PSObject]${VMHostGroup}, [switch]${Mandatory}, [switch]${KeepTogether} ) Process { Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## check if VMGroup and VMHostGroup (if specified) are valid groups in this cluster if($PSBoundParameters.ContainsKey("VMGroup")) { if ($null -eq (Get-DrsVMGroup -Cluster $oThisCluster -Name $VMGroup)) {Throw "No DrsVmGroup named '$VMGroup' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVmGroup '$VMGroup' found in cluster '$($oThisCluster.Name)'"} } if($PSBoundParameters.ContainsKey("VMHostGroup")) { if ($null -eq (Get-DrsVMHostGroup -Cluster $oThisCluster -Name $VMHostGroup)) {Throw "No DrsVMHostGroup named '$VMHostGroup' in cluster '$($oThisCluster.Name)'. Valid group name?"} else {Write-Verbose "DrsVMHostGroup '$VMHostGroup' found in cluster '$($oThisCluster.Name)'"} } ## verify that rule of this name exists in this cluster $target = Get-DrsVMtoVMHostRule -Cluster $oThisCluster -Name ${Name} -ReturnRawRule if ($null -eq $target) {Throw "No DRS rule named '$Name' exists in cluster '$($oThisCluster.Name)'"} else {Write-Verbose "Good -- DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'"} if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Set DRS rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::edit $ruleSpec.Info = $target if($PSBoundParameters.ContainsKey("Enabled")) { $ruleSpec.Info.Enabled = ${Enabled} } if($null -ne ${VMGroup}) { $ruleSpec.Info.VmGroupName = ${VMGroup} } if($PSBoundParameters.ContainsKey("Mandatory")) { $ruleSpec.Info.Mandatory = ${Mandatory} } ## if -KeepTogether param passed if ($PSBoundParameters.ContainsKey("KeepTogether")) { ## if KeepTogether is $true, set affinehostgroupname to either -VMHostGroup if specified or the HostGroup name that was already either affine or antiaffine in target rule if ($KeepTogether) { $ruleSpec.Info.AffineHostGroupName = $( if ($null -ne ${VMHostGroup}) {${VMHostGroup}} else {$target.AffineHostGroupName, $target.AntiAffineHostGroupName | Where-Object {-not [String]::IsNullOrEmpty($_)}} ) $ruleSpec.Info.AntiAffineHostGroupName = $null } ## else set ANTIaffinehostgroupname to either -VMHostGroup if specified or the HostGroup name that was already either affine or antiaffine in target rule else { ## order matters here, as $ruleSpec.Info is a reference to $target; so, need to use the values before setting AffineHostGroupName property to $null $ruleSpec.Info.AntiAffineHostGroupName = $( if ($null -ne ${VMHostGroup}) {${VMHostGroup}} else {$target.AffineHostGroupName, $target.AntiAffineHostGroupName | Where-Object {-not [String]::IsNullOrEmpty($_)}} $ruleSpec.Info.AffineHostGroupName = $null ) } } ## if -VMHostGroup param passed _without_ -KeepTogether param elseif ($PSBoundParameters.ContainsKey("VMHostGroup")) { ## if this was a VM-to-Host _affinity_ rule already, set the affine group to the new value if ($null -ne $target.AffineHostGroupName) { $ruleSpec.Info.AffineHostGroupName = ${VMHostGroup} $ruleSpec.Info.AntiAffineHostGroupName = $null } ## else, set the antiaffine group to the new value else { $ruleSpec.Info.AffineHostGroupName = $null $ruleSpec.Info.AntiAffineHostGroupName = ${VMHostGroup} } } $spec.RulesSpec += $ruleSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMtoVMHostRule -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function Set-DrsVMToVMRule { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = [System.Management.Automation.Confirmimpact]::Medium)] [OutputType([DRSRule.VMToVMRule])] param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()] [string]${Name}, [Parameter(Position = 1, ValueFromPipelineByPropertyName=$True)] [ValidateNotNullOrEmpty()][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [switch]${Enabled}, [switch]${Mandatory}, [switch]${KeepTogether}, [PSObject[]]${VM}, [Switch]${Append} ) Process { Get-ClusterObjFromClusterParam -Cluster ${Cluster} | ForEach-Object -Process { $oThisCluster = $_ ## verify that rule of this name exists in this cluster $target = Get-DrsVMtoVMRule -Cluster $oThisCluster -Name ${Name} -ReturnRawRule if ($null -eq $target) {Throw "No DRS rule named '$Name' exists in cluster '$($oThisCluster.Name)'"} else {Write-Verbose "Good -- DRS rule of name '$Name' found in cluster '$($oThisCluster.Name)'"} ## verify that VM exists if($PSBoundParameters.ContainsKey("VM")) { $VM = $VM | Foreach-Object { $oThisVMItem = $_ if($_ -is [System.String]){ try { ## limit scope to this cluster $oThisCluster | Get-VM -Name $oThisVMItem -ErrorAction:Stop } catch {Write-Warning "No VM of name '$oThisVMItem' found in cluster '$($oThisCluster.Name)'. Valid VM name?"; Throw $_} } else { $oThisVMItem } } } if($psCmdlet.ShouldProcess("$($oThisCluster.Name)","Set DRS rule '${Name}'")) { $spec = New-Object VMware.Vim.ClusterConfigSpecEx $ruleSpec = New-Object VMware.Vim.ClusterRuleSpec $ruleSpec.Operation = [VMware.Vim.ArrayUpdateOperation]::edit ## Check if -KeepTogether param passed $ruleSpec.Info = $( if($PSBoundParameters.ContainsKey('KeepTogether')) { if(${KeepTogether}) { if($target -is [VMware.Vim.ClusterAffinityRuleSpec]){$target} else{ New-Object VMware.Vim.ClusterAffinityRuleSpec -Property @{ Enabled = $target.Enabled VM = $target.VM Key = $target.Key Name = $target.Name UserCreated = $target.UserCreated } } } else { if($target -is [VMware.Vim.ClusterAntiAffinityRuleSpec]){$target} else{ New-Object VMware.Vim.ClusterAntiAffinityRuleSpec -Property @{ Enabled = $target.Enabled VM = $target.VM Key = $target.Key Name = $target.Name UserCreated = $target.UserCreated } } } } else { $target } ) ## Enabled switch if($PSBoundParameters.ContainsKey("Enabled")) { $ruleSpec.Info.Enabled = ${Enabled} } if($PSBoundParameters.ContainsKey("Mandatory")) {$ruleSpec.Info.Mandatory = ${Mandatory} } ## VM passed if($PSBoundParameters.ContainsKey("VM")) { if(${Append}) { $ruleSpec.Info.VM = $ruleSpec.Info.VM + $($VM | Foreach-Object {$_.Id}) } else { $ruleSpec.Info.VM = $($VM | Foreach-Object {$_.Id}) } } $spec.RulesSpec += $ruleSpec $oThisCluster.ExtensionData.ReconfigureComputeResource($spec,$True) Get-DrsVMtoVMRule -Cluster $oThisCluster -Name ${Name} } } } } #.ExternalHelp DRSRule.Help.xml Function Export-DrsRule { [CmdletBinding()] [OutputType([System.IO.FileInfo])] param( [Parameter(Position = 0)] [string]${Name} ='*', [Parameter(Position = 1, ValueFromPipeline = $True)][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster}, [parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [String]${Path} ) Process { $hshParamsForGetCall = @{Name = ${Name}} if ($PSBoundParameters.ContainsKey("Cluster")) {$hshParamsForGetCall["Cluster"] = ${Cluster}} ## had to make the first items an array of values to pass to the pipeline; else, if the first item was $null, the pipeline seemed to halt, and there were no results, even if one of the other three Get-* calls returned items $strDrsRuleInfo_inJSON = @( (Get-DrsVMtoVMRule @hshParamsForGetCall), (Get-DrsVMtoVMHostRule @hshParamsForGetCall), (Get-DrsVMGroup @hshParamsForGetCall), (Get-DrsVMHostGroup @hshParamsForGetCall) ) | Where-Object {$null -ne $_} | ## for each of these items (which may be arrays), put the array's objects on the pipeline for ConvertTo-Json; else, the arrays are exported in the JSON as the parent properties of all of the objects exported (makes arrays with properties "value" and "count", and the actual rule/group objects' JSON is a sub-property of the "value" property) Foreach-Object {$_} | ConvertTo-Json -Depth 2 if ($null -ne $strDrsRuleInfo_inJSON) { Set-Content -Path ${Path} -Value $strDrsRuleInfo_inJSON if ($PSBoundParameters.ContainsKey("Verbose")) { ## get num rules in JSON file; using .Length property of the resulting item, as it is a System.Object[] object, and behaves like a hashtable (would need to use .GetEnumerator() to get the items within it) $intNumRulesFromJSON = (ConvertFrom-Json -InputObject (Get-Content -Path ${Path} | Out-String)).Length Write-Verbose ("Exported and saved information for '{0}' DRS rule{1}/group{1} to '${Path}'" -f $intNumRulesFromJSON, $(if ($intNumRulesFromJSON -ne 1) {"s"})) } Get-Item ${Path} } else {$strForVerbose = $(if ($null -eq $Cluster) {"any cluster"} else {"cluster with name like '$Cluster'"}); Write-Verbose "No DRS group/rule found for like name '$Name' in $strForVerbose"} } } #.ExternalHelp DRSRule.Help.xml Function Import-DrsRule { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([DRSRule.VMGroup],[DRSRule.VMHostGroup],[DRSRule.VMToVMRule],[DRSRule.VMToVMHostRule])] param( [Parameter(Position = 0)] [ValidateNotNullOrEmpty()] [ValidateScript({Test-Path $_})][String]${Path}, [Parameter(Position = 1)] [string]${Name}, [Parameter(Position = 2, ValueFromPipeline = $True)][ValidateScript({ ## make sure that all values are either a String or a Cluster obj _Test-TypeOrString -Object $_ -Type ([VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) })] [PSObject[]]${Cluster} = "*", [Switch]$Force, [Switch]$ShowOnly ) begin {$ruleObjects = (ConvertFrom-Json -InputObject (Get-Content -Path ${Path} | Out-String))} Process { $Cluster | Foreach-Object { ## this cluster name (could contain wildcard) $strThisClusterName = $( if ($_ -is [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]) {$_.Name} else {$_} ) ## the rule objects for clusters whose names are like $strThisClusterName $arrRuleObjects_filtered = $ruleObjects.GetEnumerator() | Where-Object -FilterScript {$_.Cluster -like $strThisClusterName} ## if -Name was specified, filter if ($PSBoundParameters.ContainsKey("Name")) {$arrRuleObjects_filtered = $arrRuleObjects_filtered | Where-Object -FilterScript {$_.Name -like $Name}} ## if just showing the matching rules/groups found in .json file, just return the info objects if ($ShowOnly) {$arrRuleObjects_filtered} ## else, proceed with rule/group creation else { ## make string messages for ShouldProcess output $strClusterInfoForShouldProcessMsg = if ($PSBoundParameters.ContainsKey("Cluster")) {"clusters with name like '$strThisClusterName'"} else {"all clusters with rules/groups in exported JSON file '${Path}'"} $strActionInfoForShouldProcessMsg = $($intNumRulesAfterFiltering = ($arrRuleObjects_filtered | Measure-Object).Count; "Recreate '$intNumRulesAfterFiltering' DRS group{0}/rule{0}" -f $(if ($intNumRulesAfterFiltering -ne 1) {"s"})) ## create the groups/rules if ($PSCmdlet.ShouldProcess($strClusterInfoForShouldProcessMsg, $strActionInfoForShouldProcessMsg)) { $arrRuleObjects_filtered | Get-DrsRuleObject -Type 'ClusterVmGroup' | New-DrsVmGroup -Force:$Force $arrRuleObjects_filtered | Get-DrsRuleObject -Type 'ClusterHostGroup' | New-DrsVMHostGroup -Force:$Force $arrRuleObjects_filtered | Get-DrsRuleObject -Type 'ClusterVmHostRuleInfo' | New-DrsVMtoVMHostRule -Force:$Force $arrRuleObjects_filtered | Get-DrsRuleObject -Type 'ClusterAffinityRuleSpec|ClusterAntiAffinityRuleSpec' | New-DrsVMtoVMRule -Force:$Force } } } } } # Fix for ScriptsToProcess bug in the module manifest # See Connect Id 903654 # Workaround #2 (credit to Ronald Rink) [string] $ManifestFile = '{0}.psd1' -f (Get-Item $PSCommandPath).BaseName $ManifestPathAndFile = Join-Path -Path $PSScriptRoot -ChildPath $ManifestFile if(Test-Path -Path $ManifestPathAndFile) { $Manifest = (Get-Content -raw $ManifestPathAndFile) | Invoke-Expression foreach( $ScriptToProcess in $Manifest.ScriptsToProcess) { $ModuleToRemove = (Get-Item (Join-Path -Path $PSScriptRoot -ChildPath $ScriptToProcess)).BaseName if(Get-Module $ModuleToRemove) { Remove-Module $ModuleToRemove } } } |