[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH virt-manager] details: Add UI for enabling UEFI via 'customize before install'



Hi Cole and Michal,

I'm attaching three patches:

On 09/20/14 02:37, Cole Robinson wrote:
> On 09/17/2014 06:55 PM, Cole Robinson wrote:
>> We expose a simple combobox with two entries: BIOS, and UEFI. The
>> UEFI option is only selectable if 1) libvirt supports the necessary
>> domcapabilities bits, 2) it detects that qemu supports the necessary
>> command line options, and 3) libvirt detects a UEFI binary on the
>> host that maps to a known template via qemu.conf
>>
>> If those conditions aren't met, we disable the UEFI option, and show
>> a small warning icon with an explanatory tooltip.
>>
>> The option can only be changed via New VM->Customize Before Install.
>> For existing x86 VMs, it's a readonly label.
>
> I've pushed this now, with follow up patches to handle a couple points
> we discussed:
>
> - Remove the nvram deletion from delete.py, since it won't work in the
> non-root case, and all uses of nvram should also be with a libvirt +
> driver that provides UNDEFINE_NVRAM
>
> - Before using UNDEFINE_NVRAM, match the same condition that libvirt
> uses: loader_ro is True and loader_type == "pflash" and bool(nvram)

(1) unfortunately virt-manager commit 3feedb76 ("domain: Match
UNDEFINE_NVRAM conditions with libvirt") is not correct (it doesn't
work), and not what I had in mind:

> diff --git a/virtManager/domain.py b/virtManager/domain.py
> index 29f3861..abf3146 100644
> --- a/virtManager/domain.py
> +++ b/virtManager/domain.py
> @@ -1403,7 +1403,9 @@ class vmmDomain(vmmLibvirtObject):
>              flags |= getattr(libvirt,
>                               "VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA", 0)
>              flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_MANAGED_SAVE", 0)
> -            if self.get_xmlobj().os.nvram:
> +            if (self.get_xmlobj().os.loader_ro is True and
> +                self.get_xmlobj().os.loader_type == "pflash" and
> +                self.get_xmlobj().os.nvram):
>                  flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_NVRAM", 0)
>          try:
>              self._backend.undefineFlags(flags)

Before virt-manager commit 3feedb76, the condition on which to set the
flag was:

  self.get_xmlobj().os.nvram

and it didn't work for all possible cases.

After the patch, what you have is

  self.get_xmlobj().os.nvram *and* blah

The commit only constrains (further tightens, further restricts) the
original condition, which had been too restrictive to begin with. Again,
the nvram element (or its text() child) can be completely absent from
the domain XML -- libvirtd will generate the pathname of the varstore
file on the fly, and it need not be part of the serialized XML file. So
in the XML all you'll have is

  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
    <boot dev='cdrom'/>
  </os>

or

  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <loader readonly='yes' type='pflash'>/custom/OVMF_CODE.fd</loader>
    <nvram template='/custom/OVMF_VARS.fd'/>
    <boot dev='cdrom'/>
  </os>

My suggestion was to *replace* the original condition with the
(loader_ro && loader_type=="pflash") one. If you check my earlier
message, I wrote *iff*, meaning "if and only if".

Cole, can you please apply the first attached patch?


(2) Unfortunately, even libvirtd needs to be modified, in addition.

My patch for (1) *does* pass VIR_DOMAIN_UNDEFINE_NVRAM to libvirtd (I
verified that with gdb), but libvirtd doesn't act upon it correctly.
Namely, in the libvirtd source code, in qemuDomainUndefineFlags(),
commit 273b6581 added:

    if (!virDomainObjIsActive(vm) &&
        vm->def->os.loader && vm->def->os.loader->nvram &&
        virFileExists(vm->def->os.loader->nvram)) {
        if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot delete inactive domain with nvram"));
            goto cleanup;
        }

        if (unlink(vm->def->os.loader->nvram) < 0) {
            virReportSystemError(errno,
                                 _("failed to remove nvram: %s"),
                                 vm->def->os.loader->nvram);
            goto cleanup;
        }
    }

Here "vm->def->os.loader->nvram" evaluates to NULL:

  6468        if (!virDomainObjIsActive(vm) &&
  6469            vm->def->os.loader && vm->def->os.loader->nvram &&
  6470            virFileExists(vm->def->os.loader->nvram)) {
  6471            if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
  6472                virReportError(VIR_ERR_OPERATION_INVALID, "%s",

  (gdb) print vm->def->os.loader
  $1 = (virDomainLoaderDefPtr) 0x7ff59c00bf20

  (gdb) print vm->def->os.loader->nvram
  $2 = 0x0

I thought that the auto-generation of the nvram pathname (internal to
libvirtd, ie. not visible in the XML file) would occur on the undefine
path as well. Apparently this is not the case.

Indeed, the only call to qemuPrepareNVRAM() is from qemuProcessStart().

Michal, would it be possible generate the *pathname* of the separate
varstore in qemuDomainUndefineFlags() too?

Please see the second attached patch; it works for me. (This patch is
best looked at with "git diff -b" (or "git show -b").)


(3) I just realized that a domain's name can change during its lifetime.
Renaming a domain becomes a problem when the varstore's pathname is
deduced from the domain's name. For this reason, the auto-generation
should use the domain's UUID (which never changes). Michal, what do you
think of the 3rd attached patch?


I can resubmit these as standalone patches / series as well (the first
to virt-tools-list, and the last two to libvir-list), if that's
necessary.

Thanks,
Laszlo

>From b8adf86d6ebee7af4aa11e9810e55276c58d7e98 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek redhat com>
Date: Sun, 21 Sep 2014 13:12:48 +0200
Subject: [PATCH] domain: relax the UNDEFINE_NVRAM condition precisely to
 libvirtd's one

(1) A separate nvram (ie. variable store) file for the domain exists if
and only if the following condition holds:

    (self.get_xmlobj().os.loader_ro is True and
     self.get_xmlobj().os.loader_type == "pflash")

(Refer to libvirtd's qemuPrepareNVRAM() function, as of commit 742b08e30.)

(2) The

    self.get_xmlobj().os.nvram

condition is sufficient, but not necessary, for the separate varstore file
to exist. That is, if the condition holds, then the separate varstore file
exists for sure, but if the condition doesn't hold, the file may exist
nonetheless. (Because libvirtd can auto-generate the varstore file's
pathname.)

This means that requiring condition (2) for setting UNDEFINE_NVRAM on
domain deletion will miss a subset of the cases, ie. when the necessary
and sufficient condition (1) holds, but the sufficient-only condition (2)
doesn't.

Make sure that the code uses the necessary and sufficient condition (1).

Signed-off-by: Laszlo Ersek <lersek redhat com>
---
 virtManager/domain.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/virtManager/domain.py b/virtManager/domain.py
index b28f454..585f64b 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -1399,8 +1399,7 @@ class vmmDomain(vmmLibvirtObject):
                              "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" and
-                self.get_xmlobj().os.nvram):
+                self.get_xmlobj().os.loader_type == "pflash"):
                 flags |= getattr(libvirt, "VIR_DOMAIN_UNDEFINE_NVRAM", 0)
         try:
             self._backend.undefineFlags(flags)
-- 
1.8.3.1

>From 40293f2ba8b6611cc4f57478700f076bd254fc06 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek redhat com>
Date: Sun, 21 Sep 2014 15:07:34 +0200
Subject: [PATCH 1/2] qemuDomainUndefineFlags: auto-generate nvram pathname
 when necessary

The condition

  (loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
   loader->readonly == VIR_TRISTATE_SWITCH_ON)

is equivalent to the domain having a separate varstore (nvram) file. The
pathname of this file can be explicitly set in the domain XML, or
auto-generated by libvirtd. In

  qemuProcessStart()
    qemuPrepareNVRAM()

the pathname is auto-generated only when starting qemu.

Auto-generate the varstore pathname also when undefining the domain, so
that the varstore file is not leaked when its pathname is not specified
explicitly in the domain XML.

Signed-off-by: Laszlo Ersek <lersek redhat com>
---
 src/qemu/qemu_driver.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b888b09..16cd3e3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6415,6 +6415,8 @@ qemuDomainUndefineFlags(virDomainPtr dom,
     int ret = -1;
     int nsnapshots;
     virQEMUDriverConfigPtr cfg = NULL;
+    virDomainLoaderDefPtr loader;
+    bool nvramPathnameGenerated = false;
 
     virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                   VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
@@ -6468,19 +6470,31 @@ qemuDomainUndefineFlags(virDomainPtr dom,
     }
 
     if (!virDomainObjIsActive(vm) &&
-        vm->def->os.loader && vm->def->os.loader->nvram &&
-        virFileExists(vm->def->os.loader->nvram)) {
-        if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
-            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                           _("cannot delete inactive domain with nvram"));
-            goto cleanup;
+        (loader = vm->def->os.loader) &&
+        loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
+        loader->readonly == VIR_TRISTATE_SWITCH_ON) {
+        if (!loader->nvram) {
+            if (virAsprintf(&loader->nvram,
+                            "%s/lib/libvirt/qemu/nvram/%s_VARS.fd",
+                            LOCALSTATEDIR, vm->def->name) < 0)
+                goto cleanup;
+
+            nvramPathnameGenerated = true;
         }
 
-        if (unlink(vm->def->os.loader->nvram) < 0) {
-            virReportSystemError(errno,
-                                 _("failed to remove nvram: %s"),
-                                 vm->def->os.loader->nvram);
-            goto cleanup;
+        if (virFileExists(loader->nvram)) {
+            if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
+                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                               _("cannot delete inactive domain with nvram"));
+                goto cleanup;
+            }
+
+            if (unlink(loader->nvram) < 0) {
+                virReportSystemError(errno,
+                                     _("failed to remove nvram: %s"),
+                                     loader->nvram);
+                goto cleanup;
+            }
         }
     }
 
@@ -6507,6 +6521,8 @@ qemuDomainUndefineFlags(virDomainPtr dom,
     ret = 0;
 
  cleanup:
+    if (nvramPathnameGenerated)
+        VIR_FREE(loader->nvram);
     VIR_FREE(name);
     if (vm)
         virObjectUnlock(vm);
-- 
1.8.3.1

>From 5fd4f9a9430c757aae8681ba7e9f65ec55bb7889 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek redhat com>
Date: Sun, 21 Sep 2014 16:07:22 +0200
Subject: [PATCH 2/2] qemu NVRAM: auto-generated pathnames should contain
 domain UUIDs

The name of a domain is unstable in the sense that the domain can be
renamed. Currently a rename will cause the domain to lose connection with
its separate varstore file, if the pathname of the varstore was
automatically generated.

Hence generate such pathnames based on the domain's UUID, because that one
never changes.

Signed-off-by: Laszlo Ersek <lersek redhat com>
---
 src/qemu/qemu_driver.c  | 7 +++++--
 src/qemu/qemu_process.c | 7 +++++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 16cd3e3..9ea1b5b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6474,9 +6474,12 @@ qemuDomainUndefineFlags(virDomainPtr dom,
         loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
         loader->readonly == VIR_TRISTATE_SWITCH_ON) {
         if (!loader->nvram) {
+            char uuidstr[VIR_UUID_STRING_BUFLEN];
+
             if (virAsprintf(&loader->nvram,
-                            "%s/lib/libvirt/qemu/nvram/%s_VARS.fd",
-                            LOCALSTATEDIR, vm->def->name) < 0)
+                            "%s/lib/libvirt/qemu/nvram/%s-VARS.fd",
+                            LOCALSTATEDIR,
+                            virUUIDFormat(vm->def->uuid, uuidstr)) < 0)
                 goto cleanup;
 
             nvramPathnameGenerated = true;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 13614e9..57bde45 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3866,9 +3866,12 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
 
     /* Autogenerate nvram path if needed.*/
     if (!loader->nvram) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+
         if (virAsprintf(&loader->nvram,
-                        "%s/lib/libvirt/qemu/nvram/%s_VARS.fd",
-                        LOCALSTATEDIR, def->name) < 0)
+                        "%s/lib/libvirt/qemu/nvram/%s-VARS.fd",
+                        LOCALSTATEDIR,
+                        virUUIDFormat(def->uuid, uuidstr)) < 0)
             goto cleanup;
 
         generated = true;
-- 
1.8.3.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]