CpuHotRemoveEnabled ?!

Was playing around enabling CPU & Memory Hot Add via PowerCli/PowerShell, and came across the CPUHotRemoveEnabled feature.

<pre>$VMSpec=New-Object -Type VMware.Vim.VirtualMachineConfigSpec -Property @{"CpuHotRemoveEnabled" =  $true}
$VM = Get-VM W2K16GA

This feature may be around for ages, I personally never used it. And as far as I know is still unsupported.. Tried it with a Windows 2016 Enterprise Edition VM, but no sigar. Both the GUI and PowerCli didn’t allow changes to be made. Could scale up CPUs but unable to scale down.

(The screenshot below doesn’t show CPU Hot Plug as Enabled, but CPU Hot Remove fails regardless of CPU Hot Plug being Enabled or not)

PowerCli error:

Set-VM W2K16GA -NumCpu 1
The operation for the entity "W2K16GA" failed with the following message: "CPU hot plug is not supported for this virtual machine."

So don’t know if this post is useful for anybody, but I smiled while playing around with this. 🙂

But if you enable it on a VM in 6.5 you get a prevously hidden check box:


Enable CPU Hot Remove checkbox visible


The ye olde fatclient also had this option (picture blatenly stolen from somewhere)


Set-CDDrive -Connected:$false may result in paused Linux VMs (RHEL 6.4)

I found lots of connected iso images connected to VMs and wanted to release the iso images. So I used Get-VM | Get-CDDrive | Set-CDDrive -Connected:$false

That seemed to work until the command seemed to halt. I killed the PowerShell session and wanted to retry later. One of my co-workers came to my office to tell me about a bunch of servers that had become non responsive.

After some searching it appeared that some VM’s asked a Virtual Machine question. During the time that the question is unawnsered the virtual machine is paused.

I didn’t think removing the CD images from VMs could result in downtime, but apparantely it does, atleast with RHEL 6 VMs. I didn’t see this behaviour with Windows VMs.

I found KB2000110 which lists the symptoms, but talks about an issue when using Update Manager with the option “Disable any removable media devices connected to the virtual machines on the host” selected during remediation. I guess that it uses the same API/method to eject the CD-ROM.

The guest operating system has locked the CD-ROM door and is probably using the CD-ROM, which can prevent the guest from recognizing media changes. If possible, eject the CD-ROM from inside the guest before disconnecting. Disconnect anyway and override the lock? [Yes/No]

The guest operating system has locked the CD-ROM door and is probably using the CD-ROM, which can prevent the guest from recognizing media changes. If possible, eject the CD-ROM from inside the guest before disconnecting. Disconnect anyway and override the lock? [Yes/No]

So after some clicking all was ok again. But it did disconnected a bunch of end-user sessions to the (web)servers resulting in failed attempts to commit data.

Maybe next time I try to disconnect ISO’s by adding

Get-VMQuestion | Set-VMQuestion -Option 'No' -Confirm:$false

Get NetApp LUN Serial from VMware naa.60a98000*

Today I needed to find the LUN ID of a NetApp iSCSI LUN. VMware shows it as naa.xxxxxx I found this forumpost in which it’s explaned that the LUN serial number is shown in hexadecimal within the naa. I wrote this script to give me all RDMs in and transcode the LUN serial number from the naa (Network Adress Authority) name.

Function Get-NetAppLunSerial ($naa) {
#Take VMware's naa indentifier as input

	#Prepare array to contain all separate ASCII characters
	#Check if the naa has the NetApp prefix of "60a98000" and cut it. 
	If (($NAA.Split(".")[1].Substring(0,8)) -eq "60a98000") {
		Write-Host "NetApp LUN"
		#Cut the prefix
		Write-Host $WWN
		# Cut the string in to one byte blocks
		$WWN -split "(\w{2})"|ForEach-Object {
			If ($_ -ne "") {
				#Convert Hex block to Decimal Number
				#Convert Decimal Number to ASCII Character
	#Read the LunSerialArray as a continues string
	$LunSerial=$LunSerialArray -join ''
	#Expose the serial string outside the function

Get-VM | Get-HardDisk -DiskType "RawPhysical","RawVirtual" | Select Parent,Name,DiskType,ScsiCanonicalName,DeviceName,@{"Name"="NetAppLunSerial";"Expression"={Get-NetAppLunSerial $_.ScsiCanonicalName}}
# $NetAppLunSerial=Get-NetAppLunSerial naa.60a9800057322d6a5aad437267302658

This translates the naa.60a9800057322d6a5aad437267302658 to W2-jZ­Crg0&X (I’ve typed some random numbers but it’s not strange to find somewhat special characters in the Serial Number.)

All logic about the hexASCII conversion I got from here

PowerCli: Get VMware Licenses from an array of vCenter Servers

VMware’s licensing is quite flexible, if you have, say 1 10 socket license, you are able to split the license in to blocks so each vSphere instance get’s it’s own dedicated license key. But sometimes you encounter a situation where the people before you just reused licenses, and the vCenters aren’t linked. Because one could’t login to the license portal, and “yeah, I know we bought extra licenses, but I already know this license key, so why bother with another..” As long as you’ve bought all the license keys you need it shouldn’t be to big of a deal. <- This is my guess, I must admit that I've never looked in to the details of the licensing agreements! But in my case I found an enviroment where keys where used in multiple instances. I needed a way to quickly find all keys used, and split them in to groups of the same kind (Enterprise, Enterprise Plus, etc) and calculate if we have over- or under-utilized them.

I've written a script to help me find out. The examples shown are old values, all systems are now fully licensed.

Output of the script: (Summary.txt)

LicenseKey                    Available Used
----------                    --------- ----
00000-00000-00000-00000-00000         0    4

Product                                                    Available Used Adheres
-------                                                    --------- ---- -------
vCenter Operations Management Suite Enterprise Edition 5.6     10175  168    True
vCenter Server 5 Standard                                          7    9   False
VMware vSphere 5 Enterprise Plus                                 120  126   False
Product Evaluation                                                 0    4   False
vCenter Operations Management Suite Standard Edition 5.6         225  279   False

The fun starts with the IIIII-IIIII-IIIII-IIIII-IIIII license. It was used on 46 sockets, while it only allows for 12. But when we looked at the type of license it’s only over utilized by 6 sockets.

The complete list of licenses added to each vCenter: (VMwareLicenses.csv)

VC,Name,Key,Total,Used,ExpirationDate,Information,Product Evaluation,00000-00000-00000-00000-00000,0,0,,,vCenter Server 5 Standard,AAAAA-AAAAA-AAAAA-AAAAA-AAAAA,1,1,,,vCenter Server 5 Standard,BBBBB-BBBBB-BBBBB-BBBBB-BBBBB,1,1,,,VMware vSphere 5 Enterprise Plus,CCCCC-CCCCC-CCCCC-CCCCC-CCCCC,12,10,,,vCenter Operations Management Suite Standard Edition 5.6,DDDDD-DDDDD-DDDDD-DDDDD-DDDDD,225,57,,vCOPS Standard,vCenter Server 5 Standard,EEEEE-EEEEE-EEEEE-EEEEE-EEEEE,1,1,,,VMware vSphere 5 Enterprise Plus,CCCCC-CCCCC-CCCCC-CCCCC-CCCCC,12,12,,,Product Evaluation,00000-00000-00000-00000-00000,0,1,,,Product Evaluation,00000-00000-00000-00000-00000,0,0,,,VMware vSphere 5 Enterprise Plus,FFFFF-FFFFF-FFFFF-FFFFF-FFFFF,12,12,,vSphere 5 Enterprise Plus,VMware vSphere 5 Enterprise Plus,CCCCC-CCCCC-CCCCC-CCCCC-CCCCC,12,6,,,vCenter Server 5 Standard,EEEEE-EEEEE-EEEEE-EEEEE-EEEEE,1,1,,,vCenter Operations Management Suite Standard Edition 5.6,DDDDD-DDDDD-DDDDD-DDDDD-DDDDD,225,222,,vCops Standard,VMware vSphere 5 Enterprise Plus,GGGGG-GGGGG-GGGGG-GGGGG-GGGGG,16,8,,,Product Evaluation,00000-00000-00000-00000-00000,0,1,,,vCenter Server 5 Standard,HHHHH-HHHHH-HHHHH-HHHHH-HHHHH,1,1,,,VMware vSphere 5 Enterprise Plus,IIIII-IIIII-IIIII-IIIII-IIIII,8,8,,,vCenter Operations Management Suite Enterprise Edition 5.6,JJJJJ-JJJJJ-JJJJJ-JJJJJ-JJJJJ,10000,0,VMware.Vim.KeyAnyValue,,Product Evaluation,00000-00000-00000-00000-00000,0,1,,,VMware vSphere 5 Enterprise Plus,KKKKK-KKKKK-KKKKK-KKKKK-KKKKK,48,48,,,vCenter Operations Management Suite Enterprise Edition 5.6,LLLLL-LLLLL-LLLLL-LLLLL-LLLLL,175,168,,,vCenter Server 5 Standard,MMMMM-MMMMM-MMMMM-MMMMM-MMMMM,1,1,,,Product Evaluation,00000-00000-00000-00000-00000,0,0,,,vCenter Server 5 Standard,NNNNN-NNNNN-NNNNN-NNNNN-NNNNN,1,1,,,VMware vSphere 5 Enterprise Plus,OOOOO-OOOOO-OOOOO-OOOOO-OOOOO,4,4,,,VMware vSphere 5 Enterprise Plus,CCCCC-CCCCC-CCCCC-CCCCC-CCCCC,12,6,,,Product Evaluation,00000-00000-00000-00000-00000,0,0,,,Product Evaluation,00000-00000-00000-00000-00000,0,0,,,vCenter Server 5 Standard,PPPPP-PPPPP-PPPPP-PPPPP-PPPPP,1,1,,,Product Evaluation,00000-00000-00000-00000-00000,0,1,,,VMware vSphere 5 Enterprise Plus,QQQQQ-QQQQQ-QQQQQ-QQQQQ-QQQQQ,20,0,,,VMware vSphere 5 Enterprise Plus,CCCCC-CCCCC-CCCCC-CCCCC-CCCCC,12,12,,,vCenter Server 5 Standard,PPPPP-PPPPP-PPPPP-PPPPP-PPPPP,1,1,,

And finally the script:

Function Get-vCenterCredential ($vCenterDomain, $UserName) {
	$CredentialsFile = $vCenterDomain+".cred"
	$UPN = $UserName+"@"+$vCenterDomain
	$Password = Get-Content C:\Scripts\Creds\$CredentialsFile | ConvertTo-SecureString
	$Creds = New-Object System.Management.Automation.PSCredential($UPN,$Password)

Function Make-Dir ($Directory) {
	If (!(Test-Path $OutputPath)) {
		New-Item $OutputPath -ItemType Directory | Out-Null

$UserName = "vmninja"
$Creds = $Null
Add-PSSnapin VMware.VimAutomation.Core
$vCenters=Import-Csv C:\Scripts\vCenters.csv -Delimiter ";"
$Date=Get-Date -Format yyyyMMdd
$vCenters|ForEach-Object {
	$Domain = $_.UserDomain
	$vCenterServer = $_.vCenterIP
	$OutputPath = "C:\Scripts\Output\LicenseInfo\"+$Date.ToString()
	Make-Dir $OutputPath
	$Creds = Get-vCenterCredential -vCenterDomain $Domain -UserName $UserName
	$VIConnection = Connect-VIServer $vCenterServer -Credential $Creds

$vSphereLicInfo = @()
$ServiceInstance = Get-View ServiceInstance
Foreach ($LicenseMan in Get-View ($ServiceInstance | Select-Object -First 1).Content.LicenseManager) {
	Foreach ($License in ($LicenseMan | Select -ExpandProperty Licenses)) {
		$Details = "" | Select VC, Name, Key, Total, Used, ExpirationDate, Information
		$Details.VC = ([Uri]$LicenseMan.Client.ServiceUrl).Host
		$Details.Name = $License.Name
		$Details.Key = $License.LicenseKey
		$Details.Total = $License.Total
		$Details.Used = $License.Used
		$Details.Information = $License.Labels | Select -ExpandProperty Value
		$Details.ExpirationDate = $License.Properties | Where-Object {$_.Key -eq "expirationDate"} | Select-Object -ExpandProperty Value
		$vSphereLicInfo += $Details

$vSphereLicInfo | Sort-Object | Export-Csv -NoTypeInformation -Path $OutputPath\VMwareLicenses.csv	
$vSphereLicInfo | Format-Table -AutoSize

$AvailableLicenses=$vSphereLicInfo | Select-Object Key, Total -Unique
$UsedLicenses=$vSphereLicInfo | Select-Object Key, Used 

$DataSet=$UsedLicenses|Group-Object -Property key -AsHashTable
$DataSet.Keys | % {$tab += @{$_ = ($DataSet[$_]|Measure-Object -Property Used -Sum)}}
$Licenses = @()
$tab.Keys | % {
	$Avail=$AvailableLicenses|Where-Object {$_.key -match $CurrentKey}|Select-Object $_.Total
	$Lic = "" | Select LicenseKey, Available, Used
	$Lic.LicenseKey = $CurrentKey
	$Lic.Available = $Avail.Total
	$Lic.Used = $tab[$CurrentKey].sum
	$Licenses += $Lic
$Licenses | ft -AutoSize | Out-File $OutputPath\Summary.txt

$AvailableLicenses=$vSphereLicInfo | Select-Object Name, Key, Total -Unique
$UsedLicenses=$vSphereLicInfo | Select-Object Name, Key, Used 

$DataSetAvail=$AvailableLicenses|Group-Object -Property Name -AsHashTable
$DataSetAvail.Keys | % {$tabAvail += @{$_ = ($DataSetAvail[$_]|Measure-Object -Property Total -Sum)}}

$DataSetUsed=$UsedLicenses|Group-Object -Property Name -AsHashTable
$DataSetUsed.Keys | % {$tabUsed += @{$_ = ($DataSetUsed[$_]|Measure-Object -Property Used -Sum)}}
$Licenses = @()
$LicInUse = @()
$LicInStock = @()

$tabUsed.Keys | % {
	$LU = "" | Select Product, UsedLicenses
	$LU.Product = $Product
	$LU.UsedLicenses = $LicUsed
	$LicInUse += $LU
	Write-Host Used: $Product`t $LicUsed

$tabAvail.Keys | % {
	$LA = "" | Select Product, AvailableLicenses
	$LA.Product = $Product
	$LA.AvailableLicenses = $LicAvail
	$LicInStock += $LA

$LicInUse | ForEach-Object {
	[string]$Product = $_.Product
	[int]$Used = $_.UsedLicenses
	$Available = $LicInStock | Where-Object {$_.Product -eq $Product} | Select-Object -ExpandProperty AvailableLicenses
	If ($Used -le $Available){
	Else {
	$LO = "" | Select Product, Available, Used, Adheres
	$LO.Product = $Product
	$LO.Available = $Available
	$LO.Used = $Used
	$LO.Adheres = $Adheres
	$LicenseOverview += $LO
$LicenseOverview | ft -AutoSize | Out-File $OutputPath\Summary.txt -Append

To save the credentials used by the script, I’ve used the following script:
The user that saves the credentials is the only one who can decrypt, so make sure you run the script with the correct credentials.

$vCenterDomain=Read-Host "Please enter the userdomain: " 
$Credential = Get-Credential
$Credential.Password | ConvertFrom-SecureString | Set-Content $File