VMware Cloud Community
aw443
Contributor
Contributor
Jump to solution

get-cluster > get-vm > get-datastore

(I'm moving this question from a previous post that was already answered when I jumped into it.)

I ran across a very useful thread (between angoletti and adias) on how to list datastores per VM using the command below. This successfully returns the datastore with the VM name, unless the VM has a VMDK on more than one datastore. In that case, it shows up blank.

get-cluster | %{$cluster = $_; get-vm -Location $_ | %{$vm = $_; $ds = get-datastore -vm $_; write-host $cluster.name $vm.name $ds.name}}

Here is an excerpt of what I see:

CLUS1 DPsrv VMFS-LUN-54

CLUS1 dpssvm VMFS-LUN-54

CLUS1 gimap1

CLUS1 websrvph VMFS-LUN-45

CLUS1 websbr VMFS-LUN-45

CLUS1 av1 VMFS-LUN-53

CLUS1 prodws2 VMFS-LUN-56

CLUS1 dpwedapts VMFS-LUN-55

CLUS1 txwebsrv

CLUS1 itracka VMFS-LUN-45

All the results are accurate except for GIMAP1 and TXWEBSRV. After checking the settings for these VM's (and all other VM's missing a datastore in the results), its clear they all have VMDK's on separate datastores.

I've tried manipulating this command, but I've not been successful in producing the desired results. Does anyone know how to successfully return all datastores per VM?

0 Kudos
1 Solution

Accepted Solutions
admin
Immortal
Immortal
Jump to solution

Correct. I was sloppy in my sample code. Thanks for cleaning it up, LucD. We can strip it down even a little further and not worry about the whole IsArray vs. not thing and just let the pipeline do what it does. Something like this:

get-cluster |`
  %{$cluster = $_; get-vm -Location $_ |
    %{$vm = $_; $dsNames = get-datastore -vm $_ | % {$_.name};
      write-host $cluster.name $vm.name $dsNames
    }
  }

View solution in original post

0 Kudos
3 Replies
LucD
Leadership
Leadership
Jump to solution

The reason it doesn't work in those cases is because the Get-Datastore cmdlet returns an array of Datastore objects.

Since the returned array doesn't have a Name property nothing is written.

A possible solution is to add instructions how the datastore names shall be listed in case of a single datastore object and in case of an array of datastore objects.

This code snippet shows one way of doing this

get-cluster |`
  %{$cluster = $_; get-vm -Location $_ |
  %{$vm = $_; $ds = get-datastore -vm $_;
      $dstxt = &{if (($ds.GetType()).IsArray) {foreach($e in $ds){$e.name}}else{$ds.name}};
      write-host $cluster.name $vm.name $dstxt}}

The ($ds.GetType()).IsArray condition returns True in case $ds contains an array, False in the other case.

If an array is returned a loop will list the datastore name for each array element to a temporary variable ($dstxt).

Note the use of the & (ampersand); this tells Powershell to excute what follows in the script block and store the result in the variable.

Otherwise $dstxt would just contain the text of actual script block.


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

admin
Immortal
Immortal
Jump to solution

Correct. I was sloppy in my sample code. Thanks for cleaning it up, LucD. We can strip it down even a little further and not worry about the whole IsArray vs. not thing and just let the pipeline do what it does. Something like this:

get-cluster |`
  %{$cluster = $_; get-vm -Location $_ |
    %{$vm = $_; $dsNames = get-datastore -vm $_ | % {$_.name};
      write-host $cluster.name $vm.name $dsNames
    }
  }

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Brilliant Powershell coding.

Wish I would have thought of that Smiley Happy


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

0 Kudos