VMware Cloud Community
piercj2
Enthusiast
Enthusiast
Jump to solution

List DataStore VM's

Does anyone have a quick way to provide a list of DataStores and get a list of the VM's contained in them ?

I've come up with the following but am having an issue in the $ds_VMs = $ds | Get-VM foreach loop

# Get the VM Information

$datastores = Get-Datastore (Get-Content C:\Temp\dslist.txt)

$ds_outputfile = "C:\Temp\dslist-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv"

$dsReport=@()

foreach($ds in $datastores){

    $dsProp=[ordered]@{

        'dsName'=$ds.Name;

    }

    $ds_VMs = $ds | Get-VM | foreach {

        $vmName = $_.Name

        $dsProp.Add("VM Name",$vmName)

    }

    $dsReport += New-Object -TypeName psobject -Property $dsProp

}

# Create the .csv file

$dsReport |

    Sort-Object -Property dsName -Descending |

    Export-Csv $ds_outputfile -NoTypeInformation

# Open the .csv file

Invoke-Item $ds_outputfile

My issue is that the $ds_VMs = $ds | Get-VM | foreach loop gets the name of the first VM in a DataStore (MyServer1 for example) and adds this to the array.

The loop then moves on to the following VM's in the DataStore but returns the error because $vmName has already been added and I can't figure out how to move on to the next position in the array

Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'VM Name'  Key being added: 'VM Name'"

What's the best way to increment this loop so that the overall output resembles the following

dsNameVMname
DataStore1MyVM1
DataStore1MyVM2
DataStore2MyVM3
DataStore2MyVM4
DataStore2MyVM5
DataStore3MyVM6

Thanks

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

An alternative which resembles the output you have shown would be something like this

# Get the VM Information

$datastores = Get-Datastore (Get-Content C:\Temp\dslist.txt)

$ds_outputfile = "C:\Temp\dslist-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv"

$dsReport=@()

foreach($ds in $datastores){

    foreach($vm in (Get-VM -Datastore $ds)){

        $dsProp=[ordered]@{

            'dsName'=$ds.Name;

            'VM Name' = $vm.Name

        }

        $dsReport += New-Object -TypeName psobject -Property $dsProp

    }

}

# Create the .csv file

$dsReport |

    Sort-Object -Property dsName -Descending |

    Export-Csv $ds_outputfile -NoTypeInformation

# Open the .csv file

Invoke-Item $ds_outputfile


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

View solution in original post

Reply
0 Kudos
10 Replies
LucD
Leadership
Leadership
Jump to solution

You're are using the constant string 'VM Name' as the key, and you can't have duplicate keys in a hash table.

You could concatenate all the VM names in the value field.

But I'm not sure how you want the output to look.

# Get the VM Information

$datastores = Get-Datastore (Get-Content C:\Temp\dslist.txt)

$ds_outputfile = "C:\Temp\dslist-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv"

$dsReport=@()

foreach($ds in $datastores){

    $dsProp=[ordered]@{

        'dsName'=$ds.Name;

        'VM Name' = [string]::Join('|',(Get-VM -Datastore $ds | Select -ExpandProperty Name))

    }

    $dsReport += New-Object -TypeName psobject -Property $dsProp

}

# Create the .csv file

$dsReport |

    Sort-Object -Property dsName -Descending |

    Export-Csv $ds_outputfile -NoTypeInformation

# Open the .csv file

Invoke-Item $ds_outputfile


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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

An alternative which resembles the output you have shown would be something like this

# Get the VM Information

$datastores = Get-Datastore (Get-Content C:\Temp\dslist.txt)

$ds_outputfile = "C:\Temp\dslist-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv"

$dsReport=@()

foreach($ds in $datastores){

    foreach($vm in (Get-VM -Datastore $ds)){

        $dsProp=[ordered]@{

            'dsName'=$ds.Name;

            'VM Name' = $vm.Name

        }

        $dsReport += New-Object -TypeName psobject -Property $dsProp

    }

}

# Create the .csv file

$dsReport |

    Sort-Object -Property dsName -Descending |

    Export-Csv $ds_outputfile -NoTypeInformation

# Open the .csv file

Invoke-Item $ds_outputfile


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

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Thank you once again Luc,

As usual, you don't fail to impress with your PowerCLI abilities

Reply
0 Kudos
vwmagic
Enthusiast
Enthusiast
Jump to solution

@LucD Don't know why but the output I got only listed all VM's, there are no any datastores names under "dsName". Thank you!

In my dslist.txt file, it contains;
datastore1
datastore2
datastore3
...

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There is a typo in that code.
The properties in that ordered object should say

    $dsProp = [ordered]@{
      'dsName' = $ds
      'VM Name' = $vm.Name
    }


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

Reply
0 Kudos
vwmagic
Enthusiast
Enthusiast
Jump to solution

Thank you so much for your time! 

One more favor to ask. Can you please add also include datastores with no VM's? 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

How would you present that in the resulting CSV?
Just the datastorename alone in that row?


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

Reply
0 Kudos
vwmagic
Enthusiast
Enthusiast
Jump to solution

Yes, that would be fine.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this

# Get the VM Information
$datastores = Get-Datastore (Get-Content C:\Temp\dslist.txt)
$ds_outputfile = "C:\Temp\dslist-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv"
$dsReport = @()
foreach ($ds in $datastores) {
  $vms = Get-VM -Datastore $ds
  if($vms.Count -eq 0){
    $dsProp = [ordered]@{
      'dsName' = $ds
      'VM Name' = ''
    }
    $dsReport += New-Object -TypeName psobject -Property $dsProp

  }
  else {
    foreach ($vm in $vms) {
      $dsProp = [ordered]@{
        'dsName' = $ds
        'VM Name' = $vm.Name
      }
      $dsReport += New-Object -TypeName psobject -Property $dsProp
    }
  } 
}
# Create the .csv file
$dsReport |
Sort-Object -Property dsName -Descending |
Export-Csv $ds_outputfile -NoTypeInformation
# Open the .csv file
Invoke-Item $ds_outputfile


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

Reply
0 Kudos
vwmagic
Enthusiast
Enthusiast
Jump to solution

Thank you!

Reply
0 Kudos