VMware Cloud Community
dbutch1976
Hot Shot
Hot Shot
Jump to solution

Get-Vm propterties including snapshot

Hi guys,

We are performing migrations and as part of that we are filling out a checklist containing the properties of the VM prior to moving it.  Critical information includes whether or not there is a snapshot, and the name and description of the snapshot.  I would then like to export the information to CSV. Sounds simple, but I can't seem to figure out how to get-snapshot as part of a single get command, this is as far as I've gotten:

$Migrationvm1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Connect-VIServer $COMVC -Credential $credential

Connect-VIServer $CARVC -Credential $credential

get-vm $Migrationvm1 | get-snapshot | Select VM,Description,Created | export-csv c:\output\$Migrationvm1.csv  -NoTypeInformation -Append

get-vm $Migrationvm1 | select Notes,NumCpu,MemoryGB | export-csv c:\output\$Migrationvm1.csv  -NoTypeInformation -Append

I get an error and the second command doesn't append any information to the csv.  Can this be simplified to a single get-vm command which gets the info I need plus the snapshot info?

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The Snapshot object contains a VM property, under which you will find the complete VirtualMachine object.
You could do

Get-VM -Name $Migrationvm1 |

Get-Snapshot |

Select @{N='VM';E={$_.VM.Name},

    @{N='Notes';E={$_.VM.Notes}},

    @{N='NumCpu';E={$_.VM.NumCpu}},

    @{N='MemoryGB';E={$_.VM.MemoryGB}},

    Name,Description,Created |

Export-Csv -Path c:\output\$Migrationvm1.csv  -NoTypeInformation -UseCulture


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

View solution in original post

0 Kudos
16 Replies
LucD
Leadership
Leadership
Jump to solution

The Snapshot object contains a VM property, under which you will find the complete VirtualMachine object.
You could do

Get-VM -Name $Migrationvm1 |

Get-Snapshot |

Select @{N='VM';E={$_.VM.Name},

    @{N='Notes';E={$_.VM.Notes}},

    @{N='NumCpu';E={$_.VM.NumCpu}},

    @{N='MemoryGB';E={$_.VM.MemoryGB}},

    Name,Description,Created |

Export-Csv -Path c:\output\$Migrationvm1.csv  -NoTypeInformation -UseCulture


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

0 Kudos
dbutch1976
Hot Shot
Hot Shot
Jump to solution

You're a rockstar LucD.

One thing I can't figure out, I would like the output in format-list, however if I use format-list the export-csv exports gibberish.  Is there a way to format the data in list rather than horizontally?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not with Export-Csv I'm afraid.

But you could send it to a regular .txt file

Get-VM -Name $Migrationvm1 |

Get-Snapshot |

Format-List -Property @{N='VM';E={$_.VM.Name},

    @{N='Notes';E={$_.VM.Notes}},

    @{N='NumCpu';E={$_.VM.NumCpu}},

    @{N='MemoryGB';E={$_.VM.MemoryGB}},

    Name,Description,Created |

Out-String |

Set-Content -Path .\report.txt


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

0 Kudos
dbutch1976
Hot Shot
Hot Shot
Jump to solution

That worked, however I need to add two fields, IP address and datastore, unfortunately both are coming up blank, any ideas?

$Migrationvm1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Get-VM -Name $Migrationvm1 |

     Get-Snapshot |

     Format-List -Property @{N='VM';E={$_.VM.Name}},   

     @{N='Notes';E={$_.VM.Notes}},   

     @{N='NumCpu';E={$_.VM.NumCpu}},   

     @{N='MemoryGB';E={$_.VM.MemoryGB}},   

     @{N='Folder';E={$_.VM.Folder}},   

     @{N="IP Address";E={@($_.guest.IPAddress[0])}},   

     @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}},   

     Name,Description,Created |

Out-String |

Set-Content -Path c:\output\$Migrationvm1.txt

0 Kudos
LucD
Leadership
Leadership
Jump to solution

These are also under the VM property.

$Migrationvm1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Get-VM -Name $Migrationvm1 |

     Get-Snapshot |

     Format-List -Property @{N='VM';E={$_.VM.Name}}, 

     @{N='Notes';E={$_.VM.Notes}}, 

     @{N='NumCpu';E={$_.VM.NumCpu}}, 

     @{N='MemoryGB';E={$_.VM.MemoryGB}}, 

     @{N='Folder';E={$_.VM.Folder}}, 

     @{N="IP Address";E={@($_.VM.guest.IPAddress[0])}}, 

     @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.VM.DatastoreIdList | Select -ExpandProperty Name))}}, 

     Name,Description,Created |

Out-String |

Set-Content -Path c:\output\$Migrationvm1.txt


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

0 Kudos
dbutch1976
Hot Shot
Hot Shot
Jump to solution

Well I came in this morning and everything had stopped working, was utterly baffled as to way.  Then it came to me, this script is ongoing to work if the VM has a snapshot.  Once I'd deleted the snapshot I had taken for testing purposes everything started coming up blank.  Do I need to add an IF statement in cases where there is no snapshot? 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not really, if a VM has no snapshot, the Select cmdlet shouldn't be getting any input.

If all your VMs have no snapshots, you will see an empty file of course.


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

0 Kudos
dbutch1976
Hot Shot
Hot Shot
Jump to solution

Can I add a simple message to the script such as this?

$mig1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

    $snapcheck = (Get-VM -Name $Migrationvm1 | Get-Snapshot)

        if ($snapcheck = $null) {

            write-output "NO snapshot"

        }else {

            write-output "Snapshot detected"

        }

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can, but I would avoid having to do the Get-VM and Get-Snapshot twice.

You could do something like this

$Migrationvm1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

$snaps = Get-VM -Name $Migrationvm1 | Get-Snapshot

if ($snaps) {

     write-output "Snapshot detected"

     $snaps | Format-List -Property @{N = 'VM'; E = { $_.VM.Name } },

     @{N = 'Notes'; E = { $_.VM.Notes } },

     @{N = 'NumCpu'; E = { $_.VM.NumCpu } },

     @{N = 'MemoryGB'; E = { $_.VM.MemoryGB } },

     @{N = 'Folder'; E = { $_.VM.Folder } },

     @{N = "IP Address"; E = { @($_.VM.guest.IPAddress[0]) } },

     @{N = "Datastore"; E = { [string]::Join(',', (Get-Datastore -Id $_.VM.DatastoreIdList | Select -ExpandProperty Name)) } },

     Name, Description, Created |

     Out-String |

     Set-Content -Path c:\output\$Migrationvm1.txt

}

else {

     write-output "NO snapshot"

}


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

dbutch1976
Hot Shot
Hot Shot
Jump to solution

Thanks LucD!  I ended up going a slightly different route.  I added a check to see if there's a snapshot, if there is one the script simply tells the user to delete it before continuing.  I couldn't think of a way to have the script write the output to the file and also type the output on the screen so I'm just running the commands twice.  How hard would it be to change the script so that I can pull multiple VMs from the spreadsheet rather that enter a VM name each time?  Here is my script:

$Migrationvm1 = Read-Host "Enter the name of the VM you intend to migrate"

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Connect-VIServer $COMVC -credential $credential

Connect-VIServer $CARVC -credential $credential

$snaps = Get-VM -Name $Migrationvm1 | Get-Snapshot

$Migvm1 = Get-VM -Name $Migrationvm1

if ($snaps) {

    write-output "Snapshot Detected. Delete Snaphosts before continuing."

    $snaps | Format-List -Property @{N = 'VM'; E = { $_.VM.Name } },

    Name, Description, Created

}

else {

    write-output "NO snapshot"

    $Migvm1 | Format-List -Property @{N = 'VM'; E = { $_.Name } },

    @{N='VMhost';E={$_.VMhost}},

    @{N='Notes';E={$_.Notes}},

    @{N='NumCpu';E={$_.NumCpu}},

    @{N='MemoryGB';E={$_.MemoryGB}},

    @{N='Folder';E={$_.Folder}},

    @{N="IP Address";E={@($_.guest.IPAddress[0])}},

    @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}} |

    Out-String |

    Set-Content -Path c:\output\$Migrationvm1.txt   

    $Migvm1 | Format-List -Property @{N = 'VM'; E = { $_.Name } },

    @{N='VMhost';E={$_.VMhost}},

    @{N='Notes';E={$_.Notes}},

    @{N='NumCpu';E={$_.NumCpu}},

    @{N='MemoryGB';E={$_.MemoryGB}},

    @{N='Folder';E={$_.Folder}},

    @{N="IP Address";E={@($_.guest.IPAddress[0])}},

    @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}}

}

Also, how do you upload you code so that it's properly formatted?  Mine keeps coming up at as text.  Sorry, I'm really rusty with PowerCLI!

0 Kudos
LucD
Leadership
Leadership
Jump to solution

If you use the  Visual Studio Code editor, you can copy/paste in HTML format from the editor directly into the VMTN thread editor.

You can use a CSV file to provide a list of VM names.

The Tee-Object cmdlet allows you to write to a file and send the received objects along on the pipeline.

Something like this

# CSV layout

#

# Name

# vm1

# vm2


$Migrationvms = Import-Csv -Path .\vmnames.csv -UseCulture | Select -ExpandProperty Name


$credential = Get-Credential


$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Connect-VIServer $COMVC -credential $credential

Connect-VIServer $CARVC -credential $credential

$Migvms = Get-VM -Name $Migrationvms

$snaps = Get-Snapshot -VM $Migvms

if ($snaps) {

    write-output "Snapshot Detected. Delete Snaphosts before continuing."

    $snaps | Format-List -Property @{N = 'VM'; E = { $_.VM.Name } },

    Name, Description, Created

}

else {

    write-output "NO snapshot"

    $Migvms | Format-List -Property @{N = 'VM'; E = { $_.Name } },

    @{N = 'VMhost'; E = { $_.VMhost } },

    @{N = 'Notes'; E = { $_.Notes } },

    @{N = 'NumCpu'; E = { $_.NumCpu } },

    @{N = 'MemoryGB'; E = { $_.MemoryGB } },

    @{N = 'Folder'; E = { $_.Folder } },

    @{N = "IP Address"; E = { @($_.guest.IPAddress[0]) } },

    @{N = "Datastore"; E = { [string]::Join(',', (Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name)) } } |

    Out-String | Tee-Object -FilePath c:\output\$Migrationvm1.txt

}


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

dbutch1976
Hot Shot
Hot Shot
Jump to solution

Hi LucD,

Won't I run into a problem where if a snapshot exists the whole script will stop and say check snapshots before continuing?  Do I need a foreach loop instead?  I've tried below and it works, but only repeats the first VM in the CSV file repeatedly:

$credential = get-credential

$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Connect-VIServer $COMVC -credential $credential

Connect-VIServer $CARVC -credential $credential

$Migrationvms = Import-Csv -Path .\Vms4migration.csv -UseCulture | Select -ExpandProperty VMName

$snaps = Get-VM -Name $Migrationvms | Get-Snapshot

$Migvm1 = Get-VM -Name $Migrationvms

Foreach ($VMname in $Migrationvms) {

if ($snaps) {

    write-output "Snapshot Detected. Delete Snaphosts before continuing."

    $snaps | Format-List -Property @{N = 'VM'; E = { $_.VM.Name } },

    Name, Description, Created

}

else {

    write-output "NO snapshot"

    $Migvm1 | Format-List -Property @{N = 'VM'; E = { $_.Name } },

    @{N='VMhost';E={$_.VMhost}},

    @{N='Notes';E={$_.Notes}},

    @{N='NumCpu';E={$_.NumCpu}},

    @{N='MemoryGB';E={$_.MemoryGB}},

    @{N='Folder';E={$_.Folder}},

    @{N="IP Address";E={@($_.guest.IPAddress[0])}},

    @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}} |

    Out-String |

    Set-Content -Path c:\output\$Migrationvms.txt   

    $Migvm1 | Format-List -Property @{N = 'VM'; E = { $_.Name } },

    @{N='VMhost';E={$_.VMhost}},

    @{N='Notes';E={$_.Notes}},

    @{N='NumCpu';E={$_.NumCpu}},

    @{N='MemoryGB';E={$_.MemoryGB}},

    @{N='Folder';E={$_.Folder}},

    @{N="IP Address";E={@($_.guest.IPAddress[0])}},

    @{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}}

}

}

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Type, I forgot to change $Migvm1 to $Migvms in the else block.
I corrected the code above, try again.


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

dbutch1976
Hot Shot
Hot Shot
Jump to solution

Hi LucD,

The first VM in my .csv file has a snapshot.  The code is working, but it's only giving the output for that single VM as follows.  It's not providing any output for any of the other VMs in the CSV file.

PowerCLI C:\PowerCLI> .\PreMigCheck.ps1

cmdlet Get-Credential at command pipeline position 1

Supply values for the following parameters:

Credential

Name                           Port  User

----                           ----  ----

aplvmw015                      443   **********

aplvmw016                      443   ***********

Snapshot Detected. Delete Snaphosts before continuing.

VM          : TestVM1

Name        : TEST

Description : Testing migration script, please delete

Created     : 10/21/2019 2:58:50 PM

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is correct.

The script only writes all the VMs that have a snapshot.

To get also the report with VMs that have no snapshots, you could do.
Note that this will create 1 file per VM that has no snapshots.

Is that what you intended?

$Migrationvms = Import-Csv -Path .\vmnames.csv -UseCulture | Select -ExpandProperty Name

$credential = Get-Credential


$COMVC = "aplvmw015"

$CARVC = "aplvmw016"

Connect-VIServer $COMVC -credential $credential

Connect-VIServer $CARVC -credential $credential


Get-VM -Name $Migrationvms |

ForEach-Object -Process {

    $snaps = Get-Snapshot -VM $_

    if($snaps){

        write-output "Snapshot(s) detected on $($_.VM.Name). Delete Snaphosts before continuing."

        $snaps | Format-List -Property @{N = 'VM'; E = { $_.VM.Name } },

        Name, Description, Created

    }

    else{

        write-output "NO snapshot on $($_.Name)"

        $_ | Format-List -Property @{N = 'VM'; E = { $_.Name } },

        @{N = 'VMhost'; E = { $_.VMhost } },

        @{N = 'Notes'; E = { $_.Notes } },

        @{N = 'NumCpu'; E = { $_.NumCpu } },

        @{N = 'MemoryGB'; E = { $_.MemoryGB } },

        @{N = 'Folder'; E = { $_.Folder } },

        @{N = "IP Address"; E = { @($_.guest.IPAddress[0]) } },

        @{N = "Datastore"; E = { [string]::Join(',', (Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name)) } } |

        Out-String | Tee-Object -FilePath "c:\output\$($_.Name).txt"

    }

}


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

dbutch1976
Hot Shot
Hot Shot
Jump to solution

This is exactly what I need, thanks for all your help!!!

0 Kudos