PowerCLI: Copy a vmdk from one VM to another

I created this script to help assist a customer automate an operation they perform regularly. Basically they restore a VM and then either attach directly to a vmdk in the restored VM or copy a vmdk into a folder of a target VM. This task is performed regularly and to reduce time and the risk of errors in attaching or moving the wrong vmdk they wanted a way to automate the process to be able to repeat the process quickly and accurately.

The script below will copy a virtual machine disk ($recoveryHD) from one VM ($Source) and then attach it to another VM ($Target).

There is a second snippet of Windows powershell code which sets the volume to read/write and mounts it in the target VM.

########################################################################################################
# PowerCLI script to copy a vmdk from one VM (a recovery VM) to another VM (the target VM)
# Usage copy_recoveryVMDK.ps1 
#
# Requires active connection to vCenter Server (using Connect-VIServer)
#
# History:
# 11/14/2015 - Hersey http://www.vhersey.com/ - Created
#
########################################################################################################
#Variables
# Recovery VM Inventory Name which contains the vmdk to copy
$Source = "CLONELABFILE01"

# Target VM Inventory Name where vmdk will be copied to
$Target = "LABFILE01"

# Define which Virtual Hard Disk is the vmdk to copy from Recovery VM to Target VM
$recoveryHD = "Hard disk 3"

Clear-Host 

Write-Host "Here. We. Go!" -ForeGroundColor Cyan

#Get Working Directory of Target VM
Write-Host "Determining Working Directory of Target VM ..." -ForeGroundColor Cyan
$targetVM = Get-VM $Target 
$targetWORK = $targetVM | Get-HardDisk | Where {$_.Name -eq "Hard disk 1"} 
$targetDIR = $targetWORK.Filename.Split("/")[0]

#Set location and name of new VMDK
$dateTime = Get-Date -Format MMddyyhhmmss #Just an attempt to add some uniqueness to the vmdk file name.
$NewVMDK = "$targetDIR/recovery-VM-$dateTime.vmdk"

#Copy VMDK from Recovery VM to Target VM Working Directory
Write-Host "Copying $recoveryHD from $Source to $Target $NewVMDK ..." -ForeGroundColor Cyan
$recoveryVM = Get-VM $Source
$recoveryWORK = $recoveryVM | Get-HardDisk | Where {$_.Name -eq "$recoveryHD"} | Copy-HardDisk -DestinationPath $NewVMDK

#Attach copied VMDK to Target VM
Write-Host "Attaching $NewVMDK to $Target ..." -ForeGroundColor Cyan
$targetVM | New-HardDisk -DiskPath $NewVMDK | Out-Null

Write-Host "Done!" -ForeGroundColor Cyan

An up-to-date version of this PowerCLI script can be found on GitHub: copy_recoveryVMDK.ps1

The script determines the current working directory of the target VM by determining where the VM’s “Hard disk 1” is stored ($targetDIR) using the Get-HardDisk cmdlet. The name and location for the new vmdk ($NewVMDK) is determined using the $targetDIR and the $dateTime in the format MMddyyhhmmss.

The vmdk associated with the $recoveryHD from the $Source is then copied to $NewVMDK using Copy-HardDisk.

PowerCLI-CopyVMDK

Once the copy is complete, $NewVMDK is attached to the $Target with New-HardDisk. The disk is now available in the guest but it is “Offline”.

New-Windows-Disk

To bring the disk online the Windows powershell code below will set the disk to read/write and then bring the disk “Online”

# Set Offline Disk to Read/Write
Get-Disk | where {$_.OperationalStatus -eq "Offline"} | Set-Disk -IsReadOnly $false
# Bring Offline Disk Online
Get-Disk | where {$_.OperationalStatus -eq "Offline"} | Set-Disk -IsOffline $false

The volume is now available to the guest OS.

Disk-Ready-for-Use

Hope you find this useful. Thoughts, comments, and questions are always welcome.

Have a great day!

Leave a Reply

Your email address will not be published. Required fields are marked *

6 + twelve =