[virt-tools-list] [virt-manager PATCH v2] domain: add support to rename domain with nvram vars file
Cole Robinson
crobinso at redhat.com
Tue Mar 7 16:20:50 UTC 2017
On 03/07/2017 07:33 AM, Pavel Hrdina wrote:
> 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 at redhat.com>
> ---
>
> new in v2:
> - properly implement the rename process
> - introduced new method has_nvram()
> - some comments
>
> virtManager/details.py | 3 +-
> virtManager/domain.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 73 insertions(+), 4 deletions(-)
>
> diff --git a/virtManager/details.py b/virtManager/details.py
> index d6fef967..0b2754d8 100644
> --- a/virtManager/details.py
> +++ b/virtManager/details.py
> @@ -1975,7 +1975,8 @@ 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(),
> + kwargs)
>
> if not kwargs and not hotplug_args:
> # Saves some useless redefine attempts
> diff --git a/virtManager/domain.py b/virtManager/domain.py
> index d9e17dbb..f7d76af6 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,63 @@ 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, kwargs):
> + if self.has_nvram():
> + try:
> + new_nvram, old_nvram = self._copy_nvram_file(new_name)
> + except Exception as e:
> + raise RuntimeError("Cannot rename nvram VARS: '%s'" % e)
> +
Rather than use the self.has_nvram() check to protect new_nvram access, can you do
new_nvram = None
old_nvram = None
if self.has_nvram():
....
Then later on just check 'if new_nvram', etc. I'm surprised pylint doesn't
warn about that pattern actually, even though the code is correct here.
> + try:
> + self.define_name(new_name)
> + except Exception as e:
> + if self.has_nvram():
> + try:
> + new_nvram.get_vol_object().delete(0)
> + except Exception as e:
> + logging.debug("rename failed and new nvram was not "
> + "removed: '%s'", e)
> + raise e
> +
Since you use 'e' twice, the intended error is overwritten if vol delete
fails. So have the second except use e2 or something
> + if self.has_nvram():
> + kwargs["nvram"] = new_nvram.path
> +
define_overview is never actually called here.
Thanks,
Cole
> + try:
> + old_nvram.get_vol_object().delete(0)
> + except Exception as e:
> + logging.debug("old nvram file was not removed: '%s'", e)
> +
> # Device Add/Remove
> def add_device(self, devobj):
> """
> @@ -621,7 +678,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 +702,9 @@ class vmmDomain(vmmLibvirtObject):
> guest.os.loader_type = "pflash"
> guest.os.loader_ro = True
>
> + if nvram != _SENTINEL and guest.os.loader is not None:
> + guest.os.nvram = nvram
> +
Is the guest.os.loader check here actually protecting something? The caller
should protect this already I think
Thanks,
Cole
More information about the virt-tools-list
mailing list