How to Use PowerCLI Get-VM | get-explanation

by Grzegorz Kulikowski
get-Vm | Get-Explanation

In the beginning there was Get-VM

No, actually not, in the beginning there is get-help, try to memorize that, GET HELP. Easy no ? Get dash help, after that it’s get-vm.. Well no, still joking, after that there is get-command, and then there is get-vm . Hehehe ,alright i tried to be funny, and it ended up like always.. As you probably noticed, i have started to put more time into my blog. I am still thinking about how to do many things here, so it will easy for you to find the things you are looking for, and do it as quick as possible. I thought i could introduce a series of posts ‘ get-explanation ‘ where i would be explaining the basics.

If you are pro, i guess there are small chances you will find something revolutionary in them, but still, who knows 😉 We can’t ignore the basics, the fact you know X, doesn’t mean that everybody else knows it, and sometimes it’s just good to revisitthe basics. Since i am already here, writing about the basics, did you know that get-help does not only contain the help for particular commands but also explains the powershell language and things around it as well ?

We use Get-Command to help us understand how the Get-Help cmdlet works, to be more specific, we try to understand what is behind the ‘Category’ parameter. What i wanted to show you is that there are also ‘books’ / ‘helpfiles’. In my opinion your goal is to be able to find it on your own, hence that above example. One other thing of figuring out that there was a category like HelpFile, is to ask Powershell to tell you this 😉

If we will make a mistake on purpose in typing, Powershell (people that wrote this cmdlet) is so nice that it suggests us the possible/valid values. You would know now, that there is a category like HelpFile.

get-help -category helpfile
get-help -category helpfile

From here you would know now that you can read a help about ‘Arrays’, get it ? about_Arrays .. (another failed pun xD). Anyway, you could now read it by using Get-Help -Name about_Arrays

get-help about_arrays
get-help about_arrays
about_arrays on microsoft docs
about_arrays on microsoft docs

This looks familiar no ? You have this information in your powershell session, but if it’s easier for you to read it online, you can always access this information through your browser https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_arrays?view=powershell-7

Basics

This brings us to the PowerCLI basics, the Get-VM. I mean if you just have installed PowerCLI, i bet the first thing that comes to your mind to test it is

SHOW ME THEM VMS !

This is the beginning and starting point for a lot of administrators that start their journey with PowerCLI. I wanted to write today about this very cmdlet. How can you check yourself what’s going on in Get-vm, or any other cmdlet later on. Let’s have a quick look, the starting point is Get-Help.

Get-Help Get-VM
Get-Help Get-VM

You can also open the help via the online docs at VMware Code website:

Get-VM at VMware code website
Get-VM at VMware code website

In regards to the VMware Code website/documentation, you have to be careful what you type in the search box. The top left corner is an input box where you type the command, it’s case sensitive. If you would type gEt-Vm, no results will be given. It’s just something you have be aware.

Let’s start from what we see at the help page:

Get-Help Get-VM ParameterSet
Get-Help Get-VM ParameterSet

I have used 4 colors / lines, to get your attention to those lines. They are quite important sections of help. They should ring a bell immediately when you look at any command. That does not ring a bell to you ? Then this paragraph is a must read. I would strongly advise you feel really comfortable with this output. It will help you almost immediately understand what is being required from you in order to run the cmdlet.

what are those meme
what are those meme

ParameterSet

Those are parameter sets. They describe the way how the author of the cmdlets envisioned using / calling it. No, it’s not hard to understand, and it is obvious why it looks sort of like a mini martix to you right now. Author of cmdlet states by them that you can run this cmdlet in 4 different ways. 4 separate ways. Those are unique ways. Author has some expectations about how does one run it. It is being expected from us, to run EXACTLY the way we were asked to in the ParameterSet. You will notice, that i am now reffering to the stuff i wrote about earlier in the post ( i hope you did not cheat, and scrolled down here 😉 ). How do we know how many parametersets are there?

We clearly see that there are 4 parametersets. We can count them using the .count

You have to put only those parameters in the command that are part of a single parameter set. You see the redline parameterset ? Ok, it has a parameter called RelatedObject, now look at the purple line, you see the Id parameter. What i am trying to say is that you can’t run this cmdlet using parameters from different parametersets that only exists in their own set. Powershell will not understand which paramterset is being ran. He can tell this by looking at the parameters that are given.

If only RelatedObject would be passed, he would know that oO, watch out this is parameterset ‘RelatedObject’ i will be now running command in way purple.. If you will give him mixed signals by using -RelatedObject and -Id he can’t clearly state which parameterset it is, as 1 parameter comes from the red set, and 1 parameter from pink. There is no (red+pink) set, there is only red AND pink..

Update 1

To clear more on parametersets i made this tiny graphica(please ignore the colors inside, they have nothing to do with the colors from above)

Powershell has to chose the right parameterset. So If you would chose just 1 parameter called ‘name’, would you be able to identify in unique way the right parameterset ? First what comes to you mind is ‘NO’, no because the name parameter exists in two sets, it is used in the ‘default’ and ‘distributedswitch’ parameterset. But but but but , ‘you wrote that i can use Get-vm -name ‘myvmname’

Math Lady / Confused Lady | Meme, Relaties, Achtergronden

Yes 😉 Welcome to the powershell Neo, lots ahead of us 😉 There is a special cmdletbinding attribute [CmdletBinding(DefaultParameterSetName = ‘ParameterSetName’)] that is helping in those cases. If you have enough parameters in order to run the right parameterset, and it ends up that there are two parametersets to chose from,

your command will go into that parameterset which is marked with DefaultParameterSet. In the case of Get-VM the parameterset name that is default is ‘default’. I know … i know.. it’s bit confusing, but its named like this. It doesn’t have to be named ‘default’ , it can be whatever you want when you will be designing your own cmdlet. So, so when powershell sees that he can use 2 paths , he will go with the one marked as being the default one. I want to show you that default parameterset does not have to be named ‘default’.. Let’s open an example from powershell help

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parameter_sets?view=powershell-7#:~:text=32%20parameter%20sets.-,Default%20parameter%20sets,information%20provided%20to%20the%20command.

Have a look at the function measure-lines

This is the source, and we clearly see inside that defaultparameterset i pointing to the parameterset ‘Path’, but we also check this on our own:

Again, benefiting from basics, get-help, get-command, your best buddies 😉

Now , the easier bit, so to select proper path for the ‘distributedswitch’ parameterset we have to use some uniqe parmater like virtualswitch:

When virtualswitch parameter is specified, its really easy to tell which parameterset will it be, DisitributedSwitch because its the only parameterset that actually has a parameter called ‘virtualswitch’. Same for relatedobject. I hope this is clear, but if for some reason it’s not , please do leave a comment below the post.

Parameters

Parameters
Parameters

You are doing good ! If feeling dizzy, go on fresh air, make tea/coffe. This is very important. I have highlighted in green, pink, red 3 different parameters. The green parameters name is Name, the pink parameter name is Server, the red parameter name is Id. Those are not just some parameters. To the right side of parameter name you can find its object type. The name is a string object, the server is a VIServer object, and Id is String object. String[] <- those brackets next to ‘String’, they mean that it can be 1 String and multiple Strings (more than 1).To exit the shortcuts i should write:

Now, let’s get back to the parameters. The green Name is inside [ ] brackets . What does mean if parameters is inside square brackets ? That it is optional, you can use it, but you don’t have to use it. [ -param <type>] now, what does mean if there are not any square brackets around the parameter ? Well, you guessed it, the opposite, meaning this is MANDATORY parameter and you have to use it. The green name is bit specific, inside the square brackets there is [-Name] …

Parameter inception…

It means that the parameter name is optional, meaning you do not have to use the -name for the parameter. I know it sounds crazy but bear with me. This implies that the parameter is positional, powershell will understand that you are submitting him VMNameABC as parameter name, because he EXPECTS it to be on the first position. How come i know it expects it on first position ? 1 – because its on the most left side in the command syntax, and 2 –

because it is being reported with ‘Position 0’. Let me show this :

This is quite clear, we gave the parameter Name value of a string ‘centos’. In return get-vm has returned us a ??? something ??? that looks like our vm and we see there centos in name. This is for later but for now you should understand that we have received a virtual machine object :

Alright, now let me explain whats with the positional thingy. It simply means that if i put it to position 0 (first position after cmd) it will get treated as the parameter ‘Name’ , and its treated like the name parameter now because you are telling him : look its a -Name ‘XyZ’ , but : look , its on the first position, so this is the name ‘ZyZ’

See ? we just wrote ‘centos’ and he understood that we gave him the value for ‘Name’ parameter. Let’s try see what happens if we will do what we were not supposed to do, mix the parameters from different parametersets.

He refuses to run it, because there is no clear way for him to pick the right parameterset.

Let’s have a look at the highlighted in red ‘Id’ parameter. You noticed that it has no square brackets around the entire parameter, nor it has any square brackets around his param name. This means that you can’t skip it, you can’t not use the parameter name

That’s right, you guess it, i tried to give him the VM id , but thought i am giving him the name of the virtual machine which would be equal to ‘VirtualMachine-vm-70’. That’s the reason why you can’t omit the -Id param, otherwise it would be not possible to understand what do you mean by this.

If you give him now properly the value for id , he returns us the VM object. To recap, parameters can be positional, mandatory, they are of a special type. You can read more about them in .. YES !! that’s righ in get-help -name about_parameters or using online version https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parameters?view=powershell-7 .

Get-VM parameter : Server

You will see this basically a lot when working with PowerCLI cmdlets. What can we learn on our own about the server param ? Let’s have a look:

get-help get-vm -parameter server
get-help get-vm -parameter server

Is it named paramater that has no default value and it’s not required for you to type it. It does not mean its not being used in behind the scenes. If you will not specify the -server parameter, it will be used according to your current configuration from Get-PowerCLIConfiguration

There can be Single or Multiple. When in single, the -Server parameter will get default to $global:defaultVIServer , when in Multiple, it will utilize the $global:defaultVIServers (plural). In single mode, when you will connect first to virtual center ‘vcA’, then you will connect to ‘vcB’, and after that you will conenct to ‘vcC’, at the moment if you would issue ‘get-vm’ if you use the last virtual center to which you have connected. It would be vcC. When in multiple mode, you would be storing your virtual center servers in an array, and the get-vm would submitted to all of the virtual centers, meaning you would get vms from vcA, vcB, vcC

This is something you have to be careful with, and always remember. Most people do not specify the -Server parameter, as i believe this is not natural when typing the command. I mean, why on earth would i specify the server parameter if i am just connected to my 1 virtual center, i just got 1 virtual center. Right, but please remember that besides ‘tiny labs’ this product is also ran in enterprises where you can multiple virtual centers connected in SSO domain, and they are big… BIG , PHAT, CHONKY, you know.. like my cat roger … look at this beautiful chonk

Now this was some introduction

Alright , i hope you are alive and kicking, and ready for the get-vm part now 😉 Why this long introduction ? It’s just simply crucial later on to understand what you will be dealing with. We can obtain virtual machines from the virtual center in 4 ways( parametersets).

get-vm syntax
get-vm syntax

First one is by simply giving to the cmdlet the VM name/s, Datastore on which they reside, Location where they are, the TAG they got marked with. On top of that in case they are in some container you can chose not to get recursive with things.

If you have a Folder in which you look for vms, that contains more folders inside with even more vms (in which you have no interest seeing) you can use the -NoRecursion switch. You notice what i just wrote ? ‘Switch’, i used this word because the parameter type is a ‘Switch’ , it can either be on or off ,like a switch 😉 If you would use it in your cmdlet by typing -SomeSwitch , it will get set to ON, as it’s true that its there. If you would not mention it, it’s set to off as its not there. You can also be really explicit and just state -Someswitch:$True or -SomeSwitch:$False ( in this case you explicitly pointing out that it has to become not true – false.

VIInventory
VIInventory

Let’s obtain our vms from TestFolder

get-vm with location parameter
get-vm with location parameter

How come we see 2 vms? Well, that’s because we are asking to obtain ALL vms that are in folder TestFolder and any other folderds down the path. What you did not see is that inside the ‘DontLookHere’ i also squeezed 1 vm.

So in order to get only the ‘vrealizelcm’ vm, we would have to use the switch parameter called ‘NoRecursion’.

Get-VM with norecursion
Get-VM with norecursion

Much better. But stil.. not explained entirely. Let’s EXPLAIN !!! What’s with the Location thingy ? How come this worked, i could just put a name of a folder there ? What is there to help us ? GET-HELP

So what does this all mean ? <type>, remember ? so this magic VIContainer is a type, so objects of this type can be passed to the -Location parameter. VMware PowerCLI team did a great job, and also provided us some documentation for the parameter, and we know that this supports a Folder (blue/yellow), Cluster, Datacenter and so on. I saw people (including me as well) using it for example like :

But by now, you know that this can be written easier, by passing to the Location paramter the folder name.

MORE !!! MORE EXPLANATION !!!

Okey, so how come we could put a folder inside the -Location parameter ?The type for Location is VIContainer, so we can lookup the folder on our own and that type is not the VIContainer.

Magic… Definitely MAGIC . So, this is because it implements the VIContainer interface

We checked the Folder type, and it’s compatible with the VIContainer. Last way from the default parameterset is to obtain VMs from the particular datastore/ds clusters but using the -Datastore parameter. We can check it with get-help. You will see that we can pass not 1 datastore, but more , because of StorageResource[] <- 1 or more (Array)

get-help -parameter 'datastore'
get-help -parameter ‘datastore’

Not only you can just type the name of your datastore

get-datastore and get-vm without pipeline
get-datastore and get-vm without pipeline

but since it is accepting pipeline input we can throw the datastore object from the left side via the pipe on it.

get-datastore and get-vm
get-datastore and get-vm

What about the fact that we can pass the datastore the parameter -Datastore using a string instead of the real datastore object ? It’s about OBN transformations described more in details here : https://pubs.vmware.com/vsphere-51/index.jsp?topic=%2Fcom.vmware.powercli.cmdletref.doc%2Fabout_obn.html . The OBN feature will transform our text into the right object. This is also valid for many other parameters, not only the datastore (I mean PowerCLI cmdlets/parameters).

trace-command with parameterbinding
trace-command with parameterbinding

As you can see above, we know that the Datastore parameter can get transformed into either a Datastore, or DatastoreCluster.

To make this more clear you should have a look about Argument Transformation Attribute. To give you some quick / brief impression of how it would work, have a look at the below script i wrote. Test-VMPowerState function job is to write to the host if the VM is poweredoff or poweredOn for example. This function takes 1 parameter (obj) which is a VM, and a VM might be a real Virtual Machine object that we already pulled using a Get-VM, or it could be just a plain String (that would pointing to vm name), or a view, or a something that is being returned by get-viobjectbyviview (VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl). Below is some tiny implementation of this.

So my parameter is fine if fed with text, vm, view, the ‘other almost vm’ types.

ByID

So the parameterset ByID is nice and easy it expects us to provide a string for parameter ID. What is an ID ? it’s a unique label for your entity in VirtualCenter , the VM has a Name and MoRef ID (Managed Object Referece). Let’s not get into details right now 😉 All you need to know, is that that there can be 10 virtual machines with the same nam of ‘MyVM’ but just 1 VM with id of ‘VirtualMachine-vm-128. You need to know the ID in first place, so let’s obtain it:

Alright , so now we can call it like:

Third parameterset contains the Tag/VirtualSwitch/Name , for example if we would want to find only those VMs which are tagged with tag: ‘TestTag’

get-vm with tag parameter
get-vm with tag parameter

Check vms which are connected to a distributed switch using the -VirtualSwitch parameter

get-vm with virtualswitch parameter
get-vm with virtualswitch parameter

You can wonder why the parameterset allows us to select not only the Tag/Switch but also a name ? Well, that’s because you might wanted to ask for VMs that belong to a TAG, but from that set you just want a particular one with a special name.

get-vm using tag parameter
get-vm using tag parameter

There is nothing wrong i guess if you would just obtain all the vms from TAG ‘TestTag’ and they filter it on your end with a Where-Object cmdlet. Important thing that you need to know at this moment is that , the more thing you filter on API/Server side, the faster the cmdlet will process. There is no need to download all the objects to compare their names on your computer in your powershell session, let your virtual center do this for you.

Last but not least – RelatedObject

The whole idea here is that , there are some objects that relate to yours in some way. Because they relate, you can obtain your VM but looking at the relation between them. Let’s say that you want to get a VirtualMachine that relate to a virtual port group from some virtual distributed switch

The virtual portgroup imeplements the interface VMRelatedObjectBase

DVSwitchPort type and implementedInterfaces
DVSwitchPort type and implementedInterfaces

It will fit without any issues for the -RelatedObject parameter. There is no OBN happening for RelatedObject parameter, so don’t try to give it a value of for example ‘name of the portgroup’, etc..

As it will fail

Get-VM examples

Always remember about virtualmachines that can have the same name.

This is not a glitch in the matrix, there are 2 VMs with name ‘vrealizelcm’. I know, shocking…

Roger shocked by the fact one can have vms with the same name

In order to have vms with the same name, you have to separate them with some container. You can’t create a VMs with the same name in the same container.

Those two vms are in different folders, lets try to create another ‘vrealizelcm’ vm inside the ‘DontLookHere’ folder:

Oopsie, can't create vms iwht the same name in the same folder
Oopsie, can’t create vms iwht the same name in the same folder

Let’s create another folder inside the ‘DontlookHereFolder’.

There we have it, 3 vms with name ‘vrealizelcm’. Can you imagine what would happen if you would do get-vm -name ‘vrealizelcm’ |remove-vm ? Instead of deleting 1 vm, you would get rid of 3 vms. Bummer… well , thank god that the remove-vm has a prevention system, that asks you if you really want to do it (ConfirmImpact) that is set to high, you would be asked 3 times if you are really sure. If you would not know that you had 3 vms of the same name, you might just think that ‘ahh another, glitch in the matrix’, i had to press 3 times yes 😉 hehe.

Let’s get some more information about the vms. The information is already there, we just don’t see it, but it’s there. Have a look:

So we know the name of the vm, the powerstate , amount of cpus, and memory in GB. Is that all ? No. This is just default displaying behavior, you will see 4 columns/properties.

In case you want to understand why do you see columns like this. for example if you ever wondered why there is displayed here column ‘Num CPUs’ , but when you would list all the VM properties you would not find anything like this ? Here is the explanation:

get-formatdata with VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl type
get-formatdata and get-formatdata with VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl type

Our VM type has a format for displaying the object that states that Name,PowerState, Num CPUs, MemoryGB will be displayed when displaying the VM object. Values coming from Name,PowerState,NumCPU, “{0:N3}” -f $_.MemoryGB will be used for providing the data. (That par with the memory string format, you dont see on the picture, but it is there).

get-formatdata with VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl type
get-formatdata with VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl type

Might be handy to read later as well:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_format.ps1xml?view=powershell-7

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_types.ps1xml?view=powershell-7

Ok, remember what i wrote in the begging ? That bla bla bla ‘something’ that looks like vm ? Ok, lets inspect this something. This is actually a Virtual Machine object. It’s time to meet our new best buddies, .gettype(), get-member . In the picture below you see ‘gm’ which is an alias of ‘get-member’, a lot of people write gm instead of get-member, please have this in mind.

get-member properties of virtualmachine

Those are the properties of the

Virtual machine type. You check the type by invoking method ‘gettype()’ on an object. Since my virtual machine object is now inside a variable $myvm i can call the methods on it.Now you see that there are way more properties inside our received Virtual Machine object. What is the fastest, easiest way to show them on the screen ? Using a format-list .

get-vm | format-list
get-vm | format-list

Now you should connect the dots, and think : ahh.. that explains why there is just 4 colums when displaying the $myvm, otherwise it would not be readable if we would have to squeeze so many columns. Later on i will show you how to chose the right set of properties you want. For the really curious ones, ‘hey, but that’s not enough of information!, need more, more more more’, have a peek what is inside the ‘ExtensionData’ 😉 Ohh boy.. another rabbit hole.

Extensiondata of VM
Extensiondata of VM

If you don’t remember full name for a vm name, datastore name, whatever name, you can use a wildcard get-vm -Name ‘*10*’ That way all vm with names that match anything_10_anything will be returned. I want also to show you something since we are now talking about wildcards. * is a wildcard, so is a ? . Let’s say i have a virtual machine called greg in square brackets, like so:

greg vm with square brackets

Ok, let’s fetch this one. So…

Nope, that did not go well. That’s because, what i forgot to tell you, and that’s what a lot of people forget is that a [ and ] are also wildcards. [set_of_characters_that_can_match] . So for example

powershell wildcard character [ ]

Now, if you will ever have to get the [name], you will have to escape the wildcard characters with ` a backtick or double backtick for double quotes, so :

escape [ ] characters for get-vm

Summary

Ahh yess… now we understand what’s what. So nice.. sooo fluffy.

Roger understands
Roger understands

That being said… I mean yeah well.. Seriously that’s lots of stuff happening here. I bet you expected something more like ‘Ohh you know, its easy, you just get-vm myvm, and bob’s your uncle’ … but no… 😉 When i started to spend more and more time with powershell, i just had to understand why sometimes things that i try to run fail… This was showing me how little i knew, and i still probably don’t know. .

I hope i explained it for you , i tried to be as precise as i could, if by any chance i left something not clear, please do leave a comment and let me know. I really want to make others understand this, i am not writing it just to write, for myself (i mean partially yes – as i also learn more while writing it ). Please remember, there are no stupid questions etc, i was rushing at the end, i will probably make few more review of this, For now , that will be all.

Big thanks

go to Chris Dent, for being so supportive and helping me out with explaining some powershell quirks, without him i would not be able to explain this is such a great detail.

You may also like

1 comment

danielhanaj (@donkojott) July 6, 2020 - 10:08 pm

This is brilliant blog entry. Wish that more bloggers would describe “basics” like you’ve just did. Looking forward for more content for beginners from your end and thank you for your hard work!

Reply

Leave a Reply

Chinese (Simplified)EnglishFrenchGermanHindiPolishSpanish