A start for those wanting to learn powercli but were afraid to ask.

Why use powercli, you can do everything from the gui people say.
Yeah sure you can do everything from the gui, sort of.

Let’s say you have three vcenter servers and eighteen clusters and 17 thousand vms and want to find out.

  • Hosts in vcenter2 cluster 9
    • o  
      connect-viserver vcenter1,vcenter2,vcenter3 | get-cluster cluster9 | get-vmhosts | sort name 
  • vms running in cluster 9
    • o   
      get-cluster cluster9 | get-vm | sort name 
  • vms powered on in cluster9
    • get-cluster cluster9 | get-vm | where {$_.PowerState -eq "PoweredOn"}
  • vms powered on with 2 cpus on cluster9
    • o  
      get-cluster cluster9 | get-vm | where {$_.PowerState -eq "PoweredOn"} | where {$_.NumCpu -eq "2"}
  • vms powered on with a note containing the word whackdiddy
    • get-vm | where {$_.PowerState -eq "PoweredOn"} | where {$_.Notes -like "*whackdiddy*"}

To work out what you can filter by choose an existing guest and get full details like this..

get-vm guestname | fl

Where guestname is the name of one of your vm’s.

Once you have the basics you will find it much easier to get information with powercli than with the gui and so much quicker.

vmware fury

Okay so I have a rather large green field / migration project I am working on.
So I started putting together some powercli scripts to build the environment and then thought to myself there must be a quicker way and something I can use again and again going forward.

So I created an excel spreadsheet (yeah dont cringe).
I ended up choosing excel because most people have it and it is easy to automate and drive.

So with the excel spreadsheet you work through the numbers and enter the details of your planned install.
Datacenter, Cluster, dvswitch, port groups, resource pools, top level folders, folder in folders.

The spreadsheet will format your entries into their relative powercli commands and then give you an output of all the commands.
The output you simply paste into your powercli session and sit back and watch.

Here is a vid demo that I have done so you can see it in action.
note… I have limited the cells to 500, I mean really who wants 500+ port groups anyway…

Create user on hosts

Simply copy and paste into notepad++ or equiv and save as createlocalshelluser.ps1

### There is a downside to this script, it does not create a permisson for you on the local host. As in you will not have admin permission so will not be able to interact with vmware as such. You will be able to login to shell and then sudo but that is about as far as you will be able to get.###

You may have to sign the script prior to running depending on your domain GPO settings.

ESXi Code:
#Vcenter name, can be FQDN
$vsphere = "Whackdiddy"
#User to create
$new_user = "Username"
#Password for new user
$new_user_passwd = "MyP@ssw0rd"
#Group to add user too
$new_user_grp = "root"

#local host username with rights to create local users
$root_user = "root"
#Password for local host user with rights to create local users
$root_passwd = "whackdiddy"

# Get all of the ESX servers (connect using Windows credentials)
connect-viserver $vsphere
$hosts = Get-View -ViewType HostSystem
disconnect-viserver -confirm:$false

# For each ESX server, connect and see if the new account exists.
# If it does, reset the password and ensure the account is granted shell access.
# If it doesn't, create it and add to the root group (this seems to be necessary to allow ssh login in ESX4.0)
$hosts | %{ $_.name } | %{
  echo $_
  connect-viserver -server $_ -user $root_user -password $root_passwd
  if ($?) {
    if (! (get-vmhostaccount | ?{ $_.id -eq $new_user })) {
      new-vmhostaccount -useraccount -id $new_user -password $new_user_passwd -grantshellaccess
   set-vmhostaccount -groupaccount $new_user_grp  -assignusers $new_user
    }
 else {
   set-vmhostaccount -useraccount $new_user -password $new_user_passwd -grantshellaccess $true
   }

 disconnect-viserver -confirm:$false "*"
  }
}
ESX Code:
#Vcenter name, can be FQDN
$vsphere = "Whackdiddy"
#User to create
$new_user = "Username"
#Password for new user
$new_user_passwd = "MyP@ssw0rd"
#Group to add user too
$new_user_grp = "esxadmin"

#local host username with rights to create local users
$root_user = "root"
#Password for local host user with rights to create local users
$root_passwd = "whackdiddy"

# Get all of the ESX servers (connect using Windows credentials)
connect-viserver $vsphere
$hosts = Get-View -ViewType HostSystem
disconnect-viserver -confirm:$false

# For each ESX server, connect and see if the new account exists.
# If it does, reset the password and ensure the account is granted shell access.
# If it doesn't, create it and add to the root group (this seems to be necessary to allow ssh login in ESX4.0)
$hosts | %{ $_.name } | %{
  echo $_
  connect-viserver -server $_ -user $root_user -password $root_passwd
  if ($?) {
    if (! (get-vmhostaccount | ?{ $_.id -eq $new_user })) {
      new-vmhostaccount -useraccount -id $new_user -password $new_user_passwd -grantshellaccess
	  set-vmhostaccount -groupaccount $new_user_grp  -assignusers $new_user
    }
	else {
	  set-vmhostaccount -useraccount $new_user -password $new_user_passwd -grantshellaccess $true
	  }

	disconnect-viserver -confirm:$false "*"
  }
}

taken from jbarbers site.

https://gist.github.com/715238

200+ port groups in 5 minutes, no sweat

Okay, so exciting news and just in time.
We are doing a major migration with 200+ vlans.
When I say migration it is a green field approach with no downtime.

Powercli is now supporting dvSwitches.
Well Powercli 5.1.0-1012425 is anyway.

Can be downloaded from here

What can we do with it…

This.

#Change the values below to what you want your hierachy to look like.
#This setting will createa a datacenter (whackdiddy), cluster (whackdiddy-cluster) and two dvswitches (dvs1-whackdiddy and dvs2-whackdiddy)
#It will then import the csv with all the vlan settings and create port groups.

$dc = "whackdiddy"
$cl = "whackdiddy-cluster"
$vds1 = "dvs1-whackdiddy"
$vds2 = "dvs2-whackdiddy"

New-Datacenter -Name $dc -Location Datacenters
New-Cluster -Name $cl -Location $dc -HAEnabled -DrsEnabled -DrsMode FullyAutomated
New-vdswitch -Name $vds1 -Location $dc -Mtu 9000 -Version 5.1.0 -contactDetails "whackdiddy" -Notes "version 5.1.0"
New-Vdswitch -Name $vds2 -Location $dc -Mtu 9000 -Version 4.1.0 -contactDetails "whackdiddy" -Notes "version 4.1.0"

Import-Csv C:\temp\whackdiddy\vlans.csv | %{
New-VDPortgroup -VDSwitch $_.Vds -Name $_.Name -NumPorts $_.UplinkPorts -VlanId $_.Vlan -Notes $_.Notes
}

Create a csv file with the following headings.
Place this file in c:\temp\whackdiddy\

Vds,Name,UplinkPorts,Vlan,Notes
dvs1-whackdiddy,vlan1,24,1,whackdiddy1
dvs1-whackdiddy,vlan2,24,2,whackdiddy2

Then we run the script in our lab environment.
The vid does not have audio, I will get around to amending this shortly.

snapshot removal powercli

Okay so a bit of a place holder for me, as I am sick of looking up these simple commands.

update… to take a snapshot

New-Snapshot -RunAsync -VM guest -Name snapshotname

I am in the habit of naming my snapshots with the date they were created and my username, in the description field I will put in any detailed information. So on a product release we end up with 7 and up guests with snapshots, the next day comes the cleanup process. So instead of running through every single guest we can simply run these..

First get the snapshots relative to the guests running.

Update…….
Use the below code instead of the old code “Get-VM | Get-snapshot …..” as it is quicker and easier to remember.

New Code (note that the name field is first – this allows for easy copy and paste into a snapshot removal code framework)

Get-Snapshot * | Select Name, VM, SizeGB, Created | ft -au

Old Code

Get-VM | Get-Snapshot | select @{name="VM Name"; Expression={$_.vm.name}},name,created | ft -au

Then delete based on the snaphot name as it appears from the output of the above command.


Get-Snapshot * "date of snapshot-usename" | Remove-Snapshot

To suppress confirmation


Get-Snapshot * "date of snapshot-username" | Remove-Snapshot -Confirm:$false

Of course it goes without saying that if somebody else created a snapshot today with the days date that would be removed as well. You could always append your name to the start or the end and then it would be unique.

There are plenty of examples out there…

http://www.interworks.com/blogs/dholm/2011/10/16/bulk-vmware-snapshot-managementremoval-powercli

http://blog.eeg3.net/2010/10/15/nifty-powercli-one-liners/

vmtools update on power cycle

So recently I had to powerdown a vast majority of my guests due to an outage.
I thought it a good time to upgrade the vmtools. But bugger me if I was going to edit the settings on every single vm, so I searched for a better way.

Work through vcenter and configure every vm that meets the OS Windows Guest to upgrade vmtools on powercycle

Once again you may need to sign these scripts in order to run them.

I strongly suggest doing the Add-Signature.ps1

Foreach ($v in (get-vm)) {
$vm = $v | Get-View | Where-Object {$_.Guest.GuestFamily -eq 'windowsGuest'}
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
$vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
$vmConfigSpec.Tools.ToolsUpgradePolicy = "upgradeAtPowerCycle"
$vm.ReconfigVM($vmConfigSpec)
}


Once complete and a powercycle has been done you can set back to manual with this.


Foreach ($v in (get-vm)) {
$vm = $v | Get-View | Where-Object {$_.Guest.GuestFamily -eq 'windowsGuest'}
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
$vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
$vmConfigSpec.Tools.ToolsUpgradePolicy = "manual"
$vm.ReconfigVM($vmConfigSpec)
}

Stolen from..
http://damiankarlson.com/2011/01/23/managing-vmware-tools-advanced-options-powercli/

So now we can use the knowledge in this code to do some really simple cool things….

Start every vm that meets the OS family Windows Guest

Foreach ($v in (get-vm)) {
$vm = $v | Get-View | Where-Object {$_.Guest.GuestFamily -eq 'windowsGuest'}
Start-VM -VM $vm</code>