I have been creating and using PowerCLI scripts for vSphere a lot again lately. And I thought it was a good idea to finally take all the snippets I collected and created over time and put them into one spot. The scripts in this post come in to play after the ESXi hosts are installed and the vCenter is up and running. If you are interested in deploying vCenter automatically you should check out my blog post about migrating from embedded to external PSC. In this post I will go over using the vcsa install tool. In here it is all PowerCLI, check out the scripts below.
- Create vCenter clusters
- Add ESXi hosts to vCenter clusters
- Create distributed switch and port groups
- Migrate hosts from vSwitch to distributed switch
- Create additional VM kernel ports
- Remove vSwitch0 from all hosts
- Create (sub) folders in vCenter
- DRS host groups
- Create and populate datastore clusters
- Change local ESXi host datastore names
- Supporting files
- Modules
As you can see, there are quite a few scripts here so this blog post will be longer then usual.
1. Create vCenter clusters
This script is used to create the initial datacenter object and multiple vCenter clusters. The script can configure all of the major settings for HA and DRS. Some of the functions are not available in the latest version of vSphere PowerCLI. Things like Admission Control, Datastore Heartbeat, VMCP Settings or VM Monitoring are missing from the New-Cluster cmdlet. To enable this functionality I made use of some extra modules (more details below).
# ------------------------------------------------------------------------------------------------------------------ # Script to create vSphere clusters including the most common settings # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Modules are psm1 files located in the user profile under \My Documents\WindowsPowerShell\Modules\<modulen_name>\<module_name.psm1> and are imported here # to add functionality that is not yet present in the default cmdlets Import-Module AdmissionConfig Import-Module DsHeartBeatConfig Import-Module VMCPSettings Import-Module VMMonitoring # Create initial datacenter object $location = Get-Folder -NoRecursion New-Datacenter -Name "Datacenter1" -Location $location # Import and loop through a CSV file containing the clusters names, admission controll CPU and MEM percentage and if it is a stretched cluster Import-Csv clusters.txt | Foreach-Object { New-Cluster -Name $_.name -DrsAutomationLevel FullyAutomated -DrsEnabled -EVCMode "intel-haswell" -HAAdmissionControlEnabled -HAEnabled -HAIsolationResponse DoNothing -Location "Datacenter1" -VMSwapfilePolicy WithVM Get-cluster -name $_.name | Set-HAAdmissionControlPolicy -percentCPU $_.admissionCPU -percentMem $_.admissionMEM Get-Cluster -name $_.name | Set-DatastoreHeartbeatConfig -Option allFeasibleDs Get-Cluster -name $_.name | Set-VMCPSettings -enableVMCP:$True -VmStorageProtectionForPDL restartAggressive -VmStorageProtectionForAPD restartConservative -VmReactionOnAPDCleared none -Confirm:$false #Stretched clusters get extra settings if ($_.isStretched -eq "true") { # To set the VM Monitoring values Set-ClusterDasVmMonitoring -cluster $_.name -Option vmMonitoringOnly -interval 50 -maxfail 3 # Set advanced settings New-AdvancedSetting -Entity $_.name -Type ClusterHA -Name das.isolationaddress[0] -Value 10.10.10.1 -Confirm:$false New-AdvancedSetting -Entity $_.name -Type ClusterHA -Name das.isolationaddress[1] -Value 10.10.20.1 -Confirm:$false New-AdvancedSetting -Entity $_.name -Type ClusterHA -Name das.heartbeatdsperhost -Value 4 -Confirm:$false New-AdvancedSetting -Entity $_.name -Type ClusterHA -Name das.usedefaultisolationaddress -Value false -Confirm:$false } }
2. Add ESXi hosts to vCenter clusters
After adding the required clusters it is time to bring the ESXi hosts in. This script will add ESXi hosts to vCenter based on a comma separated file. Hosts are placed in maintenance mode and added to the correct cluster. Finally the hosts are taken out of maintenance mode.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to add new ESXi hosts to the vCenter server and in the different clusters based on a CSV file # with the hostname and the destination cluster. # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ Import-Csv hosts.txt | Foreach-Object { Add-VMHost $_.hostname -Location (Get-Datacenter "Datacenter1") -User root -Password VMware1! -RunAsync -force:$true -Confirm:$false Get-VMHost -Name $_.hostname | Set-VMHost -State Maintenance Get-VMHost -Name $_.hostname | Move-VMHost -Destination $_.cluster -RunAsync -Confirm:$false Get-VMHost -Name $_.hostname | Set-VMHost -State Connected }
3. Create Distributed switch and port groups
This script creates a single distributed switch and several port groups. The port group settings like VLAN, load balancing scheme and active uplinks are set as well.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to create the VDSwitch and all needed portgroups and their individual settings # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Create VDswitch $vds_name = "VDS-01" $vds = New-VDSwitch -Name $vds_name -Location (Get-Datacenter -Name "Datacenter1") -mtu 9000 -LinkDiscoveryProtocol LLDP -LinkDiscoveryProtocolOperation Listen -confirm:$false # Create DVPortgroups $pg1 = New-VDPortgroup -Name "PG-10-ESXi" -Vds $vds $pg2 = New-VDPortgroup -Name "PG-20-Prod" -Vds $vds -VlanId 20 $pg3 = New-VDPortgroup -Name "PG-30-vMotion1" -Vds $vds -VlanId 30 $pg4 = New-VDPortgroup -Name "PG-30-vMotion2" -Vds $vds -VlanId 30 $pg5 = New-VDPortgroup -Name "PG-40-FT" -Vds $vds -VlanId 40 # Adjust DVPortgroup Setting Load Based Teaming Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg1 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -LoadBalancingPolicy LoadBalanceLoadBased Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg2 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -LoadBalancingPolicy LoadBalanceLoadBased Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg5 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -LoadBalancingPolicy LoadBalanceLoadBased # Adjust DVPortgroup Setting Active Uplinks Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg3 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -ActiveUplinkPort uplink1 Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg3 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -UnusedUplinkPort uplink2 Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg4 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -ActiveUplinkPort uplink2 Get-VDSwitch -Name $vds | Get-VDPortgroup -Name $pg4 | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -UnusedUplinkPort uplink1
4. Migrate hosts from standard switch to distributed switch
This script is an important one and can save you a lot of hours. The process of moving multiple ESXi hosts from a standard switch to a distributed switch can be a time consuming task. This script will do it all for you based on a list of hosts. The base for this script came from William Lam who created this back in 2013.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to migrate all hosts in the different clusters to the VDSwitch # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Get VDSwitch object $vds_name = "VDS-01" $vds = Get-VDSwitch -Name $vds_name # Set vmnic name $nic1 = vmnic0 $nic2 = vmnic1 $nic3 = vmnic2 $nic4 = vmnic3 # Loop through CSV file with hosts Import-Csv hosts.txt | Foreach-Object { # Add ESXi host to VDS Write-Host "Adding" $_.hostname "to" $vds_name $vds | Add-VDSwitchVMHost -VMHost $_.hostname # Migrate first 2 nics to VDS Write-Host "Adding $nic1 and $nic2 to" $vds_name $vmhostNetworkAdapter = Get-VMHost $_.hostname | Get-VMHostNetworkAdapter -Physical -Name $nic1 $vds | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -Confirm:$false $vmhostNetworkAdapter = Get-VMHost $_.hostname | Get-VMHostNetworkAdapter -Physical -Name $nic2 $vds | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -Confirm:$false # Migrate Management VMkernel interface to VDS $mgmt_portgroup = "PG-10-ESXi" $dvportgroup = Get-VDPortGroup -name $mgmt_portgroup -VDSwitch $vds $vmk = Get-VMHostNetworkAdapter -Name vmk0 -VMHost $_.hostname Write-Host "Migrating" $vmk "to" $vds_name Set-VMHostNetworkAdapter -PortGroup $dvportgroup -VirtualNic $vmk -confirm:$false # Migrate last 2 nics to VDS Write-Host "Adding $nic3 and $nic4 to" $vds_name $vmhostNetworkAdapter = Get-VMHost $_.hostname | Get-VMHostNetworkAdapter -Physical -Name $nic3 $vds | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -Confirm:$false $vmhostNetworkAdapter = Get-VMHost $_.hostname | Get-VMHostNetworkAdapter -Physical -Name $nic4 $vds | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -Confirm:$false }
5. Create additional VM kernel ports
To create additional VM kernel ports for things like vMotion or Fault Tolerance Logging on all hosts you can use this PowerCLI script.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to create VMK ports other then the management VMK port # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Get VDSwitch and Portgroup objects $vds = Get-VirtualSwitch -Name "VDS-01" $pg1 = Get-VirtualPortGroup -Name "PG-30-vMotion1" $pg2 = Get-VirtualPortGroup -Name "PG-30-vMotion2" $pg3 = Get-VirtualPortGroup -Name "PG-40-FT" # Loop through CSV file with hostnames to add VMK's to each host Import-Csv hosts.txt | Foreach-Object { New-VMHostNetworkAdapter -VMHost $_.hostname -PortGroup $pg1 -VirtualSwitch $vds -Mtu 9000 -VMotionEnabled:$true New-VMHostNetworkAdapter -VMHost $_.hostname -PortGroup $pg2 -VirtualSwitch $vds -Mtu 9000 -VMotionEnabled:$true New-VMHostNetworkAdapter -VMHost $_.hostname -PortGroup $pg3 -VirtualSwitch $vds -Mtu 9000 -FaultToleranceLoggingEnabled:$true }
6. Remove vSwitch0 from all hosts
After all ESXi hosts are migrated to a distributed switch you might want to remove the by default created vSwitch0. The following script removes that from all hosts in a specific vCenter.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to remove vSwitch0 from all hosts after they are migrated to the Distributed Switch # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ Write-Host "Removing virtual switch vSwitch0" Remove-VirtualSwitch -VirtualSwitch vSwitch0 -Confirm:$false
7. Create (sub) folders in vCenter
If you need to create a lot of folders in vCenter this script will come in handy. The top level scripts are created under the hidden ‘vm’ folder. Subfolders are created based on the top level folders that where created.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to create a vCenter folder structure # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Set datacenter $datacenter = Datacenter1 # Create top level folders $location = Get-Datacenter -Name $datacenter | Get-Folder -Name "vm" $folders = "Management", "VRM", "Templates", "Jump Hosts", "Automation", "Backup", "vCenter", "vCenter Update Manager", "SQL" foreach ($folder in $folders) { New-Folder -Name $folder -Location $location } # Create sub-folders Automation $location_automation = Get-Datacenter -Name $datacenter | Get-Folder -Name "Automation" $aut_folders = "vROps", "vRO", "vRLI", "vRA", "NSX" foreach ($folder in $aut_folders) { New-Folder -Name $folder -Location $location_automation } # Create sub-folders NSX $location_nsx = Get-Datacenter -Name $datacenter | Get-Folder -Name "NSX" $nsx_folders = "dLR's", "Load Balancers", "Edge Service Gateways", "Controllers" foreach ($folder in $nsx_folders) { New-Folder -Name $folder -Location $location_nsx }
8. DRS host groups
At the moment of writing this script uses cmdlets that are only available in the latest version of vSphere PowerCLI. I am using PowerCLI version 6.5.4 at this time. The two cmdlets used to create and edit DRS host groups need to be used together. The reason for this is that New-DrsClusterGroup can only add one host when creating the DRS host group. To add additional hosts the Set-DrsClusterGroup must be used to add the remaining hosts.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to create DRS affinity host groups for multiple stretched clusters # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ # Create array per stretched cluster to hold hosts belonging to that cluster $siteA_C1 = New-Object System.Collections.ArrayList $siteA_C2 = New-Object System.Collections.ArrayList $siteB_C1 = New-Object System.Collections.ArrayList $siteB_C2 = New-Object System.Collections.ArrayList # Create variables for each cluster $cluster1 = "Cluster1" $cluster2 = "Cluster2" # Create variables for each group name per cluster $drsgrpA = "Site-A-Hosts" $drsgrpB = "Site-B-Hosts" # Loop through CSV file to add hosts to the correct arrays Import-Csv hosts.txt | Foreach-Object { if ($_.site -eq "dcr" -and $_.cluster -eq $cluster1) { $siteA_C1.Add($_.hostname) } if ($_.site -eq "wpr" -and $_.cluster -eq $cluster1) { $siteB_C1.Add($_.hostname) } if ($_.site -eq "dcr" -and $_.cluster -eq $cluster2) { $siteA_C2.Add($_.hostname) } if ($_.site -eq "wpr" -and $_.cluster -eq $cluster2) { $siteB_C2.Add($_.hostname) } } # Create host DRS groups in Automation cluster New-DrsClusterGroup -Name $drsgrpA -Cluster $cluster1 -VMHost $siteA_C1[0] -Confirm:$false $siteA_C1.RemoveAt(0) New-DrsClusterGroup -Name $drsgrpB -Cluster $cluster1 -VMHost $siteB_C1[0] -Confirm:$false $siteB_C1.RemoveAt(0) foreach ($h in $siteA_C1) { $C1_grp_A = Get-DrsClusterGroup -Cluster $cluster1 -Name $drsgrpA Set-DrsClusterGroup -DrsClusterGroup $C1_grp_A -Add -VMHost $h } foreach ($h in $siteB_C1) { $C1_grp_B = Get-DrsClusterGroup -Cluster $cluster1 -Name $drsgrpB Set-DrsClusterGroup -DrsClusterGroup $C1_grp_B -Add -VMHost $h } # Create host DRS groups in NEI cluster New-DrsClusterGroup -Name $drsgrpA -Cluster $cluster2 -VMHost $siteA_C2[0] -Confirm:$false $siteA_C2.RemoveAt(0) New-DrsClusterGroup -Name $drsgrpB -Cluster $cluster2 -VMHost $siteB_C2[0] -Confirm:$false $siteB_C2.RemoveAt(0) foreach ($h in $siteA_C2) { $C2_grp_A = Get-DrsClusterGroup -Cluster $cluster2 -Name $drsgrpA Set-DrsClusterGroup -DrsClusterGroup $C2_grp_A -Add -VMHost $h } foreach ($h in $siteB_C2) { $C2_grp_B = Get-DrsClusterGroup -Cluster $cluster2 -Name $drsgrpB Set-DrsClusterGroup -DrsClusterGroup $C2_grp_B -Add -VMHost $h }
9. Create and populate datastore clusters
This script speaks for it self. It will create datastore clusters and add data stores to it. It will do this based on a comma separated file.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to create datastore clusters and populate them according to a predefined list # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ $location = "Datacenter1" Import-Csv DSClusters.txt | Foreach-Object { $exists = Get-DatastoreCluster -Name $_.DCname -ErrorAction SilentlyContinue If ($exists) { Write-Host Datastore Cluster with name $_.DCname already exists. } Else { New-DatastoreCluster -Name $_.DCname -Location $location Set-DatastoreCluster -DatastoreCluster $_.DCname -IOLatencyThresholdMillisecond 15 -IOLoadBalanceEnabled $false -SdrsAutomationLevel Disabled -SpaceUtilizationThresholdPercent 80 } } Import-Csv DSClusters.txt | Foreach-Object { Move-Datastore -Confirm:$false -Datastore $_.DSname -Destination $_.DCname }
10. Change local datastore name on ESXI hosts
If you deploy a lot of ESXi hosts with local storage you will notice a lot if Datastore1 (x)’s in your environment. To rename them all to a more friendly name.
# ------------------------------------------------------------------------------------------------------------------ # PowerCLI script to change local datastore names ie. datastore1 (1) -> hostname-local # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ Import-Csv hosts.txt | ForEach-Object { get-vmhost -name $_.hostname | Get-Datastore | where {$_.name -match "datastore1"} | Set-Datastore -name $_.DSname }
11. Supporting files
In several scripts I am looping through a comma separated file, the formatting for these files are as follows.
clusters.txt
"name","admissionCPU","admissionMEM","isStretched" "Cluster1",50,50,"true" "Cluster2",50,50,"true" "Cluster3",33,33,"false"
hosts.txt
"hostname","site","cluster","DSname" "esx0001.home.local","site-a","Cluster1","esx0001-local" "esx0002.home.local","site-b","Cluster1","esx0002-local" "esx0003.home.local","site-a","Cluster2","esx0003-local" "esx0004.home.local","site-b","Cluster2","esx0004-local"
DSClusters.txt
"DSname","DCname" "DS-STR-C1-A-001-001","DC-DS-STR-C1-A-001" "DS-STR-C1-A-001-002","DC-DS-STR-C1-A-001" "DS-STR-C1-B-001-001","DC-DS-STR-C1-B-001" "DS-STR-C1-B-001-002","DC-DS-STR-C1-B-001" "DS-STR-C2-A-001-001","DC-DS-STR-C2-A-001" "DS-STR-C2-A-001-002","DC-DS-STR-C2-A-001" "DS-STR-C2-B-001-001","DC-DS-STR-C2-B-001" "DS-STR-C2-B-001-002","DC-DS-STR-C2-B-001"
12. Modules
The first script (create clusters) uses additional code to enhance the feature set of the script. This extra code comes in the form of modules. Some of these modules I found on the internet because I was not familiar with this kind of scripting. I modified some of the code but left the original authors in the remarks where applicable, so all credits go to them. Module files have a specific extension, psm1.
They need to be stored in \My Documents\WindowsPowerShell\Modules\<module_name>\<module_name.psm1>.
AdmissionConfig
This module lets you set admission control policy to a specific percentage.
function Set-HAAdmissionControlPolicy{ <# .SYNOPSIS Set the Percentage HA Admission Control Policy .DESCRIPTION Percentage of cluster resources reserved as failover spare capacity .PARAMETER Cluster The Cluster object that is going to be configurered .PARAMETER percentCPU The percent reservation of CPU Cluster resources .PARAMETER percentMem The percent reservation of Memory Cluster resources .EXAMPLE PS C:\> Set-HAAdmissionControlPolicy -Cluster $CL -percentCPU 50 -percentMem 50 .EXAMPLE PS C:\> Get-Cluster | Set-HAAdmissionControlPolicy -percentCPU 50 -percentMem 50 .NOTES Author: Niklas Akerlund / RTS Date: 2012-01-19 #> param ( [Parameter(Position=0,Mandatory=$true,HelpMessage="This need to be a clusterobject", ValueFromPipeline=$True)] $Cluster, [int]$percentCPU = 25, [int]$percentMem = 25 ) if(Get-Cluster $Cluster){ $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo $spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy $spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = $percentCPU $spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = $percentMem $Cluster = Get-View $Cluster $Cluster.ReconfigureComputeResource_Task($spec, $true) } }
DSHeartBeatConfig
If there is a need to configure data store heart beating, you can include this module.
Function Get-DatastoreHeartbeatConfig { [CmdletBinding()] param ( [Parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String[]]$Cluster ) Get-Cluster $Cluster | select Name,@{E={$_.ExtensionData.Configuration.DasConfig.HBDatastoreCandidatePolicy};L="Heartbeat Policy"} } Function Set-DatastoreHeartbeatConfig { [CmdletBinding()] param ( [Parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String[]]$Cluster, [ValidateSet("allFeasibleDs","userSelectedDs","allFeasibleDsWithUserPreference")] [String[]]$Option ) $Spec = New-Object VMware.Vim.ClusterConfigSpecEx $Spec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo $ClusterName = Get-Cluster $Cluster if ($Option -eq "allFeasibleDs"){ $Spec.DasConfig.HBDatastoreCandidatePolicy = "allFeasibleDs" $ClusterName.ExtensionData.ReconfigureComputeResource_Task($Spec, $true) } elseif ($Option -eq "userSelectedDs"){ $Datastores = Get-Datastore | Out-Gridview -Title "Select only two datastores" -Passthru $Spec.dasConfig.heartbeatDatastore = New-Object VMware.Vim.ManagedObjectReference[](2) $Spec.dasConfig.heartbeatDatastore[0] = New-Object VMware.Vim.ManagedObjectReference $Spec.dasConfig.heartbeatDatastore[0].type = "Datastore" $Spec.dasConfig.heartbeatDatastore[0].Value = $Datastores[0].ExtensionData.MoRef.Value $Spec.dasConfig.heartbeatDatastore[1] = New-Object VMware.Vim.ManagedObjectReference $Spec.dasConfig.heartbeatDatastore[1].type = "Datastore" $Spec.dasConfig.heartbeatDatastore[1].Value = $Datastores[1].ExtensionData.MoRef.Value $Spec.DasConfig.HBDatastoreCandidatePolicy = "userSelectedDs" $ClusterName.ExtensionData.ReconfigureComputeResource_Task($Spec, $true) } elseif ($Option -eq "allFeasibleDsWithUserPreference"){ $Datastores = Get-Datastore | Out-Gridview -Title "Select only two datastores" -Passthru $Spec.dasConfig.heartbeatDatastore = New-Object VMware.Vim.ManagedObjectReference[](2) $Spec.dasConfig.heartbeatDatastore[0] = New-Object VMware.Vim.ManagedObjectReference $Spec.dasConfig.heartbeatDatastore[0].type = "Datastore" $Spec.dasConfig.heartbeatDatastore[0].Value = $Datastores[0].ExtensionData.MoRef.Value $Spec.dasConfig.heartbeatDatastore[1] = New-Object VMware.Vim.ManagedObjectReference $Spec.dasConfig.heartbeatDatastore[1].type = "Datastore" $Spec.dasConfig.heartbeatDatastore[1].Value = $Datastores[1].ExtensionData.MoRef.Value $Spec.DasConfig.HBDatastoreCandidatePolicy = "allFeasibleDsWithUserPreference" $ClusterName.ExtensionData.ReconfigureComputeResource_Task($Spec, $true) } }
VMCPSettings
Another feature that is not available in the default New-Cluster cmdlet is VCMP. This module can get and set the different settings for VCMP.
function Get-VMCPSettings { <# .NOTES =========================================================================== Created on: 10/27/2015 9:25 PM Created by: Brian Graf Twitter: @vBrianGraf VMware Blog: blogs.vmware.com/powercli Personal Blog: www.vtagion.com Modified on: 10/11/2016 Modified by: Erwan Quélin Twitter: @erwanquelin Github: https://github.com/equelin =========================================================================== .DESCRIPTION This function will allow users to view the VMCP settings for their clusters .PARAMETER Cluster Cluster Name or Object .PARAMETER Server vCenter server object .EXAMPLE Get-VMCPSettings This will show you the VMCP settings for all the clusters .EXAMPLE Get-VMCPSettings -cluster LAB-CL This will show you the VMCP settings of your cluster .EXAMPLE Get-VMCPSettings -cluster (Get-Cluster Lab-CL) This will show you the VMCP settings of your cluster .EXAMPLE Get-Cluster | Get-VMCPSettings This will show you the VMCP settings for all the clusters #> [CmdletBinding()] param ( [Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the Cluster Name?')] $cluster = (Get-Cluster -Server $Server), [Parameter(Mandatory=$False)] [VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers ) Process { Foreach ($Clus in $Cluster) { Write-Verbose "Processing Cluster $($Clus.Name)" # Determine input and convert to ClusterImpl object Switch ($Clus.GetType().Name) { "string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue} "ClusterImpl" {$CL = $Clus} } If ($CL) { # Work with the Cluster View $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server # Create Hashtable with desired properties to return $properties = [ordered]@{ 'Cluster' = $ClusterMod.Name; 'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting; 'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD; 'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts; 'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec; 'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared; 'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL } # Create PSObject with the Hashtable $object = New-Object -TypeName PSObject -Prop $properties # Show object $object } } } } function Set-VMCPSettings { <# .NOTES =========================================================================== Created on: 10/27/2015 9:25 PM Created by: Brian Graf Twitter: @vBrianGraf VMware Blog: blogs.vmware.com/powercli Personal Blog: www.vtagion.com Modified on: 10/11/2016 Modified by: Erwan Quélin Twitter: @erwanquelin Github: https://github.com/equelin =========================================================================== .DESCRIPTION This function will allow users to enable/disable VMCP and also allow them to configure the additional VMCP settings For each parameter, users should use the 'Tab' button to auto-fill the possible values. .PARAMETER Cluster Cluster Name or Object .PARAMETER enableVMCP Enable or disable VMCP .PARAMETER VmStorageProtectionForPDL VM Storage Protection for PDL settings. Might be: - disabled - warning - restartAggressive .PARAMETER VmStorageProtectionForAPD VM Storage Protection for APD settings. Might be: - disabled - restartConservative - restartAggressive - warning .PARAMETER VmTerminateDelayForAPDSec VM Terminate Delay for APD (seconds). .PARAMETER VmReactionOnAPDCleared VM reaction on APD Cleared. Might be: - reset - none .PARAMETER Server vCenter server object .EXAMPLE Set-VMCPSettings -cluster LAB-CL -enableVMCP:$True -VmStorageProtectionForPDL ` restartAggressive -VmStorageProtectionForAPD restartAggressive ` -VmTerminateDelayForAPDSec 2000 -VmReactionOnAPDCleared reset This will enable VMCP and configure the Settings on cluster LAB-CL .EXAMPLE Set-VMCPSettings -cluster LAB-CL -enableVMCP:$False -VmStorageProtectionForPDL ` disabled -VmStorageProtectionForAPD disabled ` -VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none This will disable VMCP and configure the Settings on cluster LAB-CL .EXAMPLE Set-VMCPSettings -enableVMCP:$False -VmStorageProtectionForPDL ` disabled -VmStorageProtectionForAPD disabled ` -VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none This will disable VMCP and configure the Settings on all clusters available #> [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")] param ( [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the Cluster Name?')] $cluster, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='$True=Enabled $False=Disabled')] [bool]$enableVMCP, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Actions that can be taken in response to a PDL event')] [ValidateSet("disabled","warning","restartAggressive")] [string]$VmStorageProtectionForPDL, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Options available for an APD response')] [ValidateSet("disabled","restartConservative","restartAggressive","warning")] [string]$VmStorageProtectionForAPD, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Value in seconds')] [Int]$VmTerminateDelayForAPDSec, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')] [ValidateSet("reset","none")] [string]$VmReactionOnAPDCleared, [Parameter(Mandatory=$False)] [VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers ) Process { Foreach ($Clus in $Cluster) { Write-Verbose "Processing Cluster $Clus" # Determine input and convert to ClusterImpl object Switch ($Clus.GetType().Name) { "string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue} "ClusterImpl" {$CL = $Clus} default {Throw 'Please provide a cluster name or object'} } If ($CL) { # Get the actual configuration of the Cluster $ActualSettings = Get-VMCPSettings -Cluster $CL -Server $Server # Show actual settings in the verbose mode Write-Verbose "[$($CL.Name)] Actual VMCP settings " Write-Verbose $ActualSettings # Create the object we will configure $settings = New-Object VMware.Vim.ClusterConfigSpecEx $settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo # Based on $enableVMCP switch if ($enableVMCP -eq $false) { $settings.dasConfig.vmComponentProtecting = "disabled" } elseif ($enableVMCP -eq $true) { $settings.dasConfig.vmComponentProtecting = "enabled" } #Create the VMCP object to work with $settings.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings #Storage Protection For PDL If ($PSBoundParameters.ContainsKey('VmStorageProtectionForPDL')) { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $VmStorageProtectionForPDL } else { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $ActualSettings.'Protection For PDL' } #Storage Protection for APD If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $VmStorageProtectionForAPD } else { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD' } #Storage Protection for APD If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) { switch ($VmStorageProtectionForAPD) { "disabled" { # If Disabled, there is no need to set enable Timeout Value $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled' $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false } "restartConservative" { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative' $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true } "restartAggressive" { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive' $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true } "warning" { # If Warning, there is no need to enable the Timeout Value $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning' $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false } } } else { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD' $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $ActualSettings.'APD Timeout Enabled' } #APD Timeout Enabled If ($PSBoundParameters.ContainsKey('VmTerminateDelayForAPDSec')) { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec } else { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $ActualSettings.'APD Timeout (Seconds)' } # Reaction On APD Cleared If ($PSBoundParameters.ContainsKey('VmReactionOnAPDCleared')) { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared" } else { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = $ActualSettings.'Reaction on APD Cleared' } # Execute API Call If ($pscmdlet.ShouldProcess($CL.Name,"Modify VMCP configuration")) { $modify = $true $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server $Task = $ClusterMod.ReconfigureComputeResource_Task($settings, $modify) } # Wait for the reconfiguration task to finish to show the result If ($Task) { $TaskID = "Task-" + $($Task.Value) Get-Task -Id $TaskID -Server $Server | Wait-Task | Out-Null Get-VMCPSettings -Cluster $CL -Server $Server } } } } }
VMMonitoring
The final module I used can set the VM Monitoring settings.
# ------------------------------------------------------------------------------------------------------------------ # Module to set VM Monitoring settings when configuring a cluster with HA (this is not yet part of the new-cluster # cmdlet # # By Wesley van Ede, www.dutchvblog.com # # ------------------------------------------------------------------------------------------------------------------ function Set-ClusterDasVmMonitoring { param ( [Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the Cluster Name?')] [String[]]$cluster, [ValidateSet("vmMonitoringDisabled", "vmMonitoringOnly", "vmAndAppMonitoring")] [String[]]$Option, [int]$interval = 30, [int]$minup = 120, [int]$maxfail = 3, [int]$failwin = 3600 ) if(Get-Cluster $cluster){ $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo if ($option -eq "vmMonitoringDisabled" ) { $spec.dasConfig.vmMonitoring = "vmMonitoringDisabled" $spec.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.failureInterval = $interval $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.minUpTime = $minup $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailures = $maxfail $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow = $failwin $clusterobj = Get-Cluster -Name $cluster $clusterview = Get-View $clusterobj.Id $clusterview.ReconfigureComputeResource_Task($spec, $true) } elseif ($option -eq "vmMonitoringOnly" ) { $spec.dasConfig.vmMonitoring = "vmMonitoringOnly" $spec.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.failureInterval = $interval $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.minUpTime = $minup $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailures = $maxfail $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow = $failwin $clusterobj = Get-Cluster -Name $cluster $clusterview = Get-View $clusterobj.Id $clusterview.ReconfigureComputeResource_Task($spec, $true) } elseif ($option -eq "vmAndAppMonitoring" ) { $spec.dasConfig.vmMonitoring = "vmAndAppMonitoring" $spec.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.failureInterval = $interval $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.minUpTime = $minup $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailures = $maxfail $spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow = $failwin $clusterobj = Get-Cluster -Name $cluster $clusterview = Get-View $clusterobj.Id $clusterview.ReconfigureComputeResource_Task($spec, $true) } } }
Conclusion
This has become a monster blog post because of all the scripts. Usually I write a conclusion at the end. For now I would like to say, hopefully these PowerCLI scripts are of use to you. Please feel free to change or enhance as you see fit. And please leave a comment if there is anything I could do to make these more efficient or better in general.
HI
Is there any script for compute_cluster to display all the data stores under the cluster, along with that finding out which datastore under cluster has more capacity.
Please provide the script,