5

We have 2 separate VMWare environments, one is the main environment which has hundreds of virtual machines across lots of sites. The other is a much smaller one installed on one server, just for archiving old systems.

What I would like to do is take a snapshot of the current state of one of our live VMs, and use that to copy across to the other VMWare environment and create a new machine there, using that as the archive of that system.

Is this going to be possible/easy?

GregL
  • 9,030
  • 2
  • 24
  • 35
CMR
  • 133
  • 1
  • 2
  • 10
  • What versions of vSphere and ESXi? – GregL Jul 09 '15 at 11:42
  • Both are running 5.5.0 – CMR Jul 09 '15 at 12:04
  • Really I just need to know at the moment if it's possible, as I will leave it to the network manager to actually do when he's back from holiday, I just wanted to know if that's going to be feasiable, or if I need to start looking at a different method of transferring everything – CMR Jul 09 '15 at 12:09
  • No, it's possible. I'm just writing up an answer now.. – GregL Jul 09 '15 at 12:10

2 Answers2

6

Dang, if you had been using vSphere 6, you could have done inter-vCenter clones and be done with it.

In any event, this task isn't super-hard with 5.5 either if you use the PowerCLI.

The steps are as such:

  1. Take a snapshot of the VM (use PowerCLI, or either of the GUIs, doesn't matter)

  2. Clone the snapshot to a new VM using this handy little bit of PowerCLI:
    New-VM -Name $CloneName -VM $SourceVM -Location $CloneFolder -Datastore $Datastore -ResourcePool $ResourcePool -VMHost $VMHost -LinkedClone -ReferenceSnapshot $Snapshot
    You can look at the "New-VM" documentation for what all the options mean and how to fill them.
    They key is the '-ReferenceSnapshot' option.

  3. Export your shinny new VM to OVF/OVA, or copy the folder from the DS to somewhere on the network

  4. Import it to the other vCenter

I've had my IT Security team request a "forensic" copy of a running VM, including memory snapshot, so they can do some investigations in cases where there's been a virus or some sort of breach. To make my life easier, I wrote a PS function which does all the heavy lifting. It just needs a source VM (by name or object), and a folder on disk. It does the rest.

Function ExportVM {
    Param(
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [PSObject]$SourceVM,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]$DestinationPath
    )

    #Check if the destination path exists, bail out if it doesn't
    if ( -not (Test-path $DestinationPath -IsValid) ) {
        Write-Warning "Please provide a valid path for the exported VM"
        return
    }
    
    #Get the SourceVM, bail out if it fails
    if ($SourceVM.GetType().Name -eq "string"){
        try {
            $SourceVM = Get-VM $SourceVM -ErrorAction Stop
        }
        catch [Exception]{
            Write-Warning "VM $SourceVM does not exist"
            return
        }
    }
    elseif ($SourceVM -isnot [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]){
        Write-Warning "You did not pass a string or a VM object for 'SourceVM'"
        Return
    }

    try {
        $DestinationPath = $DestinationPath + "\" + $SourceVM.Name

        #Setup the required compoments to compute an MD5 hash
        $algo = [System.Security.Cryptography.HashAlgorithm]::Create("MD5")
        $md5StringBuilder = New-Object System.Text.StringBuilder 50
        $ue = New-Object System.Text.UTF8Encoding

        #Define the snapshot name
        $SnapshotName = "IT-Security Export - " + (Get-Date -UFormat "%b-%d-%Y, %R")
        #Create the snapshot
        $Snapshot = New-Snapshot -VM $SourceVM -Name $SnapshotName -Description "Snapshot for IT-Security Forensic export" -Memory -Quiesce -Confirm:$false

        $Snapshot

        #Define variables needed to create the clone
        $CloneFolder = $SourceVM.Folder
        $Datastore = Get-Datastore -RelatedObject $SourceVM
        $ResourcePool = Get-ResourcePool -VM $SourceVM
        $VMHost = Get-VMHost -VM $SourceVM

        #Build a unique name for the cloned machine based on the snapshot name
        $algo.ComputeHash($ue.GetBytes($SnapshotName)) | % { [void] $md5StringBuilder.Append($_.ToString("x2")) }
        $CloneName = $SourceVM.Name +"_ITSecExport_" + $md5StringBuilder.ToString().SubString(0,15)

        #Clone the VM
        $CloneVM = New-VM -Name $CloneName -VM $SourceVM -Location $CloneFolder -Datastore $Datastore -ResourcePool $ResourcePool -VMHost $VMHost -LinkedClone -ReferenceSnapshot $Snapshot

        #Define the name of the PSDrive, based on the Datastore name
        $DSName = "ITSecExport_" + ($Datastore.name -replace "[^a-zA-Z0-9]","")
        #Check to see if it already exists, remove if it does
        if (Get-PSDrive | Where {$_.Name -like $DSName}) {
            Remove-PSDrive $DSName
        }
        #Add the new drive
        $PSDrive = New-PSDrive -Location $Datastore -Name $DSName -Scope Script -PSProvider VimDatastore -Root "\"

        #Define variables needed to copy the SourceVM's VMX and the snapshot's VMSN
        $SnapshotID = (Get-VM $SourceVM |Get-Snapshot | where {$_.Name -like $SnapshotName}).ExtensionData.ID
        $SourceVM_VMXPath = (Get-View $SourceVM).Config.Files.VmPathName.Split(" ")[1].replace("/","\")
        $SourceVM_VMSNPath = $SourceVM_VMXPath.Replace(".vmx", "-Snapshot" + $SnapshotID + ".vmsn")
        #$CloneVM_VMPath = (Get-View $CloneVM).Config.Files.VmPathName.Split(" ")[1].Split("/")[0]

        #Copy the VMSN and VMX
        Copy-DatastoreItem -Item ${DSName}:\$SourceVM_VMXPath -Destination $DestinationPath -Force
        Copy-DatastoreItem -Item ${DSName}:\$SourceVM_VMSNPath -Destination $DestinationPath -Force

        #Copy-DatastoreItem -Item ${DSName}:\$CloneVM_Path\* $DestinationPath"$CloneName" -Force -Recurse

        #Export the VM
        $CloneVM | Export-VApp -Destination $DestinationPath -Force

        #Clean up
        Remove-VM -DeletePermanently $CloneVM -Confirm:$false
        Remove-Snapshot -Snapshot $Snapshot -Confirm:$false
        Remove-PSDrive -Name $DSName
    }
    catch [Exception]{
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Warning "Looks like we ran in to an error"
        Write-Warning "  $ErrorMessage"
        return
    }
}
ricmarques
  • 1,112
  • 1
  • 13
  • 23
GregL
  • 9,030
  • 2
  • 24
  • 35
-1

As far as I know, you can just plain copy Virtual Machines between hosts. First shut down safely and then stop the VM; then copy the full folder to the other VMWare environment. After copying the folder, in the web UI, go to Virtual Machine menu -> Add Virtual Machine to Inventory and add the copied machine to the host. When powering on the machine you will get a message asking if you have copied or moved the machine, choose "Copied it". Once you have the VM successfully running in the second VMWare environment you can safely remove and delete it on the first VMWare environment. Depending on your network configuration you may need to change some settings, but it should work fine.

Wayfarer
  • 203
  • 1
  • 2
  • 6
  • OP is looking to copy a *snapshot* of a VM, which presumably is still running and can't be shutdown. – GregL Jul 09 '15 at 11:44
  • That's correct. Whilst I can shut it down for a short period of time, i'd like to avoid it if possible. – CMR Jul 09 '15 at 12:02