virt-clone: add support to clone nvram VARS

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1243335

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
Pavel Hrdina 2017-03-06 09:43:10 +01:00
parent 191896d0dc
commit 5e2b63c1ff
7 changed files with 121 additions and 0 deletions

View File

@ -88,6 +88,12 @@ for the new guest's virtual disk. If the original guest has multiple disks,
this parameter must be repeated multiple times, once per disk in the original
virtual machine.
=item B<--nvram> NVRAMFILE
Optional path to the new nvram VARS file, if no path is specified and the
guest has nvram the new nvram path will be auto-generated. If the guest
doesn't have nvram this option will be ignored.
=item B<--force-copy> TARGET
Force cloning the passed disk target ('hdc', 'sda', etc.). By default,

View File

@ -0,0 +1,23 @@
<domain type='kvm'>
<name>clone-orig</name>
<uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid>
<memory>262144</memory>
<currentMemory>262144</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='cdrom'/>
<loader readonly='yes' type='pflash'>/usr/share/ovmf/ovmf-efi.fd</loader>
<nvram>/nvram/clone-orig_VARS.fd</nvram>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-kvm</emulator>
</devices>
</domain>

View File

@ -0,0 +1,23 @@
<domain type="kvm">
<name>clone-new</name>
<uuid>12345678-1234-1234-1234-123456789012</uuid>
<memory>262144</memory>
<currentMemory>262144</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch="i686" machine="pc">hvm</type>
<boot dev="cdrom"/>
<loader readonly="yes" type="pflash">/usr/share/ovmf/ovmf-efi.fd</loader>
<nvram>/nvram/clone-new_VARS.fd</nvram>
</os>
<features>
<acpi/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-kvm</emulator>
</devices>
</domain>

View File

@ -175,3 +175,7 @@ class TestClone(unittest.TestCase):
return
raise AssertionError("Expected exception, but none raised.")
def testCloneNvramAuto(self):
base = "nvram-auto"
self._clone_helper(base)

View File

@ -2164,6 +2164,33 @@ ba</description>
</source>
</pool>
<pool type="dir">
<name>nvram</name>
<source>
</source>
<target>
<path>/nvram</path>
<permissions>
<mode>0700</mode>
<owner>0</owner>
<group>0</group>
</permissions>
</target>
<volume type='file'>
<name>clone-orig_VARS.fd</name>
<capacity>1000</capacity>
<allocation>1000</allocation>
<target>
<permissions>
<mode>0700</mode>
<owner>0</owner>
<group>0</group>
</permissions>
</target>
</volume>
</pool>
<pool type='mpath'>
<name>mpath</name>

View File

@ -136,6 +136,8 @@ def parse_args():
dest="preserve", default=True,
help=_("Do not clone storage, new disk images specified "
"via --file are preserved unchanged"))
stog.add_argument("--nvram", dest="new_nvram",
help=_("New file to use as storage for nvram VARS"))
netg = parser.add_argument_group(_("Networking Configuration"))
netg.add_argument("-m", "--mac", dest="new_mac", action="append",
@ -192,6 +194,8 @@ def main(conn=None):
design.clone_sparse = options.sparse
design.preserve = options.preserve
design.clone_nvram = options.new_nvram
# This determines the devices that need to be cloned, so that
# get_clone_diskfile knows how many new disk paths it needs
design.setup_original()

View File

@ -57,6 +57,8 @@ class Cloner(object):
self._clone_uuid = None
self._clone_sparse = True
self._clone_xml = None
self.clone_nvram = None
self._nvram_disk = None
self._force_target = []
self._skip_target = []
@ -361,6 +363,33 @@ class Cloner(object):
clone_disk.validate()
def _prepare_nvram(self):
if self.clone_nvram is None:
nvram_dir = os.path.dirname(self._guest.os.nvram)
self.clone_nvram = os.path.join(nvram_dir,
"%s_VARS.fd" % self._clone_name)
nvram = VirtualDisk(self.conn)
nvram.path = self.clone_nvram
if (not self.preserve_dest_disks and
nvram.wants_storage_creation()):
old_nvram = VirtualDisk(self.conn)
old_nvram.path = self._guest.os.nvram
nvram_install = VirtualDisk.build_vol_install(
self.conn, os.path.basename(nvram.path),
nvram.get_parent_pool(), nvram.get_size(), False)
nvram_install.input_vol = old_nvram.get_vol_object()
nvram_install.sync_input_vol(only_format=True)
nvram_install.reflink = self.reflink
nvram.set_vol_install(nvram_install)
nvram.validate()
self._nvram_disk = nvram
self._guest.os.nvram = nvram.path
def setup_clone(self):
"""
Validate and set up all parameters needed for the new (clone) VM
@ -420,6 +449,9 @@ class Cloner(object):
if channel.type == VirtualChannelDevice.TYPE_UNIX:
channel.source_path = None
if self._guest.os.nvram:
self._prepare_nvram()
# Save altered clone xml
self._clone_xml = self._guest.get_xml_config()
logging.debug("Clone guest xml is\n%s", self._clone_xml)
@ -452,6 +484,8 @@ class Cloner(object):
if self.preserve:
for dst_dev in self.clone_disks:
dst_dev.setup(meter=meter)
if self._nvram_disk:
self._nvram_disk.setup(meter=meter)
except Exception, e:
logging.debug("Duplicate failed: %s", str(e))
if dom: