VMware Cloud Community
BenLiebowitz
Expert
Expert
Jump to solution

Help Migrating VMs

My company is currently moving the datacenter to a Co-Location facility.  The way the migration is being performed, there are ESXi hosts and shared storage at the colo already.  Datastores are being replicated to the storage at the colo to datastores with the same name.  The plan was to shutdown the VMs at the datacenter, remove them from inventory, browse the datastore from one of the ESXi hosts at the colo and add the VM back to inventory...  rince & repeat.

The problem that we ran into had to do with the fact that each VM has VMDKs on multiple datastores.  This process only acknowledged the change of the primary VMDK, the VMX file was still looking for the other 2 volumes on the old datastores, which could not be accessed from the colo. 

I have to think that there is a way to script this to avoid this from occuring.  If we know the identifier for the new storage volume, we should be able to script it, yes? 

I'd like the script to read VM names from a txt file, remove the VM from inventory on host1, browse the datastore from host2 (which is at the colo) and add the VM back to inventory, and then remove & re-add the other volumes based on the name of the datastore (if hard disk 2 is on datastore2 then use 9d0fac87-....)

Any help would be grately appreciated!

Thanks in advance!

- Ben

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
0 Kudos
1 Solution

Accepted Solutions
mattboren
Expert
Expert
Jump to solution

Hello, BenLiebowitz-

I looked through your script.  You had a fair amount of it right on.  There were a couple of things to tweak, and a couple of things to correct.  Here is the updated script from what I saw could/should change (and, below the code is the explanation of the things that I changed).

# export list of Staging VMs
Get-Folder -Name "Staging" | Get-VM | select Name | Sort Name | Export-CSV "c:\staging.csv" -NoTypeInformation

# Get Staging VMs
$stg = Get-Folder -Name "Staging"

# Shutdown VMs (cleanly)
$stg | Get-VM | Shutdown-VMGuest -Confirm:$false

# Remove Hard Disk 2 and 3
$stg = $null
$stg = Get-Folder -Name "Staging"    ## getting Staging folder again
$hdName2 = "Hard disk 2"
$hdName3 = "Hard disk 3"
$stg | Get-VM | Get-HardDisk -Name $hdName2,$hdName3 | Remove-HardDisk -Confirm:$false

# Remove VMs from Inventory
Get-Folder -Name "Staging" | Get-Inventory | Remove-Inventory -Confirm:$false

## then, disconnect from the vCenter to which you were connected



## then, when connected to the vCenter server in the co-location facility:
#
Add VMs to Inventory
$esxhost = "prpp6-vmwhst23.i3global.net"
$datastore1 = "someDatastoreName" ## need to set this value!

## and, add hard disks back to VMs
foreach ($row in (Import-Csv c:\staging.csv)) {
   
$vmName = $row.Name
   
$vmxfile = "[$datastore1] $vmName/$vmName.vmx"
   
$vmNewVM = New-VM -VMFilePath $vmxfile -VMhost $esxhost

   
# Add hard Disks 2 and 3
    New-HardDisk -VM $vmNewVM -DiskPath "[transient_deviceid] $vm/$vm.vmdk"
   
New-HardDisk -VM $vmNewVM -DiskPath "[data_deviceid] $vm/$vm.vmdk"
}
## end foreach

Comments about what I updated/changed:

  • To shutdown the VMs, you should be able to just pipe the Get-VM results straight to Shutdown-VMGuest (I rewrote that)
  • for removing harddisk 2 and 3, you can utilize the Remove-Harddisk cmdlet, and just do it in the pipeline (I rewrote that)
    • the "$vm = Get-VM $stg| Get-View" line in the foreach loop was going to be problematic as you had it:  "$vm" contained the managed objects Views for all of the VMs in the Staging folder, not just of the VM currently being acted upon in that iteration, so things would have been broken
  • for the Remove-Inventory line, you might want to add "-Confirm:$false", as the default behavior might be to prompt for confirmation
  • the "$esxhost = prpp6-vmwhst23.i3global.net" line needed quotes around the host name
  • you don't use the $fields variable anywhere, so that can be removed
  • I renamed the "$add" variable to "$row" for a bit more clarity
  • in the portion that adds the VMs to inventory in the co-lo vCenter:
    • the part that tries to set the value for "$vm" is not quite right; I updated that (and changed the variable name to "$vmName" for clarity)
    • you did not initialize "$datastore1" variable -- you need to set a value for it (and the way that you are using it assumes that all of the VMs in the co-lo facility are on the same datastore -- is that the case?)
    • you need square brackets around the datastore name, and quotes around the value for $vmxfile
    • for the New-VM call, you might consider supplying a folder with -Location (if you want the newly registered VMs to be in a particular folder)
    • for the New-HardDisk calls, you need quotes around the -DiskPath value

I would give that a shot with just one machine, and see how things go.  Let us know the result.

View solution in original post

0 Kudos
6 Replies
lakshya32
Enthusiast
Enthusiast
Jump to solution

Hi BenLiebowitz

Welcome to the forums.

Could you please go through below link ,it may help you through GUI instead of script.

http://www.virtualizationteam.com/virtualization-vmware/vsphere-virtualization-vmware/how-to-export-...

"When you fail to plan, you plan to fail."
0 Kudos
BenLiebowitz
Expert
Expert
Jump to solution

Sorry, I am not looking to export a list of VMs to a spreadsheet or anything like that.  I am looking for a script that will remove a VM from inventory on one datastore and then re-add it on another.  Then, remove Hard Disk 2 and Hard Disk 3 and re-add them on different datastores.

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
0 Kudos
BenLiebowitz
Expert
Expert
Jump to solution

Ok, i wrote a script pieced together from different things I found online..  can someone double check it for me?

# export list of Staging VMs
get-folder -Name "Staging" | get-vm | select Name | Sort Name | Export-CSV "c:\staging.csv" -NoTypeInformation

# Get Staging VMs
$stg = get-folder -Name "Staging"

# Shutdown VMs
Foreach ($VM in ($stg | Get-VM)){
    # Shutdown the guest cleanly
    $VM | Shutdown-VMGuest -Confirm:$false
}

# Remove Hard Disk 2 and 3
$stg = $null
$stg = get-folder -name "Staging"
Foreach ($VM in ($stg | Get-VM)){

# Remove Transient and Data disks
$hdName2 = “Hard disk 2"
$hdName3 = “Hard disk 3"
$vm = Get-VM $stg| Get-View
$tgtdev = $vm.Config.Hardware.Device | where {$_.DeviceInfo.Label -eq $hdName2}
$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
$dev.operation = “remove”
$dev.device = $tgtdev
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.DeviceChange += $dev
$vm.ReconfigVM($spec)
$tgtdev = $vm.Config.Hardware.Device | where {$_.DeviceInfo.Label -eq $hdName3}
$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
$dev.operation = “remove”
$dev.device = $tgtdev
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.DeviceChange += $dev
$vm.ReconfigVM($spec)
}

# Remove VMs from Inventory

get-folder -Name "Staging" | get-inventory | remove-inventory

# Add VMs to Inventory

$esxhost = prpp6-vmwhst23.i3global.net
$vm = $null
$fields = "01.Field 1"

foreach ($add in (import-csv staging.csv)) {
$vm = $vms | Where {$.Name -eq $add."01.Field 1"
$vmxfile = $datastore1 $vm/$vm.vmx
new-vm -VMfilepath $vmxfile -VMhost $esxhost

# Add hard Disk 2 and 3
New-harddisk -VM $vm -DiskPath [transient_deviceid] $vm/$vm.vmdk
new-harddisk -VM $vm -DiskPath [data_deviceid] $vm/$vm.vmdk
}

}

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
0 Kudos
mattboren
Expert
Expert
Jump to solution

Hello, BenLiebowitz-

I looked through your script.  You had a fair amount of it right on.  There were a couple of things to tweak, and a couple of things to correct.  Here is the updated script from what I saw could/should change (and, below the code is the explanation of the things that I changed).

# export list of Staging VMs
Get-Folder -Name "Staging" | Get-VM | select Name | Sort Name | Export-CSV "c:\staging.csv" -NoTypeInformation

# Get Staging VMs
$stg = Get-Folder -Name "Staging"

# Shutdown VMs (cleanly)
$stg | Get-VM | Shutdown-VMGuest -Confirm:$false

# Remove Hard Disk 2 and 3
$stg = $null
$stg = Get-Folder -Name "Staging"    ## getting Staging folder again
$hdName2 = "Hard disk 2"
$hdName3 = "Hard disk 3"
$stg | Get-VM | Get-HardDisk -Name $hdName2,$hdName3 | Remove-HardDisk -Confirm:$false

# Remove VMs from Inventory
Get-Folder -Name "Staging" | Get-Inventory | Remove-Inventory -Confirm:$false

## then, disconnect from the vCenter to which you were connected



## then, when connected to the vCenter server in the co-location facility:
#
Add VMs to Inventory
$esxhost = "prpp6-vmwhst23.i3global.net"
$datastore1 = "someDatastoreName" ## need to set this value!

## and, add hard disks back to VMs
foreach ($row in (Import-Csv c:\staging.csv)) {
   
$vmName = $row.Name
   
$vmxfile = "[$datastore1] $vmName/$vmName.vmx"
   
$vmNewVM = New-VM -VMFilePath $vmxfile -VMhost $esxhost

   
# Add hard Disks 2 and 3
    New-HardDisk -VM $vmNewVM -DiskPath "[transient_deviceid] $vm/$vm.vmdk"
   
New-HardDisk -VM $vmNewVM -DiskPath "[data_deviceid] $vm/$vm.vmdk"
}
## end foreach

Comments about what I updated/changed:

  • To shutdown the VMs, you should be able to just pipe the Get-VM results straight to Shutdown-VMGuest (I rewrote that)
  • for removing harddisk 2 and 3, you can utilize the Remove-Harddisk cmdlet, and just do it in the pipeline (I rewrote that)
    • the "$vm = Get-VM $stg| Get-View" line in the foreach loop was going to be problematic as you had it:  "$vm" contained the managed objects Views for all of the VMs in the Staging folder, not just of the VM currently being acted upon in that iteration, so things would have been broken
  • for the Remove-Inventory line, you might want to add "-Confirm:$false", as the default behavior might be to prompt for confirmation
  • the "$esxhost = prpp6-vmwhst23.i3global.net" line needed quotes around the host name
  • you don't use the $fields variable anywhere, so that can be removed
  • I renamed the "$add" variable to "$row" for a bit more clarity
  • in the portion that adds the VMs to inventory in the co-lo vCenter:
    • the part that tries to set the value for "$vm" is not quite right; I updated that (and changed the variable name to "$vmName" for clarity)
    • you did not initialize "$datastore1" variable -- you need to set a value for it (and the way that you are using it assumes that all of the VMs in the co-lo facility are on the same datastore -- is that the case?)
    • you need square brackets around the datastore name, and quotes around the value for $vmxfile
    • for the New-VM call, you might consider supplying a folder with -Location (if you want the newly registered VMs to be in a particular folder)
    • for the New-HardDisk calls, you need quotes around the -DiskPath value

I would give that a shot with just one machine, and see how things go.  Let us know the result.

0 Kudos
mattboren
Expert
Expert
Jump to solution

Oh, and I just realized that in the New-HardDisk calls, you will likely need to add some "_1" and "_2" in the VMDK names for hard disk 2 and 3.  If you know that all of the VMDKs are uniformly named, that would work, or you could change up the Export-Csv part to include the VMs' VMDK names.

Then, you could use those saved VMDK names when going through the New-HardDisk portion.

0 Kudos
BenLiebowitz
Expert
Expert
Jump to solution

Matt - Thank you so much for cleaning up my script!  I will give it a test and let you know! 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
0 Kudos