We have two VMware datacenters, both attached to our vCenter server. All VMware 5.5. I have a VM (not template) that I am tying to clone in an automated way using pyvmomi . The script works fine if I specify that I want the VM cloned to a host in the same datacenter as the source VM. However, if I specify a host in the other datacenter, the clone fails with a vmodl error:
A specified parameter was not correct.
As far as I have been able to tell, I am setting everything right in the RelocateSpec and CloneSpec, as well as the actual CloneVM_Task call. Any pointers in the right direction would be gratefully received. Thanks.
Here's the script:
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim, vmodl
import atexit
import sys
import time
import pprint
#import pudb
pp = pprint.PrettyPrinter(indent=4)
def WaitForTasks(tasks, si):
global pp
"""
Given the service instance si and tasks, it returns after all the
tasks are complete
"""
pc = si.content.propertyCollector
task_result = None
taskList = [str(task) for task in tasks]
# Create filter
objSpecs = [vmodl.query.PropertyCollector.ObjectSpec(obj=task) for task in tasks]
propSpec = vmodl.query.PropertyCollector.PropertySpec(type=vim.Task, pathSet=[], all=True)
filterSpec = vmodl.query.PropertyCollector.FilterSpec()
filterSpec.objectSet = objSpecs
filterSpec.propSet = [propSpec]
filter = pc.CreateFilter(filterSpec, True)
try:
version, state = None, None
# Loop looking for updates till the state moves to a completed state.
while len(taskList):
update = pc.WaitForUpdates(version)
for filterSet in update.filterSet:
for objSet in filterSet.objectSet:
task = objSet.obj
for change in objSet.changeSet:
if change.name == 'info':
state = change.val.state
elif change.name == 'info.state':
state = change.val
else:
continue
if not str(task) in taskList:
continue
if state == vim.TaskInfo.State.success:
#save info
task_result = task.info.result
# Remove task from taskList
taskList.remove(str(task))
elif state == vim.TaskInfo.State.error:
raise task.info.error
# Move to next version
version = update.version
except Exception, e:
print "Caught Exception in WaitForTasks : " + pp.pprint(e)
finally:
if filter:
filter.Destroy()
return task_result
"""
Get the vsphere object associated with a given text name
"""
def GetObject(content, vimtype, name):
obj = None
container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True)
for c in container.view:
if c.name == name:
obj = c
break
return obj
def WaitForIP(target_machine):
while target_machine.guest.ipAddress == None:
print "Waiting for IP to be visible..."
sys.stdout.flush()
time.sleep(1)
def main():
global pp
try:
si = None
server = 'vcenter'
try:
si = SmartConnect(host=server, user='adminuser', pwd='password', port=443)
except IOError, e:
pass
if not si:
print "Could not connect to vCenter using specified username and password"
return -1
atexit.register(Disconnect, si)
# Get references to the needed objects
content = si.content
source_machine = GetObject(content,[vim.VirtualMachine],'ubuntu14.04')
destination_host = GetObject(content, [vim.HostSystem], 'vmhostname')
if "bos" in destination_host.name:
dsname = 'bosdatastore'
dcname = 'Boston'
else:
dsname = 'reddatastore'
dcname = 'Redmond'
# Configure where the new machine is to be located
rs = vim.VirtualMachineRelocateSpec()
cs = vim.VirtualMachineCloneSpec()
dc = GetObject(content, [vim.Datacenter], dsname)
target_folder = dc.vmFolder
rs.host = destination_host
cs.location = rs
cs.powerOn = False
# Clone it
tasks = [source_machine.CloneVM_Task(target_folder, 'newmachine', cs)]
print "Clone initiated..."
sys.stdout.flush()
target_machine = WaitForTasks(tasks, si)
print("Virtual Machine %s has been cloned successfully" % "newmachine")
# update NIC settings if needed
for dev in target_machine.config.hardware.device:
if dev.deviceInfo.label == 'Network adapter 1':
nic = dev
break
if nic.backing.deviceName != 'vlan1':
net = GetObject(content,[vim.Network],'vlan2')
vds = vim.vm.device.VirtualDeviceSpec()
nic.backing.deviceName = 'vlan2'
nic.backing.network = net
nic.deviceInfo.summary = 'vlan2'
vds.device = nic
vds.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
vmcs = vim.vm.ConfigSpec()
vmcs.deviceChange = [vds]
tasks = [target_machine.ReconfigVM_Task(vmcs)]
print "Network change started..."
sys.stdout.flush()
WaitForTasks(tasks,si)
print "Network update complete."
# Power the machine on
tasks = [target_machine.PowerOnVM_Task()]
print "New machine is starting..."
sys.stdout.flush()
WaitForTasks(tasks,si)
# Wait for target to have IP so we can save it
WaitForIP(target_machine)
except vmodl.MethodFault, e:
print "Caught vmodl fault in main : " + pp.pprint(e)
except Exception, e:
print "Caught Exception in main : " + pp.pprint(e)
print "Done."
# Start program
if __name__ == "__main__":
main()
CloneSpec
takes a parameter RelocateSpec
. So basically you are cloning a vm/template and migrating(I don't know it is hot or cold) it to a different host/cluster.
After seeing your question the first thing I googled is, "vMotion is possible across Datacenters or not". I get the answer that, "vMotion is not possible across datacenters but a cold migration is possible"
Now as I said that I don't know RelocateSpec
use vMotion or not. But looks like it is not possible even if all the hosts of each datacenter shares a common repo.
Have a look at this article Cloning VM from one datacenter to another datacenter from Vmware. It basically clones and exports it as ovf and then imports the ovf in the target datacenter.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.