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 this parameter must be repeated multiple times, once per disk in the original
virtual machine. 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 =item B<--force-copy> TARGET
Force cloning the passed disk target ('hdc', 'sda', etc.). By default, 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 return
raise AssertionError("Expected exception, but none raised.") 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> </source>
</pool> </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'> <pool type='mpath'>
<name>mpath</name> <name>mpath</name>

View File

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

View File

@ -57,6 +57,8 @@ class Cloner(object):
self._clone_uuid = None self._clone_uuid = None
self._clone_sparse = True self._clone_sparse = True
self._clone_xml = None self._clone_xml = None
self.clone_nvram = None
self._nvram_disk = None
self._force_target = [] self._force_target = []
self._skip_target = [] self._skip_target = []
@ -361,6 +363,33 @@ class Cloner(object):
clone_disk.validate() 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): def setup_clone(self):
""" """
Validate and set up all parameters needed for the new (clone) VM 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: if channel.type == VirtualChannelDevice.TYPE_UNIX:
channel.source_path = None channel.source_path = None
if self._guest.os.nvram:
self._prepare_nvram()
# Save altered clone xml # Save altered clone xml
self._clone_xml = self._guest.get_xml_config() self._clone_xml = self._guest.get_xml_config()
logging.debug("Clone guest xml is\n%s", self._clone_xml) logging.debug("Clone guest xml is\n%s", self._clone_xml)
@ -452,6 +484,8 @@ class Cloner(object):
if self.preserve: if self.preserve:
for dst_dev in self.clone_disks: for dst_dev in self.clone_disks:
dst_dev.setup(meter=meter) dst_dev.setup(meter=meter)
if self._nvram_disk:
self._nvram_disk.setup(meter=meter)
except Exception, e: except Exception, e:
logging.debug("Duplicate failed: %s", str(e)) logging.debug("Duplicate failed: %s", str(e))
if dom: if dom: