Libvirt storage API doesn't support renaming storage volumes so we need to copy the nvram file and remove the old one. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1368922 Signed-off-by: Pavel Hrdina <phrdina@xxxxxxxxxx> --- new in v3: - always assign some value into new_nvram and old_nvram - fixed overwriting exception error - call define_overview() inside rename_domain() - dropped overly protective check new in v2: - properly implement the rename process - introduced new method has_nvram() - some comments virtManager/details.py | 2 +- virtManager/domain.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/virtManager/details.py b/virtManager/details.py index d6fef967..a2097ec8 100644 --- a/virtManager/details.py +++ b/virtManager/details.py @@ -1975,7 +1975,7 @@ class vmmDetails(vmmGObjectUI): # This needs to be last if self.edited(EDIT_NAME): # Renaming is pretty convoluted, so do it here synchronously - self.vm.define_name(self.widget("overview-name").get_text()) + self.vm.rename_domain(self.widget("overview-name").get_text()) if not kwargs and not hotplug_args: # Saves some useless redefine attempts diff --git a/virtManager/domain.py b/virtManager/domain.py index d9e17dbb..4eb9fa47 100644 --- a/virtManager/domain.py +++ b/virtManager/domain.py @@ -32,6 +32,7 @@ from virtinst import DomainSnapshot from virtinst import Guest from virtinst import util from virtinst import VirtualController +from virtinst import VirtualDisk from .libvirtobject import vmmLibvirtObject @@ -479,6 +480,10 @@ class vmmDomain(vmmLibvirtObject): return "-" return str(i) + def has_nvram(self): + return bool(self.get_xmlobj().os.loader_ro is True and + self.get_xmlobj().os.loader_type == "pflash") + ################## # Support checks # ################## @@ -552,11 +557,65 @@ class vmmDomain(vmmLibvirtObject): raise RuntimeError(_("Could not find specified device in the " "inactive VM configuration: %s") % repr(origdev)) + def _copy_nvram_file(self, new_name): + """ + We need to do this copy magic because there is no Libvirt storage API + to rename storage volume. + """ + old_nvram = VirtualDisk(self.conn.get_backend()) + old_nvram.path = self.get_xmlobj().os.nvram + + nvram_dir = os.path.dirname(old_nvram.path) + new_nvram_path = os.path.join(nvram_dir, "%s_VARS.fd" % new_name) + + new_nvram = VirtualDisk(self.conn.get_backend()) + new_nvram.path = new_nvram_path + + nvram_install = VirtualDisk.build_vol_install( + self.conn.get_backend(), os.path.basename(new_nvram.path), + new_nvram.get_parent_pool(), new_nvram.get_size(), False) + nvram_install.input_vol = old_nvram.get_vol_object() + nvram_install.sync_input_vol(only_format=True) + + new_nvram.set_vol_install(nvram_install) + new_nvram.validate() + new_nvram.setup() + + return new_nvram, old_nvram + ############################## # Persistent XML change APIs # ############################## + def rename_domain(self, new_name): + new_nvram = None + old_nvram = None + if self.has_nvram(): + try: + new_nvram, old_nvram = self._copy_nvram_file(new_name) + except Exception as error: + raise RuntimeError("Cannot rename nvram VARS: '%s'" % error) + + try: + self.define_name(new_name) + except Exception as error: + if new_nvram: + try: + new_nvram.get_vol_object().delete(0) + except Exception as warn: + logging.debug("rename failed and new nvram was not " + "removed: '%s'", warn) + raise error + + if new_nvram: + try: + old_nvram.get_vol_object().delete(0) + except Exception as warn: + logging.debug("old nvram file was not removed: '%s'", warn) + + self.define_overview(nvram=new_nvram.path) + # Device Add/Remove def add_device(self, devobj): """ @@ -621,7 +680,8 @@ class vmmDomain(vmmLibvirtObject): self._redefine_xmlobj(guest) def define_overview(self, machine=_SENTINEL, description=_SENTINEL, - title=_SENTINEL, idmap_list=_SENTINEL, loader=_SENTINEL): + title=_SENTINEL, idmap_list=_SENTINEL, loader=_SENTINEL, + nvram=_SENTINEL): guest = self._make_xmlobj_to_define() if machine != _SENTINEL: guest.os.machine = machine @@ -644,6 +704,9 @@ class vmmDomain(vmmLibvirtObject): guest.os.loader_type = "pflash" guest.os.loader_ro = True + if nvram != _SENTINEL: + guest.os.nvram = nvram + if idmap_list != _SENTINEL: if idmap_list is not None: # pylint: disable=unpacking-non-sequence @@ -1426,14 +1489,21 @@ class vmmDomain(vmmLibvirtObject): @vmmLibvirtObject.lifecycle_action def delete(self, force=True): + """ + @force: True if we are deleting domain, False if we are renaming domain + + If the domain is renamed we need to keep the nvram file. + """ flags = 0 if force: flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA", 0) flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_MANAGED_SAVE", 0) - if (self.get_xmlobj().os.loader_ro is True and - self.get_xmlobj().os.loader_type == "pflash"): + if self.has_nvram(): flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_NVRAM", 0) + else: + if self.has_nvram(): + flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_KEEP_NVRAM", 0) try: self._backend.undefineFlags(flags) except libvirt.libvirtError: -- 2.12.0 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list