VMware Cloud Community
FruitFly
Contributor
Contributor

Get Disk Type (HDD/SSD) of all VMs in a specific vcenter server

Hello everyone,

I am in dire need of your knowledge (and probably wisdom too).

I am currently trying to get into powershell and powercli.
My first project is almost complete and most everything works.
EXCEPT one thing.

The script gives me a list (csv) of VMs including a lot of relevant informations, such as OS, Number of vCPUs, RAM, Storage space summed up and several custom fields.

But I can't for the life of me get one thing to work:
For each VM listed I want to display all attached disks including if they are HDD or SSD (e.g. VM1 should have listed "300 GB HDD, 500 GB SSD, 250 GB HDD")

Now I tried to first only list HDD  and SSD and take it from there:
@{n="HDD/SSD"; e={[string]::Join(',',(foreach ($disk in (Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name)) {if ($disk -eq 'Datacenter-Name1' -or $disk -eq 'Datacenter-Name2' -or $disk -eq 'Datacenter-Name3'){'HDD'} elseif ($disk -eq 'Datacenter-Name01-lun0' -or $disk -eq 'Datacenter-Name10-lun1 (Reserve)' -or $disk -eq 'Datacenter-Name2-lun0' -or $disk -eq 'Datacenter-Name2-lun1 (Reserve)'){'SSD'} else}{'SSD'}{'Please check Datastore'}}))}}

With the names Datacenter-Name1 etc. being the actual Datacenter names.

But somehow my IDE tells me this will never work and I can't figure out why.
I also played around with get-HardDisk and Get-PhysicalDisk, but this yielded no results either.

Can anyone point me into the right direction. I feel like this is probably way less complex then I make it out to be.

Thanks in advance
FruitFly

Reply
0 Kudos
11 Replies
LucD
Leadership
Leadership

What IDE are you using?
And what exactly do you have in there?
And what is the message you get from the IDE?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

FruitFly
Contributor
Contributor

Sorry for not putting this in earlier.

These are the error messages I get in Visual Studio Code (and when I try to run the script):

 

At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:482
+ ... Sum}},@{n="HDD/SSD"; e={[string]::Join(',',(foreach ($disk in (Get-Da ...
+                                                                ~~
Unexpected token 'in' in expression or statement.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:481
+ ... m).Sum}},@{n="HDD/SSD"; e={[string]::Join(',',(foreach ($disk in (Get ...
+                                                                  ~
Missing closing ')' in expression.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:554
+ ... astore -Id $_.DatastoreIdList | Select -ExpandProperty Name)) {if ($d ...
+                                                                  ~
Missing ')' in method call.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:555
+ ... tore -Id $_.DatastoreIdList | Select -ExpandProperty Name)) {if ($dis ...
+                                                                 ~
Unexpected token '{' in expression or statement.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:446
+ ... re-Object -Property CapacityGB -Sum).Sum}},@{n="HDD/SSD"; e={[string] ...
+                                                                 ~
Missing closing '}' in statement block or type definition.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:868
+ ... -lun1 (Reserve)'){'SSD'} else{'Bitte Zieldatastore pruefen'}})}},@{n= ...
+                                                                  ~
The hash literal was incomplete.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:868
+ ... lun1 (Reserve)'){'SSD'} else{'Bitte Zieldatastore pruefen'}})}},@{n=" ...
+                                                                 ~
Unexpected token ')' in expression or statement.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:869
+ ... un1 (Reserve)'){'SSD'} else{'Bitte Zieldatastore pruefen'}})}},@{n="T ...
+                                                                 ~
Unexpected token '}' in expression or statement.
At C:\Users\User1\Documents\Skripte\highwaytoshell.ps1:11 char:870
+ ... n1 (Reserve)'){'SSD'} else{'Bitte Zieldatastore pruefen'}})}},@{n="TN ...
+                                                                 ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

 



Reply
0 Kudos
LucD
Leadership
Leadership

I tried to untangle that snippet of code you posted earlier, but I'm sorry that does not make any sense at all for me.
Is this an attempt at a calculated property part of a Select-Object, in a script?
The context of what you posted completely escapes me I'm afraid.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

FruitFly
Contributor
Contributor

Before I answer: Thanks for trying so far! I really appreciate that.

My end goal for this snippet is a column that displays all the disks appointed to a VM with total capacity and disk type.

For example VM1 has three disks attached: Disk1 with 500 GB SSD, Disk2 with 300 GB SSD and Disk3 with 450 GB HDD.
In this case the column should display 500 SSD, 300 SSD, 450 HDD

My script starts with a "Get-VM".
The way I tried to solve the first step (getting HDD/SSD without the actual size of the disk) is by piping the VM-Name into a "Get-Datastore -Id $_.DatastoreIdList", thus getting the Datastore name. I then hard coded some if loops into associating each Datastore name with either SSD or HDD. These loops should be run through for each disk attached to the VM.
The end result then should be joined with a comma separation and given out as the column entry.

I hope this clears up my (often times screwed up) thought process.

Reply
0 Kudos
LucD
Leadership
Leadership

Why don't you use the SSD property on the datastore object?
Something like this for example


Get-VM -PipelineVariable vm |
Get-HardDisk -PipelineVariable hd |
Select @{N='VM';E={$vm.Name}},
  @{N='HD';E={$hd.Name}},
  @{N='Datastore';E={$hd.Filename.Split(']')[0].TrimStart('[')}},
  @{N='HDD/SSD';E={
    $ds = Get-View -Id $hd.ExtensionData.Backing.Datastore
    if($ds.Info.Vmfs.SSD){'SSD'}else{'HDD'}
  }}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

FruitFly
Contributor
Contributor

Thanks @LucD for your reply.
To be plain honest: I didn't know this command and didn't stumble upon it in my research.

Your code works like a charm, but when I try to integrate it into my pre existing one, it fails.
I'll play around a bit in the evening, see where it leads me and will post another reply then.

Once again: Thanks a lot. This really helped

Reply
0 Kudos
FruitFly
Contributor
Contributor

I finally got to play around with this, but for some reason HDD/SSD always returns "HDD". I suspect a Null value, but am still trying to get behind your commands.

Reply
0 Kudos
LucD
Leadership
Leadership

Are the datastores VMFS datastores?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
FruitFly
Contributor
Contributor

The SSD ones are, yes. 
So if this does actually hit "null" because of it being NFS, then it's HDD anyhow and thus correctly displayed.

I have still not found the answer, but the following works:

 

 

Get-VM -PipelineVariable vm |
Get-HardDisk -PipelineVariable hd |
Select @{N='VM';E={$vm.Name}},
  @{N='HD';E={$hd.Name}},
  @{N='Datastore';E={$hd.Filename.Split(']')[0].TrimStart('[')}},
  @{N='HDD/SSD';E={$dt = $hd.Filename.Split(']')[0].TrimStart('[')} 
    if ($dt -eq 'Datacenter-Name1' -or $dt -eq 'Datacenter-Name2' -or $dt -eq 'Datacenter-Name3'){'HDD'} elseif ($dt -eq 'Datacenter-Name01-lun0' -or $dt -eq 'Datacenter-Name10-lun1 (Reserve)' -or $dt -eq 'Datacenter-Name2-lun0' -or $dt -eq 'Datacenter-Name2-lun1 (Reserve)'){'SSD'} else{'Please check Datastore'}}}

 

Now it far from elegant, but as long as it works I'm fine with that.

Problem is, that this will create an entry for each disk a VM has. I rather want all disks to be displayed in one column. 
E.g.: |HDD/SSD|SSD, HDD, SSD| instead of |HDD/SSD|SSD| and |HDD/SSD|HDD| and |HDD/SSD|SSD|.

I promise to you, that this will be my last question and I will either find out the rest by myself, or fuse with my desk by refusing to shower or nourish myself until this problem is solved.

 

Reply
0 Kudos
LucD
Leadership
Leadership

I suspect your version works because you are in fact hard coding the type based on the datastore name.

Btw, instead of using multiple -or in your test, you can use the -contain operator.
Which would make maintenance (adding/removing names) somewhat easier.

$hddDS = 'Datacenter-Name1','Datacenter-Name2','Datacenter-Name3'
$ssdDS = 'Datacenter-Name01-lun0','Datacenter-Name10-lun1 (Reserve)','Datacenter-Name2-lun0','Datacenter-Name2-lun1 (Reserve)'

if($hddDS -contains $dt){
  'HDD'
}
elseif ($ssdDS -contains $dt){
  'SSD'
}
else}{
  'Please check Datastore'
}

 


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

FruitFly
Contributor
Contributor

Very true and a lot easier. 
Thanks for the tip.
I really need to learn a whole lot until I will be somewhat decent at this 😄

Anyhow. Thank you very much for your help, I'll focus on improving my skills now instead of relying on yours.

Reply
0 Kudos