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
dsName | VMname |
---|---|
DataStore1 | MyVM1 |
DataStore1 | MyVM2 |
DataStore2 | MyVM3 |
DataStore2 | MyVM4 |
DataStore2 | MyVM5 |
DataStore3 | MyVM6 |
Thanks
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
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
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
Thank you once again Luc,
As usual, you don't fail to impress with your PowerCLI abilities
@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
...
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
Thank you so much for your time!
One more favor to ask. Can you please add also include datastores with no VM's?
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
Yes, that would be fine.
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
Thank you!