PowerCli: Finding amount of GB used by VMs in a folder/vApp/datacenter

Sometimes it can be useful to know how much space the VMs in a specific folder (or vApp/datacenter) is occupying. For example if you are a hosting provider of some sort and need to know how much space a customer is using.

It’s a simple one-liner!

Get-VM -Location <name of folder/vApp/datacenter> | foreach {Get-HardDisk -VM $_.name} | Measure-Object CapacityGB -Sum

That will give an output that looks something like this:
temp
Meaning, in this case, that the folder named “Templates” has 2 VMs occupying 140GB of disk space

You can also get a list per vm with this one-liner:

get-vm -Location <folder> | select name,@{Name="Size";Expression={(Get-HardDisk -VM $_.name |
Measure-Object CapacityGB -sum).Sum}}

Posted in PowerCLI, Powershell, VMware Tagged , ,

Powershell: Write-Progress, a step-by-step guide

For whatever reason, I had a really difficult time wrapping my head around the usage of Write-Progress. The basic usage is off-course quite easy:

Write-Progress -Activity "Something" -Status "Something else" -CurrentOperation "thinking" -PercentComplete 30

This will show a quick progress bar stating that “Something” is going on, the status is “Something else” and it has gotten to 30%. However, when I wanted to use Write-Progress in a large script I quickly got confused when I looked at some of the examples out there. I mean, look at this for example:

$wmiQuery = "Select name from win32_service where state = 'running'"
$colItems = Get-WmiObject -Query $wmiQuery
For($i = 1; $i -le $colItems.count; $i++)
{ Write-Progress -Activity "Gathering Services" -status "Found Service $i" `
-percentComplete ($i / $colItems.count*100)}
$colItems | Select name

I’m sure that if I had a stronger background in programming and/or scripting I could have figured it out quite easily (for what it’s worth: I understand the code now Smilie: ;) ). But since I haven’t really been scripting before Powershell came along I just sat there scratching my head.

So let’s write a simpler guide!

Let’s start by explaining a briefly how Write-Progress works:
If you type the command in your Powershell console it will display the progress bar, but it will disappear again in a split second.
If you put your Write-Progress snippet in a script, the progress bar will be displayed until another Write-Progress snippet comes along, or until the script finishes.

The basic usage of Write-Progress is, as I wrote further up, something like this:

Write-Progress -Activity "Something" -Status "Something else" -CurrentOperation "thinking" -PercentComplete 30

That will create an output looking something like this:

It’s also quite easy to create a child progress bar by using the Id and ParentId parameters:

Write-Progress -Activity Something -Status "Something else" -CurrentOperation Thinking -PercentComplete 30 -Id 1
 Write-Progress -Activity "Another thing" -Status "Something different" -CurrentOperation Sleeping -PercentComplete 30 -Id 2 -ParentId 1

This will create an output looking something like this:

Cool ey?

Now, this is all fine and dandy as a starting point, and you CAN use write-progress this way in your scripts, but thats not exactly a dynamic way of doing it.
Often in your script you will have one or more foreach loops. Those are a great place to put your write-progress snippet and have PercentComplete and perhaps even Status or CurrentOperation filled out automagically.

First off we will need some data to parse through, I like to use Get-Process for that:

$data = Get-Process

Then we create a variable for our progress and set it to 1:

$progress = 1

This way PercentComplete will start at 1, you’ll see why in a bit.

Now we can create our foreach loop (I assume you know how they work):

$data | foreach {
 Write-Progress -Activity Sleeping -Status $_.ProcessName -CurrentOperation $_.Id -PercentComplete ($progress/$data.count*100) -Id 1
 Start-Sleep -Milliseconds 50
 $progress++
 }

This Write-Progress line will show Activity as “Sleeping”, the status will be the name of the process and currentoperation will be the ID of the process. Percentagecomplete will the correct progress (since $progress++ will increment $progress by 1 for each time the loop runs).
Start-Sleep is only there to delay the operation, so you can actually see whats going on.

So the final result will be:

$progress = 1
$data = Get-Process
$data | foreach {
 Write-Progress -Activity Sleeping -Status $_.ProcessName -CurrentOperation $_.Id -PercentComplete ($progress/$data.count*100) -Id 1
 Start-Sleep -Milliseconds 50
 $progress++
 }

And it will look something like this:

Comments?

Posted in Microsoft, Powershell Tagged , ,

PowerCLI: Consolidate all VMs that need consolidation

Robert van den Nieuwendijk has a nice post on how to use PowerCLI to find VMs that need consolidation and then how to start consolidation. You can that post here: http://rvdnieuwendijk.com/2012/09/26/use-powercli-to-consolidate-snapshots-in-vsphere-5/

But, as always, I prefer to make a function of these kind of things. A function is much easier to remember than a bunch of parameters and cmdlets.
So here’s the code for a function that will search through the vCentre for VMs that need disk consolidation:

function Start-Consolidation
{
    [CmdletBinding()] 
        Param (
            [string]$Location = '*',
            [switch]$ListOnly
              )

        $VMs = Get-VM -Location $Location | Where-Object {$_.Extensiondata.Runtime.ConsolidationNeeded} 

        if ($ListOnly) {
              $VMs
              }

        else {
            $VMs | ForEach-Object {
                Write-Host "Starting disk consolidation on $_.Name"
                $_.ExtensionData.ConsolidateVMDisks()
                Write-Host "Finished disk consolidation on $_.Name"
                                  }
              }
        }
<#
 .Synopsis
  Searches vCentre for VMs in need of disk consolidation and starts disk consolidation
 .Description
  This function searches the entire vCentre, or the given folder,datasenter,cluster,vApp or ResourcePool for VMs that is in need of disk consolidation. It will then start disk consolidation on those that need it
 .Parameter Location
  If you want to narrow the search to a specific folder,datasenter,cluster,vApp or ResourcePool
 .Example
  Start-Consolidation
  Searches the entire vCentre for VMs that need consolidation and starts consolidating them
 .Example
  Start-Consolidation -Location vApp01
  Searches through vApp01 for VMs that need consolidation and starts consolidation on them
 .Link
  http://cloud.kemta.net
 #>

Any input is much appreciated Smilie: :)

Posted in PowerCLI, Powershell, VMware Tagged , , , ,

PowerCLI: Locate a MAC-address in vCenter

To find out to which vm a MAC address belongs, you can use a simple one-liner:

Get-vm | Select Name, @{N=“Network“;E={$_ | Get-networkAdapter | ? {$_.macaddress -eq“00:50:56:A4:22:F4“}}} |Where {$_.Network-ne “”}

(Courtesy of this page: http://www.virtu-al.net/2009/07/07/powercli-more-one-liner-power/ )

Thats really great, and you can easily extend the one-liner to include more data if you like. But for someone who isn’t comfortable with using PowerCLI yet, it can seem a bit terrifying. Therefore I usually create functions for long one-liners like this one.

A basic function doing the same thing can look something like this:

function Get-MACAddress ($MAC)
 {
 Get-vm | Select Name,Folder,PowerState, @{N="Network";E={$_ | Get-networkAdapter | ? {$_.macaddress -eq $MAC}}} | Where {$_.Network-ne ""}
 }

That way, it enough to type Get-MACAddress 00:50:56:A1:50:43

Or, you can take the time to create a proper function:

function Get-MACAddress 
{
 [CmdletBinding()] 
 Param (
 [parameter(Mandatory=$True,ValueFromPipeline=$True)][Validatelength(17,17)][string]$MAC,
 [string]$Location = '*'
 )
 Get-VM -Location $Location | Select Name,Folder,PowerState, @{N="Network";E={$_ | Get-networkAdapter | ? {$_.macaddress -eq $MAC}}} | Where {$_.Network -ne ""}
<#
 .Synopsis
 Searches vCentre for the given MAC address
 .Description
 This function searches the entire vCentre, or the given folder,datasenter,cluster,vApp or ResourcePool for VMs using the given MAC address. VMs with the given MAC address will be listed with Name,Folder,PowerState and to which network adapter the MAC address is assigned
 .Parameter MACAddress
 The MAC address you want to search for. Use the following format: 00:00:00:00:00:00
 .Parameter Location
 If you want to narrow the search to a specific folder,datasenter,cluster,vApp or ResourcePool
 .Example
 Get-MACAddress 00:50:56:a4:04:ce
 Searches the entire vCentre for VMs with the mac address 00:50:56:a4:04:ce
 .Example
 Get-MACAddress 00:50:56:a4:04:ce -Location vApp01
 Searches the vApp called vApp01 for VMs with the mac address 00:50:56:a4:04:ce
 .Link
 http://cloud.kemta.net
 #>
}

This more advanced function will allow you to narrow the search, it will check that the mac address you type is the correct length and it provides a little help section that you can call with get-help get-macaddress.

 

 

Posted in PowerCLI, Powershell, VMware Tagged , , , , ,

PowerCLI: List all vm’s with ISO mounted and dismount them

Easy-peasy and a pretty short post…

To get all vm’s with iso mounted:

Get-VM | Get-CDDrive | select @{N="VM";E="Parent"},IsoPath | where {$_.IsoPath -ne $null}

Then, to dismount those:

Get-VM | Get-CDDrive | where {$_.IsoPath -ne $null} | Set-CDDrive -NoMedia -Confirm:$False

Posted in PowerCLI, Powershell, VMware Tagged , , , , ,

PowerCLI: Migrate all vm’s on a datastore

PowerCLI is just awsome Smilie: :)

This simple one-liner migrates all vm’s off one datastore to a new one:

Get-VM -Datastore <datastore1> | Move-VM -Datastore <datastore2>

You can also move vm’s off one datastore and place them in any datastore within a specified datastore cluster:

$DatastoreCluster1 = Get-DatastoreCluster -Name 'DatastoreCluster1'
Get-VM -Datastore <datastore1> | Move-VM -Datastore $DatastoreCluster1

Posted in PowerCLI, Powershell, VMware Tagged , , , ,

PowerCLI: List all snapshots

It’s been a while since last update, again, so I figured I should at least provide something..

I recently started in a new job, and one of the first things I looked into was the amount of snapshots in our vmware environments. Not surprisingly there was a lot of snapshots, and very few of them had any hints of when they were taken and why.

The vsphere console doesn’t provide this info so I had to turn to PowerCLI to get the info I needed. PowerCLI is really just a snap-in to powershell so I felt right at home Smilie: :)

After you start PowerCLI, you need to first connect to your vcenter server:

Connect-VIServer <vcenter server>

You will be promted for username and password for vcenter. After powershell has connected to the vcenter server, all you need to is run this one-liner:

Get-VM | Get-Snapshot | Select VM,Name,@{N="SizeGB";E={@([math]::Round($_.SizeGB))}},Created

This will return a list of all vm’s, their snapshots, size of the snapshots and the date the snapshot was taken.

Posted in PowerCLI, Powershell, VMware Tagged , , , , , , ,

Powershell: Invoke-Sound function

I stumbled upon this brilliant powershell function for playing sounds using powershell, check it out: http://community.spiceworks.com/scripts/show/1337-powershell-function-invoke-sound

He even added a switch for playing the imperial march from Star Wars Smilie: :)

 

 

Posted in Microsoft, Powershell Tagged , ,

Powershell: Install role or feature on multiple remote servers

Today I was presented with a task that sounded pretty boring and repetitive: Install the Windows Search service on all our citrix servers.

Now, I could just log on each and every one of our citrix servers, open Server Manager and then install the role service but where’s the fun in that?

As always Powershell is a lot more fun:

First I had to find the name of all our citrix servers. Luckily we have a strict naming convention so I could just poll Active Directory and store the names in an array:

$servers = Get-ADComputer -Filter 'Name -like "ctx_srv*"' | select name

Next I only had to create a foreach loop that enters a PSSession on each of the servers and install the role service:

$servers | ForEach-Object {
 Enter-PSSession -ComputerName $_.name
 import-module servermanager
 Add-WindowsFeature FS-Search-Service
 Exit-PSSession
 }

It is worth mentioning that you can’t connect to remote servers using the Enter-PSSession cmdlet if you haven’t enabled remote management, if you want to enable it you can check this guide: http://blog.powershell.no/2010/03/04/enable-and-configure-windows-powershell-remoting-using-group-policy/

Posted in Microsoft, Powershell Tagged , ,

Powershell: Export-Csv and non-English letters

The Export-Csv cmdlet is a really nice tool if you want to gather info from e.g. Active Directory that you later want to import to Excel. But as you might have noticed it doesn’t play well with non-English letters.

Working in Norway with users from all the Nordic countries means that we have a lot of users i Active Directory who have non-English letters in their names (æ ø å ö ä and so on). Unless you specify which encoding Export-Csv should use they will show in the csv as ?.

The magical switch to Export-Csv is -encoding. E.g. for us we would use unicode as encoding as this will export the Nordic letters:

Export-Csv <filename> -Encoding unicode

 

 

 

 

 

 

Posted in Microsoft, Powershell Tagged , , ,