Get-view, list viewtypes, filter usage, Get-VIObjectbyVIView, and get-vm in powercli

From time to time i check my blog to see how people are getting to my blog 😉 Today i thought that if so many of you are trying to find this information although for some reason it is not in that post to which you are being redirected, i will create a new post about it. So that you will not be disappointed that the information is not there.
So few things about get-view. I think that VMware offers a GREAT documentation so why not take their explanation 😉

The vSphere PowerCLI list of cmdlets includes the Get-View and Get-VIObjectByVIView cmdlets, which enable access to vSphere PowerCLI views from .NET.

Using the vSphere PowerCLI views cmdlets for low-level VMware vSphere management requires some knowledge of both PowerShell scripting and the VMware vSphere APIs.

Continue reading

Change ESXi server license to evaluation while connected to esxi directly using powercli

In order to change license to the evaluation one when the host is still not connected to Virtual Center we can use this approach.

connect-viserver esxi1.local
$lm = Get-View -Id 'LicenseManager-ha-license-manager'
$lm.UpdateLicense("00000-00000-00000-00000-00000", $null)

This will change esxi licene to the evaluation one on Esxi 5.

Report for all vms regarding uuid,network card, macaddress, ipaddress, network card type e1000/vmxnet in a csv ;)

Right,
i wanted to see all vms, with their current ips, macaddresses, names, networkcard types.
This report should also have all network cards in separate columns in csv. So i needed to dynamically adjust number of those ‘columns’.
Below script will output only ipv4 addresses without ipv6.

$reportedvms=New-Object System.Collections.ArrayList
$vms=get-view -viewtype virtualmachine  |Sort-Object -Property {  $_.Config.Hardware.Device |  where {$_ -is [VMware.Vim.VirtualEthernetCard]} |  Measure-Object | select -ExpandProperty Count} -Descending 

foreach($vm in $vms){
  $reportedvm = New-Object PSObject
  Add-Member -Inputobject $reportedvm -MemberType noteProperty -name Guest -value $vm.Name
  Add-Member -InputObject $reportedvm -MemberType noteProperty -name UUID -value $($vm.Config.Uuid)
$networkcards=$vm.guest.net | ?{$_.DeviceConfigId -ne -1}
$i=0
foreach($ntwkcard in $networkcards){
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.Network" -Value $ntwkcard.Network
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.MacAddress" -Value $ntwkcard.Macaddress  
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.IpAddress" -Value $($ntwkcard.IpAddress|?{$_ -like "*.*"})
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.Device" -Value $(($vm.config.hardware.device|?{$_.key -eq $($ntwkcard.DeviceConfigId)}).gettype().name)
$i++
}
$reportedvms.add($reportedvm)|Out-Null
}

$reportedvms|Export-Csv c:\myreport.csv

Ok, and what if somebody doesn’t want those multiple columns, but wants to have only 1 column that will describe all network cards for particular vm ?

$vms=get-view -viewtype virtualmachine
$(
foreach($vm in $vms){
$networkcards=$vm.guest.net | ?{$_.DeviceConfigId -ne -1}
""|select  @{n="VM name";e={$vm.name}},@{n="uuid";e={$vm.config.uuid}},@{n="net  info";e={[string]::join(',',  $($networkcards|%{$devid=$_.DeviceConfigId;[string]::join(',',$(($vm.config.hardware.device|?{$_.key  -eq $devid}).gettype().name,$_.network,($_.ipaddress -join ';'),$_.Macaddress))})  )}}
}
)|export-csv c:\myreport.csv

I know 😉 a lot of joining.
@Update: Luc has noticed my error there that i was not sorting $vms array. We have to sort it by the vm with most network cards so that export-csv will work properly.
@Update: Thanks Steve for the feedback. I have updated the code in both examples.
27/02/2014@Update : Fixed issue with reporting multiple ip addresses in second example.

Searching for cdrom devices with Emulate Ide or Passthrough IDE mode in powercli

Right,
so we want to find all vms that have their cdrom device set to Emulate Ide mode.

$vms=get-view -viewtype virtualmachine
foreach($vm in $vms){
 if ($vm.Config.Hardware.Device |? {$_.backing -is [vmware.vim.VirtualCdromRemoteAtapiBackingInfo]}) {$vm.name}
}

If we want to look for vms with cdrom devices mode set to Passthrough:

$vms=get-view -viewtype virtualmachine
foreach($vm in $vms){
 if ($vm.Config.Hardware.Device |? {$_.backing -is [vmware.vim.VirtualCdromRemotePassthroughBackingInfo]}) {$vm.name}
}

No fancy output 😉 Just sending to screen affected vm names.

New-Folder in datacenter of vm type

I was trying to create a vm folder in Datacenter. This can not be achieved using new-folder directly without specifying proper location(as per MicaH comment) , because as per get-help from new-folder, this will result in creating a “yellow” host and cluster folder. In order to create a vm folder i had to use method CreateFolder(string)
Lets say i have a datacenter with name: “myDC” in which i want to create a folder “myTopLevelFolder”

(get-view (get-view -ViewType datacenter -Filter @{"name"="myDC"}).VmFolder).CreateFolder("myTopLevelFolder")

get-view -ViewType datacenter -Filter @{“name”=”myDC”}
We want to select only datacenter with name ‘myDC’
Then, we take the vmfolder from this datacenter
(get-view -ViewType datacenter -Filter @{“name”=”myDC”}).VmFolder
Then we create view from this:
get-view (get-view -ViewType datacenter -Filter @{“name”=”myDC”}).VmFolder
After that we can invoke method from this object using CreateFolder

It’s done 😉

How to check template settings without converting it to vm using get-teamplate and get-view?

So if we will look at a template vm using vSphere client we can’t see more than basic settings. We can check the guest OS, vm version, cpu, memory, vmware tools status, state, on which host was it registered, and on which datastore it resides. That’s it.
Ok, so in order to get some more information from template we can use get-view.

get-template vm2
-----
Name                Id
----                --
vm2            VirtualMachine-vm-738

Is this all ? Let’s see what else can we see using this view id

get-view -id (get-template vm2).id
-------
Capability           : VMware.Vim.VirtualMachineCapability
Config               : VMware.Vim.VirtualMachineConfigInfo
Layout               : VMware.Vim.VirtualMachineFileLayout
LayoutEx             : VMware.Vim.VirtualMachineFileLayoutEx
Storage              : VMware.Vim.VirtualMachineStorageInfo
EnvironmentBrowser   :
ResourcePool         :
ParentVApp           :
ResourceConfig       : VMware.Vim.ResourceConfigSpec
Runtime              : VMware.Vim.VirtualMachineRuntimeInfo
Guest                : VMware.Vim.GuestInfo
Summary              : VMware.Vim.VirtualMachineSummary
Datastore            : ...
Network              : {}
Snapshot             :
RootSnapshot         : {}
GuestHeartbeatStatus : gray
LinkedView           :
Parent               : Folder-group-v..0
CustomValue          : {..}
OverallStatus        : green
ConfigStatus         : green
ConfigIssue          : {}
EffectiveRole        : {-1}
Permission           : {}
Name                 : vm2
DisabledMethod       : {MakePrimaryVM_Task, TerminateFaultTol
RecentTask           : {}
DeclaredAlarmState   : {}
TriggeredAlarmState  : {}
AlarmActionsEnabled  : True
Tag                  : {}
Value                : {507}
AvailableField       : {}
MoRef                : VirtualMachine-vm-738
Client               : VMware.Vim.VimClient

So as you can see we can see similar output as if you would apply get-view to normal virtual machine. From here you can query your template just as it would be virtual machine. What is worth mentioning here is that it will be impossible to make any tasks on the template, but still we can get information.
So let’s check for example what network interfaces our templates has:

$templateview=get-view -id (get-template vm1).id
($templateview.config.hardware.device | ? {$_ -is [vmware.vim.VirtualVmxnet]})|%{$_.DeviceInfo}
--------
Label                      Summary
-----                      -------
Network adapter 1          VM Network

So we can see that we have 1 network adapter which is connected to ‘VM Network’ portgroup.
Now let’s see how were the disks configured

($templateview.config.hardware.device | ? {$_ -is [vmware.vim.VirtualDisk]})|%{$_.DeviceInfo}
---------
Label                         Summary
-----                         -------
Hard disk 1                   1,048,576 KB
Hard disk 2                   1,048,576 KB

Now again, we create some templates and we try to remind “have i put this floppy device or not ?” So normally you would have to mark template as a vm, then edit settings and so on..
Let’s check if i have put floppy to template:

($templateview.config.hardware.device | ? {$_ -is [vmware.vim.VirtualFloppy]})|%{$_.DeviceInfo}
--------
Label                                        Summary
-----                                        -------
Floppy drive 1                               Remote
Floppy drive 2                               Remote

Wow! Not one but two! 😉
Ok few times i have seen situation when people were surprised that some of vms have memory reservations/limit on them and they were wondering how ?! “i did not set it up”
Let’s see if we have some memory limits or reservations

$templateview.ResourceConfig.MemoryAllocation
----------
Reservation           : 100
ExpandableReservation : False
Limit                 : -1
Shares                : VMware.Vim.SharesInfo

Well it seems that my template has 100 mb memory reserved, and no limit set. You can query cpu allocation as well:

$templateview.ResourceConfig.CpuAllocation
----------
Reservation           : 0
ExpandableReservation : False
Limit                 : -1
Shares                : VMware.Vim.SharesInfo

What tools upgrade policy will my vms have after deployment ? We can also check this :

$templateview.config.tools.ToolsUpgradePolicy
----------
upgradeAtPowerCycle

Nice… And all this information AND MORE! we can grab without converting template to vm. So if you want really quickly take a look on some specific property of your template , get-view will help you out 😉

Storage vmotion to different datastores for different vm hard disks

I’ve spent some time today figuring out how to do storage vmotion so that 1 disk could go to datastoreA, and 2nd disk could go to datastoreB, and forexample to choose if i want to move the configuration vm files to different datastore. After playing 20 minutes with onyx and reading api guide for 30 minutes i have finally made it 😉
RelocateSpec
RelocateSpec is most important thing in writing the relocatevm_task
relocateVM_task description

You can omit the $spec.datastore object when you do not want to move vm config files.
This is example if you would have 3 disks inside vm, and would like to send disk 1 to ds1, disk 2 do ds3, and disk3 to ds3.This example also moves configuration files of vm to datastore selected in $vmxds

$ds1=(Get-Datastore your_1_destination_datastore|get-view).moref.value
$ds2=(Get-Datastore your_2_destination_datastore|get-view).moref.value
$ds3=(Get-Datastore your_3_destination_datastore|get-view).moref.value
$vmxds= (Get-Datastore your_vmx_destination_datastore|get-view).moref.value
$myvmtomove=get-vm 'some_vm'
$disks=$myvmtomove|Get-harddisk|% {$_.id.split('/')[1]}  #-> 3 disk ids should be here
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec

$spec.datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.datastore.type = "Datastore"
$spec.datastore.Value = $vmxds

$spec.disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator[] (3)
$spec.disk[0] = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$spec.disk[0].diskId = $disks[0]
$spec.disk[0].datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.disk[0].datastore.type = "Datastore"
$spec.disk[0].datastore.Value =  $ds1
$spec.disk[1] = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$spec.disk[1].diskId = $disks[1]
$spec.disk[1].datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.disk[1].datastore.type = "Datastore"
$spec.disk[1].datastore.Value =  $ds2
$spec.disk[2] = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$spec.disk[2].diskId = $disks[2]
$spec.disk[2].datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.disk[2].datastore.type = "Datastore"
$spec.disk[2].datastore.Value = $ds3

(Get-View -Id $myvmtomove.id).RelocateVM_Task($spec, "defaultPriority")

Moving VMX to location of Disk1 datastore in case there is only 1 hard disk in vm:

#Script:
#Get our VMa
$VMname = 'VMa'
$vm = Get-View  -viewtype virtualmachine -Filter @{'name'=$VMname}
#you need to make sure you get only 1 vm, normally that's the case...

#VMa vmx path
$VMXpath = ($vm.LayoutEx.File |?{$_.Type -eq 'Config'}).Name
Write-Host "VMx lays here: $VMXpath"

#don't do anything if you have more than 1 disk
if (@($vm.LayoutEx.Disk.Key).length -eq 1){

#don't do anything if you will spot snapshots
if (@($vm.LayoutEx.File |?{$_.Type -eq 'diskDescriptor'}).length -eq 1) {

#Disk1 path
$Disk1path = ($vm.LayoutEx.File |?{$_.Type -eq 'diskDescriptor'}).Name
Write-Host "Disk 1 lays here: $Disk1path"

$Disk1ID = $vm.LayoutEx.Disk.Key
$Disk1Device = $vm.Config.Hardware.device | ?{$_.Key -eq $Disk1ID}
$Disk1DeviceDatastoreMoref = $Disk1Device.Backing.Datastore
#Writing spec
#Move VMX to Disk1 datastore spec

$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.datastore.type = "Datastore"
$spec.datastore.Value = $Disk1DeviceDatastoreMoref.Value

#Disk1 stays where it is, if you dont add this , you will move the Disk to the vmx DS
$spec.disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator[] (1)
$spec.disk[0] = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$spec.disk[0].diskId = $Disk1ID
$spec.disk[0].datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.disk[0].datastore.type = "Datastore"
$spec.disk[0].datastore.Value = $Disk1DeviceDatastoreMoref.Value

$vm.RelocateVM_Task($spec, "defaultPriority")

#check
$vm = Get-View  -viewtype virtualmachine -Filter @{'name'=$VMname}
$VMXpath = ($vm.LayoutEx.File |?{$_.Type -eq 'Config'}).Name
Write-Host "VMx lays here: $VMXpath"
$Disk1path = ($vm.LayoutEx.File |?{$_.Type -eq 'diskDescriptor'}).Name
Write-Host "Disk 1 lays here: $Disk1path"

}

}else {Write-Error "Amount of disks is not equal to 1"}

And i wrote recently this example , function to move VMX to destination DS of a particular disk name.

Function Move-VMX{
param([Parameter(Mandatory=$True,Position=1)][string]$VMname,[Parameter(Mandatory=$True,Position=2)][string]$disk)

#Get our VM
#disk is 'Hard disk 1' , or 'Hard disk 2', same as you see in vsphere client

$vm = Get-View -viewtype virtualmachine -Filter @{‘name’=$VMname}

if(($vm.Config.Hardware.Device |?{$_ -is [vmware.vim.virtualdisk]}) | ?{$_.DeviceInfo.Label -eq $disk})
{

$disks = $vm.Config.Hardware.Device |?{$_ -is [vmware.vim.virtualdisk]}
$VMXDestinationDisk = ($vm.Config.Hardware.Device |?{$_ -is [vmware.vim.virtualdisk]}) | ?{$_.DeviceInfo.Label -eq $disk}

$VMXDestinationDatastoreMorefValue = $VMXDestinationDisk.Backing.Datastore.Value

$numberOfDisks = @($disks).Length

#VM vmx path
$VMXpath = ($vm.LayoutEx.File |?{$_.Type -eq ‘Config’}).Name
Write-Host “VMx lays here: "$VMXpath

#DEstination disk path
Write-Host “Disk $disk lays here: "$VMXDestinationDisk.Backing.FileName

foreach ($dsk in $disks){
Write-Host "Disk "$dsk.DeviceInfo.Label" Lays in: " $dsk.Backing.FileName
}

#Writing spec
#Move VMX to Disk destination

$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.datastore.type = “Datastore”
$spec.datastore.Value = $VMXDestinationDatastoreMorefValue

#Specs to make our disks stay where they are
$spec.disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator[] ($numberOfDisks)
$i=0
Foreach($dsk in $disks) {
$spec.disk[$i] = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$spec.disk[$i].diskId = $dsk.Key
$spec.disk[$i].datastore = New-Object VMware.Vim.ManagedObjectReference
$spec.disk[$i].datastore.type = “Datastore”
$spec.disk[$i].datastore.Value = $dsk.Backing.Datastore.Value
$i++
}

Write-Host 'Started task for moving now VMX '$VMXpath' to '$disk' location'
$task = $vm.RelocateVM_Task($spec, “defaultPriority”)

} else {Write-Error 'Could not find the disk, example: ''Hard disk 1 '' '}
}