VMware Cloud Community
Ewan_Curtis
Enthusiast
Enthusiast

Copying a snapshotted, running VMDK to another datastore

Hello all,

Hoping someone can help out here. I'm trying to put together a process for copying a VMDK for a running VM to another ESX host for rudimentary DR purposes. I could have sworn it was working perfectly, until I put it aside for a couple of weeks and tried it again just recently. The process I have at the moment is like this:

  • map source and destination datastores to PowerShell drives

  • create a snapshot of the VM I wish to copy

  • copy the *.vmdk and *-flat.vmdk files to the destination datastore

  • remove the snapshot

It's dying at the "copy to destination" phase with a "A file was not found" error, referencing the *-flat.vmdk file. Strangely, if I copy from the source to a different folder also on the source (say, /win2k3/win2k3-flat.vmdk -> /copy/win2k3-flat.vmdk) it works perfectly, so it's not a locking issue. Also, using the vmkfstools -i method on the host works fine.

I'm hoping the CopyVirtualDisk_Task might save me, but I'm having trouble constructing the correct object to make it work. I think I'm getting lost at correct usage of the VMware.Vim.ServiceInstance object. Can anyone assist please?

Cheers

0 Kudos
5 Replies
LucD
Leadership
Leadership

The provider in the current VITK release is rather limited in it's implemented features.

So I'm afraid you can't use that path.

The CopyVirtualDisk_Task method is still experimental and only works on ESX 3.5 but at least it allows you to do what you envisage.

Note1: the VirtualDiskManager is only available when you connect to an ESX server, not when you are connected to the VC.

Note2: although the method has a source and destination datacenter parameter this is not possible with this version since an ESX can only belong to 1 datacenter

Note3: you will need to choose the adapter type and the disk type of the destination vmdk

The following script copies the disk from a snapshot to another VMFS datastore.

$vm = <VM-name>
$hostname = (Get-VM $vm).host.name

# Connect to the ESX server
Connect-VIServer -Server $hostname

$vdiskMgr = Get-View (Get-View ServiceInstance).Content.VirtualDiskManager

$sourceDS = (Get-VM $vm | Get-Snapshot | Get-HardDisk).Filename
$sourceDC = (Get-View -Id (Get-VM $vm |  Get-Datacenter).Id).MoRef
$destDS = <datastore-path-to-target-vmdk-file>
$destDC = $sourceDC
$destSpec = New-Object VMware.Vim.VirtualDiskSpec
$destSpec.adapterType = "lsiLogic"
$destSpec.diskType = "thin"
$force = $false
$taskMoRef = $vdiskMgr.CopyVirtualDisk_Task($sourceDS, $sourceDC, $destDS, $destDC, $destSpec, $force)

$task = Get-View $taskMoRef 
while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued") {
  sleep 2
  $task = Get-View $taskMoRef
}

- The script assumes there is only 1 snapshot for the VM but you can easily select the intended snapshot when there are more present (use for example the Where-Object)

- The destination of the copy has to be entered in the datastore path syntax. Something like this "\[<ds-name>\] <folder-name>/<vmdk-name>" (do not forget the blank after the closing square bracket !)

- The loop that waits for the completion of the copy task includes a "sleep 2" command. This to avoid additional load on the CPU(s)

- A copy of a VMDK can take some time (depending on the size). Feel free to add a progress-bar or any other indicator that the script is actually running.


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

0 Kudos
Ewan_Curtis
Enthusiast
Enthusiast

Thanks Luc, that's truely brilliant. Unfortunately for me, I think I'm still stuck - the datastore I'm attempting to copy to is local storage on a different ESX host to the host that the VM is running on. This means that if I connect to the host with the datastore I can't see the VM, and vice versa.

I suspect this can't be engineered around without VC involvement. I might still be able to use this, though, for the thin-provisioning function and do a copy-move - it's not a very clean solution though.

Thank you anyway.

0 Kudos
SCampbell1
Enthusiast
Enthusiast

It may be cumbersome, but you might try the download/upload features of the VITK extensions at [[www.codeplex.com/vitoolkitextensions|http://www.codeplex.com/vitoolkitextensions]]

You should be able to download from one ESX server by connecting to it, then upload to the other one by connecting to that. You may need to convert the disks to export format first.

Another option would be to have an iSCSI server somewhere (there are free Linux ones out there, including a VM appliance you could use just for this purpose) and create a Datastore on that, then use LucD's method to transfer to/from the iSCSI datastore

All are a bit cumbersome to be sure, but free if you can get it to work.

0 Kudos
admin
Immortal
Immortal

Hi Ewan,

What Stephen says will work, unfortunately it's rather slow and probably won't be of much use for several gigabytes of data. I'm not sure the reason for the slowness but the file upload for ESX seems to be the problem. The alternative is to use SCP to move the file, which works fairly well.

0 Kudos
Ewan_Curtis
Enthusiast
Enthusiast

Thanks for the suggestions. It's quite frustrating that what I want to do is logically straight-forward, but the tools just aren't quite there to do it cleanly. I think given my requirements, and given that I'd probably like to avoid "experimental" features as much as possible, I'll stick with the dumb-but-functional copy then move solution. It's heavy on disk requirements and time, but I don't think either of these will be a problem to me. I think.

0 Kudos