56
57
return False, [val]
58
def generate_clone_disk_path(origpath, design):
59
def generate_clone_disk_path(origpath, design, newname=None):
60
origname = design.original_guest
61
newname = newname or design.clone_name
62
65
# Try to split the suffix off the existing disk name. Ex.
65
68
# If the suffix is greater than 7 characters, assume it isn't
66
69
# a file extension and is part of the disk name, at which point
67
70
# just stick '-clone' on the end.
68
if basename.count(".") and len(basename.rsplit(".", 1)[1]) <= 7:
69
basename, suffix = basename.rsplit(".", 1)
71
if origpath.count(".") and len(origpath.rsplit(".", 1)[1]) <= 7:
72
path, suffix = origpath.rsplit(".", 1)
70
73
suffix = "." + suffix
72
return _util.generate_name(basename + "-clone",
73
lambda p: VirtualDisk.path_exists(design.original_conn, p),
75
dirname = os.path.dirname(path)
76
basename = os.path.basename(path)
78
clonebase = basename + "-clone"
79
if origname and basename == origname:
82
clonebase = os.path.join(dirname, clonebase)
83
return _util.generate_name(
85
lambda p: VirtualDisk.path_exists(design.original_conn, p),
77
89
def generate_clone_name(design):
78
90
# If the orig name is "foo-clone", we don't want the clone to be
175
188
self._valid_guest.set_name(name)
176
189
except ValueError, e:
177
raise ValueError, _("Invalid name for new guest: %s") % (str(e),)
190
raise ValueError(_("Invalid name for new guest: %s") % e)
179
192
# Make sure new VM name isn't taken.
193
206
self._valid_guest.set_uuid(uuid)
194
207
except ValueError, e:
195
raise ValueError, _("Invalid uuid for new guest: %s") % (str(e),)
208
raise ValueError(_("Invalid uuid for new guest: %s") % e)
197
210
if _util.vm_uuid_collision(self._hyper_conn, uuid):
198
211
raise ValueError(_("UUID '%s' is in use by another guest.") %
368
381
doc="List of policy rules for determining which "
369
382
"vm disks to clone. See CLONE_POLICY_*")
384
def get_clone_running(self):
385
return self._clone_running
386
def set_clone_running(self, val):
387
self._clone_running = bool(val)
388
clone_running = property(get_clone_running, set_clone_running,
389
doc="Allow cloning a running VM. If enabled, "
390
"domain state is not checked before "
371
393
# Functional methods
373
395
def setup_original(self):
390
412
logging.debug("Original sizes: %s" % (self.original_devices_size))
392
414
# If domain has devices to clone, it must be 'off' or 'paused'
393
if self._original_dom and len(self.original_devices) != 0:
415
if (not self.clone_running and
416
(self._original_dom and len(self.original_devices) != 0)):
394
417
status = self._original_dom.info()[0]
396
419
if status not in [libvirt.VIR_DOMAIN_SHUTOFF,
397
420
libvirt.VIR_DOMAIN_PAUSED]:
398
raise RuntimeError, _("Domain with devices to clone must be "
399
"paused or shutoff.")
421
raise RuntimeError(_("Domain with devices to clone must be "
422
"paused or shutoff."))
402
425
def setup_clone(self):
428
451
count = ctx.xpathEval("count(/domain/devices/interface/mac)")
429
for i in range(1, int(count+1)):
452
for i in range(1, int(count + 1)):
430
453
base_xpath = "/domain/devices/interface[%d]" % i
431
454
base_node = ctx.xpathEval(base_xpath)[0]
432
455
node = ctx.xpathEval(base_xpath + "/mac/@address")
452
475
node.setContent(mac)
454
477
if len(self.clone_virtual_disks) < len(self.original_virtual_disks):
455
raise ValueError(_("More disks to clone that new paths specified. "
478
raise ValueError(_("More disks to clone than new paths specified. "
456
479
"(%(passed)d specified, %(need)d needed") %
457
480
{"passed" : len(self.clone_virtual_disks),
458
481
"need" : len(self.original_virtual_disks) })
563
586
count = _util.get_xml_path(xml, "count(/domain/devices/disk)")
564
for i in range(1, int(count+1)):
587
for i in range(1, int(count + 1)):
565
588
# Check if the disk needs cloning
566
589
(path, target) = self._do_we_clone_device(xml, i)
567
590
if target == None: