Category Archives: Automation

PowerCLI: Reconfigure for vSphere HA


Sometimes when you change something to the vSphere HA configuration like an Advanced Option, you have to reconfigure vSphere HA on each host inside that particular cluster. You can do that by hand via the Reconfigure for vSphere HA.. option inside the vSphere (Web) Client:

Screenshot 2016-01-22 13.11.47

Or you can use the following PowerCLI one-liner to perform this step on every host inside that cluster.

Get-Cluster <clusterName | Get-VMhost | Sort Name | %{$_.ExtensionData.ReconfigureHostForDAS()}

Just change <clusterName> the to the name of the cluster en open PowerCLI, connect to the vCenter server and run the one-liner.

PowerCLI: Easy NFS datastore setup vSphere 5.x


For vSphere 4.1 I wrote a PowerCLI script to attach NFS shares. You can find the script here.

In vSphere 5 the properties has changed so I had to change the script. In fact the script is much simpler because all the properties can be found in $nfs.info.nas:

image

The RemoteHost presents the IP address, The RemotePath presents the Share and the Name property presents the name of the share. Now we have the correct variables so it’s time to fix the old script. You can find the result below:

$REFHOST = Get-VMHost "<esxi hostname>"
foreach($NEWHOST in (Get-Cluster <cluster> | Get-VMhost | Where {$_.Name -ne $REFHOST.Name}) | Sort Name){
    foreach($nfs in (Get-VMhost $REFHOST | Get-Datastore | Where {$_.type -eq "NFS"} | Get-View)){
        $share = $nfs.info.Nas
        if($share.Remotehost -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"){
            $remotePath = $share.RemotePath
            $remoteHost = $share.Remotehost
            $shareName = $nfs.Name            

            if ((Get-VMHost $NEWHOST | Get-Datastore | Where {$_.Name -eq $shareName -and $_.type -eq "NFS"} -ErrorAction SilentlyContinue )-eq $null){
                Write-Host "NFS mount $shareName doesn't exist on $($NEWHOST)" -fore Red
                New-Datastore -Nfs -VMHost $NEWHost -Name $Sharename -Path $remotePath -NfsHost $remoteHost    | Out-Null
            }
        }
    }
}

PowerCLI: Get-VirtualPortgroup -Distributed VlandId value is empty


Today I was busy with PowerCLI and dvPort groups.  I started to use the Get-VirtualPortgroup –Distributed cmdlet and parameter to retrieve some information about the dvPort group. But the default output doesn’t show the VlanId. See the screen shot below for the default output.

image

I don’t know if this is a known issue between PowerCLI 5.1 release 1 and vSphere 4.1 update 2. So I have to test it in a vSphere 5 environment.

But how can you find the vlanid of a distributed portgroup? You can use a PowerCLI script which I created  to fix this little “bug” and I have also added the PortsFree column to the output of the script.

$dvPortgroup = get-virtualportgroup -Distributed -Name "vlan1"
$dvPortgroupInfo = New-Object PSObject -Property @{            
    Name = $dvPortgroup.Name
    Key = $dvPortgroup.Key
    VlanId = $dvPortgroup.ExtensionData.Config.DefaultPortConfig.Vlan.VlanId
    Portbinding = $dvPortgroup.Portbinding
    NumPorts = $dvPortgroup.NumPorts
    PortsFree = ($dvPortgroup.ExtensionData.PortKeys.count - $dvPortgroup.ExtensionData.vm.count)
}  
$dvPortgroupInfo | ft -AutoSize

The output of the script:

image

If you want to create a report of all the dvPort groups. You can use the following script to achieve that goal:

$info = @()
foreach($dvPortgroup in (Get-VirtualPortgroup -Distributed | Sort Name)){
    $dvPortgroupInfo = New-Object PSObject -Property @{            
        Name = $dvPortgroup.Name
        Key = $dvPortgroup.Key
        VlanId = $dvPortgroup.ExtensionData.Config.DefaultPortConfig.Vlan.VlanId
        Portbinding = $dvPortgroup.Portbinding
        NumPorts = $dvPortgroup.NumPorts
        PortsFree = ($dvPortgroup.ExtensionData.PortKeys.count - $dvPortgroup.ExtensionData.vm.count)
    }  
    $info += $dvPortgroupInfo
}
$info | Export-Csv -UseCulture -NoTypeInformation C:\tmp\dvportgroup_info.csv

PowerCLI: dvPortgroup ports report


In this post I will show you how you can generate a simple report of your dvPortgroups. The report shows the Name of the dvPortgroup, The portbinding configuration, The total ports configured, The total ports in use and last but not least the total ports left on the dvPortgroup.

The script below will search for all distributed portgroups in your vCenter where you’re connected to with PowerCLI.

$pgInfo = @()
foreach($pg in (get-virtualportgroup -distributed | Sort Name)){
    $details = "" | Select Name, PortBinding, Totalports, Portsinuse, Portsleft
    
    $totalPorts = $pg.ExtensionData.PortKeys.count    
    $Portsinuse = $pg.ExtensionData.vm.count
    $portsleft = ($totalPorts - $Portsinuse)
        
    $details.Name = $pg.name
    $details.PortBinding = $pg.PortBinding
    $details.Totalports = $totalPorts
    $details.Portsinuse = $Portsinuse
    $details.Portsleft = $portsleft   
    
    $pgInfo += $details
}    
$pgInfo | Export-Csv -UseCulture -NoTypeInformation C:\Scripts\dvPortgroupInfo.csv

The CSV output will look like this:

Name PortBinding Totalports Portsinuse Portsleft
vlan1 Static 32 4 28
vlan2 Static 32 0 32
vlan3 Static 32 7 25
vlan4 Static 32 1 31
vlan5 Static 32 12 20
vlan6 Static 32 0 32

With a simple PowerCLI script you can create a report of all your dvPortgroups. I am going to create another PowerCLI script to use as a Nagios plugin to see witch of the dvPortgroups have less than <X> ports left. So to be continued.

PowerCLI: Copy Datastore Items


In this short post I will show a PowerCLI script I wrote to copy ISO files from datastore y to datastore x. The datastores are in the same vCenter and virtual datacenter accessible but the vSphere hosts are located inside two different IP subnets and a firewall rule prevents to copy files between the two subnets. So I had to think about a work around. Well this one is easy. On the vCenter server I created a script to peform the following steps:

  1. Create two PSDrives for each Datastore
  2. Get al the ISO filenames
  3. Downlad the ISO to the c:\tmp directory from datastore y
  4. Upload the ISO from the C:\tmp directory to the datastore<X>\iso directory
  5. Remove the ISO from C:\tmp
  6. repeat the steps above until all the ISO files are copied to the new datastore.

The PowerCLI script to perform the described tasks:

New-PSDrive -location (get-datastore template-01) -name tpl01 -PSProvider VimDatastore -Root '\'
New-PSDrive -location (get-datastore template-02) -name tpl02 -PSProvider VimDatastore -Root '\'

$isos = ls tpl01:\iso\ | % {$_.Name}
foreach($iso in $isos){
    Write-Host "copy $($iso) to C:\tmp" -fore Yellow
    Copy-DatastoreItem -item tpl01:\iso\$iso -Destination C:\tmp
    
    Write-Host "copy $($iso) to template-02\iso" -fore Yellow
    Copy-DatastoreItem -item C:\tmp\$iso -Destination tpl02:\iso
    
    Write-Host "removing the tmp file $($iso) from C:\tmp" -fore Yellow
    Remove-Item C:\tmp\$iso -confirm:$false
    
    Write-Host "done" -fore Green
}

So once again PowerCLI to the rescue.

PowerCLI: Disable / Enable HA Host Monitoring


In the case you need to or your network team needs to do some network maintenance on the switches which VMware HA uses to communicate with the other hosts or where the das.isolationaddress (default gateway) is configured/ It’s smart to disable the Host Monitoring feature of VMware HA. You can do this easily by hand via edit cluster – VMware HA and uncheck the Enable Host Monitoring feature. See screenshot below:

image

But what if you have to disable Host Monitoring on multiple VMware HA cluster? Well, if you like PowerCLI, you can use the following script to disable or enable the HA Host Monitoring feature:

param(
    $vCenter,
    $option
)

if($vCenter -eq $null){
    Write-Host "Please enter the name of the vCenter Server" -ForegroundColor Yellow
    exit 
} 

switch($option){
    enabled {"The HA Host Monitoring feature will be enabled"}
    disabled {"The HA Host Monitoring feature will be disabled"}
    default {"the option value could not be determined."
    exit
    }
}

Connect-VIServer $vCenter

$clspec = New-Object VMware.Vim.ClusterConfigSpecEx
$clspec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
$clspec.dasConfig.hostMonitoring = $option

foreach($cluster in (Get-Cluster | sort Name)){
    $clview = Get-Cluster $cluster | Get-View
    $clview.ReconfigureComputeResource_Task($clspec, $true)
}

Disconnect-VIServer -Confirm:$false

Just save the script to change-HAHostMonitoring.ps1 and run it like this to disable the HA Host Monitoring feature:

Change-HAHostMonitoring vcenter.domain.loc disabled

If you want to enable Host Monitoring, just change disabled to enabled:

Change-HAHostMonitoring vcenter.domain.loc enabled

Note: Please test the script mentioned in this blog post in a lab or test environment before you use the script in a production environment.

PowerCLI: Migrate templates during the Enter Maintenance Mode task


Normally when you put a host into Maintenance mode the templates will stay on the host instead of being migrate to a different host. This can be very annoying if you are performing maintenance on the vSphere host and a colleague needs to deploy a VM from the template. I am running vSphere 4.1 update 1. I don’t know if this is still the case with vSphere 5. The host in Maintenance mode will look like this:

image

So to fix this annoying “issue” I have created a PowerCLI function to place the vSphere host into maintenance mode and if there are Templates registered on the vSphere host, the Templates will be moved to another host in the Cluster.

Function Enter-MaintenanceMode{
<#
.SYNOPSIS   Enter Maintenance mode 
.DESCRIPTION   The function starts the Enter Maintenance task and also migrates the Templates to another host.
.NOTES   Author:  Arne Fokkema
.PARAMETER vmHost
   One vmHosts.
.EXAMPLE
   PS> Enter-MaintenanceMode<vmHost Name>
.EXAMPLE
  PS> Get-VMHost <vmHost Name> | Enter-MaintenanceMode
#>

[CmdletBinding()]
param(
    [parameter(ValueFromPipeline = $true,
    position = 0,
    Mandatory = $true,
    HelpMessage = "Enter the vmHost to start the Enter Maintenance mode task")]
    $vmHost
)    

    $templates = Get-VMHost $vmHost | Get-Template
    if($templates -eq $null){
        $tplMigrate = $false
    }
    else{
        $tplMigrate = $true
    }
    
    $targetVMHost = Get-VMHost -Location (Get-Cluster -VMHost (Get-VMhost $vmHost)).Name | Where {$_.Name -ne $vmHost} | Sort Name | Select -First 1
    if($tplMigrate -eq $true){
        foreach($tpl in $templates){
            Write-Host "Converting template $($tpl.Name) to VM" -ForegroundColor Yellow
            $vm = Set-Template -Template (Get-Template $tpl) -ToVM 
            
            Write-Host "Moving template $($tpl.Name) to vmHost: $($targetVMHost)" -ForegroundColor Yellow
            Move-VM -VM $vm -Destination (Get-VMHost $targetVMHost) -Confirm:$false | Out-Null
            
            Write-Host "Converting template $($tpl.Name) back to template" -ForegroundColor Yellow
            ($vm | Get-View).MarkAsTemplate() | Out-Null    
        }    
    }
    Write-Host "Enter Maintenance mode $($vmHost)" -ForegroundColor Yellow
    Set-VMHost $vmHost -State Maintenance | Out-Null
}

You can run the script like this:

Enter-MaintenanceMode esx07

Or from the pipeline:

Get-VMHost esx07 | Enter-MaintenanceMode

The output will be the same:

image

And the host is completely empty and ready for maintenance:

image