VMware Hands-on Labs - HOL-SDC-1607

Lab Overview - HOL-SDC-1607 - From Beginner to Advanced Features with PowerCLI

Lab Guidance

This lab covers PowerCLI for the beginning and advanced users.

Module  - From Beginner to Advanced Features with PowerCLI (60 Minutes)

NOTE: If you are using a device with non-US keyboard layout, you might find it difficult to enter CLI commands, user names and passwords throughout the modules in this lab.

This lab will take you approximately 60 minutes to complete.

We have included videos throughout the modules of this lab. To get the most out of these videos, it is recommenced that you have headphones to hear the audio. The timing of each video is noted

Lab Captains: Phil Balfanz, Paval Dimitrov, Pierre Grothe, Tom Lusk, Carl Olafson

This lab manual can be downloaded from the Hands-on Labs Document site found here:


Module 1: From Beginner to Advanced Features with PowerCLI - (60 Minutes)

Module overview

This module will introduce you to VMware vSphere PowerCLI. Novice users will easily learn to use the tool and more advanced users will get familiar with the new functionality available in the latest releases of the product like configuring an OVA before deploying it and filtering objects by their tags. Both new and experienced users are sure to learn something new.

Getting Started With PowerShell and PowerCLI

In this lesson you'll learn the basics of PowerShell and PowerCLI. You'll learn how to start the PowerCLI console and PowerShell ISE, how to list available commands and view their help.


Starting PowerCLI


After installation, PowerCLI can be started by double clicking the desktop icon labeled "VMware vSphere PowerCLI". This will open the PowerShell console and load all PowerCLI modules.



Using Powershell ISE


As an alternative to the simple console, you can use Powershell ISE script editor, which provides a better user experience. You can start the editor by double clicking its icon on the desktop (1). The upper pane (2) is for viewing/editing script files, and the lower pane (3) is for running individual commands and displaying their output (an analog of the standard PowerShell console).



Using Powershell ISE


During this lab you will execute various PowerCLI commands in the lower pane of PowerShell ISE or in the PowerShell console. You can either type the commands yourself or copy-paste them from the "Module7.ps1" files located on the desktop. The most convenient way to go through the lab is to open Module7.ps1 in the upper pane of Powershell ISE. This file contains all commands you will call in this module. Each command can be selected (1) and executed by pressing F8 (or "Run Selection" button (2)). Before executing a new command make sure the previous one is completed - you will see "Completed" message (3) at the bottom of the console.



Listing Available Commands

Let's explore what we can do with PowerCLI. PowerCLI's snapins provide more than 500 commands (called cmdlets in PowerShell) for managing vSphere, vCloud Air, SRM, vR Ops, and VUM. You can view the available PowerCLI commands by typing:


This will list all PowerCLI commands. As the list is quite large, you may want to narrow it down to something more specific, for example all commands for managing VMs:

Get-VICommand *VM

Hint: You can use autocomplete for faster typing - just start typing the beginning of the command/parameter and press "Tab".



Connecting to vSphere


The first thing we need to do in order to manage our vCenter Server is to connect to it. This is done by using the Connect-VIServer command. Our vCenter is named "vcsa-01a" and here's how to connect to it:

Connect-VIServer vcsa-01a -User corp\administrator -Password VMware1!

The command will connect to the vCenter with the specified user's credentials.



Getting Help


If you are unsure how to use a specific cmdlet, you can easily view its help by typing Get-Help (or for short - just "help") and the name of the cmdlet:

help Connect-VIServer

If you want to see the full help with example usages of the cmdlet and parameter descriptions you should open the full help of the cmdlet:

help Connect-VIServer -Full

If you want to see only the examples, you can use -examples switch like this:

help Connect-VIServer -Examples

You can also search for a specific word in the entire help archive. Let's try searching for a cmdlet that vmotions VMs:

help vmotion

The result contains the cmdlet we need - Move-VM. We'll use it later in this module.

Feel free to check the help of any cmdlet we demonstrate in this lab.



Using PowerCLI for reporting

With more than 100 Get-* cmdlets PowerCLI is also a powerful reporting tool. In this lesson, you'll learn more about this usage of PowerCLI.


Retrieving VMs


One of the most common things to do is list the VMs in your vCenter Server. This is useful for browsing the inventory and reporting as well as for further processing of specific VMs (e.g. batch modification of VMs). You can retrieve all VMs with:


You can also retrieve one or more VMs by name. Try out the following:

Get-VM linux-CPU-Load-01a
Get-VM linux*



Retrieving specific properties of an object


When you call a cmdlet (like Get-VM) the result you get is an object or array of objects (in this case it's a VM object). To see what properties the object(s) have you can use Get-Member cmdlet like this:

Get-VM linux-CPU-Load-01a | Get-Member -MemberType property

This will list all the available properties of the VM object.

Note: Here we use a PowerShell functionality called "pipeline" (or "piping"). Get-Member cmdlet actually has a parameter called "InputObject" that accepts VM objects (as well as all other PowerShell objects). Instead of retrieving our VMs, storing them in a variable and passing them to that parameter of Get-Member, we simply "pipe" the output of Get-VM to Get-Member. This way the output of the first cmdlet becomes the input of the second.

Then you can use PowerShell's 'select' command to retrieve only the properties you need from resulting object:

Get-VM linux-CPU-Load-01a | Select Name, NumCPU, MemoryMB, PowerState, VMHost



Filtering report results


When the Get-* cmdlet has no parameter to filter the objects by the property you need, you can use PowerShell's 'where' command to filter the results from a cmdlet call:

Get-VM | Where {$_.Powerstate -eq "PoweredOn"} | Select Name, NumCPU, MemoryMB, PowerState, VMHost

Hint: $_ is a reserved powershell variable that holds the current object from the pipeline


Exporting report results to various formats

To present the data to your manager or another team or to transfer them to another system that your company uses you need them formatted in some way.In this lesson you'll learn how to export the data, generated by your PowerCLI reports to various different formats (txt, csv, xml, html).


Exporting to txt


Let's start with the most basic export - to txt file. To export your report to txt use Out-File PowerShell cmdlet:

Get-VM | Select Name, NumCPU, MemoryMB, PowerState, VMHost | Out-File c:\myPowerCLIReport.txt

Open the text file to check the result.



Exporting to csv


Now let's export the same data to csv format. We'll use Export-Csv cmdlet to do that:

Get-VM | Select Name, NumCPU, MemoryMB, PowerState, VMHost | Export-Csv c:\myPowerCLIReport.csv -NoTypeInformation

Check the result in the csv file



Exporting to xml


The next format that you'll export to is XML. The PowerShell cmdlet we'll use is ConvertTo-Xml. Since this cmdlet returns XMLDocument object we need to call its Save method to write formatted data to file:

(Get-VM | Select Name, NumCPU, MemoryMB, PowerState, VMHost | ConvertTo-Xml -NoTypeInformation).Save("c:\myPowerCLIReport.xml")

Check the result in the xml file



Exporting to HTML


You can also export the data in HTML format by using ConvertTo-Html cmdlet. Since this command just formats the data in HTML you also need Set-Content cmdlet to write formatted data to file:

Get-VM | Select Name, NumCPU, MemoryMB, PowerState, VMHost | ConvertTo-Html | Set-Content "c:\myPowerCLIReport.html"

Now go to 'c:\' folder and open the report.



Adding formatting to the HTML page


If we want to make our HTML report look a bit better we can apply some styles on it like this:

$a = "<style>"
$a = $a + "BODY{background-color:Gainsboro;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:SkyBlue}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:PaleTurquoise}"
$a = $a + "</style>"
Get-VM | Select Name, NumCPU, MemoryMB, PowerState, VMHost | ConvertTo-Html -head $a | Set-Content "c:\myPowerCLIReport.html"

If you open the report now you'll see that it looks much better



Setting up and configuring a cluster

In the next few lessons you'll setup a small virtual environment of a fictional company - Nephosoft. You'll start with creating and configuring a cluster. Then you'll setup networking by creating and configuring a virtual distributed switch (VDS). At the end you'll create several virtual machines based on a predefined specification, tag them accordingly and then do a batch update of multiple VM specifications, based on their tag.  In this lesson we'll start with information on how to create and configure a cluster with PowerCLI. You'll setup its EVC, HA and DRS settings.



Creating a cluster

To create a new cluster we'll use the New-Cluster cmdlet. We have to specify the name and the location of the new cluster:

$cluster1 = New-Cluster -Name "Nephosoft Cluster 1" -Location "Datacenter Site A"



Configuring cluster's Enhanced vMotion Compatibility Mode


Now let's configure the cluster's enhanced vMotion compatibility mode to ensure CPU compatibility for vMotion. To do that we'll first determine what EVC modes are supported by our hosts:

$evcModes = Get-VMHost | Select MaxEVCMode

Now inspect the content of the $evcModes variable. Just type the name of the variable ($evcModes) and its value will be printed to the screen. You'll notice that both hosts have the same evc mode.

Note: The EVC mode might be different from the one on the screenshot above, because it depends on the physical hardware that your lab environment runs on.

Let's set that EVC mode to the cluster to make sure that any other hosts that might be added to the cluster in the future will have to match this EVC mode:

Set-Cluster $cluster1 -EVCMode $evcModes[0].MaxEVCMode

When you are prompted for confirmation - click yes.

Hint: Prompting for confirmation is good for interactive usage, however it is undesired in scripts since it will halt them. You can automatically confirm the operation by appending "-Confirm:$false" parameter to your cmdlet call.



Enabling HA on the cluster


The next step is to enable HA on our cluster to ensure that our VMs are protected in case of host failure:

Set-Cluster $cluster1 -HAEnabled:$true -Confirm:$false



Enabling DRS on the cluster and configuring DRS settings


Now let's enable DRS on this cluster and set its automation level to "manual" to make it generate recommendations for VM placement and migration (you can retrieve and apply those recommendations with Get-DrsRecommendation and Apply-DrsRecommendation cmdlets):

Set-Cluster $cluster1 -DRSEnabled:$true -DRSAutomationLevel "Manual" -Confirm:$false


Moving hosts to the cluster

In this lesson you'll learn how to move our hosts to the already created cluster.


Moving hosts to the cluster


To move the hosts into the new cluster we need to put them in maintenance mode first. To put them in maintenance mode we have to shut down all the running VMs before that. So, let's retrieve all the running VMs and then stop them:

$vmsToStop = Get-VM | Where {$_.Powerstate -eq "PoweredOn"}
Stop-VM $vmsToStop -Confirm:$false

Now let's put the hosts in maintenance mode:

Get-VMHost | Set-VMHost -State Maintenance

Next we'll use the Move-Host cmdlet to move the hosts to the cluster:

Get-VMHost | Move-VMHost -Destination $cluster1

And at the end let's take the hosts out of maintenance mode:

Get-VMHost | Set-VMHost -State Connected


Setting up and configuring virtual distributed switch

In this lesson you'll learn how to create a distributed switch and migrate host networking to the distributed switch.


Creating a VDS (virtual distributed switch)


We'll start by creating a VDS with the New-VDSwitch cmdlet:

$vds = New-VDSwitch -Name "Nephosoft VDS" -Location "Datacenter Site A"

You can check the content of the $vds variable.



Adding ESX hosts to the VDS


Next step is to add both our ESX hosts to the distributed switch:

Add-VDSwitchVMHost -VDSwitch $vds -VMHost esx-01a.corp.local, esx-02a.corp.local

You can verify ESX hosts are successfully added in the distributed switch:

Get-VMHost -DistributedSwitch $vds



Creating distributed portgroups


Now let's create portgroups for the management, storage, vMotion and VM networks with the New-VDPortGroup cmdlets:

$pgManagement = New-VDPortGroup $vds -Name "management"
$pgvMotion = New-VDPortGroup $vds -Name "vMotion"
$pgStorage = New-VDPortGroup $vds -Name "storage"
$pgVM = New-VDPortGroup $vds -Name "VM"

You can verify that portgroups are successfully created:

Get-VDPortGroup -VDSwitch $vds



Migrating host networking to the VDS

We'll migrate our hosts' networking host by host. First we'll save both our hosts in a variable:

$hosts = Get-VMHost  esx-01a.corp.local, esx-02a.corp.local 

Then we'll migrate the networking for each one of them by using PowerShell's foreach loop. For each host we'll first retrieve its physical nics and then its management, storage, and vMotion VMKernel nics. Then we'll migrate them together by using the Add-VDSwitchPhysicalNetworkAdapter cmdlet, while specifying the distributed portgroups for each VMKernel nic with the VirtualNicPortGroup parameter:

foreach ($vmhost in $hosts) {
  $pNics = Get-VMHostNetworkAdapter -VMHost $vmhost -Physical
  $vNicManagement = Get-VMHostNetworkAdapter -VMHost $vmhost -Name vmk0
  $vNicStorage = Get-VMHostNetworkAdapter -VMHost $vmhost -Name vmk1
  $vNicvMotion = Get-VMHostNetworkAdapter -VMHost $vmhost -Name vmk2
  Add-VDSwitchPhysicalNetworkAdapter -DistributedSwitch $vds -VMHostPhysicalNic $pNics -VMHostVirtualNic $vNicManagement,$vNicStorage,$vNicvMotion -VirtualNicPortGroup $pgManagement,$pgStorage,$pgvMotion -Confirm:$false



Migrating VM networking to the VDS


In the end let's migrate the VM networking as well. First we'll get the network adapters of all the VMs:

$vmNetworkAdapters = Get-VM | Get-NetworkAdapter

Next we'll migrate these network adapters to the "VM" portgroup that we created in the previous step:

Set-NetworkAdapter -NetworkAdapter $vmNetworkAdapters -Portgroup $pgVM -Confirm:$false

Now the network traffic of all the VMs is going through the VDSwitch.


Creating a VM and vMotioning it between the hosts

In this lesson you'll learn how to create a VM and vMotion it between the two hosts in the cluster.


Creating a VM from scratch


Let's start by creating a VM with the New-VM cmdlet. We'll specify the VM's name, hard disk and memory size, the host and the datastore, on which we want to create it. Also we'll specify the portgroup for the VM network to be in the distributed switch, created earlier. We'll place the VM on our NFS datastore, which is shared between our two hosts.

$vm = New-VM -Name 'jsmith' -VMHost esx-01a.corp.local -DiskGB 10 -MemoryMB 512 -Datastore ds-site-a-nfs01 -Portgroup $pgVM 

Let's start that VM:

$vm | Start-VM



vMotioning the VM between the host


Now let's move the VM to the other host to make the workload more equally distributed:

Move-VM $vm -Destination esx-02a.corp.local

Note: If this is not the first module you're doing in this session, there is a chance that you may have some disconnected datastores in your environment. In this case you'll receive an error that Move-VM is unable to access the virtual machine configuration. If this happens you'll have to reconnect the NFS datastore on one of your hosts. To do so we'll use Get-EsxCli cmdlet:

Retrieve EsxCLli for esx-02a.corp.local:

$esxCli = Get-EsxCli -VMhost esx-02a.corp.local

Verify NFS datastore isn't accessible:

Accessible          : false

Disconnect NFS datastore:


Reconnect NFS datastore:

$esxCli.storage.nfs.add('', $false, $false, '/mnt/NFSA', 'ds-site-a-nfs01')

If needed repeat the same procedure for esx-01a.corp.local

Tip: Since Move-VM operation could take significantly long time, you may want to move the VMs asynchronously and continue your work in the meantime. You can do that by specifying -RunAsync parameter of Move-VM. Many other cmdlets that may take long time to complete also support -RunAsync.


Creating multiple VMs and tagging them appropriately

In this lesson you'll learn how to create multiple VMs with PowerCLI by a specification saved in csv file. You'll also tag the VMs according to the same specification.


Reviewing the specification


First of all let's review the specification that we'll follow when creating the VMs. Open the 'vmspec.csv' file located on your desktop. For every VM we have the name, memory size (in MB), disk size (in GB), department and type (user or server VM).



Reading the information from the csv file to an array


Now let's import that file to a PowerShell variable:

$spec = Import-Csv 'C:\Users\Administrator\Desktop\vmspec.csv'

Inspect the content of the $spec variable. You'll find out that it contains an array of objects (one object for each VM) and each one of these objects has a corresponding property for name, memory size, disk size, department and type.



Creating VMs based on the specification


Now let's create the VMs based on the specification. We'll use the foreach PowerShell loop again:

foreach ($vmSpec in $spec)
   New-VM -Name $vmSpec.Name -MemoryMB $vmSpec."Memory size" -DiskGB $vmSpec."Disk size" -VMHost esx-01a.corp.local -Portgroup $pgVM



Creating tag categories


Our next task is to tag our newly created VMs appropriately. To do that we'll start by creating two different tag categories - "Department" and "Type":

New-TagCategory -Name Department 
New-TagCategory -Name Type 



Creating tags based on the specification


Let's retrieve the unique department names first:

$departmentTagNames = $spec | select -Unique Department

Now let's create tag for each department:

foreach ($departmentTagName in $departmentTagNames) 
  New-Tag -Name $departmentTagName.Department -Category Department 

Next we have to do the same for the VM types:

$vmTypes = $spec | select -Unique Type
foreach ($vmType in $vmTypes) 
  New-Tag -Name $vmType.Type -Category Type

You can check what tags were defined as a result by calling:





Assigning tags to the VMs based on the specification


Now when we have the tags and tag categories properly defined it's time to tag the VMs appropriately. We'll use the New-TagAssignment to assign a tag to a VM:

foreach ($vmSpec in $spec) 
  $departmentTag = Get-Tag $vmSpec.Department
  $typeTag = Get-Tag $vmSpec.Type
  $vm = Get-VM -Name $vmSpec.Name
  New-TagAssignment -Entity $vm -Tag $departmentTag
  New-TagAssignment -Entity $vm -Tag $typeTag


Modifying multiple VMs based on their tag

In this lesson you'll learn how to modify multiple VMs simultaneously with PowerCLI, based on their tags.


Updating VMs memory capacity based on their tags


A new application will be deployed in the Nephosoft sales department and that requires the memory on the user machines to be updated to 1GB. Now that we have our VMs properly tagged it's easier to make a mass update of the VMs. Let's retrieve all the VMs from the sales department first:

$salesVMs = Get-VM -Tag sales

Next let's retrieve all the user VMs:

$userVMs = Get-VM -Tag user

Note: We cannot use "Get-VM -Tag sales, user", because that will return all the VMs are either from the sales department, or user VMs and what we actually want is to get the VMs that are both from the sales department and are user VMs

Now let's select all VMs that have both tags assigned. For that purpose we'll use Compare-Object Powershell cmdlet:

$salesUserVMs = Compare-Object $salesVMs $userVMs -IncludeEqual -ExcludeDifferent -PassThru

Before we can update the VMs memory we need to make sure that they are all stopped:

$salesUserVMs | where {$_.PowerState -eq "PoweredOn"} | Stop-VM -Confirm:$false                                                 

Finally we'll update the VM's memory capacity with the Set-VM cmdlet:

Set-VM $salesUserVMs -MemoryGB 1 -Confirm:$false


Configuring and deploying an OFV template

In this lesson you'll learn how you can apply configuration to an OVF template, when deploying one.


Retrieve OvfConfiguration object


The OVF configuration in PowerCLI is represented as an OvfConfiguration object, which can be retrieved from an ovf file by Get-OvfConfiguration cmdlet. Note that you have to be connected to a vCenter server in order to use this cmdlet, as it needs the connection to parse the OVA properties.

$linuxMicroConfig = Get-OvfConfiguration -Ovf C:\OVF\linux-micro-01a\linux-micro-01a.ovf 

Take a look at the object inside the $linuxMicroConfig variable. It contains one property, which points to the source ovf file and second, which is the actual configurable property for the selected ovf file - NetworkMapping. When we take a look inside the NetworkMapping object we'll see that it contains single property VM_Network, which is the only configuration that can be applied to that ovf tempalte.



Update OVF configuration

You can update the retrieved configuration just by assigning values to the object properties, matching the configurations you want to apply. In our case we will assign value to the "VM_Network"

$linuxMicroConfig.NetworkMapping.VM_Network.Value = 'VM'



Import vApp applying configuration


When you import your vApp you can apply its configuration using the new Import-VApp parameter "OvfConfiguration".

Import-VApp -Source 'C:\linux-micro-01a\linux-micro-01a.ovf' -OvfConfiguration $linuxMicroConfig -Name 'LinuxMicro' -VMHost 'esx-01a.corp.local' 

Let's verify that configuration has been applied:

$linuxMicroVM = Get-VM 'LinuxMicro' 
$linuxMicroVM | Get-NetworkAdapter 

As you can see, the vApp has been deployed with the correct network mapping.


Further Reading

This lesson is for information purpose only and lists some of the more advanced features of PowerCLI, useful reading materials for both novice and advanced users as well as information for other PowerCLI related labs. Feel free to experiment with these if you like.


Other PowerCLI related labs

HOL-SDC-1602 vSphere with Operations Management - Advanced Topics: Module 8 will introduce you to the new PowerCLI cmdlets for managing vRealize Operation Manager.

HOL-HBD-1683 Managing Your Hybrid Cloud: Module 3 is all about managing vCloud Air with VMware vSphere PowerCLI.



Accessing the entire vSphere API

Although PowerCLI offers more than 300 cmdlets for managing vSphere they don't cover the entire functionality of the platform. Despite that you are still able to access all of the functionality by using the Get-View cmdlet. This special cmdlet is an access point to the entire vSphere API. The objects returned by the cmdlet are known as "Views" and represent an exact copy of the vSphere API objects. You can find more information about these objects in the vSphere API Reference



Using this cmdlet you will be able to write scripts directly against the API in an object-oriented manner.



Onyx for the Web Client

Onyx for the Web Client is a Fling that translates actions taken in the vSphere Web Client to PowerCLI.Net code. This Fling was the winning entry in last year’s 2014 Fling Contest. It’s an update, of sorts, to the Onyx fling, as it allows for similar functionality in the web client.

The Onyx for the Web Client Fling provides the ability to record actions taken in the vSphere Web Client and turn these actions into PowerCLI.Net code. The resulting code can then be used to understand how VMware performs an action in the API and also better define functions. You could also input the resulting code into search engines to find the API documentation and information on how to use this area of the vSphere API.




Useful materials to get you started with advanced PowerCLI scripting

If you are new to PowerCLI or want to learn more about the product then here are a few blogs you can follow. There you can find great articles and scripts about PowerCLI:

• The official PowerCLI blog: http://blogs.vmware.com/PowerCLI/

• Alan Renouf's blog: http://www.virtu-al.net

• Luc Dekens' blog: http://www.lucd.info



Thank you for participating in the VMware Hands-on Labs. Be sure to visit http://hol.vmware.com/ to continue your lab experience online.

Lab SKU: HOL-SDC-1607

Version: 20160223-080509