Identifying orphoned virtual machines and hard disks in vSphere

Connect to the shell of the ESXi host system and browse to location of the datastore (/vmfs/volumes/{datastore name}) to which you want to identity orphoned virtual machine hard disks and invoke the following command. This will return all virtual machine hard disks to which the modified date is seven days in the past (-mtime +7) and return the filename pattern match (find -name “*flat.vmdk*) with the modified date timestamp (-exec stat -c “%n %y” {} \;).

find -iname "*flat.vmdk" -mtime +7 -exec stat -c "%n %y" {} \;

This approach assumes that if the virtual machine hard disk has not been touched in the specified timespan the virtual machine hard disk is orphoned. This may not be accurate, as the virtual machine may be in a powered off state for a period that exceeds the timespan and the virtual machine may be valid. The output should be similar to the below:

./vmfs/volumes/424b26ec-4294ea41/ubuntu-01/ubuntu-01-flat.vmdk 2017-01-29 10:52:03.000000000
./vmfs/volumes/424b26ec-4294ea41/ubuntu-02/ubuntu-02-flat.vmdk 2017-01-29 10:17:46.000000000
./vmfs/volumes/424b26ec-4294ea41/ubuntu03/ubuntu03-flat.vmdk 2017-01-29 11:04:18.000000000
./vmfs/volumes/424b26ec-4294ea41/ubuntu04/ubuntu04-flat.vmdk 2017-01-29 10:17:49.000000000
./vmfs/volumes/424b26ec-4294ea41/ubuntu05/ubuntu05-flat.vmdk 2017-01-29 10:52:03.000000000

An alternative method, is using RVTools which can identify orphoned virtual machines and hard disks (categorised as ‘zombie’) from the inventory scan of a vCenter Server System or ESXi Host System. On completion of the inventory scan, the vHealth tab will display any virtual machines and hard disks identified and may be exported for reference.

PowerCLI: Retrieving DRS rules

I was recently looking to retrieve a list of DRS rules in each cluster managed by a single vCenter server and to export the output using PowerCLI.

The script will be required to be invoked as a scheduled task and therefore we will specify two paramaters. Firstly the VI Server we will be required to establish a connection to, where by default this will use the host name and require a mandtory parameter for the output directory for exporting the output.

Param ([string] $vCenter = ([System.Net.Dns]::GetHostByName(($env:computerName))).HostName, [parameter(Mandatory=$true)][string] $Output) 

Now, we will load the vSphere PowerCLI snap-in to the current powershell session and establish a connection to the VI Server.

if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) 
    Add-PSSnapin VMware.VimAutomation.Core | Out-Null 

Connect-VIServer $vCenter | Out-Null

Once a connection to the VI Server has been established we will retrieve all the DRS rules from each cluster and store this as a collection.

$DRSRules = Get-Cluster | Get-DrsRule

For each DRS rule returned in the collection we will retrieve the following property values and store the results in a variable to later export to a CSV file.

  • Cluster Name
  • DRS Name
  • DRS Enabled
  • DRS Type
  • VM Names

In order to retrieve the VM names, we will require to retrieve the name from the retrieved VM Id, by splitting the property value and for each VM invoking the Get-VM cmdlet to retrieve the name value and then join each returned VM name to a single string.

$Results = ForEach ($DRSRule in $DRSRules)
    "" | Select-Object-Property @{N="Cluster";E={(Get-View- Id $DRSRule.Cluster.Id).Name}},
    @{N="DRS Type";E={$DRSRule.KeepTogether}}, 
    @{N="VMs";E={$VMIds=$DRSRule.VMIds -split "," 
      $VMs = ForEach ($VMId in $VMIds) 
        (Get-View -Id $VMId).Name
      $VMs -join ","}}

Finally, we will export the output to a CSV file and close the connection to the VI Server.

$Results | Export-Csv -NoTypeInformation -Path ($Output + "\" + $vCenter+ "_DRS Rules.csv") -Force
Disconnect-VIServer -Server $vCenter -Confirm:$False

PowerCLI: Configure Log rotation and size options for vmware.log

By default, the virtual machine log file (vmware.log) is rotated as a result of the virtual machine’s Power On or Power Off operation. , In order to limit the total size this can grow to you may configure the log you may configure a log rotation size and level of rotation.

Also, this can add a level of protection where denial of service attack could write information to a log entry where these limits are not configured,as uncontrolled logging could lead to denial of service due to the datastore’s being filled.

In the below example, I am going to configure each VM to have a log rotate size of ‘1,000’ KB (the configuration value is in bytes, so 1,024,000) and set the level of rotation to ’10’. This can be achieved by adding the following to each VMs configuration parameters (VM Options > Advanced).

log.KeepOld = 10
log.rotatesize = 1024000

As I want to configure these settings for a large number of VMs, I can achieve this by using PowerCLI to build a collection of VMs at a cluster object level and  then add these settings.

Firstly, we will connect to our vCenter server and build a collection of VMs from a single cluster by invoking the Get-VM cmdlet.

if (-not (Get-PSSnapin VMware.VimAutomation.Core-ErrorAction SilentlyContinue)) 
    Add-PSSnapin VMware.VimAutomation.Core | Out-Null 

Connect-VIServer server1.domain.local 
$VMs = Get-Cluster cluster1 | Get-VM

For Each VM returned in the collection, we will now add the configuration settings as above, by invoking the cmdlet New-AdvancedSetting specifying the name and value, where the ‘Confirm’ parameter value is False to prevent the script block requiring user interaction.

ForEach ($VM in $VMs)
    Get-VM $VM.Name | New-AdvancedSetting -Name "log.keepOld" -value "10" -Confirm:$false 
    Get-VM $VM.Name | New-AdvancedSetting-Name "log.rotatesize" -value"1024000" -Confirm:$false 


Retrieving VM CDDrive information using PowerCLI

I was recently looking at retrieving a number of VMs where the CD Drive was connected to a Datastore ISO file.  This is possible be using the Get-CDDrive cmdlet to retrieve the device type information. To retreive information for a single VM we can use the following:

Get-VM VM1 | Get-CDDrive

The below information will be retrieved, where the IsoPath value is the Datastore ISO filename and Parent is the name of the VM.

IsoPath         : [********] SW_DVD9_SQL_Svr_Enterprise_Edtn_2008_R2_English_MLF_X16-29540.ISO
HostDevice      :
RemoteDevice    :
ParentId        : VirtualMachine-vm-15465
Parent          : vm1
Uid             : /VIServer=domain\user1@server1:443/VirtualMachine=VirtualMachine-vm-15465/CDDrive=3002/
ConnectionState : Connected, GuestControl, StartConnected
ExtensionData   : VMware.Vim.VirtualCdrom
Id              : VirtualMachine-vm-15465/3002
Name            : CD/DVD drive 1
Client          : VMware.VimAutomation.ViCore.Impl.V1.VimClient

For a number of VMs, we can retrieve theses as a collection and pass these to the Get-CDDrive cmdlet. In this instance I wanted to return all VMs where the CD Drive was connected to the Datastore ISO file ‘SW_DVD9_SQL_Svr_Enterprise_Edtn_2008_R2_English_MLF_X16-29540.ISO’.

The Datastore ISO file value can be retrieved from the IsoPath property, in the below example we will filter the retrieved information to return only the above file and include only the name of the VM and the IsoPath in the output.

Get-VM | Get-CDDrive  | Select Parent, IsoPath |  Where-Object {$_.IsoPath -like "*SW_DVD9_SQL_Svr_Enterprise_Edtn_2008_R2_English_MLF_X16-29540.ISO"}

We may also choose to remove the connected Datastore ISO file by using the output from the above and passing to the Set-CDDrive cmdlet to remove the media.

Get-VM | Get-CDDrive |  Where-Object {$_.IsoPath -like "*SW_DVD9_SQL_Svr_Enterprise_Edtn_2008_R2_English_MLF_X16-29540.ISO"} | Set-CDDrive -NoMedia -Confirm:$False

Calculate vCPU to pCPU ratio for Hosts using PowerCLI

In some capacity planning scenarios, statistical information is not taken into account and the management of resources through best efforts can become a  rule of thumb scenario. In the case, of CPU resource the concept of vCPU to CPU ratio has been discussed as a possible method.

Using PowerCLI I was able to produce the ratio of vCPU to pCPU ratio by retrieving Host and VM information and combing this with math.

Firstly we will connect to the VI Server and create a collection of Hosts.

Connect-VIServer server1.domain.local
$VMHosts = Get-VMHost

For each host returned in the collection I will retrieve the number of vCPUs for all VMs on that particular host by returning the NumCPU of each VM, joining each value returned with a ‘+’ and invoking an expression agaisnt the string to produce the total number of vCPUS on the host.

ForEach ($VMHost in $VMHosts)
    $vCPU = Invoke-Expression ((Get-VMHost $VMHost.Name | Get-VM).NumCPU -join '+')

Now we will produce an informational message to show the vCPU to pCPU ratio, we can return the number of physical cores on the Host by returning the ‘Hardware.CPUInfo.NumCPUCores’ value and then dividing the total number of vCPUS on the Host by this value and use the Math.Round method to round the calculated value to one decimal place.

"The vCPU to pCPU ratio for Host '" + $VMHost.Name + "' is " + ([math]::round($vCPU / $VMHost.Hardware.CPUInfo.NumCpuCores,1)) + ":1"

Running the above will return the following output:

The vCPU to pCPU ratio for Host 'esxi1.domain.local' is 3:1
The vCPU to pCPU ratio for Host 'esxi2.domain.local' is 6.6:1
The vCPU to pCPU ratio for Host 'esxi3.domain.local' is 2.4:1
The vCPU to pCPU ratio for Host 'esxi4.domain.local' is 2.2:1

Whilst this will generate the current vCPU to pCPU ratio, this alone shouldn’t be used as a capacity planning/sizing method, from using management tools and/or retrieving  the statistical information (Get-Stat) for both Hosts and VMs you can generate a far more accurate picture of your environment.

The main reason for me generating the above was to get a quick overview whilst killing a bit of down time with PowerCLI.