PowerCLI Collection: PowerNSX DFW Synchronization Script

At several EUC projects we have a testing Workspace ONE environment(s) where desktop image and application packaging takes place, and a production Workspace ONE environment where only tested and approved items from the test are released. The environments are separated into vCenter/NSX managers. Actually, the production ones are even more separated in management and two or more desktop pods. All with their own NSX managers, and with there own management and rules. There is a need for a way to synchronize the approved NSX DFW rule set from testing to production, and between the production pods, without too much effort or human interference. We couldn’t find a cmdlet that does this all, so I wrote up the following script to synchronize the NSX configuration between pods: PowerNSX DFW Synchronization Script. We also have the same need for other projects, and I think it will benefit the next iteration of the NSXHorizonJumpstart I was working on earlier. You can go and grab the first version of the PowerNSX DFW synchronization script at https://github.com/Paikke/NsxSynchronization. In the remainder of this blog post, I will explain some further this script.

Continue reading PowerCLI Collection: PowerNSX DFW Synchronization Script

PowerCLI Collection: PowerNSX Horizon Jumpstart script ready to rumble

A few blog posts ago (https://www.pascalswereld.nl/2017/08/24/nsx-for-desktop-jumpstart-microsegmentation-with-horizon-service-installer-fling/) I wrote about using the Horizon Service Installer fling for adding Horizon services to NSX for Desktop. From that blog post, I have been continuing to evolve the services file with services, sections, and rules that will normally appear in an EUC solution with VMware products. I tried to maintain the services yml file to keep on working with the fling. Currently you still can, however I don’t know how long this will be.

Sections - This One

And this is because of another part I am working on, using PowerNSX for adding the services file to the NSX environment, and in turn, replace the need of the fling. You can read about me starting this at the post PowerCLI Collection: PowerNSX Desktop Jumpstart and process YAML (yml) config file. And this blog post is about explaining the first version to reach feature parity to the Horizon Service installer fling. The NSXHorizonJumpstart script now reads and adds to the complete yml file to NSX services, service groups, security groups and adds the Firewall sections with the firewall groups.

Rules Example

You can find both the services file as the current version of the script from the master branch at: https://github.com/Paikke/NSXHorizonJumpstart.

Continue reading PowerCLI Collection: PowerNSX Horizon Jumpstart script ready to rumble

Hello Hackathon VMworld EU!

This post first appeared as an article on the ITQ blog: https://itq.nl/hello-hackathon-vmworld-eu/

For the second year in a row, a hackathon was organized at VMworld Barcelona. The hackathon is mainly to provide the VMware {code} community with a fun and energizing space to “learn, code and connect” and create cool new things the world needs. And so we did 😉

If you’re new to the VMware {code} hackathons and expect only evil hacking, you are not completely wrong but:

  • Hackathons are open to experts and newbies alike.
  • Participants don’t actually need to know how to code to be a productive member of a team
  • Ideas don’t have to be limited to VMware products. But yeah, strangely enough, most ideas hovered around the large VMware product suite…

Continue reading Hello Hackathon VMworld EU!

PowerCLI Collection: PowerNSX Desktop Jumpstart and process YAML (yml) config file

In my last blog post (https://www.pascalswereld.nl/2017/08/24/nsx-for-desktop-jumpstart-microsegmentation-with-horizon-service-installer-fling/) I wrote about using the Horizon Service Installer fling for adding Horizon services to NSX for Desktop. From that blog post I have been evolving the services file with services and rules that will normally appear in an EUC solution with VMware products. Not just sticking with Horizon 7, but also getting App Volumes, UEM, UAG, and infrastructure components in the picture. And I will be continuing to evolve the services.

Another part I am working on is using PowerShell/PowerNSX for adding the services file to the NSX environment, and in turn, replace the need of the fling. And this blog post is about explaining the current structure from reading the yml file and using this information to check and add to NSX. For now, the services yml file will be maintained to keep on working with the fling.

Continue reading PowerCLI Collection: PowerNSX Desktop Jumpstart and process YAML (yml) config file

WebCommander Walnut Installation Walk-through

In a previous blog post from a far away history, I wrote about the WebCommander Fling (https://www.pascalswereld.nl/2013/10/30/webcommander/). Man that one is from 2013, I have been putting blog posts out there for a while now, hope you did find something useful on the blog…..
Anyhow back to this one. The WebCommander developer reached out in that previous post comment with a request to write-up a guide for WebCommander Walnut. I am writing it up as a walk-through to get it started and showing some output. If you would like some additions to the post, add some of the information your would like to see added to the post, or post questions / remarks and I will try to look if I can make some additions. But first….a little reminder about that commander out on the web…

What is WebCommander

WebCommander is a collection of web services around PowerShell and PowerCLI scripts. The interface can be used to provide users with scripts without them learning or knowing the PowerCLI commands. Or to give users access only to specific prepared tasks without giving them access to the web client (they still need to have permissions in the environment to do their operations). A great way in delegating specific tasks!

WebCommander was initially released and maintained as a VMware Fling. WebCommander was received very well by the community and saw the Fling being released as, and in turn moved to, an open source project on GitHub in 2014 (as announced on http://www.virtu-al.net/2014/09/03/webcommander-goes-open-source/).

The WebCommander project page can be found at: https://github.com/vmware/webcommander. This WebCommander version mainly uses XML with browser side transforming (XSLT). And when you hear version you know there might be another one, and yes there is WebCommander Walnut in a different branch.

WebCommander Walnut is to be used when :

  • you prefer JSON over XML,
  • combining commands in workflows for more or complex automation,
  • run local or cloud scripts (WebCommander Hybrid),
  • having a history,
  • 64-bit PowerShell,
  • more new features,
  • and a new User Interface


Take a look at WebCommander Walnut for yourself, go to GitHub: https://github.com/9whirls/webcommander_walnut

Installation Guide

Prepare the system:

Create a VM

Use Windows 2012R2 or Windows 2008R2 as the OS.

When using Windows2008R2 there are the following specifics:

  • Install .Net Framework 4.5.2. Needed for the installation of PowerShell v5 on 2008R2
  • Install PowerShell version 5

When using a fresh installation of Windows2012R2 install PowerShell Version 5.

For installation of the PowerShell version 5 install the Windows Management Framework 5.0 that can be downloaded as an update, or directly from https://www.microsoft.com/en-us/download/details.aspx?id=50395&ranMID=24542&ranEAID=TnL5HPStwNw&ranSiteID=TnL5HPStwNw-UGYM_0Jpr8QpSOcSBwTXfQ&tduid=(97816b302a22d507fcc1386696df4801)(256380)(2459594)(TnL5HPStwNw-UGYM_0Jpr8QpSOcSBwTXfQ)().

For Webcommander and PowerShell: Set-ExecutionPolicy Unrestricted -Force.

IIS Web-Server (including SubFeatures and Management Tools). Either use the Add Roles and Features GUI to install the Web Server role or use PowerShell:

Install-WindowsFeature Web-Server -IncludeManagementTools -IncludeAllSubFeature

PHP from https://php.iis.net. Click  ‘Install PHP now’ from the web site to download the latest version. Execute the downloaded exe to start the Web Platform Installer. Continue the installer with all the default options (you can change by clicking the options link) and accept to do the installation. The installer will download and install the prerequisites.

PHP IIS Installation

And click Finish when done.

Install MongoDB for commands history.

In short the procedure for MongoDB is:

  • Install Visual C++ Redistributable, you can get the 64-bit here: https://go.microsoft.com/fwlink/?LinkId=746572.
  • Download community version at: https://www.mongodb.com/download-center#community.

MongoDB download CEIt should offer you the correct release and OS.

  • Install via the downloaded msi. Select complete or customize if you want. Complete will install in the default locations.
  • Add the installation location as a system path environment. The default installation location is C:\Program Files\MongoDB\Server\3.4\bin.
  • Use your powershell window used to install IIS or open a command prompt
  • MongoDB requires a data directory to store all data. MongoDB’s default data directory path is \data\db. Create this folder using the following a command line
md \data\db
  • Or use another location to suit your needs.
  • MongoDB also requires a location to store logs. Create the log folder using command line
md \data\log
  • Create a config file location with
md \data\conf
  • And add a text file mongodb.cfg there (watch the view – file extensions there!)
  • Add the following to the cfg file and save:
                  destination: file
                  path: c:\data\log\mongod.log
                  dbPath: c:\data\db


  • Install MongoDB as a Windows service by running mongod.exe with –install parameter (as administrator!).
mongod.exe --config "C:\data\conf\mongodb.cfg" --install

If you get api-ms-win-crt-runtime-l1-1-0.dll is missing from your computer like this

System Error - Mongod

your Windows updates either screwed up or you have to install Visual C++ Redistributable. (Re)installing Visual C++ will mostly do the trick.

  • And now we will have a MongoDB service (use –serviceName and –serviceDisplayName to change to another name if you wish).
  • Start the MongoDB service with net start MongoDB.
  • Create database and collection in MongoDB for WebCommander by running the commands below:
    • exe
    • use webcmd
    • createCollection(“history”)
    • Mongo should respond with “ok”:1
  • Install the MongoDB powershell module:
    • In PowerShellv5
Install-Module Mdbc
    • Accept the installation of required components.

Install latest version of VMware PowerCLI (version 6.5.1 at time of writing):

  • Good thing is that version 6.5.1 does not require a msi installer anymore. You can install from the PowerShell Gallery via PowerShellGet (and the correct version of PowerShell, but we covered that one already):
Install-Module VMware.PowerCLI
    • Use –Scope CurrentUser to use only for this user and no admin permissions required

Install WebCommander:

Download the files from GitHub, for example for the zip file: https://github.com/9whirls/webcommander_walnut/archive/master.zip

Extract the zip and copy to c:\WebCommander. Or use your own location.

The Zip is composed of the following files and directories as subdirs of the master directory:
www/ – These are the files that need to be setup as the web service in IIS. _def is the file that is used to add the locations to the local scripts as defined in sources.json.
powershell/ …the local commands powershells
README.md – Readme file of the project
sources.json – Locations of local and remote scripts when wanting to use the remote script capability.
Note: that is, currently composed of… You never know what the future brings

Note: For scripts depending on your security policy Windows will normally block the files because they were downloaded from an external location, so you will have to unblock these files. Select the file – properties – and press the unblock in the security part at the bottom.

Open IIS Manager to configure the WebCommander site:

  • Remove the default site
  • Add a new site (in this case I used the administrator to connect as to know which user is running, don’t just copy but do what is appropriate for your environment)

Add Webcommandersite

  • select the WebCommander site and open the authentication feature
  • Enable Windows Authentication, and disable Anonymous.

Site Authentication

  • If we now open a browser we will see the initial page

Initial Localhost

When clicking on select a command we can only select the remote commands. use the source.json to define the local locations. For me it was fixed when removing http://localhost/ from the local configuration to read: “local” : “_def.json”,

This one could also help as the _def.json was also a bit empty. Go to c:\WebCommander\powershell\ and execute .\genDefJson.ps1 to recreate the definition json. We should use genDefJson when updating any ps1 scripts.

And voila local also shows up

WebCommander Local also


Test drive WebCommander

There are scripts for vSphere actions and Horizon view actions distributed with the Git.

I have seen the following error message pop-up: AuthorizationManager check failed. The following is witnessed, and changed:

  • For some reason the execution policy is back to restricted, Set-ExecutionPolicy RemoteSigned or Unrestricted.
  • with the ExecutionPolicy set to RemoteSigned or Unrestricted, this error may occur if the script or some of the other included scripts is still blocked. From the explorer right-click the file, select Properties and click Unblock. Go through all the files!

Let see if we can get some vSphere information:

  • Add Command vSphere (local)
  • Add the required parameters, go to method to select what you want to do. I just want to see, so listDatastore is my option.
  • And press the play
  • Go to the output if there is a Pass
  • And ….

Pass vSphere (local)

If we want to get rid of the PowerCLI Customer Experience Improvement Program (CEIP) warning in the output. Run the following in Powershell:

Set-PowerCLIConfiguration -ParticipateInCEIP $false

(optionally with -Scope User / AllUsers)

And that’s it for now

– Enjoy WebCommanding throughout the universe!

Sources: labs.vmware.com, virtu-al.net, github.com/9whirls/webcommander_walnut

PowerCLI Collection: Back up the ESXi configuration (and restore it)

I happen to run in to vSphere environments without Enterprise plus, or need to implement vSphere environments where for example budget is a constrain, and one or more other limiting factors are there for having Enterprise Plus.

When we don’t have a vSphere edition supporting Host Profiles, Auto Deploy and Distributed switches, we need to have to create a way to (multiple) host back up and restoring for a disaster recovery or such. It can be easy with PowerCLI…


In this post I want to write about the PowerCLI cmdlet to back-up a host configuration. We can use the Get-VMHostFirmware cmdlet to back-up the local configuration to a tarbal and save this on a disk location. The Get-VMHostFirmware takes the following options:

Get-VMHostFirmware -VMHost <host> -BackupConfiguration -DestinationPath <directorywithouttrailing\>

This creates a tarbal (in other words tar archive zipped in .tgz) bundle with the the filename configBundle-hostname.tgz. In this tarbal there is a manifest text file with the release level of the host, UUID, kernel options and user options.  There is also a state.tgz tarbal with the host state of the moment the tarbal is created. In this state tarbal is the local tarbal (getting lost a bit here ;-)) with local dump of the configuration of the host. Here you will find the files for creating local settings, vSwitch configurations, Resource Pools, Authentication, NTP, SSH etc. etc. etc.

Configuration Tarbal


We need to build a script around this to occasionally take the dumps from hosts, for example with a schedule task. For the current customer I’m doing this for clusters. An side effect to doing the configuration dump, is checking the configuration is the same across all hosts in the cluster. If you happen to have a tarbal with a different size there is probably something different about this host. This can be with a reason or not. But something worth to check.

The following script takes input in variables for the vCenter, cluster, Hostroot, Hostpassword (note: plain text!), Destinationpath (without trailing \). It furthermore creates a log file name with the cluster and date. In this logfile we put the hostname, buildnumber to get the exact patchlevel and output of the Get-VMHostFirmware.

# This script dumps the config of hosts in cluster
# to be used with restoring via Set-VMHostFirmware (and Set-VMHost -State ‘maintenance’)
# To be runned with a user with access to the environment
# Must be runned against hosts with same build, when needed use -f force to override

# Log is created where name and build is written with time stamp

$vCenter = “<vcenter server>”
$Cluster = “<clustername>”
$HostRoot = “root”
$HostPassword = “<password>”
$DestinationPath = “<driveletter:\pathname>”

# connect to vCenter
Connect-VIServer $vCenter

# Create LogFileName
$LogFile = “$DestinationPath\Dump-$Cluster-$(Get-Date -Format ddMMyyyy).log”

# Open Logfile with timestamp
Get-Date | Out-File $LogFile

Foreach($Hostname in (Get-VMHost -Location $Cluster | Select-Object name, build)){
“Dump and build for $Hostname” | Out-File $LogFile -Append
Get-VMHostFirmware -VMHost $Hostname.name -BackupConfiguration -DestinationPath $DestinationPath | Out-File $LogFile -Append
“Dump created” | Out-File $LogFile -Append

Disconnect-VIServer -Confirm:$False


Restoring the configuration when something goes amiss? Take a host at the same build number, either the one where some configuration change went wrong or reinstall a host in case of a complete disaster.

For restoring we need two cmdlets, one to put the host in maintenance and one to restore.

Set-VMHost -VMHost <host> -State ‘Maintenance’

And to restore:

Set-VMHostFirmware -VMHost <host> -Restore -SourcePath <backupfile complete pathname.tgz> -HostUser <user> -HostPassword <password>

The Sourcepath must include the driveletter\directory-tree\dumpfilename.extension.

Like said when restoring configuration the build number of the host must match the build number of the host that created the backup file. If this not possible, use the -force option to override this requirement. Recommended is having the same build number.

– Enjoy!

Sources: vmware.com

PowerCLI Collection: Reporting to HTML

Another PowerCLI for the collection, this time a returning job of creating reports of the environment with specific information requested by Service Delivery or other IT management report. Basic PowerCLI (and with that basic powershell) outputs to the screen, but there are several cmdlets to help and export to a different output; in this case the ConvertTo-HTML cmdlet for export to a nice HTML output. This output can be send to an output file or send via e-mail.

We want a report of VM’s and their power state, vCPU count and vRAM. And specifically resources in a defined cluster. In the final report this shows the cluster resources in the top part and a breakdown of the VM’s in a lower part.


ConvertTo-HTML takes the output of an inventory cmdlet (Get-VM for example) and converts the output to an HTML table. When using no formatting it actually creates a ready to use information HTML table. But with the management reports we also want to add some markup to show the information in a nice report.

Let see if we can get some of the wanted information. After we connect to a vCenter server:

$ClusterName = “Testlab”

Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object Name,PowerState,NumCPU, MemoryGB | Sort-Object Name | ConvertTo-HTML | Out-File “testlab.html”

We set the clustername in a variable, and use the Get-VM cmdlet to get information of the VM’s in this cluster. With Select-Object we choose the VM Name, the power state, the number of vCPU’s and the configured Memory. We sort on the name of the VM’s and pipe to Convert-HTML to get a nice HTML markup. We pipe this yet again to Out-File for saving the HTML that we can view from disk in a HTML browser.

What output do we have:


Wasn’t this what was asked? Yes and no, the report needs to be displayed in a nicer format (you know management ;-)) and we were asked some totals as well.

Get more results and a nicer view

More results? Yes part of the job was to get the cumulative vCPU and vRAM of the cluster.

For this we check the cluster for the specific counts and add this to a total variable (that has been declared at 0 and added with a +=).

#Get VMHost info for CPU and Memory totals
$countcpu = 0
$countmem = 0
$MemoryGBtot = 0
$cpu=Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object NumCPU
Foreach ($itemcpu in $cpu) { $countcpu += $itemcpu.NumCpu }

$memory=Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object @{Name = ‘MemoryGBtot’; Expression = {“{0:N2}” -f ($_.MemoryGB)}}
Foreach ($itemmem in $memory) { $countmem += $itemmem.MemoryGBtot }
# Now we have $countcpu and $countmem for cluster totals
# Memory should be formatted to two decimals which is #done via Expression N2.

Next up creating a HTML style and markup. We declare a CSS stylesheet with colors in the organization colors. And place box objects where we put the information, this we use in the HTML line to add HTML code and information into the ConvertTo-HTML. A small snippet, in the total script you can see it all together (this part does not work on it’s own).

# Style of the Report in Css
body {
font-family: Verdana, sans-serif;
font-size: 14px;
color: #666666;
background: #FEFEFE;
font-size: 30px;
font-weight: bold;
height: 50px;


And for some div boxes:

# HTML Markup
$PageBoxOpener=”<div id=’box1’>”
$ReportClusterStats=”<div id=’boxheader’>ClusterTotal $ClusterName</div>”
$ReportClusterHeader=”<table><tr><th>vCPU Count</th><th>Memory GB Total</th></tr>”
$BoxContentOpener=”<div id=’boxcontent’>”
$ReportGetVmCluster=”<div id=’boxheader’>VM Details $ClusterName</div>”

Create some Div boxes with the styles as we defined and markup in the CSS.

We use these declarations in the report making:

# Create HTML report
$MyReport = ConvertTo-Html -Title “VM Details Report” -Head “<div id=’title’>VM CPU and Memory Reporting</div>$br<div id=’subtitle’>Report generated on: $(Get-Date)</div>” -Body ” $Css $PageBoxOpener $ReportClusterStats $BoxContentOpener $ReportClusterHeader <tr><td>$countcpu</td> <td>$countmem</td></tr> $PageBoxCloser </table> $br $ReportGetVmCluster $BoxContentOpener $GetVmCluster $PageBoxCloser”

The report is created as $MyReport with a ConvertTo-HTML to create a HTML format and with – title to give a title instead of HTML Table. in the Body we put the $Css style, the box parts and the collected information.

This creates the report in a nice markup as shown in the following screenshot:


To save or to send, that’s the question

Or both of course, if you want. We can use the earlier mentioned Out-File cmdlet to send pipelined output directly to a text file rather than displaying that output on screen. Well, as we will be directing the output to a variable we don’t see the output on screen, but we still can use this cmdlet to save to a file. A nice declaration of the file name and pipe the HTML report to Out-File.

$fileNameReport = “$OutputPathReportVMDetails-$ClusterName-$(Get-Date -Format o | foreach {$_ -replace “:”, “.”}).html”

and add | Out-File $fileNameReport to the report $MyReport line (add at the end after closing “) when wanting to save

FileNameReport marks up the filename with a clustername and date stamp.

We can also use an e-mail to inform our whomever it is that is interested in the report. For this will need some declaration of from and to adresses, mail title, a SMTP server. We send our HTML marked up report as body.

function Send-SMTPmail($to, $from, $subject, $smtpserver, $body) {
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true

Write-Host “Sending e-mail” -foregroundcolor “red”
# Sending the report
Send-SMTPmail $EmailTo $EmailFrom “$ClusterName Capacity Report $(Get-Date)” $SMTPSRV $MyReport

We create a Send-SMTPmail function where we need input in the form of a to, from and subject, a SMTP server where the host where the script is run is allowed to relay and a $body. When we call this function we add this values via declared variables. The last is the Report that we put in an HTML markup.

Putting it all together

And to conclude we put this all together in the following script. I left out the saving as I want the report to the e-mail. The code is still in there. Here we go:

# Settings
# vCenter Connection details
# Name of the Cluster on which you need to run the report
#Location where you want to place generated report
$OutputPath=”<output path>”
# Set the SMTP Server address
$SMTPSRV = “<SMTP Server>”
# Set the Email address to recieve from
$EmailFrom = “<from email address>”
# Set the Email address to send the email to, comma separate when using multiple reciptients
$EmailTo = “<to e-mail address>”

Write-Host “Connecting to vCenter” -foregroundcolor “red”
Connect-VIServer -Server $vCenterFQDN -User $vCenterUser -Password $vCenterPass

# Style of the Report in Css
body {
font-family: Verdana, sans-serif;
font-size: 14px;
color: #666666;
background: #FEFEFE;
font-size: 30px;
font-weight: bold;
height: 50px;
font-size: 11px;
#main {
background: #F8F8F8;
border: 1px solid #DCDCDC;
font-family: Arial, sans-serif;
padding: 5px 20px;
position: relative;
z-index: 20;
display: block;
height: 30px;
color: #777;
text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
line-height: 33px;
font-size: 19px;
background: #fff;
background: -moz-linear-gradient(top, #ffffff 1%, #eaeaea 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eaeaea));
background: -webkit-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
background: -o-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
background: -ms-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
background: linear-gradient(top, #ffffff 1%,#eaeaea 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=’#ffffff’, endColorstr=’#eaeaea’,GradientType=0 );
0px 0px 0px 1px rgba(155,155,155,0.3),
1px 0px 0px 0px rgba(255,255,255,0.9) inset,
0px 2px 2px rgba(0,0,0,0.1);

table td, table th {
border:1px solid #FA5858;
padding:3px 7px 2px 7px;
table th {
table tr.alt td {
# End the Style.

# HTML Markup
$PageBoxOpener=”<div id=’box1’>”
$ReportClusterStats=”<div id=’boxheader’>ClusterTotal $ClusterName</div>”
$ReportClusterHeader=”<table><tr><th>vCPU Count</th><th>Memory GB Total</th></tr>”
$BoxContentOpener=”<div id=’boxcontent’>”
$ReportGetVmCluster=”<div id=’boxheader’>VM Details $ClusterName</div>”

Write-Host “Getting Cluster Details for CPU and Memory totals” -foregroundcolor “red”
#Get VMHost info for CPU and Memory totals
$countcpu = 0
$countmem = 0
$MemoryGBtot = 0
$cpu=Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object NumCPU
Foreach ($itemcpu in $cpu) { $countcpu += $itemcpu.NumCpu }

$memory=Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object @{Name = ‘MemoryGBtot’; Expression = {“{0:N2}” -f ($_.MemoryGB)}}
Foreach ($itemmem in $memory) { $countmem += $itemmem.MemoryGBtot }
# Now we have $countcpu and $countmem for cluster totals
# Memory should be formatted to two decimals

Write-Host “Getting VM information for $ClusterName” -foregroundcolor “red”
#Get VM infos
$GetVmCluster=Get-VM -Location (Get-Cluster -Name $ClusterName) | Select-Object Name,PowerState,NumCPU, MemoryGB | Sort-Object Name | ConvertTo-HTML -Fragment

# Create HTML report
# and export to HTML out file
# Use $fileNameReport = “$OutputPathReportVMDetails-$ClusterName-$(Get-Date -Format o | foreach {$_ -replace “:”, “.”}).html” and | Out-File $fileNameReport when wanting to save
$MyReport = ConvertTo-Html -Title “VM Details Report” -Head “<div id=’title’>VM CPU and Memory Reporting</div>$br<div id=’subtitle’>Report generated on: $(Get-Date)</div>” -Body ” $Css $PageBoxOpener $ReportClusterStats $BoxContentOpener $ReportClusterHeader <tr><td>$countcpu</td> <td>$countmem</td></tr> $PageBoxCloser </table> $br $ReportGetVmCluster $BoxContentOpener $GetVmCluster $PageBoxCloser”

# Disconnect
Write-Host “Closing vCenter connection” -foregroundcolor “red”
Disconnect-VIServer -Confirm:$false

function Send-SMTPmail($to, $from, $subject, $smtpserver, $body) {
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true

Write-Host “Sending e-mail” -foregroundcolor “red”
# Sending the report
Send-SMTPmail $EmailTo $EmailFrom “$ClusterName Capacity Report $(Get-Date)” $SMTPSRV $MyReport

Notice: at this time the script takes a plaintext password.

Add your environment entries to the settings variables and your good to go.


You can add more or specific required cmdlets and information to the report to get what you want. Or you could go on the community and find an already made reporting scripts out there. Maybe not the best way to learn, but you can check in the source what these guys and gals have been up to. A great one for example, vCheck is highly recommended to get an overview report of your environment. This script can be found at: http://www.virtu-al.net/vcheck-pluginsheaders/vcheck/.

– Enjoy!

Sources: Microsoft.com powershell cmdlet library, vmware.com PowerCLI reference, community.vmware.com for examples.

PowerCLI Collection – Adding SNMP settings to ESXi hosts

It’s been a while since I posted a PowerCLI script, but since I started a new project one of my first tasks was to help out and setup SNMP to monitor ESXi hosts from Nagios (which is a great product BTW).  So a new script for the collection.
O yeah, a little notice as I’m not always working with scripts there are probably better scripts or better scripters out there that will be more efficient. I have chosen to use a script and not a killer one liner, just to make clear what is happening and for others to use and understand what is happening.
If you have tips and leave a comment to help me, no problem I would appreciate that and probably any reader out there as well.

SNMP Scripts

To change the SNMP settings we need some information about what need to be set. For this example I will set the readonly community, trap destination and trap community name.  I have set up the script to take input from the user for these values.

I’m using two scripts, one to change a single hosts and one to change hosts connected to vCenter in a specific cluster. The main difference is that the single host script takes a input for the ESXi hostname, while the cluster script takes vCenter and cluster name (which can be easily changed to another object location for example replacing Get-cluster with nothing or Get-datacenter) and loops through the hosts. There is a host connection needed to change the SNMP values for that host, this is what is done first in the loop. If not direct connected to the host, the SNMP settings will not be changed. This goes for the single host script as well.

For SNMP there are two cmdlet’s relevant Get-VMHostSNMP and Set-VMHostSNMP, respectively getting the SNMP values from the host and setting the values. First enable SNMP with Set-VMHostSNMP to set value –Enabled to true. The SNMP settings value are done via two more Set-VMHostSNMP cmdlets, first setting the Read only community with –ReadOnlyCommunity option and the other to set a SNMP trap target and communityname (-Target and -TrapCommunity).

The rest of the comments in the script should tell what action is done at that time. If not, you know where to find me….

I have chosen not  to hardcode or use files that store passwords, again this is user input with the Get-Credential cmdlet. For the ESXi hosts in the cluster script this is stored to a variable to be used in the host loop. The condition is that the hosts use the same credentials.

The Singlehost script:


$ESXHost = Read-Host “ESXi hostname to change:”

$trapDestination = Read-Host “SNMP Trap Mgmt server hostname: “

$trapCommunity = Read-Host “Trap Community Name: “

$ReadOnlyCommunity = Read-Host “Read Only Community Name: “

# Running no need to change under this line

# Connect to the ESX server

$viServer = Connect-VIServer -Server $ESXHost -Credential (Get-Credential)


# Get snmp

$snmpConn = Get-VMHostSnmp -Server $defaultViServer


# Enable snmp

Set-VMHostSnmp -HostSnmp $snmpConn -Enabled:$true


# Set read-only community

Set-VMHostSnmp -HostSnmp $snmpConn -ReadOnlyCommunity $ReadOnlyCommunity


# Set trap target and community name

Set-VMHostSnmp -HostSnmp $snmpConn -AddTarget -TargetCommunity $trapCommunity -TargetHost $trapDestination


#disconnect from ESX server

Disconnect-VIServer -Server $viServer -Confirm:$false


The cluster script with a host loop:


$vCenterFQDN = Read-Host “Enter vCenter FQDN: “

$ClusterName = Read-Host “Enter Cluster name of hosts that will need to be changed: “

$trapDestination = Read-Host “SNMP Trap Mgmt server hostname: “

$trapCommunity = Read-Host “Trap Community Name: “

$ReadOnlyCommunity = Read-Host “Read Only Community Name: “


# Running no need to change under this line

# Connect to the vCenter server

Write-Host “vCenter credentials”

$viServer = Connect-VIServer -Server $vCenterFQDN -Credential (Get-Credential)


# Get all hosts in vCenter managed Cluster so we can cycle thru them

$Hosts = Get-Cluster -Name $ClusterName | Get-VMHost


# Get ESXi Host credentials

Write-Host “ESXi host credentials”

$EsxCred = Get-Credential


# Cycle through each host

ForEach ($VMHost in $Hosts)


                # Need to connect to ESXi itself

                $esxconnect = Connect-VIServer -Server $VMHost -Credential $EsxCred


                # Get snmp object

                $snmpConn = Get-VMHostSnmp


                # Enable snmp

                Set-VMHostSnmp -HostSnmp $snmpConn -Enabled:$true


                # Set read-only community

                Set-VMHostSnmp -HostSnmp $snmpConn -ReadOnlyCommunity $ReadOnlyCommunity


                # Set trap target host and trap community

                Set-VMHostSnmp -HostSnmp $snmpConn -AddTarget -TargetCommunity $trapCommunity -TargetHost $trapDestination


                # Disconnect-VIServer

                Disconnect-VIServer -Server $esxconnect -Confirm:$false



#disconnect from ESX server

Disconnect-VIServer -Server $viServer -Confirm:$false

Just copy and save the scripts. And when your execution policy allows it, execute them.

–          Enjoy!

WebCommander – VMware Lab Flings

An other post in the VMware Lab Flings series. This time a fling that I was re-introduced to when following the PowerCLI session at VMworld Europe.

So what’s is WebCommander?

Webcommander is a GUI framework around PowerShell and PowerCLI scripts. It gives an easy to use web interface. This can be used to provide users with scripts without those users knowing the PowerCLI commands, or to give users access only to specific prepared tasks without giving them access to the web client (they still need to have permissions to do there operations). A great way in delegating specific tasks!

What’s needed, WebCommander Architecture?

WebCommander is a package that uses or needs the following components:

– Windows Server 2008 or 2012.
– PowerShell v3 or v4.
– vSphere PowerCLI.
– IIS (minimal v8).
– PHP 5.

The installer also needs .Net Framework 3.5 to be installed on the system. And of course the WebCommander package from the VMware Fling site. This can be found at http://labs.vmware.com/flings/web-commander. At that site there is also a install instruction manual.. Setup of WebCommander is done by installing above apps and running the Setup powerscript supplied with the WebCommander installer. Here you add the default password to connect to ESXi hosts. Default user is set to root, default guest user is set to administrator (you can select them in several of the actions).

Before running the setup script you have to change the Execution policy to unrestricted first…


Change the default user to Adminstrator in IIS Manager after installation is finished. 


After installing and checking your installation you can open the default interface.


There are several categories of PowerShell/PowerCLI included with the installation. You have the option to do Active Directory, View Broker, Guest, VM and vSphere actions. Actions for adding, removing, start/stop/restart operations, renaming and taking snapshots are included.
Of course you can add (or remove) you own specific organisation tasks. The how to is also included in the installation manual.

When running a command a screen is shown where you can add the VC or ESXi host FQDN/IP, and select the users.


After running the results also show an URL with the command just run. You can give this URL to your user when you want only access to this command. Great feature!. Unfortunately the supplied password is in plain text in the URL (in this case root……).


– Enjoy commanding your environment! Thank to the developers of this fling.

PowerCLI collection – Changing PSP

On storage controllers in combination vSphere 5.x multi path IO, path selecting policy should be Round Robin (always check if your storage supports this). When receiving the LUN it happens that those PSP are defaulted to Fixed. You can change the PSP policies of all attached storage with this PowerCLI oneliner (Round Robin in the example):

get-cluster -Name “Cluster” | Get-VMHost | Get-ScsiLun -LunType disk | Where-Object {$_.MultipathPolicy -ne “RoundRobin”} | Set-ScsiLun -MultipathPolicy “RoundRobin”

A little caution when you have storage from mixed storage providers (mixed storage controllers without a SVC,Vplex or such layer).

What does this one do:

– get-cluster -Name ”Cluster”; Retreives the cluster information for Cluster. This command can be replaced with get-datacenter. And pipe’s this information to:

– Get-VMHost; retreives the hosts information (one by one in from the cluster). The output is piped to:

– Get-ScsiLun – Luntype disk | Where-Object {$_.MultipathPolicy -ne “RoundRobin}

Get de Scsi Lun of type disk en checks if this object current policy is not equal with Rond Robin. The output is piped to:

– Set-ScsiLun -MultipathPolicy “RoundRobin. The Lun found with previous part is changed to a RoundRobin policy.

The policies can be set to:

RoundRobin, MostRecentlyUsed, Fixed or Unknown.