This is a VM clone/”backup” script that I use in my home lab. I schedule this script to make a clone of important VMs (works with vCenter) and clones them to another datastore. Obveusly this is not a proper backup but if I make a config change or lose a datastore then this will (and has) saved me a huge amount of rebuild time.
The script works as follows
- Reads a CSV and gets the name of my Protected VM, Source Datastore and Target Datastore
- Continues if the VM is on the source Datastore
- Gets the VM object and builds a new spec using the target datastore
- renames the Spec to (VM)-Backup-(date)
- Checkes there is enougth room on the target datastore for the VM
- Clones the VM with new name to the target datastore
- Deletes the old backup (clone) if there is one.
- Reads the next line of the CSV and repeats
To set this up you will need a CSV file in the following format
ProtectedVM,SourceDS,TargetDS
VM01,any,DS-Backup
VM02,DS01,DS02
VM03,DS01,DS-Backup
You may need a credentual object if you run the script using an account that can not access the vCenter. I use a backup service account to logon to vCenter.
Just run the following in a powershell window (with the your file location)
$cred = get-credential
$cred | export-Clixml "your cred file location"
You will be prompted for the account details, Enter them and the cred file will be created. Make sure you do this on the computer that will be running the script as the user that will also be running the script.
Then deploy your script.
import-module VMware.VumAutomation
import-module VMware.VumAutomation.core
import-module VMware.VumAutomation.vds
import-module VMware.VumAutomation.storage
$CredFile = "c:\Backup\sa_backup.xml"
$BackupFile = "c:\Backup\vmBackups.csv"
$vCenter = "MyvCenter.Server.FQDN"
# Import Backup CSV
$VMBackupList = Import-Csv $BackupFile
#Set Date format for clone names
$date = Get-Date -Format "yyyyMMdd"
#Connect to vCenter
$Creds = Import-Clixml $CredFile
Connect-VIServer $vCenter -Credential $Creds
foreach ($VMtoBackup in $VMBackupList)
{
$vm = Get-VM $VMtoBackup.ProtectedVM
if($VM)
{
# check VM is on the source DS. and there is enougth free space on the targetDS
if((((get-datastore -vm $VM).name -eq $VMtoBackup.SourceDS) -or $VMtoBackup.SourceDS -eq "any") -and ($VM.UsedSpaceGB -lt (get-datastore $VMtoBackup.targetDS).FreeSpaceGB))
{
$oldVMName = $VMtoBackup.ProtectedVM + "-backup-"
$OldVM = get-vm $oldVMName*
# Create new snapshot for clone
$cloneSnap = $vm | New-Snapshot -Name "Clone Snapshot"
# Get managed object view
$vmView = $vm | Get-View
# Get folder managed object reference
$cloneFolder = $vmView.parent
# Build clone specification
$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot
# Make linked disk specification
$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.Datastore = (Get-Datastore -Name $VMtoBackup.TargetDS | Get-View).MoRef
$cloneSpec.Location.Transform = [Vmware.Vim.VirtualMachineRelocateTransformation]::sparse
$cloneName = "$vm-Backup-$date"
# Create clone
$vmView.CloneVM( $cloneFolder, $cloneName, $cloneSpec )
$VMNewBackup = Get-VM $cloneName
# Remove Snapshot created for clone
Get-Snapshot -VM (Get-VM -Name $VMtoBackup.ProtectedVM) -Name $cloneSnap | Remove-Snapshot -confirm:$False
if($OldVM){$OldVM | remove-vm -DeletePermanently -Confirm:$false}
}
}
}
#Disconnect from vCentre
Disconnect-VIServer -Confirm:$false
Then just create a sheduled task to run powershell.exe with arguments of the full script path (with name), and starting location of the script path.
Once created you will have a very basic “backup” script. Unles the target Datastore is somewere else this is only going to protect you from config or corruption issues. But it is better then a poke in the eye.