Ebook PowerCLI
Ebook PowerCLI
Automation, scripting and PowerCLI are words that most people working with VMware products know
pretty well and have used once or twice. Everyone also knows automation is a great tool to have
in your tool belt. The problem usually is that getting into automation and scripting appears daunting
to many people who feel like the learning curve is just too steep and they usually don't know where
to start. The good thing is you don't need to learn everything straight away to start working with
PowerShell and PowerCLI. Once you have the basics down and have your curiosity tickled,
you will learn what you need as you go... a lot faster than you thought you would!
This eBook doesn't contain absolutely everything about automation, but it serves as an ideal starting
point explaining what need to know to get started. Just like a mechanic’s starter kit, you can't build
a car engine with it but you can do the basics to call yourself a budding mechanic. This book contains
the first few steps of a long stairway paved with cmdlets, properties and methods and a little more
than that.
PowerCLI: An Aspiring Automator’s Guide was first released in 2019 and received widespread acclaim
from the community. The aim of the original release was to deliver solid foundation skills for anyone
to get started with PowerCLI and PowerShell. In this second edition, a full revision of the original text
has been undertaken as well as updated app features and additional content on actions that go
a bit more in-depth compared to just how to use the standard built-in cmdlets.
Here is an overview of the additional content you can expect to find in this edition:
• Reporting on snapshots
Requirements ......................................................................................................... 14
Credential store....................................................................................................... 21
List All Powered-on Virtual Machines with their Folders in Cluster "Management" ........... 25
List Virtual Machines and the Hosts they are Running on .............................................. 25
PSScriptAnalyzer ..................................................................................................... 34
Functions ............................................................................................................... 34
Preparation............................................................................................................. 40
Requirements ......................................................................................................... 49
Progress bar............................................................................................................ 62
Browsing ESXCLI...................................................................................................... 85
Help() ..................................................................................................................... 86
Invoke() .................................................................................................................. 87
CreateArgs() ............................................................................................................ 88
Let's get to know PowerCLI a little better before we start getting our hands dirty in the command
prompt. If you are reading this, you probably already know what PowerCLI is about or have a vague
idea of it but if not, we’ll quickly get you up to speed. After a while working with PowerCLI, it becomes
second nature and you can't really imagine life without it anymore. You then forget that many IT folks
out there don't use PowerCLI or simply haven't heard of it. Thanks to VMware's drive to push
automation, the product's integration with all of their components grew bigger and better over
WHAT IS POWERCLI?
As opposed to what some may think, PowerCLI is not a software but a command-line and scripting
tool built on Windows PowerShell for managing and automating vSphere environments. It used
to be distributed as an executable file to install on the workstation. An icon was generated that would
essentially launch PowerShell and load the PowerCLI snap-ins in the session. This behaviour changed
back in version 6.5.1 when the executable file was removed and replaced by a suite of PowerShell
modules to install from within the prompt since they were added to the PowerShell Gallery
These modules provide the means to interact with the components of a VMware environment
resume, there are many compelling reasons why one should learn PowerShell, and PowerCLI
Virtualization is generally associated with cool words like system architecture, design and
troubleshooting of complex environments. While this is definitely true, the operational side of it
is often forgotten because it is a lot less attractive and consists mostly of monotonous and time-
consuming tasks. Unfortunately, it has to be done and in a vast majority of cases the vSphere
administrator will wear both the project work hat and operational work hat. These repetitive
operations include boring tasks like datastore and snapshots monitoring, VM creation, host
implementation, you name it. All these little things that if not done could quickly ruin your day.
PowerCLI will allow you to automate most of them, be it in the command prompt or in a script that
can be run in a schedule task. People are often surprised when they see the time they could save
and use it to do more interesting things (like writing more scripts to automate even more!).
When something goes wrong, 9 times out of 10 it is due to human error. Obviously, you will never be
free from the possibility of a hardware component failing or a bug in a firmware, but these are events
you cannot prevent. What PowerCLI can help you with is consistency and avoiding silly mistake. What
if you detached the wrong LUN in the vSphere client because you read "b" instead of "d" and 15 VMs
go down… This wouldn't have happened if you gathered the Lon ID from a datastore object in PowerCLI.
For example, what if your colleague configured a standard port group with VLAN ID 148 instead of 1048
Every company running a vSphere infrastructure should have a solid agent-based monitoring system
like Zabbix or Nagios and enable vCenter alerts at the very least. Complementary solutions like
vRealize Operations Manager can greatly improve your visibility of the environment, but as great
as they are, these come at a cost and may not allow reporting on the information you are after.
Once again, PowerCLI can increase your reporting and alerting capabilities to fill the gaps in your
monitoring. You will be able to create well formatted HTML reports served on a web page or sent
via email.
get the information you are after or change a configuration much quicker than in the vSphere client.
The most common example is automating the deployment of a large number of VMs which we will
POWERCLI 12.2
The latest version of PowerCLI (at the time of publication) is PowerCLI 12.2. This version brings
a number of new features as well as support for newly released products and new product versions:
• HCX management
• Namespace Management
• vSAN management
• DRaaS management
• vSphere 7.0
• DRaaS
• VMware Horizon PowerCLI module now supported for macOS and Linux
• PowerShell versions
This version also includes a new VMware Cloud Services Management module that contains 11 new
recommend that you always check that they work correctly with the new version before updating
a few weeks down the line where you realize a script hasn’t been running properly.
You can find the procedure on how to update PowerCLI in the Downloading and Installation section
of this book.
REQUIREMENTS
Before you begin, find all the requirements and interoperability information about PowerCLI
in the compatibility matrix for PowerCLI to make sure your configuration is supported. Head over
to VMware code, select your version of PowerCLI and open the associated compatibility matrix.
You will need .NET Framework 4.7.2 and above. Since version 11.2.0, PowerCLI is officially supported
on PowerShell version 4.0 and above as well as Windows 10 / Server 2012 R2 and above.
Note that PowerCLI is now also available on Linux and macOS thanks to PowerShell Core.
BEFORE INSTALLING
Prior to installing the latest version, you need to uninstall any version of PowerCLI older than 6.5 R1
from your system. You can uninstall it like any installed software in "Programs and Features".
INSTALLING
The installation procedure has been simplified since the modules have been added to the PowerShell
The modules will be automatically downloaded and stored in the correct folder.
Note that you can use the -Scope parameter to make the PowerCLI modules
available to AllUsers.
UPDATING
Although it will work, it is recommended to avoid using the Update-Module cmdlet to update
PowerCLI as it will not remove any files rendered obsolete by the new version. Therefore,
• Next, install the new version by following the install procedure outlined previously
INSTALLING
If your system does not have Internet access you will need to download PowerCLI as a zip file from the
VMware website and copy the modules into your modules folder. Unlike many of the VMware products,
• Transfer the file to your offline machine and copy all the folders present in the zip to your
PowerShell Modules folder. Again, choose the location accordingly to make it available
UPDATING
To update PowerCLI, delete the existing PowerCLI module folders and follow the procedure
outlined above.
EXECUTION POLICY
Execution policies are a security mechanism that determines if files can be loaded in PowerShell
such as config files, modules, scripts… You can find your current execution policy by running:
Get-ExecutionPolicy
You may need to change the default execution policy to be able run scripts you wrote. Unless a GPO
changed the default setting, you won't need to if you are on a Windows Server OS. However, it is required
it to RemoteSigned with:
Some highly secured environments may require that all the scripts (even those written in-house) are
digitally signed by the enterprise PKI. This means the execution policy must be set to AllSigned if not
already done via GPO. In which case you will have to digitally sign your scripts prior to running them.
CONFIGURING POWERCLI
Apart from the execution policy mentioned previously, there is no configuration required before
using PowerCLI. However, it is worth talking about a few recommended settings that could be useful.
You can use the Set-PowerCLIConfiguration cmdlet to amend the configuration of PowerCLI.
Once again, a "-scope" parameter will allow you to modify the settings for the session, current user
or all users. The Session scope has the highest priority, and the All Users scope has the lowest of the three.
Note: Any setting configured with the Session scope will not be persisted after
Other parameters allow you to configure settings such as whether or not to use the system proxy,
display warnings about deprecated elements, increase the timeout of commands (which defaults
Let’s take a look at two of the most common parameters you’ll use here.
-DefaultVIServerMode
than one vCenter server. This parameter defines whether you can connect to more than one
vCenter at a time. It is important because a mistake can quickly occur if you have forgotten that you
have two active vCenter sessions in your PowerShell prompt, for example. You typically won’t have
problems with Get commands where you’re just retrieving information, but you REALLY need to start
paying attention once you start working with Set, Remove…etc…etc in this situation.
-InvalidCertificateAction
This parameter defines the behaviour of the Connect-VIServer with regards to the vCenter certificate.
This parameter does not apply to you if the installed vCenter certificate is signed by a trusted root CA.
If the certificate isn’t valid (expired, self-signed, not trusted, etc.) the default setting is to display a warning
when you establish the connection. You can change this behaviour with the following parameter:
a few different ways thanks to the various parameters it offers. You can connect with a Session ID,
The most common way to connect is to specify the IP or FQDN of the server and use the current
Connect-VIServer vcsa.test.local
You can retrieve the list of the connected vCenter servers by displaying the content of the global
here: this is a variable). This means that if a network interruption occurs, for instance, and the session
is no longer connected, the variable will remain populated, and in which case you will need to reconnect,
causing the variable to be overwritten with the new active session. This object contains information
about the server and the session such as the session ID, user, version and build… If it cannot connect
with the current user, a credential popup appears to let you enter a different user/password combination.
You can also add the credential parameter, so you don’t have to wait for the current user to fail
the connection:
I would also like to point out a nifty little parameter of this cmdlet that displays a list of the recently
connected vCenter servers. You don’t see this one too often, but it can be very useful if you manage
a bunch of different servers. You can then select the one you want to connect to with its number
Connect-VIServer -menu
20
CREDENTIAL STORE
By default, when connecting to a vCenter server, PowerCLI will check what is referred to as the
Credential Store. Similar to the Windows Credentials Manager, the Credential Store saves sets
of host credentials you have at your disposal. There are 2 main benefits to using the Credential Store:
1. Credentials are encrypted and stored securely (never put credentials in your scripts!)
Use the Credential Store if your domain user has no access permissions to vCenter.
To use the credential store, you will need to save credentials into it, as shown below
"Don'tL00kAtM3!"
Once it is stored you can just connect to the vCenter with the usual command:
Connect-VIServer srv-vcenter.domain.pri
POWERCLI OBJECTS
Just like with traditional PowerShell, you will be constantly working with PowerShell objects. Any object
acquired with a PowerCLI cmdlet will be assigned the specific type associated with their nature
(virtual machine, datastore, GuestID…). You’ll discover more of them as you go deeper into PowerCLI.
PowerCLI includes a mechanism called OBN selection that allows you to refer to an object by its name
instead of passing the actual object through the pipeline or as a parameter. It simplifies and makes
• Traditional Selection
• OBN Selection
DATA STRUCTURE
Data structure is not something you have to worry about when initially working with PowerCLI.
However, it is important to be aware of the object types to understand what is going on behind
the scenes. For that reason, we won't go too deep into the theory and summarize instead for
There are four category types for objects in PowerCLI, and each serves a different purpose:
1. Managed Object Types - Make managing objects possible. They can contain both properties
and methods, meaning they can hold values (VM name, Data objects) or run an action (Start VM).
2. Data Object Types - As the name suggests, they hold data about the object. They can contain
the MoRef (which allows you to get a managed object) or other data objects (mac address,
set and nothing else. They are usually reserved for runtime statuses such as the power state
of a virtual machine that can only be "powered on", "powered off" or "suspended".
4. Fault Types - Provides information about errors. It also contains a data object (property)
OBJECT STATE
Generally in PowerShell, it is very common to store objects in variables rather than running the cmdlet
every time to retrieve it. It saves time as a variable name is usually shorter to enter than a cmdlet,
and there is no processing time because it is already stored locally. When doing so, you are storing its
state at this point in time. Meaning that if a property were to change on the server-side object, it would
not be reflected on the object in the variable. You would then need to run the cmdlet again to
VMHost
------
ESX-Host-1
(As you can see it is still showing the host it was previously running on)
VMHost
------
ESX-Host-1
5. Update the variable and display the host value once again:
(The variable now reflects the actual value of the server side object)
VMHost
------
ESX-Host-2
You can see how this could cause confusion on systems managed by several administrators,
with reporting scripts showing outdated data about the environment, for example.
Note: This is true for all kind of objects, not only virtual machines.
if you are fairly new to PowerShell as well. If you don’t have a test lab to practice with, I recommend
being on the safe side and sticking with Get commands for a little while. Build your confidence and
get comfortable with how it works before moving on to cmdlets that change the state of objects like
the opportunity of using these simple commands to show you a few concepts applied to the prompt.
To get a complete list of the PowerCLI cmdlets, type the following command (I recommend to use
IN CLUSTER "MANAGEMENT"
The best place to start in PowerCLI is to list the VMs in the environment. This cmdlet is probably one
of the most commonly used. It includes a lot of information about your servers. Similarly with traditional
PowerShell commands, you can use the pipe " | " to narrow down the results to only what you are after,
for example:
| Select Name,Folder
In this example we list the cluster named "Management", then we list the VMs registered in this cluster,
then we filter only the ones that have the property "Powerstate" (Enumerated object) set to "PoweredOn".
Virtual machines include lots of useful properties in their "base" object (extended properties excluded -
Another simple cmdlet that you’ll find useful display more about PowerCLI objects in context this time.
As mentioned previously, virtual machine objects contain many interesting properties, including
the host they are running on. In PowerCLI, hosts are referred to as VMHost.
Name VMHost
---- ------
Test-vm ESX-Host-2
The interesting thing with the VMHost property is that, even though the name of the host is displayed,
it actually contains a VMHost object. Meaning you can obtain information about the host by working
with the VMHost property - no need to retrieve the object with the Get-VMHost cmdlet.
In other words, the following two commands return the same result. In the first command, we retrieve
the VMHost using the cmdlet on the VM object In the second, we display the VMHost property of
the VM object.
$VM | Get-VMHost
$VM.VMHost
Of course, this is not only true for VMHost but for most object types like clusters, resource pools,
Note: When using variables you can’t use $Host as it is already a PowerShell automatic
Now that we touched base on a few basic cmdlets, it is time to start poking around in the PowerCLI
objects so you can be able to find what you are after by yourself. There are essentially two ways
of discovering PowerCLI object properties. You can either look it up in the online documentation
VMware provides a reference guide listing all the cmdlets and properties in PowerCLI. It’s very useful
as it consolidates all the information about cmdlets, parameters and object types. For instance,
• Expand the “All Types” tab and find the “VirtualPortGroup” link. It is sorted alphabetically
so pretty convenient.
• After clicking the VirtualPortGroup link, you’ll get information about the type.
1) The Virtual Port Group Object be returned as a property of these PowerCLI objects
cmdlets. If you click on the cmdlet link you will be redirected to its documentation page.
2. PowerShell Prompt
Now if you don’t want to get out of your PowerShell prompt (and be a real automator), you can find
• Start by looking for the cmdlet that will help you find the information using Get-Command.
Then filter the cmdlets matching Get*portgroup* (case insensitive) that are provided
As you can see, several cmdlets match the filter, but a quick Get-Help on each of them will tell you
The output will list the properties and methods of the object. You will see basic information
on them such as object type for properties, object type returned by a method, arguments
ESX-Host-1
$PortGroup | Get-Member
The benefit of using the prompt over the online documentation is that you get to display the value
of the properties. This is useful for objects whose property names are not obviously clear at first glance.
As you may already know, just like with traditional PowerShell, only a selection of properties is displayed
when running a cmdlet like Get-VM. This behavior is dictated by special XML files in PowerCLI.
Below, you can see the values of the properties shown in the Get-Member output. Of course, you will
Note: Remember that select as shown above is the shortened version of Select-Object.
This screenshot also depicts the warning messages about object deprecation. You can turn these
contains a nicely formatted set of properties that most people will be interested in about a VM,
and you get more properties when you pipe it in “| select *”. But that’s not all - as you may have
realized not everything is available at first glance. Those cmdlets only return a fraction of the data
the ExtensionData property which is different from the others (highlighted in yellow). That property
offers a convenient way of interacting with the underlying API and returns a lot more methods
and properties. In Use Cases we will stick to properties, but we will experiment with more later.
Note: The Get-View cmdlet returns the same results as the ExtensionData property,
31
To access this “hidden” information, display the content of the ExtensionData property on a VM object.
The properties that make up the list contain categories in which you will find other sub-categories etc.
Using this process, you have access to information such as hardware devices, file types locations,
guest related information retrieved by VMware tools, and more! Some might require a little more
digging than other to find, but it is easy enough to browse through the properties.
Now that we introduced PowerCLI and started using it, let's take a small break to talk about script
quality. When writing scripts, regardless of the language used, it is important to ensure that it is clean,
efficient, flexible and as short as possible. Should you fail to do so, you will make it harder for others
and your future self to understand your scripts and ensure consistency. I will cover a few topics here
that may not apply to everyone but are considered best practices. You will find your own style
of scripting and figure out what works best for you as you gain more experience in this area but
SHORTER IS BETTER
One thing that makes a script enjoyable to read is its optimization. Try to avoid repeating the same
operation several times. For instance, you can usually make it shorter and more optimized by using
a loop that specifies said operation only once. Start by writing the script so it does everything you
want it to do, and then go through the code and look for opportunities to optimize it, hence making
it cleaner. It might take a bit more time when writing the code but you’ll be thankful you did it. Trust me!
NO HARDCODED VALUES
This one has been repeated many times already, but it’s very important. Scripts should always avoid
hard-coded values. It makes them difficult to maintain. It is sure to break any time something is changed
in the environment, and no one will remember there is this one script that uses the old value.
Now sometimes you may need to specify values inside a script for whatever reason, and if you
• If you write a library of scripts/functions spread across several files, it might be a good idea
to consolidate all your statically defined variables into a csv or xml file that is imported
at the start of every script. That way when you change a value, you will change it globally.
• Populate variables dynamically as much as possible through the use of vSphere tags, naming
conventions, etc. The point is to design your script so it survives changes in the environment.
ERROR HANDLING
This part is maybe the least fun of script writing but it is a necessary evil. Including error-handling
in your functions will make them a lot safer to use and easier to debug. This can be achieved in a number
of ways but the “Try, Catch, Finally” triad is probably the most convenient one. This method is used
PSSCRIPTANALYZER
If you really want to make sure your scripts follow Microsoft’s guidelines, you can use PSScriptAnalyzer
to check the quality of your code. I usually don't go that far but it is there if you need it.
FUNCTIONS
One way of making your script leaner and cleaner is through the use of functions. Similar to a subroutine
or a procedure in other programming languages, a function is a bit of code that can take parameters
(arguments) and return some results. Writing a function may seem daunting at first, but you’ll soon
get used to it. Some people think it’s a complicated programmer technique when it’s actually very
Function Hello {
Param ($WhoAreYou)
Write-host “Hello $WhoAreYou”
}
This is obviously a silly example as it serves no purpose but the reality is not too far from it
If the same section of an operation is repeated several times throughout a script, these can be made
into a function that is called in one line instead of writing all the operations again. Should a change
need to be made to this section, amending the content of the function will update it everywhere
in the script, hence reducing the risk of forgetting one of them during a script update.
By placing each main activity inside a function that is parameterized and tested, the execution script
becomes an orchestration script that calls the functions one after the other, making it shorter and
easier to debug.
PowerShell and PowerCLI offer a wide selection of cmdlets but some operations might not be covered
by them or you might want to have the possibility to make something quicker and easier to do.
For instance, you could have a function that decommissions a datastore properly by un-mounting
it and detaching the LUN on all the hosts. By putting them into your own PowerShell module,
you can have your own functions available in the prompt! The possibilities are endless!
There is a lot to say about functions, in fact they could be the topic of a book all by themselves!
For that reason, we will only skim the surface of what you can and should do with them. For more
information, there is a plethora of great content online that talks about them in greater detail.
Below are a few guidelines to write clean functions and help others, as well as your future-self,
For cleaner functions, always use the param() block and put the parameter segment below the title,
not on the same line. Doing so will allow you to add attributes to your parameters. Attributes are
a great way to lock down your function to ensure it is used properly. In this manner, functions can
Function Convert-DSToCanonical {
param(
[Parameter(Mandatory = $True,ValueFromPipeline=$True)]
[VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl[]]
$Datastore
)
Attributes apply conditions to parameters to ensure they is used the way they're intended.
Lots of attributes are available that deal with a variety of needs. Among them, you can lock a parameter
to a specific type, make it mandatory or not, allow only a certain set of values, allow one or multiple
values, set a default value, validate a parameter with a bit of code, give it parameter aliases, prevent
sets of parameters to be used together, and much more! Find an extensive list on Microsoft Docs.
[CmdletBinding(DefaultParameterSetName=1)]
param(
[Parameter(Mandatory=$true,ValueFromPipeline =
$True,position=0)]
[string]
$Destination,
[parameter(position=1)]
[ValidateRange(1,65535)]
[int]
$Port,
[parameter(parametersetname=2)]
[Alias('t')]
[switch]
$Continuous,
[parameter(parametersetname=1)]
[Alias('n')]
[int]
$Count = 4
It is always best to try and stick to Microsoft's guidelines to make your functions as intuitive as possible.
Follow the verb-noun nomenclature and use approved verbs (Get-Verb). That way your scripts will
have a more “PowerShell feel” to them. For instance, use Get-VMHost instead of Retrieve-VMHost.
Using indentation greatly helps in understanding the structure of the code and increases clarity.
Any script that is not correctly indented will require extra effort to make sense of what it does
and makes troubleshooting more difficult. And please, avoid mile-long one-liners. Don’t be that guy.
Here is another one that has been repeated since well before PowerShell existed. Include as many
comments as possible to help others, or your future self, understand your code. Note that you
If your function is going to return something after execution, make it PowerShell object and not strings.
Returning object will allow you to use them for other purposes. And in the same spirit as the nomenclature,
use common names for the property names of the objects returned (like VMHost). That way, you can
I grouped these two sections together because they often work hand in hand. I usually write a script
that produces a report in HTML format and then store it on a web server or send it via email.
TASK SCHEDULING
We have all been creating scheduled tasks for a long time now and everyone should be familiar with it.
Here we are covering a nifty convenient way to execute PowerShell scripts in scheduled tasks. Those scheduled
tasks can be used for many things like a simple snapshots listing, an advanced VM inventory or a more
PREPARATION
• It needs to be a Windows machine that has at least access to vCenter Server on port 443
• Install the PowerCLI modules at the local machine level or user profile level of the service
• A domain user on the AD is better but local users also work. We’ll name it svc-task-ps in this example
• Open the Local Security Policy console by typing secpol in windows search
• Launch a PowerShell session as this user and set the execution policy if necessary
• Create the folder anywhere on the server that makes sense to you (C:\Scripts for instance)
• Log in the vSphere web client and select the vCenter object
• Apply permissions to svc-task-ps. Try and restrict them to the bare minimum. For instance,
if the scripts are only doing reports, you can give the user "Read-Only" access permission
• Open a PowerShell session as svc-task-ps on the machine that will run the scheduled tasks
Connect-VIServer vcsa.test.local
• Make sure you can perform some of the command you will need in your scripts
The idea here is to make scheduling scripts as flexible and easy as possible. To achieve this, we have
a batch file that runs a PowerShell script of the same name in the same folder and prints its execution
in a log file. It is convenient because whenever you need to schedule a new script, just copy this batch
file in the new folder, rename it like the ps1 file and you're done!
C:\Scripts\ListVMs.ps1
$VCENTER = "vcsa.test.local"
$CSVFile = C:\Scripts\VMList.csv
Connect-VIServer $VCENTER
Get-VM | Export-Csv $CSVFile
3. Executes a ps1 file with the same name as this bat file (%~n0) in PowerShell and sends
C:\Scripts\ListVMs.bat
CD %~dp0
SET runDate=%DATE:~6,4%_%DATE:~3,2%_%DATE:~0,2%
• Configure the Trigger tab as you want. You can leave it empty for this test as we can run
• In the Action tab leave the default settings and select the batch file
in the General tab to confirm and run the task to make sure that it works
HTML REPORTING
Reporting is an important part of managing and automating an environment. Not only does it give
you a wider view, it also takes jobs off your hands by scheduling it. You won't forget small tasks and
you can use your time on more interesting or important concerns. While most of the vSphere
monitoring can be done through vROps (vRealize Operations Manager), many companies
don't have the budget for it or simply want quick and dirty email reports.
PowerShell offers a convenient way to convert objects into HTML code with a single cmdlet
"ConvertTo-HTML". Once again, we will take the example of a VM inventory that we store as an HTML
Let's start from the beginning, first we need to retrieve our VM inventory, then convert it to HTML,
Connect-VIServer vcsa.test.local
TIP: Add style to your HTML to create borders in your reports. Write your CSS in a $Style
variable that you pass in the -Head parameter of the ConvertTo-Html cmdlet. For instance, you
could use this to add a background color to the front row according to the status of an object.
There are many other interesting parameters in ConvertTo-Html. Have a look at its documentation
EMAIL REPORT
• I suggest you populate a set of variables with the information relative to your email environment.
That way you can re-use it for your next script and only change some values.
cmdlet. This is called Splatting and gives flexibility when adding/removing parameters
in a clean fashion.
Note 2: The From field is dynamically populated with the name of the server as address prefix.
Send-MailMessage @Email
WEB SERVER
If you want to have the report available at any time in your web browser, all you need to do is to export
it to the web server's www folder with the .html extension. Note that in order to achieve this, the user
running the task must have write permissions to the www folder. Also, I suggest you add the date and
time of the execution in the web page to know at which point in time this information was retrieved.
"<h1>$(get-date)</h1>"
$File = "\\srv-web\www\ListVMs.html"
Not the most beautiful report as you can see but it gets the job done. Once you have a framework
down for nicer reports, you can start experiencing with more advanced scripts and maybe build
While a large number of administrative tasks can be achieved using the built-in vCenter alerts
and the web client, others can only be done through the use of the API (which PowerCLI leverages).
On top of that, some actions may take a painfully long time when performed manually in the vSphere
In this section, we will look at how you can improve your daily admin operations and make the RUN
Deploying virtual machines is a day-to-day task, but it can take a lot of time and IT departments are
understandably eager to automate this process. Here we are going to show you how to deploy several
virtual machines based on the details stored in a CSV file. Keep in mind that this is merely an example -
REQUIREMENTS
These requirements are only true for the purpose of this script because I wanted to keep it as simple
as possible. You can make them irrelevant with a few changes to the code.
• A CSV file including the details of the VMs to deploy. The file should include the following columns:
◦ VMName
◦ Template
◦ IP
◦ Mask
◦ Gateway
◦ Dns
◦ Cluster
◦ Datastore
◦ Portgroup
VMName,template,IP,mask,gateway,dns,cluster,datastore,portgroup
test-vm-1,W2016Template,10.1.1.5,255.255.255.0,10.1.1.254,10.1.1.1,
Cluster_test,vsandatastore,Test-PG
test-vm-2,W2016Template,10.1.1.6,255.255.255.0,10.1.1.254,10.1.1.1,
Cluster_test,vsandatastore,Test-PG
The script below does exactly what we just mentioned. I used comments (in green) to define sections
ranging from A to H that will be explained independently so you can refer to the script.
Note that this script is sequential, meaning it does things one by one. You can make this kind of scripts
run faster by using jobs running concurrently but this is out of the scope here.
######################## SECTION B
# Verifying that the input is correct and that the VM name is
not already in use.
$VmTemplate = Get-Template $CSVRow.Template
$VmPortgroup = Get-VirtualPortGroup -Name $CSVRow.Portgroup
$VmDatastore = Get-Datastore $CSVRow.datastore
$VmCluster = Get-Cluster $CSVRow.Cluster | where
DrsAutomationLevel -ne "manual"
if (Get-VM $CSVRow.VMName -ErrorAction SilentlyContinue) {Throw
"A virtual machine with name $($CSVRow.VMName) already exists"}
######################## SECTION C
# Cloning existing custom specs to a temporary one
$CustomSpec = New-OSCustomizationSpec -OSCustomizationSpec Test-
win -Name (New-Guid | select -ExpandProperty guid) -Type
NonPersistent
######################## SECTION D
# Configuring the network settings in the custom specs
$CustomSpec | Get-OSCustomizationNicMapping | Set-
OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $CSVRow.IP
-SubnetMask $CSVRow.mask -DefaultGateway $CSVRow.gateway -Dns
$CSVRow.dns
######################## SECTION E
# Deploying the VM
$NewVM = New-VM -Template $VmTemplate -OSCustomizationSpec
$CustomSpec -ResourcePool $VmCluster -Datastore $VmDatastore -Name
$CSVRow.VMName
######################## SECTION F
# Connecting the correct portgroup
$NewVM | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected
$true -Confirm:$false -NetworkName $CSVRow.portgroup
######################## SECTION G
# Starting the VM
$NewVM | Start-VM
}
######################## SECTION H
Write-Error $_.Exception -ErrorAction stop
}
SECTION A
As part of the error handling to implement, we want the script to stop should any error occur. In order
to achieve this ,we use the TRY, CATCH blocks that offer a convenient and clean solution. However,
non-terminating errors are not caught by the CATCH block and the cmdlets we use here generate some
for input check purposes. The $ErrorActionPreference variable is a preference variable that determines
how PowerShell responds to a non-terminating error. In this section we set the variable to “Stop”
Then we use the Import-CSV cmdlet to import the content of the CSV file as a collection of PowerShell
Finally, we start a foreach{} block that loops through every record of the CSV file (shown above).
SECTION B
This section serves two purposes. It retrieves vSphere inventory objects for later use and breaks
the execution if the object cannot be found. That way we can ensure that the user didn’t make a typo
in an object name or chose a VM name already in use. Because it is located inside the TRY{} block,
any error that occurs will be caught by the CATCH{} block (more on that in section H).
Here we are essentially cloning an existing customization specifications file into a temporary one.
The type NonPersistent means that the cloned custom specs are only available in the current PowerCLI
session; it doesn’t appear in the UI and is destroyed when the session is closed. Because it is
SECTION D
We now need to configure the cloned custom specs using the input from the CSV file. In order to do so,
we have to use yet another type of object with the Get/Set-OSCustomizationNicMapping cmdlet.
We then use the input of the CSV file to set the properties.
SECTION E
The ground work is done so we can now deploy the VM with the cloned custom specs, template and
resources configured in the CSV (datastore and cluster). The prompt will stay on hold for the duration
of the deployment with a progress bar before moving on to the next step. Once the VM is created
SECTION F
By default, the VM created sits on the same network portgroup as the template it originates from.
Any hardware changes (CPU, Memory, disk, etc.) should be done here, including the portgroup that
SECTION G
The VM is now here and configured and it is time to power it on. Once the VM boots up, it will start
the guest customization following the cloned custom specs we created earlier. So be patient as it
SECTION H
If any error occurs within the TRY{} block, it is intercepted and processed in the Catch{} block.
Here the $_ variable contains the error encountered which Exception property contains the description
of the problem. Ending up here means the script will display the error and stop its execution.
There are different schools of thought as to how error handling should be performed. Some prefer
to break the current loop and move on to the next record to process, others like me prefer to stop
everything so I can do my debugging and check my inputs. No right or wrong answer here, a good
Note: If you’d like to see another PowerCLI Deployment Sample, we have a great article
It wasn’t easy selecting which use case to cover and which to leave aside as so much can be done in
PowerCLI. However, I couldn’t leave out vSphere tags because they offer so much versatility and can
greatly simplify automation. They are similar to attributes, like metadata you apply to vSphere objects
in the inventory, allowing you to create organizational groups that would otherwise not exist
Tags that are related to each other are assigned to a category that can only contain one type of object
tags (virtual machine, host, datastore, etc.). Categories have a cardinality property that defines
whether more than one tag in the category can be applied to an object.
The Entity types you can use for a tag category are the following: All (default), Cluster, Datacenter,
When setting the Cardinality, "Single" means that only a single tag from this category can be assigned
CREATE TAGS
Create as many tags as required and assign them to the category. You can also use the Get-Tag cmdlet
to list them.
Now tag the VMs. As you can see below the VM object can be fed from the pipe to the cmdlet.
Tag Entity
--- ------
Test-Servers/Test-Server-DB srv-test-db
Tag Entity
--- ------
Test-Servers/Test-Server-Web srv-test-web
It is now possible to retrieve vSphere inventory based on the tags assigned to them.
The -Tag parameter is available on all vSphere object types that can be tagged:
The former lets you create a portgroup quickly on all hosts that are part of the vSwitch. However,
standard switches are often used due to license restriction or simply personal preferences. With that
in mind, adding portgroups to standard vSwitches on a number of hosts can get slightly frustrating
This can be done a lot faster using PowerCLI instead of the web client.
I stored the vSwitches in a variable to make the command shorter and easier to read.
Note: That the -VirtualSwitch parameter does not accept multiple objects. So, you cannot
specify an array of values using the named parameter. However, you can use it in the pipeline
as it means each record is processed one after the other. You can find in the help page
of the cmdlet which object accepts multiple values if there is "[ ]" next to its type.
58
MONITOR VM CPU USAGE IN NEAR REAL TIME
In this use case, we are going to play a little bit with the progress bar capabilities of PowerShell
and discover the PowerCLI cmdlet to get performance data. We want to monitor the CPU usage
of a VM in near-real time, which is every 20 seconds in vCenter. First, we will learn how to retrieve
the correct stats about a VM, and then we will see how to present it graphically.
Some resource usage values like CPU can be retrieved quicker in the
ExtensionData.Summary.QuickStats property. However, here I will demonstrate the use of the Get-Stat
RETRIEVE STATS
PowerCLI includes the Get-Stat cmdlet that returns statistical information available on a vCenter
server. The Get-StatType cmdlet allows you to list all the available counters on an entity.
• List the counters that can be retrieved and find the one you need (in this case it is the first one):
cpu.usage.average
cpu.usagemhz.average
cpu.ready.summation
mem.usage.average
mem.swapinRate.average
mem.swapoutRate.average
mem.vmmemctl.average
mem.consumed.average
mem.overhead.average
disk.usage.average
disk.maxTotalLatency.latest
net.usage.average
By default, vCenter stores a limited number of counters as the interval increases to save space in the database.
The latest 5 minutes period contains the real-time counters with an interval of 20 seconds.
If you add the -RealTime switch to the command below you will get a lot more available counters,
just like you would in the performance tab of the vSphere Web Client.
REAL-TIME
A large number of records is returned with an occurrence every 20 seconds. We notice that there
are MHz per core (instance number), MHz global (no instance number) and percent global.
PROGRESS BAR
It may look like a gadget to some, but the Write-Progress feature of PowerShell is pretty neat to build
visual depiction of information inside the prompt. The progress bar is usually used to track installation
or script steps, but you can trick it into displaying any kind of values you want formatted as a bar,
provided you can make it a percentage. For our particular case, in order to make it act like a real-time
• Make a loop that runs every 20 seconds (interval for real-time counters)
while ($true) {
sleep 20
}
while ($true) {
sleep 20
}
while ($true) {
sleep 20
}
• Run the code and enjoy the view. It only refreshes every 20 seconds but it's the best you can do
We can also add other counters to the progress bar stacked under the VM name. We need to make
a few changes to the code. And to make things more interesting we will make a function out of it.
Progress bars can have an ID and a parent ID. You can stack multiple progress bars under another one
by specifying a Parent ID. In the example below we added the memory usage that we stacked with
Below is the modified code with added comments. Notice the ID and ParentID parameters.
Function Invoke-VMMonitor {
param(
[parameter(position=0,Mandatory=$True)]
[VMware.VimAutomation.ViCore.types.V1.Inventory.VirtualMachine]
$VM
)
# Wait interval
sleep 20
}
}
of objects that are stripped or mirrored across multiple hosts to achieve redundancy. When a host goes
down for planned maintenance or following a failure, the VMs that have objects stored on this host
a rebuild of these objects is initiated to restore the compliance with their storage policies.
overhead during the processing. To avoid such an event occurring during a planned maintenance,
it is usually a good idea to increase the duration of the countdown. In the next example, we are going
to demonstrate how to do this using PowerCLI to make it quicker and easier than with the UI.
• To change an advanced setting, we need to retrieve the AdvancedSettings object of the host
• Then we can modify the setting by using the Set command. Some operations like this one
require a confirmation in order to proceed. You can bypass this interaction by adding
Note that in VSAN 6.7U1 it is possible to change this setting within the VSAN configuration pane in the
advanced options. It is specified that you should wait for at least 180 seconds before proceeding with
(VCHA) at the vCenter level. Much like your average firewall clusters, there is an active node and a passive
In order to set up VCHA you have to clone the vCenter appliance to the passive and witness nodes
while in VCHA configuration mode. The postgres database is then replicated to the passive node while
the witness acts as a tie breaker and doesn’t hold any data.
most of time.
Note that in this section, we won’t describe how to set up VCHA with PowerCLI. It is possible but it’s
something you will probably only do a few times now and then so there is little value in automating it.
Therefore, it’s preferable to retain more control by doing it manually and focusing your automation
efforts on more repetitive tasks that will actually save you time.
VCHA clusters must always be destroyed before performing certain operations such as replacing
certificates. If you use this feature in production, always check the relevant documentation before
You may sometimes need to get information about your VCHA cluster, for example, to find out which
node is the current active one or to check its status. Unfortunately, PowerCLI offers no cmdlets out
of the box to interact with VCHA. Thankfully, the required methods are exposed on the vCenter object
which we can leverage to build our own cmdlets. Let’s find out how.
We already worked a little bit with properties and methods in this book, especially when using
• Property - A single value of a certain type or a collection of objects. In our analogy, the color
of the car could be a property of value “red” for instance. It could also contain a property
“engine” which will sport a collection of objects with the components that make up the engine.
• Method - The actions that can be executed on an object. For our car, a method could be
In the VCHA case, because there are no built-in cmdlets, we will have to use properties and methods
The methods and properties in relation to vCenter HA are exposed in the following property
This function will display the status of the vCenter HA cluster. It contains the health state as well
THE SCRIPT
Function Get-VCHAState {
param(
[VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl]
$DefaultVIServer = $DefaultVIServer
)
USAGE
The use of this script is as simple as it gets, just run “Get-VCHAState” and you will get an output.
If you don’t specify the parameter, the current vCenter to which you are connected will be used.
You can specify it in the parameters if you are connected to multiple instances.
everything is fine (in sync). This is a simple output straight from the “GetVchaClusterHealth().
it could be interesting to include this in whatever reporting framework you are using to keep track of them.
As mentioned previously, a vCenter HA cluster is made of 3 nodes; active, passive and witness.
While the witness node will always remain on the same virtual machine, the VMs that assume
the active and passive role can switch. The means the vCenter VM that once was the passive node
may be the active one today, so don’t just assume VC02 is the passive node if you want to do
You can verify which one is active in the vSphere client, though as usual, why not do it instantly
in PowerCLI and skip the browsing through the UI. You can with this script.
THE SCRIPT
Function Get-VCHANodes {
param(
[VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl]
$DefaultVIServer = $DefaultVIServer
)
# Obtain the VCHA object that contains the methods and properties.
$failoview = get-view
# Executes the method to display the runtime info on the VCHA nodes.
$failoview.GetVchaClusterHealth().runtimeinfo.nodeinfo
}
USAGE
The use of this function is similar to the previous one. Execute “Get-VCHANodes” without a parameter
to retrieve information about the VCHA cluster of the currently connected vCenter or specify one
in “-DefaultVIServer”.
The output will show you the role associated with the IP address on the private network used
for vCenter HA. From here you can easily find which VM is active and which one is passive.
GOING FURTHER
FailoverClusterManager” so this is where you would start if you wanted to do more with it.
to see what’s inside and what you can do with it. As usual, unless you only work with “Get” cmdlets,
it is recommended that you practice in a lab environment if possible and never experiment in production.
• getClusterMode – Displays the current mode of the VCHA cluster. "enabled", "disabled"
or "maintenance"
• initiateFailover - Commences a failover from the active node to the passive node.
The cluster mode must be in the "enabled" mode and all cluster members must be present.
○ $True: Failover initiated after the active node flushes its state to passive, no data loss
○ Enabled: State replication enabled, automatic failover if the active node fails
FailoverClusterConfigurator” in which you will find the ones associated with the administration
of VCHA (configure, create nodes, destroy, deploy, etc.). As mentioned previously, you might have
a use case for automation here but it’s usually more sensible to perform the initial config and main
the use of RDM disks (Raw Device Mapping). In this case, there is no -flat.vmdk file that contains
the volume’s data, instead it acts as a mapping file that redirects the SCSI commands directly
A common use case is Microsoft Failover clusters. Because there are multiple Windows server nodes
in a failover cluster, the volumes must be locked by only one of them, which would not work with
a traditional virtual disk as VMFS (Virtual Machine File System) would intercept the SCSI locking
It’s a rather long introduction to get to the point that RDMs are a special breed of disks which can be
tricky to keep track of. In this section we will explain how to quickly get information on the raw disks
in the environment. This will prove useful when assembling an inventory or performing any kind
In order to identify the VMs that have an RDM mounted, we can use the “Get-HardDisk” cmdlet with
the disktype parameter to display the parent object (VM). We also use the “-Unique” switch to avoid
getting the same VMs for those that have more than one RDM multiple times.
Finding information about LUNs and RDMs in the vSphere client is cumbersome and takes many
clicks to get what you need. Using PowerCLI, you can achieve the same result, and indeed even more,
in a lot less time. We are going to build a function that display details about the RDM disk and the SCSI
controller it is connected to. Now we are basing this function on VM objects but you could choose
to set the parameter on disk objects, LUNs, or whatever else. You can customize the function to fit
your environment.
THE SCRIPT
Function Get-VMRdm {
Param(
[parameter(position=0,ValueFromPipeline=$True,ValueFromPipelineByPro
pertyname=$True,Mandatory=$True)]
$VM
)
Process {
VM = $V.name
Name = $Disk.name
CapacityGB = $Disk.capacitygb
Naa = $Disk.scsicanonicalname
Node = "$DiskBus"
File = $Disk.filename
Persistence = $Disk.Persistence
DiskType = $Disk.disktype
CompatibilityMode =
$Disk.ExtensionData.Backing.CompatibilityMode
DiskMode = $Disk.ExtensionData.Backing.DiskMode
Sharing = $Disk.ExtensionData.Backing.Sharing
Controller = $Controller.deviceinfo.summary
ControllerSharedBus = $Controller.SharedBus
}
}
}
}
}
USAGE
This function will display information about the RDM disks connected to the VMs specified
in parameter. You can run it against multiple VMs and remember to use the pipe “ | “.
In the example below you will see that the VM “Test” has one RDM disk connected. You get to find
the NAA (Network Addressing Authority) of its LUN, which type of controller it is, as well as the controller
and node ID. These details are particularly useful when working with storage admins to extend,
be interested in adding this to your inventory to get a holistic view of all your RDMs.
hosts. This won’t apply to everyone as some prefer to ensure configuration compliance with the use
of Host Profiles but others who have standard licenses for instance may get some peace of mind
If you are in the latter category, VMware thought about you with the “Get/Set-VMHostFirmware”
cmdlets. Although this may appear a bit confusing at first with the Firmware keyword, this will enable
In the example below we trigger a backup of a host and store the file in the current folder. That’s actually
all there is to it - it’s a very simple process! The file is created and named after the host in .tgz format.
Host Data
---- ----
192.168.10.11 C:\Users\xavier\configBundle-192.168.10.11.tgz
In order to automate the process, we can now wrap this cmdlet into a scheduled task that will keep
the last x files tidy in a backup location. Now there are plenty of ways to go about doing this so we
The script is formatted as a function so it can be executed against several vCenter servers.
However, it could be turned into a regular script if you only have one vCenter for instance.
To use it you will need to specify a destination where to put the backup files (-BackupLocation),
the number of files to keep (-FileRotation) and the name or IP of the vCenter server.
Note: No credentials are specified in this script, which means the user that will run it
THE SCRIPT
Function Backup-ESXiConfig {
param (
[ValidateNotNullOrEmpty()]
[string]
$BackupLocation,
[ValidateNotNullOrEmpty()]
[int]
[ValidateNotNullOrEmpty()]
[string]
$vCenterServer
)
TRY {
} CATCH {
Note that there is a “Catch” component that will display the exception. This can be useful for
troubleshooting purposes if you redirect the output of the script execution to a log file.
Restoring the host’s configuration is just as easy as backing it up. Once the basic configuration of the
host is completed (IP address, etc.) and it is placed in maintenance mode, you can restore a backed-up
Note: The build number and UUID of the host must match the ones of the host on backup file.
However, you can force to ignore a UUID mismatch with the “-Force” switch. Once again ensure that
REPORTING ON SNAPSHOTS
Ever since VMware offered this feature - which was a long time ago - snapshots have been infamous
for causing confusion among administrators who are not well versed on virtualization. Now you
probably heard a colleague or a contractor stating with a certain sense of passion that “Snapshots
are not backups and shouldn’t be kept for too long!” Well, they are right. If you are serious about
protecting your data, always use a proper backup solution such Altaro VM Backup to back up your
virtual machines.
A snapshot records a frozen state of a VM at a certain point in time, which it can be reverted to if desired.
This could be useful in a number of scenarios for example a botched software update or simply testing
some obscure software or configuration that you don’t want persisting in the guest system. The problem
with snapshots is that they will grow in size if you don’t remove them quickly. In which case it can cause
enough free space. You don’t want to leave snapshots laying around your environment which
In this section, you’ll learn how to report on the snapshot situation and make recommendations based
on the age and size of the snapshots. We recommend against removing the snapshots automatically
You can report on snapshots in a HTML report like we have previously described in this book.
Here we will send a table in HTML format in an email when certain thresholds are reached.
THE SCRIPT
if ($Table) {
Once the script is running and monitoring the snapshots, every time a snapshot is discovered to be too
Note: You can change the thresholds in the script. The ones already in place are rather
conservative in terms of space. Once again, the user that runs the script (scheduled task)
space to work with and that the overprovisioning ratio isn’t getting out of hand is paramount
to an environment that leverages thin disks - which is most of them. While thin provisioning
is very useful to optimizing the use of your storage, it is important to keep an eye on it as all your
thin provisioned VMs would end up in IO failure situation if the datastore were to fill up at 100%.
Here is a useful script that provides a little bit extra information than you would otherwise get which
will help you make reasoned decisions with regards to VM placements should you not use datastore
clusters. It provides a quick and clear overview of the provisioning of the datastore with a percentage,
whether it is expandable or not and how many VMs are running on it.
THE SCRIPT
Function Get-VMFSDatastore {
param(
[parameter(position=0,ValueFromPipeline=$True,ValueFromPipelineByPro
pertyname=$True)]
[VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.VmfsDatast
ore[]]
$Datastore = (Get-Datastore | where type -eq VMFS)
)
Process{
ForEach ($DS in $Datastore) {
if ($ds.type -eq "VMFS") {
If you don’t specify a datastore in the $Datastore parameter, all the datastores will be processed.
You can use the pipe “ | “ with this function. Because there are more than 4 fields, the output
is displayed as a list. You can get a table by using “| format-table” at the end of the command.
As you can see, we get a lot more information here as we now know the provisioning ratio,
how many VMs are running on it, if there is unused capacity on the Lun (expandable), etc.
Here is an example of the function with the “out-gridview” display format (alias ogv) with no given
ESXCLI is a command line tool embedded in ESXi that allows administrators to performs various
administrative tasks and manage many aspects of the host with a fairly easy-to-use syntax. ESXCLI
commands are particularly useful when troubleshooting situations where traditional means are not
available, for instance. These can be run when logged in the interactive shell (DCUI), in SSH sessions,
Even though PowerCLI offers more than 600 cmdlets, there is still a large number of tasks that can
only be performed with ESXCLI. To fill that gap, VMware provided the powerful Get-EsxCLI cmdlet that
allows you to run ESXCLI commands from within PowerCLI. It can be a very useful cmdlet when used
It used to be a bit convoluted to use in previous versions as it worked with positional arguments.
This means that you had to specify every single argument in the right order, including NULL where no value
was required. The -V2 switch was introduced in PowerCLI 6.3R1 and makes Get-EsxCLI a lot easier to use.
BROWSING ESXCLI
To start using ESXCLI, run the cmdlet with the -V2 switch, a vSphere host as parameter and store
it in a variable that we will name $EsxCLI. Then display the content of the variable. As you can see,
RUNNING COMMANDS
While browsing through the ESXCLI categories is fairly straightforward, running commands differs
slightly. Everything is done through the use of methods that we will describe below.
HELP()
This first one is pretty self-explanatory. You can run this method against any ESXCLI object in PowerCLI
just like you would in ESXCLI. Take the VIB subcategory, for example, and let's compare it with
traditional ESXCLI.
$EsxCLI.software.vib.help()
SSH
INVOKE()
This method runs the ESXCLI command against the vSphere host. It is comparable to pressing "Enter"
in the SSH prompt. Commands that don't require arguments can be run by simply typing ".Invoke()"
at the end of the command. For instance, to display the installed vib packages:
Note: I added "| Format-Table" to compare it with esxcli in SSH, so you will see that the output
is very similar.
$EsxCLI.software.vib.list.Invoke() | Format-Table
SSH
CREATEARGS()
This method is to be used when you need to invoke an ESXCLI command with arguments. This is where
the introduction of the -V2 switch changes things. It is now really easy to create an argument object
and populate each of its properties before passing it to the Invoke() method. For this example,
As you can see, only one argument is available to specify the name of the uplink (nicname):
PS C:\> $Arguments
Name Value
---- -----
nicname Unset, ([string])
PS C:\> $Arguments
Name Value
---- -----
nicname vmnic0
$EsxCLI.network.nic.get.Invoke($Arguments)
realize that even the 16GB of memory in your laptop isn’t as plentiful as you thought when you bought
it. Sure, it’s easy enough to a start workstation and spin up a vSphere host but once you add a vCenter
appliance it already starts getting toasty. If you want to add more hosts and VMs you better not be too
vCenter simulator (VCSIM) is a useful tool that has been around for a while now that enables practice
without the need for a full-scale environment. It was actually first introduced in the vCenter Server
Appliance way back in version 5.1! It was aimed at simulating changes in a vSphere environment.
due to a lack of resources. Someone going by the alias Nimmis wrapped VCSIM inside a container
I’ve decided to cover this container in this book because it is incredibly handy and can get you started
with PowerCLI even if you have a 10-year-old netbook with 4GB of memory as all you need is a basic
Linux distro to run a docker host. We will quickly show you how to get a docker host running and deploy
DOCKER ENGINE
• Add Docker’s GPG key. This is optional but then you don’t have to worry about the validation
of the signatures
key add -
• Now we need to install the Docker repository. Note that we set it to stable but you could choose
test or nightly
Once this is done the docker engine should be ready to run some containers.
The great thing about containers is that they are very quick and easy to spin up.
• Run the following command to deploy the VCSIM container and it will execute in “vCenter mode”:
You should get an output such as the following. You will see that the container information
is automatically downloaded from the repository and stored locally on your docker host.
command.
You will need it to start the container when you reboot the machine.
Now you cannot connect to the vSphere web client as there isn’t one running but you can connect to it
Connecting to the simulator is similar to connecting to any other VI instance by using the “Connect-
Now that you are connected you can start playing with the simulated environment.
GET-VMHOST
CLONING A VM
You will find that many commands don’t work as not everything can be simulated in the container.
You can find the list of supported methods if you open a web browser to https://@IPvCenter/about.
When working with VCSIM, you may find oddities here and there compared to a real environment.
Meaning if a script of yours fails, it is not necessarily a problem with the script itself, it could very well
be that VCSIM that doesn’t support the particular action you are performing. This is the drawback
of the virtual environment. You will need to double check that what you are doing is actually supposed
For instance, the “New-VM” cmdlet’s output is a string instead of a VM object which you cannot pipe
VCSIM:
VCENTER:
Now don’t take that as a deal breaker as the tool is still incredibly useful, just keep it in mind when
VMware went to great lengths in providing the community with a convenient way of interacting
In these times of increasing cloud adoption and automation, learning advanced scripting has
never been more relevant. PowerCLI is an incredible tool that everyone should have in their toolbox.
It unlocks many doors you didn’t even know existed before you started using it.
In this book, we barely scratched the surface of what PowerCLI can do. We explained several core
concepts and demonstrated several use cases ranging from beginner to medium/advanced usage.
While PowerCLI was indeed the main focus, most concepts also apply directly or indirectly
After reading this book, the first thing you should do is think about use-cases for PowerCLI that would
be useful in your environment. Spend some time experimenting with new scripts and always keep
trying to improve them. A good way to progress quickly in PowerShell, in general, is to avoid relying
on pre-existing scripts. Instead, take the time to try to write it yourself. The investment will soon pay
off as you will learn much faster and will be invaluable when you really need it. If you get stuck somewhere,
there is nothing wrong with having a peek at a script you found online to see how he/she did it or ask
Once you get comfortable with PowerCLI and end up writing that one awesome script that changed
your vSphere admin life, make sure to share it with the community!
at those articles and subscribe to the newsletter to be informed when my next article is published!
Xavier started his IT career in the early 2010's and evolved from a Windows SysAdmin to virtualization
specialist. He now works as a freelancer specializing in VMware technologies for a large customer.
Xavier is also a 4 time VMware vExpert and holds VMware VCP certifications. He grew a passion for
scripting and automation ever since he started using PowerCLI which offers a fine balance between
Xavier also always tries to give back to the online community as much as possible on his blog and the
VMware forums by sharing his knowledge and various scripts; as PowerShell says "Help and Get-Help”.
Finding a reliable backup and replication solution for Hyper-V and VMware is a real challenge.
You risk spending a huge chunk of your budget on software that is bloated with features you don’t
need, that is hard to manage, and impossible to get support on.
We’ve created a solid backup and replication solution that does what it says it will; is intuitive, easy to
use and well-priced; and most of all, offers 24/7 lightning-fast support as part of the package, with an
average call response of less than 30 seconds. Altaro VM Backup is a full-featured, affordable backup
and replication solution for Hyper-V and VMware environments.
Founded in 2009, Altaro has grown rapidly over the years. We develop robust backup solutions to
address the core data protection need of businesses and organizations worldwide , as well as the IT
resellers, VARs, consultants and managed service providers who serve them.
Out aim is to exceed your data protection needs with reliable, affordable backup solutions backed by
an outstanding, personal 24/7 Support team that’s determined to help you succeed in protecting your
environment.
ALTARO DOJO
The Altaro DOJO is a dedicated training and educational platform for system administrators and IT
professionals. It boasts a section dedicated entirely to Vmware content with new content published on
a regular basis.
Register to the Altaro DOJO now to gain unrestricted access to all Vmware content and stay notified
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means
or fitness is implied. The information provided is on an “as is” basis. The authors and the publisher
shall have neither liability nor responsibility to any person or entity with respect to any loss or damages
FEEDBACK INFORMATION
We’d like to hear from you! If you have any comments about how we could improve the quality
of this book, please don’t hesitate to contact us by visiting www.altaro.com or sending an email
102