Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.

Commit 73ae9db

Browse files
committed
Fix CloneManager to accomodate a VM with disks that don't need to be cloned (rhbz 480253)
1 parent 824f49f commit 73ae9db

1 file changed

Lines changed: 30 additions & 18 deletions

File tree

virtinst/CloneManager.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ def __init__(self, connection):
5858
self._original_devices_type = []
5959
self._original_xml = None
6060

61+
# Deliberately private: user doesn't need to know this
62+
self._original_devices_idx = []
63+
6164
# clone guest
6265
self._clone_name = None
6366
self._clone_devices = []
@@ -211,11 +214,13 @@ def setup_original(self):
211214
# Pull clonable storage info from the original xml
212215
self._original_devices, \
213216
self._original_devices_size,\
214-
self._original_devices_type = self._get_original_devices_info(self._original_xml)
217+
self._original_devices_type,\
218+
self._original_devices_idx = self._get_original_devices_info(self._original_xml)
215219

216220
logging.debug("Original paths: %s" % (self._original_devices))
217221
logging.debug("Original sizes: %s" % (self._original_devices_size))
218222
logging.debug("Original types: %s" % (self._original_devices_type))
223+
logging.debug("Original idxs: %s" % (self._original_devices_idx))
219224

220225
# Check original domain is SHUTOFF
221226
# XXX: Shouldn't pause also be fine, and guests with no storage/
@@ -278,16 +283,14 @@ def setup_clone(self):
278283

279284
# Changing storage paths
280285
clone_devices = iter(self._clone_devices)
281-
count = ctx.xpathEval("count(/domain/devices/disk)")
282-
for i in range(1, int(count+1)):
283-
node = self._get_available_cloning_device(ctx, i, self._force_target)
284-
if node == None:
285-
continue
286+
for i in self._original_devices_idx:
287+
node = ctx.xpathEval("/domain/devices/disk[%d]/source" % i)
286288
node = node[0].get_properties()
287289
try:
288290
node.setContent(clone_devices.next())
289291
except Exception:
290-
raise ValueError, _("Missing new file to use disk image for %s") % node.getContent()
292+
raise ValueError, _("Missing new file to use disk image "
293+
"for %s") % node.getContent()
291294

292295
# changing uuid
293296
node = ctx.xpathEval("/domain/uuid")
@@ -320,7 +323,9 @@ def setup_clone(self):
320323
# Change xml disk type values if original and clone disk types
321324
# (block/file) don't match
322325
self._change_disk_type(self._original_devices_type,
323-
self._clone_devices_type, ctx)
326+
self._clone_devices_type,
327+
self._original_devices_idx,
328+
ctx)
324329

325330
# Save altered clone xml
326331
self._clone_xml = str(doc)
@@ -357,12 +362,13 @@ def _check_mac(self, mac):
357362
# Parse disk paths that need to be cloned from the original guest's xml
358363
# Return a tuple of lists:
359364
# ([list of paths to clone], [size of those paths],
360-
# [file/block type of those paths])
365+
# [file/block type of those paths], [indices of disks to be cloned])
361366
def _get_original_devices_info(self, xml):
362367

363368
lst = []
364369
size = []
365370
typ = []
371+
idx_lst = []
366372

367373
doc = libxml2.parseDoc(xml)
368374
ctx = doc.xpathNewContext()
@@ -373,6 +379,7 @@ def _get_original_devices_info(self, xml):
373379
node = self._get_available_cloning_device(ctx, i, self._force_target)
374380
if node == None:
375381
continue
382+
idx_lst.append(i)
376383
lst.append(node[0].get_properties().getContent())
377384
finally:
378385
if ctx is not None:
@@ -386,7 +393,7 @@ def _get_original_devices_info(self, xml):
386393
typ.append(t)
387394
size.append(sz)
388395

389-
return (lst, size, typ)
396+
return (lst, size, typ, idx_lst)
390397

391398
# Pull disk #i from the original guest xml, return it's xml
392399
# if it should be cloned (skips readonly, empty, or sharable disks
@@ -436,18 +443,21 @@ def _local_paths_info(self, paths_lst):
436443

437444
# Check if original disk type (file/block) is different from
438445
# requested clones disk type, and alter xml if needed
439-
def _change_disk_type(self, org_type, cln_type, ctx):
440-
441-
for i in range(len(org_type)):
442-
disk_type = ctx.xpathEval("/domain/devices/disk[%d]/@type" % (i+1))
443-
driv_name = ctx.xpathEval("/domain/devices/disk[%d]/driver/@name" % (i+1))
444-
src = ctx.xpathEval("/domain/devices/disk[%d]/source" % (i+1))
446+
def _change_disk_type(self, org_type, cln_type, idxs, ctx):
447+
448+
type_idx = 0
449+
for dev_idx in idxs:
450+
disk_type = ctx.xpathEval("/domain/devices/disk[%d]/@type" %
451+
dev_idx)
452+
driv_name = ctx.xpathEval("/domain/devices/disk[%d]/driver/@name" %
453+
dev_idx)
454+
src = ctx.xpathEval("/domain/devices/disk[%d]/source" % dev_idx)
445455
src_chid_txt = src[0].get_properties().getContent()
446456

447457
# different type
448-
if org_type[i] != cln_type[i]:
458+
if org_type[type_idx] != cln_type[type_idx]:
449459
# changing from file to disk
450-
if org_type[i] == True:
460+
if org_type[type_idx] == True:
451461
disk_type[0].setContent("block")
452462
driv_name[0].setContent("phy")
453463
src[0].get_properties().unlinkNode()
@@ -459,6 +469,8 @@ def _change_disk_type(self, org_type, cln_type, ctx):
459469
src[0].get_properties().unlinkNode()
460470
src[0].newProp("file", src_chid_txt)
461471

472+
type_idx += 1
473+
462474
#
463475
# start duplicate
464476
# this function clones the virtual machine according to the ClonDesign object

0 commit comments

Comments
 (0)