I have written a script that will clone a live vm, but i am not able to get it to do so to another hosr in a different cluster.
Am I missing an option in my code or is it not possible yet? I really need this to work but have been beating myself against the wall with my current issue.
Here is the code I have so far. It might be a bit crude but you can copy it and run it and it will work as long as the session you run it under has valid rights to the server (ESX or VC)
*
Add-PSSnapin VMware.VimAutomation.Core
**
Connect-VIServer -Server vc.setclear.com -Protocol https | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
*
$erroractionpreference = "Continue" #"SilentlyContinue"
Function CreateNewClone #Must be passed 5 agruments (<VM to Clone>,<New Clone Name>,<Server[Host/VC]>,<DataStore Name>,<Folder>)
{
$vm2c = $args[0] #Name of the virtual to be cloned.
$destcln = $args[1] #Name of the clone to be made.
$erver = $args[2] #Name of the host or vitrual cener server.
$destdatastr = $args[3] #Name of the destination datastore to which the new clone will be deployed (Optional).
$foldername = $args[4] #Name of the destinaion folder for the clone.
Now "Initializing clone task for: $vm2c >>-->> $destcln" | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
Now "Using DataStore named: $destdatastr" | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
$serv = Connect-VIServer -Server $erver -Protocol https
$FolderID = Get-Folder -Server $serv -Name $foldername
$targetfolder = get-view ($FolderID).ID
$destdsview = get-view (get-datastore -name $destdatastr).id
$VMCloneSpec = New-Object VMware.Vim.VirtualMachineCloneSpec
$VMCloneSpec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$vmclonespec.location.datastore = $destdsview.moref
$VMCloneSpec.powerOn = $false
$vmclonespec.template = $false
$clntask = (Get-View (Get-VM -Name $vm2c).ID).CloneVM_Task($targetfolder.MoRef, $destcln, $VMCloneSpec)
$clntask | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
}
cls
Now "Beginning DR Cloning Process..." | out-file C:\Scripts\SCClone.log -Encoding "ASCII"
if ($args.length -ge 6)
{
$chkvm = $args[0]
$chkcln = $args[1]
$force = $args[5]
Now "Scanning for VM named: $chkvm" | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
If (Get-VM -Name $chkvm)
{ Now "The VM $chkvm was found." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
Now "Scanning for clone named: $chkcln" | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
If (Get-VM -Name $chkcln)
{ Now "The Clone $chlcln was found." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
If ($force -eq $true)
{ Now "Removing existing $chkln clone." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
Remove-VM -VM $chkcln -DeleteFromDisk -Confirm:$false
CreateNewClone $args[0] $args[1] $args[2] $args[3] $args[4]
If ($args[6])
{
(.\blat.exe SCClone.log -t IT-Support@SetClear.com -s "SetClear DR/HA Clone Process report for: $chkvm" -f InfraAlerts@SetClear.com)
}
}
else
{ Now "The Force agrument was not set to true." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
Now "Script will now exit." | out-file C:\Scripts\SCClone.log -Append
}
}
Else
{ Now "The Clone wasn't found." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
CreateNewClone $args[0] $args[1] $args[2] $args[3] $args[4]
If ($args[6])
{
(.\blat.exe SCClone.log -t IT-Support@SetClear.com -s "SetClear DR/HA Clone Process report for: $chkvm" -f InfraAlerts@SetClear.com)
}
}
}
Else
{ Now "The Virtual Machine to be cloned wasn't found." | out-file C:\Scripts\SCClone.log -Append -Encoding "ASCII"
Now "In order to use this script you must supply an existing Virtual Machine(State: On/Off) or Template to clone from." | out-file C:\Scripts\SCClone.log -Append
}
}
Else
{ " "
"Incorrect number of argumanets passed."
" "
"Usage of this script is by passing the following argumanets:"
" "
"CloneVM.ps1 <vm2c> <destcln> <server> <destdatastr> <folder> <force>"
" "
" vm2c: Name of the Virtual to be cloned."
" destcln: Name of the Clone to be made."
" server: Name of the host or vitrual cener server."
" destdatastr: Name of the destination datastore(Optional)."
" folder: Name of the destinaion folder for the clone."
" force: $true or $false, If clone already exists. $true = Remove-VM."
" "
"CloneVMc.ps1 SCT SCTc vc.setclear.com 'NYI - Vmware_VR5_1000G-001_ProdClonesOnly' 'Discovered Virtual Machine' $true"
}
*
Remove-PSSnapin VMware.VimAutomation.Core
*
So it took a while but I got everything working...
Ill explain how we are configured so that you understand how this all works below:
We have 3 clusters all managed by a single instance of VirtualCenter(VM).
Out of those 3 Clusters 2 are in NYC and 1 in NJ.
Being that they are all managed by the same VirtualCenter(VM) instance we have the ability to VMotion between the locations.
We use this functionality for Local & DR Cloning which is done daily for a subset of highly visable systems.
All of the ESX Hosts are BL680c G5 fully loaded and are multi-attached to the HP EVA 8K's.
All Network Connections are aggregated to offer as much bandwidth as possible.
Connectivity between the 2 DC's are DS3 (45Mbps) which is used for this process and also DoubleTake Replication for our SQL Servers.
So heres the code:
The first file is the configuration file which is where the specifications of the clones is stored. the file is descriptive so that you know what details to pass for each VM to clone.
###########################################################################################################################
SetClear VirtualMachine DR Cloning Utility Configuration file.
##
Comments: Production - Even Day Cloning
##
This file details the configuration of the cloning tasks by setting the default values for the following:
Argument #0; Virtual Machine to clone
Argument #1: Clone Name
Argument #2; ESX Host or VirtualCenter Server
Argument #3: DataStore to be used to the clones
Argument #4; Folder to place the object into
Argument #5: Remove existing clone if it exists without asking for confirmation
Argument #6: VirtualCenter Resource Pool
Argument #7: Blat results Notification. (if blank nothing is sent othrwise send notification)
##
###########################################################################################################################
VM2Clone,CloneName,VirtualCenterHostName,DataStore,Folder,True/False,ResourcePool,True/False
#EOF
The Second file is what is scheduled and contains the link to the above file.
It detects if the day is odd or even as we keep 2 days worth of online(Powered Off) clones for each VM.
################################################################
#
Written by Bill Scott for SetClear PTE LTD | SetClear Inc.
#
################################################################
# *Code is free to use with no implied or written warrantee* #
################################################################
#
Any modifications to this code are at you risk and should
be tested in such a way as to not impact you production
# or other daily environments
#
# The object of this PowerShell Script is to enable Automation
# of the cloning of Live VM's from one Cluster to another
# without having to pause or shutdown the VM. In order for this
# to be possible the Cluster to which the clones will be done
# must be managed by the same VirtualCenter Server.
#
# Anyone with Questions regarding this script can post them to
# the VMware Community when you got this script from (Its
# origination.).
#
# This Portion of the script is used to determine which date
# of the week it is (Odd or Even) and to run the appropriate
# script and arguments.
#
################################################################
$erroractionpreference = "SilentlyContinue" #"Continue" #Choose Error handling
###Add in the VMware VI TookKit Modules###
Add-PSSnapin VMware.VimAutomation.Core
$a = (get-date).day
Connect-VIServer -Server vc.setclear.com -Protocol https
CLS
###Find out if the current day is even or Odd and run for relative VM's.###
$i = (get-date).day
if ($i % 2)
{
###The Day is Odd###
$cfg = Get-Content c:\scripts\SC_DR_O.cfg
foreach ($a in $cfg)
{
if ($a.substring(0,1) -ne "#")
{
$b = $a.split(",")
if ($b.Length -ge 7)
{
$vm2c = $b[0]
$c2m = $b[1]
$svr = $b[2]
$ds2u = $b[3]
$f2u = $b[4]
$ovrwrt = $b[5]
$ResPool = $b[6]
$notify = $b[7]
.\SC_CloneVM_Task.ps1 $vm2c $c2m $svr $ds2u $f2u $ovrwrt $ResPool $notify
}
}
}
}
else
{
###The Day is Even###
$cfg = Get-Content c:\scripts\SC_DR_E.cfg
foreach ($a in $cfg)
{
if ($a.substring(0,1) -ne "#")
{
$b = $a.split(",")
if ($b.Length -ge 7)
{
$vm2c = $b[0]
$c2m = $b[1]
$svr = $b[2]
$ds2u = $b[3]
$f2u = $b[4]
$ovrwrt = $b[5]
$ResPool = $b[6]
$notify = $b[7]
.\SC_CloneVM_Task.ps1 $vm2c $c2m $svr $ds2u $f2u $ovrwrt $ResPool $notify
}
}
}
}
###Remove the VMware VI TookKit Modules###
Remove-PSSnapin VMware.VimAutomation.Core
#EOF
Third and Last file does the work and the reporting.
It takes shape by being called from the above PowerShell Script.
################################################################
#
Written by Bill Scott for SetClear PTE LTD | SetClear Inc.
#
################################################################
# *Code is free to use with no implied or written warrantee* #
################################################################
#
Any modifications to this code are at you risk and should
be tested in such a way as to not impact you production
# or other daily environments
#
# The object of this PowerShell Script is to enable Automation
# of the cloning of Live VM's from one Cluster to another
# without having to pause or shutdown the VM. In order for this
# to be possible the Cluster to which the clones will be done
# must be managed by the same VirtualCenter Server.
#
# Anyone with Questions regarding this script can post them to
# the VMware Community when you got this script from (Its
# origination.).
#
# This Portion of the script is to do the actual Cloning
#
################################################################
$erroractionpreference = "SilentlyContinue" #"Continue" #
Add-PSSnapin VMware.VimAutomation.Core
#########################
Log File Location
$SC_Clonelog = "C:\Scripts\SCClone.log" #Change the log file location to where you want it to be placed also
#########################
Mail variables
$enablemail="yes" #Change to Yes or No if you do or dont want email sent.
$smtpServer = "xxx.xxx.xxx.xxx" # Change to the IP or FQDN of your SMTP Server.
$mailfrom = "VMCloning <VMClone@YourOrg.com>"
$mailto = "Administrators@YourOrg.com"
Change the ###### below to your VirtualCenter Servers FQDN
Connect-VIServer -Server ###### -Protocol https | out-file $SC_CloneLog -Append -Encoding "ASCII"
Function CreateNewClone #Must be passed 6 agruments ()
{
$vm2c = $args[0] #Name of the virtual to be cloned.
$destcln = $args[1] #Name of the clone to be made.
$erver = $args[2] #Name of the host or vitrual cener server.
$destdatastr = $args[3] #Name of the destination datastore to which the new clone will be deployed (Optional).
$foldername = $args[4] #Name of the destinaion folder for the clone.
$resourcepool = $args[5] #Name of the destination Resource Pool for the clone.
Now "Initializing clone task for: $vm2c >>-->> $destcln" | out-file $SC_CloneLog -Append -Encoding "ASCII"
Now "Using DataStore named: $destdatastr" | out-file $SC_CloneLog -Append -Encoding "ASCII"
Now "Using ResourcePool named: $resourcepool" | out-file $SC_CloneLog -Append -Encoding "ASCII"
$serv = Connect-VIServer -Server $erver -Protocol https
$FolderID = Get-Folder -Server $serv -Name $foldername
$targetfolder = get-view ($FolderID).ID
$destdsview = get-view (get-datastore -name $destdatastr).id
$destpool = Get-View (Get-ResourcePool -Name $resourcepool).id
$VMCloneSpec = New-Object VMware.Vim.VirtualMachineCloneSpec
$VMCloneSpec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$VMCloneSpec.location.datastore = $destdsview.moref
$VMCloneSpec.location.pool = $destpool.moref
$VMCloneSpec.powerOn = $false
$VMCloneSpec.template = $false
$clntask = (Get-View (Get-VM -Name $vm2c).ID).CloneVM_Task($targetfolder.MoRef, $destcln, $VMCloneSpec)
$clntask | out-file $SC_CloneLog -Append -Encoding "ASCII"
}
E-mail HTML output
function Sendemail
{
if ($enablemail -match "yes")
{ Write-Host "Sending eMail containing collected information."
$msg = new-object Net.Mail.MailMessage
$filelocationContent = Get-Content $SC_Clonelog
$att = new-object Net.Mail.Attachment($SC_Clonelog)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $mailfrom
$msg.To.Add($mailto)
$msg.Subject = “SetClear DR/HA Clone Process report for: $chkvm”
$msg.Body = $filelocationContent
$msg.Attachments.Add($att)
$msg.IsBodyHTML = $false
$smtp.Send($msg)
Write-Host "Sending eMail containing collected information Successful."
}
}
cls
Now "Beginning DR Cloning Process..." | out-file $SC_CloneLog -Encoding "ASCII"
if ($args.length -ge 7)
{
$chkvm = $args[0]
$chkcln = $args[1]
$force = $args[5]
Now "Scanning for VM named: $chkvm" | out-file $SC_CloneLog -Append -Encoding "ASCII"
If (Get-VM -Name $chkvm)
{ Now "The VM $chkvm was found." | out-file $SC_CloneLog -Append -Encoding "ASCII"
Now "Scanning for clone named: $chkcln" | out-file $SC_CloneLog -Append -Encoding "ASCII"
If (Get-VM -Name $chkcln)
{ Now "The Clone $chlcln was found." | out-file $SC_CloneLog -Append -Encoding "ASCII"
If ($force -eq $true)
{ Now "Removing existing $chkln clone." | out-file $SC_CloneLog -Append -Encoding "ASCII"
Remove-VM -VM $chkcln -DeleteFromDisk -Confirm:$false
CreateNewClone $args[0] $args[1] $args[2] $args[3] $args[4] $args[6]
If ($args[7])
{
Sendemail $chkvm
}
}
else
{ Now "The Force agrument was not set to true." | out-file $SC_CloneLog -Append -Encoding "ASCII"
Now "Script will now exit." | out-file $SC_CloneLog -Append
}
}
Else
{ Now "The Clone wasn't found." | out-file $SC_CloneLog -Append -Encoding "ASCII"
CreateNewClone $args[0] $args[1] $args[2] $args[3] $args[4] $args[6]
If ($args[7])
{
Sendemail $chkvm
}
}
}
Else
{ Now "The Virtual Machine to be cloned wasn't found." | out-file $SC_CloneLog -Append -Encoding "ASCII"
Now "In order to use this script you must supply an existing Virtual Machine(State: On/Off) or Template to clone from." | out-file $SC_CloneLog -Append
}
}
Else
{ " "
"Incorrect number of argumanets passed."
" "
"Usage of this script is by passing the following argumanets:"
" "
"CloneVM_Task.ps1 "
" "
" vm2c: Name of the Virtual to be cloned."
" destcln: Name of the Clone to be made."
" server: Name of the host or vitrual cener server."
" destdatastr: Name of the destination datastore(Optional)."
" folder: Name of the destinaion folder for the clone."
" Resource Poll: Name of the Resource Pool for the Clone to be placed into."
" force: $true or $false, If clone already exists. $true = Remove-VM."
" "
}
###Remove the VMware VI TookKit Modules###
Remove-PSSnapin VMware.VimAutomation.Core
#EOF
If you have any questions post them to this forum and I am sure someone will answer your questions.
The Code did not get input correctly and I am not able to attach it from where I am working so I will post once more to this to attach the code with formatting.
Hi SetClear
today i have try to insert your script in my test environment
but i have always an error in more line the first is 54:
Now "Initializing clone task for: $vm2c >>-->> $destcln" | out-file $SC_CloneLog -Append -Encoding "ASCII"
in this line i suppose there is syntax error with " and Now what do in this command (do a timestamp or what? )
Thank you for your script
Simone
I don't have any Resource Pools defined on my ESX hosts. Can I simply comment out the referenses to $resourcepool and remove that paramater from the script?
This look like exactly what I need for a DR project so I just want to say thanks for posting this here!
Wayne
replace $resourcepool with the name of the folder that you see in the view Virtual Macine & template , not host & cluster
Bye
Simone
I thought that was the folder to use ($f2u)
Argument #4; Folder to place the object into#
Is argument 4 then supposed to be a folder name the (that is usually the same as the server name)? An actual example commented out in the cfg file would go a long way the what each argument expects and how it should be formatted (i.e. do you need quotes around these strings?)
This is what I currently have:
VM2Clone,CloneName,VirtualCenterHostName,DataStore,Folder,True/False,ResourcePool,True/False
servername,servername,InfraServer.mycompany.org,DR_02,Development,True, ,True
Currently resourcepool is null...
Thanks for the assistance.
Wayne
Hi
VMNAME,BK_VMNAME,VCENTER NAME,DATASTORE NAME,DATASTORE FOLDER NAME,Remove Clone: True/False,Resources Pool,EMAIL Yes/no
This from my cfg file.
If you go in your virtualcenter, select the view virtual machine & template
expand the tree of your organization and Here you can find the "resource pool" - "folder"
replace Resource Pool with this name
Bye
I'm also having some issues getting the parameters right with the script...
Initially I was getting an error indicating that I was passing the incorrect number of parameters into the script. (I was not doing anything with the .cfg file, I was simply trying to pass the necessary parameters in from the command line. However, the .cfg file defines 8 parameters, the SC_CloneVM_Task.ps1 script lists 6 parameters with 1 being optional, but the comments state that you must pass in 6 parameters. Also, I'm not sure if the parameters need to be comma-delimited or space-delimited... I've tried both with no success.)
I also have no resource pools defined in the environment I'm testing this script in. When I change to "Virtual Machines and Templates" view, I have the name of my datacenter, and inside of that I have the list of all my VMs that are running in the VMware Datacenter; no resource pool. So I'm not sure what I need to pass in for the "ResourcePool" parameter.
If anyone could please help steer my on the right track I would appreciate it tremendously. If I can get this script to work, it looks like it would help me tremendously in addressing a DR situation that I've been trying to address.
Thanks in advance...
I now have this working as a scheduled task! I had to make several changes so I will try to cover them all here.
First the NOW command had to be changed as done in SimoFi's version of the script.
Hmmm... the datetime part doesn't want to display properly, it should be <leftsquarebracket>DateTime<rightsquarebracket> . Lame.
Second, since I don't have resource pools I had to comment that part out (I have left the code in though in case I do add resource pools in the future).
The format for the cfg file I am using is like so, (I copied the folder name as the resource pool name just so there was a paramater, it gets tossed though):
Server1,Server1-dr,viserver.company.org ,DR_02,DR,True,DR,
To get this to run as a scheduled task you need to insert some code to set the user environment up as documented here RobMokkink's solution:
Added to the primary script: ###Add in the VMware VI TookKit Modules### $erroractionpreference = "SilentlyContinue" #"Continue" # Add-PSSnapin VMware.VimAutomation.Core #FIX FOR TOOLKIT 1.5 $USER = $env:username $APPPATH = "C:\Documents and Settings\" + $USER + "\Application Data" #SET THE APPDATA ENVIRONMENT WHEN NEEDED if ($env:appdata -eq $null -or $env:appdata -eq 0) { $env:appdata = $APPPATH } |
The scheduled task syntax is a bit different than running a batch file (the redirection on the end helps with debugging):
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -command "& " > err.log 2>&1
With a default directory of: F:\Scripts
I hope this helps,
Wayne
I found that to move servers to a different datacenter you have to have a Resource Pool defind in the destination datacenter.
I also found that subsequent tasks will time out in about 10 minutes when you are copying machines to a remote site with a slow(er) link. The question is can I change the timeout value of the clone task?
Or do I need to use code like so:
while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued")
{
$task = Get-View $taskMoRef
}
I found this in an old thread and I was wondering if 1) it still works this way & 2) should there be a pause timer in there so it only looks once a minute or so?
Hello, I was trying to use this script as backup for the "not so often changed machines". But the way this script works it may overload the ESX servers or LUNs, is there a way to protect against overload? If the copy tasks were synchronous it would help a lot, so the code pointed wboaz can be quite helpful, right?
while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued")
{
$task = Get-View $taskMoRef
}
This code works:
$clntask = (Get-View (Get-VM -Name $vm2c).ID).CloneVM_Task($targetfolder.MoRef, $destcln, $VMCloneSpec) $task = Get-View $clntask while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued") { Start-Sleep 10 $task = Get-View $clntask } |
For the last line this should also work:
$task.UpdateViewData("Info.State")
Wayne
Thanks for sharing, works great!
Good works wboaz for your sleep implementation in cloning
"
First the NOW command had to be changed as done in SimoFi's version of the script.
Hmmm... the datetime part doesn't want to display properly, it should
be <leftsquarebracket>DateTime<rightsquarebracket> . Lame.
"
in my version of scriptthere was the <leftsquarebracket><rightsquarebracket> correctly download it
I have a little problem about this script:
when i clone more VM in datastore create a new folder (Ex. Bk_VMname) sometime isn't possible to delete the old VM (a file is lock) and then it's create a new folder (Ex. Bk_VMname_1, Bk_VMname_2, Bk_VMname_3, Bk_VMname_4 )
all days that the script run
How can i solve it?
When a VM is on it locks its VMDK and a few other files. Make sure that all VMs using files in this directory are powered off before deleting the files.
thanks for reply
i'm sure that all bk_VM is power off but i have this problem...
the BK_Vm is only registered in Virtual center
any suggest?
More than one VM can use a VMDK, even at the same time. Do you have any VMs like that? If so they would all need to be powered off.
little update...
this is step by step the procedure:
Launch clone
verify if cloen exist
delete the old clone (i don't need golden copy) then
clone the VM in the new folder BK_VM and register it in VC
When delete the old VM i see that a single file is not delete. this file is *.vmss (VM suspended state) but i not create this file.
This file is the real problem.
Do you know a process in SDK that create a suspended file? is possilbe remove it?
Thanks