Get-LicenseReport to obtain informations regarding licenses within Virtual Center

If you need to create reports regarding licenses usage you can the below script. It gathers all licensing information for virtual center to which you are currently connected. Before running this function make sure you are connected to one single virtual center instance. Please run this function within PowerCLI console, as for now i haven’t put check/loading vmware snappin

Function Get-LicenseReport
{
  <#

   .Synopsis

    Get licensing report from currently connected Virtual Center

   .Description

    This function returns licensing information from the currently connected 
	Virtual Center server. It can output to screen or to html file using the
	ConvertTo-HTML option.
	PreContent of html report can be modified in source code.
	Variable $PreContent describes what is written before generating 
	the table.

   .Example

    Get-LicenseReport

    Will create licenses usage report from currently connected VirtualCenter
	server and output to screen

   .Example

    Get-LicenseReport -htmlfile "C:\licensereport.html"

    Will create licenses usage report from currently connected VirtualCenter
	server and output to file "C:\licensereport.html"
	
	Get-LicenseReport -htmlfile "C:\licensereport.html" -Name "Grzegorz 
	Kulikowski" -Email "myemail@web.com" -CustomerNumber "123123"

    Will create licenses usage report from currently connected VirtualCenter
	server and output to file "C:\licensereport.html" and fill out predefined
	field within report such as name, email, vmware customer number

   .Parameter CustomerNumber

    If you need to specifi additional field like Customer Number
	
	.Parameter Name

    If you need to specify name of the person who creates the report
	
	.Parameter Email

    If you need to specify e-mail of the person who creates the report
	
   .Parameter htmlfile

    Specifies the file name to which html version report will be written

   .Notes

    NAME:  Get-LicenseReport

    AUTHOR: Grzegorz Kulikowski

    LASTEDIT: 08/13/2012
	
	SPECIAL THANKS: Luc Dekens, Robert van den Nieuwendijk, Yasen Kalchev
	CSS TABLE: http://www.textfixer.com/resources/css-tables.ph
	
	NOT WORKING ? #powercli @ freenode.irc.net / 

   .Link

    https://psvmware.wordpress.com

 #>
param (
[string]$htmlfile,
[string]$CustomerNumber,
[string]$Name,
[string]$Email
)
$Head=@"
<Title>License Report for $($global:DefaultVIServer.name)</Title>
 <Style type="text/css">
  P.myinfo {text-align: Left}
  body {
   margin-left: 20%;
   margin-right: 20%;
   padding-top: 30px;
   padding-bottom: 40px;
   color: #2E2E2E;
   background-color: #E6E6E6 }
   
  table.gridtable {
	font-family: verdana,arial,sans-serif;
	font-size:11px;
	color:#333333;
	border-width: 1px;
	border-color: #666666;
	border-collapse: collapse;
}
  table.gridtable th {
	border-width: 1px;
	padding: 8px;
	border-style: solid;
	border-color: #666666;
	background-color: #dedede;
}
  table.gridtable td {
	border-width: 1px;
	padding: 8px;
	border-style: solid;
	border-color: #666666;
	background-color: #ffffff;
}
 </Style>
"@
 
$PreContent=@"
<center>
<p><h1>License Report</h1></p>
<p class=myinfo>VMware License Review – for VC:<b> $($global:DefaultVIServer.name) </b></br>
Customer Number:<b> $CustomerNumber </b></br>
Name of Person completing this form: <b>$Name</b></br>
Email of Person completing this form: <b>$Email</b></br>
Date: <b> $(get-date) </b></br></br</p>
"@

if(-not ($global:DefaultVIServer) ) { 
	Write-Host -ForegroundColor Red -BackgroundColor Black "You are not connected to any VirtualCenter server. Please connect manually."
	Write-Host -ForegroundColor Yellow -BackgroundColor Black "hint: Connect-VIServer -server myVC.domain.biz -Credential (Get-Credential)"
	break
}
$param = @($null)
$ServiceInstance = Get-View ServiceInstance
$LicenseManager= Get-view $ServiceInstance.Content.LicenseManager
$LicenseAssignmentManager= Get-View $LicenseManager.LicenseAssignmentManager
$LicensesArrayList=New-Object System.Collections.ArrayList 
$LicenseAssignmentManager.GetType().GetMethod("QueryAssignedLicenses").Invoke($LicenseAssignmentManager,$param) |Foreach-Object{
$License=New-Object -TypeName PsObject -Property @{ProductName=$null;Version=$null;Edition=$null;DisplayName=$null;PhysProcessors=$null;CoresPerCpu=$null}
$License.ProductName= ($_.Properties.GetEnumerator()|?{$_.Key -eq 'ProductName'}).Value
$License.Version= ($_.Properties.GetEnumerator()|?{$_.Key -eq 'ProductVersion'}).Value
$License.Edition= $_.AssignedLicense.Name
$License.DisplayName=$_.EntityDisplayName
    if($_.AssignedLicense.EditionKey -like "vco*"){
			$License.DisplayName+=" Used: $($_.AssignedLicense.Used) from: $($_.AssignedLicense.Total)"
		}
	if($_.EntityId -like "host-*"){
		$HostView=Get-View -Id  "HostSystem-$($_.EntityID)"
		$License.PhysProcessors=$HostView.Hardware.CpuInfo.NumCpuPackages
		$License.CoresPerCpu=$hostview.Hardware.CpuInfo.NumCpuCores/$HostView.Hardware.CpuInfo.NumCpuPackages
	}
		else {
			$License.PhysProcessors="N/A"
			$License.CoresPerCpu="N/A"
		}
$LicensesArrayList.Add($License)|Out-Null
}
if($htmlfile){
	($LicensesArrayList | Select-Object ProductName,Version,Edition,DisplayName,CoresPerCpu,PhysProcessors | ConvertTo-Html -PreContent $PreContent -Head $Head ) -Replace '<table>','<table class="gridtable">' |Out-File $htmlfile
	}
	else{
		return $LicensesArrayList
	}
}

I would like to thank Luc Dekens, Robert van den Nieuwendijk, Yasen Kalchev for their support while i was trying get all the information which was needed in order to obtain all data from Virtual Center, as this one was bit tricky 😉

get-licensereport image

get-licensereport image


While writing this script it was very difficult to pass $null to QueryAssignedLicenses method, i mean it was impossible ;). Why did i have to query like that ?

$LicenseAssignmentManager.GetType().GetMethod("QueryAssignedLicenses").Invoke($LicenseAssignmentManager,$param)

http://communities.vmware.com/message/2096977#2096977 Yasen Kalchev explains why do we have to use this approach in order to get ALL licensing information from virtual center.
By the way it’s very easy to obtain exactly the same result if you will point your web browser directly to
https://your-vc-address.biz/?moid=LicenseAssignmentManager&method=queryAssignedLicenses
And leave the EntityID parameter as empty.
What i have also learned while writing this script is that EntityID for VC is kept in

(Get-View ServiceInstance).Content.About.InstanceUuid

And for all esx/i hosts the id is the Value of its MoRef for example HostSystem-host-123 . So EntityID in this case would be the ‘host-123’ part.
If you want to change the content of the html report just edit contents of PreContent/Head variables. If you want to change the look of the html report , you have to edit css style. If you will modify the css table style, make sure you will also change the style name in the -replace section as well, because by default ConvertTo-Html creates a table tag without any style.
Enjoy!

:Update
I have added functionality to get-LicenseReport. If it will discover VC OPS, it will also put into displayname TOTAL and USED numbers for that license.

Advertisements

#powercli @ irc.freenode.net

While i am still struggling with writing the powercli course, i thought that anybody who is interested in real time chat (irc) , talking about powercli / scripts / etc… can join channel #powercli.
If you do not know how to connect to irc using na irc client(x-chat,mirc,irssi,etc…) you can join freenode webchat client at
http://webchat.freenode.net/
And select #powercli channel while joining. If you know irc, you know what/how etc 😉
See you there!

ESX/ESXi host in vCenter Server reports the error: Unable to apply DRS resource settings on host. The operation is not allowed in the current state

What helped in my situation:
service mgmt-vmware restart
on the service console
Official KB for this situation:
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1028351

Checking vmware tools upgrade policy using powercli, setting vmware tools upgrade policy

If you want to check what is the policy regarding upgrading vmware tools for vms in cluster, here it is 😉

get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'your-cluster').id | select name,@{N='ToolsUpgradePolicy';E={$_.Config.Tools.ToolsUpgradePolicy } }

If you want to query all vms in VC

get-view -ViewType virtualmachine | select name,@{N='ToolsUpgradePolicy';E={$_.Config.Tools.ToolsUpgradePolicy } }

Ok nice, we know what tools upgrade policy settings have our vms. Now we want to change this settings for example to ‘upgradeAtPowerCycle’. I am assuming that we want to change this setting only for vms that have ‘manual’ settings selected for toolsupgradepolicy. There is no need to force it on all vms.

get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'your_Cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' } | select name,@
{N='ToolsUpgradePolicy';E={$_.Config.Tools.ToolsUpgradePolicy } }

If you want to limit the vms for which we will be changing this setting, don’t forget that you still can filter them
|? {$_.guest.guestFamily -eq ‘windowsGuest’}
|? {$_.guest.guestFamily -eq ‘linuxGuest’}
|? {$_.guest.guestFullName -eq ‘Microsoft Windows Server 2008 R2 (64-bit)’}
And so on and on…
for example to apply this only for windows 2k8 r2 64bit, you would select them applying proper filter:

get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'your_Cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' } |? {$_.guest.guestFullName -eq 'Microsoft Windows Server 2008 R2 (64-bit)'} |select name,@ {N='ToolsUpgradePolicy';E={$_.Config.Tools.ToolsUpgradePolicy } }

As you can see by running get-view for vms using filter ‘Config.Tools.ToolsUpgradePolicy’ = ‘manual’ , we will select only those which have manual. Alright, now the upgrade part.
Right, so i could not find any cmdlet within powercli to do this. Still let’s not give up on this one yet 😉 What to do in this case ?
Onyx!
Download/extract onyx from vmware.com. While running onyx, select option to run using vSphere client. Make sure that onyx is recording from this moment

So we received vsphere api code that our vSphere client executed.

# ------- ReconfigVM_Task -------

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.changeVersion = "2012-08-01T08:26:54.934341Z"
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo
$spec.tools.toolsUpgradePolicy = "manual"

$_this = Get-View -Id 'VirtualMachine-vm-754'
$_this.ReconfigVM_Task($spec)
#-------------------

We need to apply this part of code to our vms that have wrong upgradetoolspolicy.
Let’s take our query part here first:

get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'your_Cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' }

Those will be our vms
Let’s make a loop for them

Foreach($vmview in get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'your_cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' } ) {
$vmview.name
}

Ok, loop with your get-view from vms is ready.

Now let’s take closer look at the configuration spec

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$spec.changeVersion = "2012-08-01T08:26:54.934341Z" 
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo 
$spec.tools.toolsUpgradePolicy = "manual" 

vim.vm.ConfigSpec
changeVersion
vim.vm.ToolsConfigInfo
toolsUpgradePolicy

If you want to read about those objects and their specification in vmware api use the above links. One thing that could be not so simple to understand is the ChangeVersion. The rest should be self explanatory i believe.
1. Create configuration specification object
2. Populate changeversion
3. In order to set the toolsUpgradePolicy property , we have to initialize ToolsConfigInfo object first.
4. Execute method on vsphere api vm object called ReconfigVM_task which takes as a parameter the specification object which we have just created.

ad.2 To be honest it will work even without giving this parameter. It is not necessary. Let’s say we are going to configure this settings, but meanwhile some evil evil evil administrator has changed some other settings in some particular vm on which we are running our loop. Now, as we do not know what has he changed(this evil evil administrator) then we might ask, do we still want to make our change ? IF we do not care about this, i guess there is no point in filling the changeversion at all. If we do, we have first assign to some variable current changeversion number, and then while reconfiguring our vm, give the changeversion on which we wanted to work. If meanwhile (evil evil evil) administrator did some reconfiguration of this machine, the changeversion number will be not equal to our number. Guess what will happen ?

Our change will not proceed as the number does not match. When that evil…il..l… administrator has reconfigured our vm, the changeversion number has changed to some 9999 for example…, but when we started our script, and wrote to variable the current change number it was 7777, so we are trying to do a spec with $spec.changeVersion = “xxxxxx7777” , and it fails because it’s not 7777 anymore but 9999.
Back to our loop 😉

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo 
$spec.tools.toolsUpgradePolicy = "upgradeAtPowerCycle" 
Foreach($vmview in get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'my_cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' } ) {
$vmview.ReconfigVM_task($spec)
}

And this is it 😉
Lines: 1-3 : We create specification object , we are putting information bout the toolsUpgradePolicy
Lines: 4-6 : In our loop where we query for vms that have manual option for toolsUpgradePolicy, we invoke method ReconfigVM_Task and giving it our $spec specification object
Like i mentioned earlier you could use here the changeversion if you want to be really sure. Where i work i have no evil evil evil admins 😉 No need to set it here ! but… if you have them , do it like this 😉

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo 
$spec.tools.toolsUpgradePolicy = "upgradeAtPowerCycle" 
Foreach($vmview in get-view -ViewType virtualmachine -SearchRoot (get-Cluster 'my_cluster').id -Filter @{'Config.Tools.ToolsUpgradePolicy' = 'manual' } ) {
$spec.changeVersion=$vmview.Config.changeversion
$vmview.ReconfigVM_task($spec)
}

One more example, few seconds ago i had to update this only on vms that were in text file so in order to do that:

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo 
$spec.tools.toolsUpgradePolicy = "upgradeAtPowerCycle" 
foreach ($vm in gc c:\vmlist.txt) {
$vmview = get-view -viewtype virtualmachine -Filter @{'name'=$vm} 
$vmview.ReconfigVM_task($spec)
}