[libvirt] [PATCH 05/12] Plumb the loader source into generation of QEMU command line.

Prerna Saxena saxenap.ltc at gmail.com
Mon May 14 11:15:15 UTC 2018


Given that nvram & loader elements can now be backed by a non-local
source too, adjust all steps leading to generation of
QEMU command line.

Signed-off-by: Prerna Saxena <saxenap.ltc at gmail.com>
---
 src/qemu/qemu_cgroup.c          | 13 +++++++++----
 src/qemu/qemu_command.c         | 21 ++++++++++++++++-----
 src/qemu/qemu_domain.c          | 31 +++++++++++++++++++++---------
 src/qemu/qemu_driver.c          |  7 ++++---
 src/qemu/qemu_process.c         | 42 ++++++++++++++++++++++++++++-------------
 src/security/security_dac.c     |  6 ++++--
 src/security/security_selinux.c |  6 ++++--
 7 files changed, 88 insertions(+), 38 deletions(-)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index d88eb78..2068eb0 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -580,16 +580,21 @@ qemuSetupMemoryCgroup(virDomainObjPtr vm)
 static int
 qemuSetupFirmwareCgroup(virDomainObjPtr vm)
 {
+    virStorageSourcePtr src = NULL;
+
     if (!vm->def->os.loader)
         return 0;
 
-    if (vm->def->os.loader->path &&
-        qemuSetupImagePathCgroup(vm, vm->def->os.loader->path,
-                                 vm->def->os.loader->readonly == VIR_TRISTATE_BOOL_YES) < 0)
+    src = vm->def->os.loader->src;
+
+    if (src->type == VIR_STORAGE_TYPE_FILE &&
+        qemuSetupImagePathCgroup(vm, src->path,
+                                 src->readonly == VIR_TRISTATE_BOOL_YES) < 0)
         return -1;
 
     if (vm->def->os.loader->nvram &&
-        qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram, false) < 0)
+        vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+        qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram->path, false) < 0)
         return -1;
 
     return 0;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 08f67a4..e9d6e4b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9260,6 +9260,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
     virDomainLoaderDefPtr loader = def->os.loader;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
     int unit = 0;
+    char *source = NULL;
 
     if (!loader)
         return;
@@ -9267,7 +9268,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
     switch ((virDomainLoader) loader->type) {
     case VIR_DOMAIN_LOADER_TYPE_ROM:
         virCommandAddArg(cmd, "-bios");
-        virCommandAddArg(cmd, loader->path);
+        virCommandAddArg(cmd, loader->src->path);
         break;
 
     case VIR_DOMAIN_LOADER_TYPE_PFLASH:
@@ -9279,9 +9280,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
                                  NULL);
         }
 
+        if (qemuGetDriveSourceString(loader->src, NULL, &source) < 0)
+            break;
+
         virBufferAddLit(&buf, "file=");
-        virQEMUBuildBufferEscapeComma(&buf, loader->path);
-        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
+        virQEMUBuildBufferEscapeComma(&buf, source);
+        free(source);
+        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d",
+                          unit);
         unit++;
 
         if (loader->readonly) {
@@ -9294,9 +9300,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
 
         if (loader->nvram) {
             virBufferFreeAndReset(&buf);
+            if (qemuGetDriveSourceString(loader->nvram, NULL, &source) < 0)
+                break;
+
             virBufferAddLit(&buf, "file=");
-            virQEMUBuildBufferEscapeComma(&buf, loader->nvram);
-            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
+            virQEMUBuildBufferEscapeComma(&buf, source);
+            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d",
+                              unit);
+            unit++;
 
             virCommandAddArg(cmd, "-drive");
             virCommandAddArgBuffer(cmd, &buf);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 9bb6d8a..2d4e299 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3318,6 +3318,9 @@ qemuDomainDefPostParse(virDomainDefPtr def,
      * function shall not fail in that case. It will be re-run on VM startup
      * with the capabilities populated. */
     virQEMUCapsPtr qemuCaps = parseOpaque;
+    virDomainLoaderDefPtr ldr = NULL;
+    char *nvramPath = NULL;
+
     int ret = -1;
 
     if (def->os.bootloader || def->os.bootloaderArgs) {
@@ -3332,13 +3335,20 @@ qemuDomainDefPostParse(virDomainDefPtr def,
         goto cleanup;
     }
 
-    if (def->os.loader &&
-        def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
-        def->os.loader->readonly == VIR_TRISTATE_SWITCH_ON &&
-        !def->os.loader->nvram) {
-        if (virAsprintf(&def->os.loader->nvram, "%s/%s_VARS.fd",
+    ldr = def->os.loader;
+    if (ldr &&
+        ldr->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
+        ldr->readonly == VIR_TRISTATE_SWITCH_ON &&
+        !ldr->nvram) {
+        if (virAsprintf(&nvramPath, "%s/%s_VARS.fd",
                         cfg->nvramDir, def->name) < 0)
             goto cleanup;
+        ldr->nvram = virStorageSourceNewFromBackingAbsolute(nvramPath);
+        if (!ldr->nvram) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unable to add NVRAM drive %s"), nvramPath);
+            goto cleanup;
+        }
     }
 
     if (qemuDomainDefAddDefaultDevices(def, qemuCaps) < 0)
@@ -10494,19 +10504,22 @@ qemuDomainSetupLoader(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
 
     VIR_DEBUG("Setting up loader");
 
-    if (loader) {
+    if (loader && loader->src) {
         switch ((virDomainLoader) loader->type) {
         case VIR_DOMAIN_LOADER_TYPE_ROM:
-            if (qemuDomainCreateDevice(loader->path, data, false) < 0)
+            if (loader->src->type == VIR_STORAGE_TYPE_FILE &&
+                qemuDomainCreateDevice(loader->src->path, data, false) < 0)
                 goto cleanup;
             break;
 
         case VIR_DOMAIN_LOADER_TYPE_PFLASH:
-            if (qemuDomainCreateDevice(loader->path, data, false) < 0)
+            if (loader->src->type == VIR_STORAGE_TYPE_FILE &&
+                qemuDomainCreateDevice(loader->src->path, data, false) < 0)
                 goto cleanup;
 
             if (loader->nvram &&
-                qemuDomainCreateDevice(loader->nvram, data, false) < 0)
+                loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+                qemuDomainCreateDevice(loader->nvram->path, data, false) < 0)
                 goto cleanup;
             break;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c129321..9c491b2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7540,12 +7540,13 @@ qemuDomainUndefineFlags(virDomainPtr dom,
 
     if (vm->def->os.loader &&
         vm->def->os.loader->nvram &&
-        virFileExists(vm->def->os.loader->nvram)) {
+        vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+        virFileExists(vm->def->os.loader->nvram->path)) {
         if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
-            if (unlink(vm->def->os.loader->nvram) < 0) {
+            if (unlink(vm->def->os.loader->nvram->path) < 0) {
                 virReportSystemError(errno,
                                      _("failed to remove nvram: %s"),
-                                     vm->def->os.loader->nvram);
+                                     vm->def->os.loader->nvram->path);
                 goto endjob;
             }
         } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 37876b8..e4c05e2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3994,25 +3994,41 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
     const char *master_nvram_path;
     ssize_t r;
 
-    if (!loader || !loader->nvram || virFileExists(loader->nvram))
+    /* return early if either loader is network-backed
+     * or NVRAM is already specified.
+     */
+    if (!loader || !loader->src || !loader->nvram ||
+        loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH ||
+        loader->src->type == VIR_STORAGE_TYPE_NETWORK ||
+        loader->nvram->type == VIR_STORAGE_TYPE_NETWORK)
+        return 0;
+
+    if (loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+        virFileExists(loader->nvram->path))
         return 0;
 
     master_nvram_path = loader->templt;
-    if (!loader->templt) {
+    /* Even if a template is not specified, we associate "known" EFI firmware
+     * to their NVRAM templates.
+     * Ofcourse this only applies to local firmware paths, as it is diffcult
+     * for libvirt to parse all network paths.
+     */
+    if (!loader->templt && loader->src->type == VIR_STORAGE_TYPE_FILE) {
         size_t i;
         for (i = 0; i < cfg->nfirmwares; i++) {
-            if (STREQ(cfg->firmwares[i]->name, loader->path)) {
+            if (STREQ(cfg->firmwares[i]->name, loader->src->path)) {
                 master_nvram_path = cfg->firmwares[i]->nvram;
                 break;
             }
         }
     }
 
-    if (!master_nvram_path) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("unable to find any master var store for "
-                         "loader: %s"), loader->path);
-        goto cleanup;
+    if (!master_nvram_path && loader->nvram) {
+        /* There is no template description, but an NVRAM spec
+         * has already been provided.
+         * Trust the client to have generated the right spec here
+         */
+        return 0;
     }
 
     if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY,
@@ -4022,13 +4038,13 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
                              master_nvram_path);
         goto cleanup;
     }
-    if ((dstFD = virFileOpenAs(loader->nvram,
+    if ((dstFD = virFileOpenAs(loader->nvram->path,
                                O_WRONLY | O_CREAT | O_EXCL,
                                S_IRUSR | S_IWUSR,
                                cfg->user, cfg->group, 0)) < 0) {
         virReportSystemError(-dstFD,
                              _("Failed to create file '%s'"),
-                             loader->nvram);
+                             loader->nvram->path);
         goto cleanup;
     }
     created = true;
@@ -4046,7 +4062,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
         if (safewrite(dstFD, buf, r) < 0) {
             virReportSystemError(errno,
                                  _("Unable to write to file '%s'"),
-                                 loader->nvram);
+                                 loader->nvram->path);
             goto cleanup;
         }
     } while (r);
@@ -4060,7 +4076,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
     if (VIR_CLOSE(dstFD) < 0) {
         virReportSystemError(errno,
                              _("Unable to close file '%s'"),
-                             loader->nvram);
+                             loader->nvram->path);
         goto cleanup;
     }
 
@@ -4070,7 +4086,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
      * copy the file content. Roll back. */
     if (ret < 0) {
         if (created)
-            unlink(loader->nvram);
+            unlink(loader->nvram->path);
     }
 
     VIR_FORCE_CLOSE(srcFD);
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 8938e2d..3febea6 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1604,7 +1604,8 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr,
     }
 
     if (def->os.loader && def->os.loader->nvram &&
-        virSecurityDACRestoreFileLabel(priv, def->os.loader->nvram) < 0)
+        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+        virSecurityDACRestoreFileLabel(priv, def->os.loader->nvram->path) < 0)
         rc = -1;
 
     return rc;
@@ -1732,8 +1733,9 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr,
         return -1;
 
     if (def->os.loader && def->os.loader->nvram &&
+        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
         virSecurityDACSetOwnership(priv, NULL,
-                                   def->os.loader->nvram, user, group) < 0)
+                                   def->os.loader->nvram->path, user, group) < 0)
         return -1;
 
     if (def->os.kernel &&
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 5f74ef7..bcda939 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2459,7 +2459,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr,
         rc = -1;
 
     if (def->os.loader && def->os.loader->nvram &&
-        virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram) < 0)
+        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
+        virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram->path) < 0)
         rc = -1;
 
     return rc;
@@ -2851,8 +2852,9 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr,
     /* This is different than kernel or initrd. The nvram store
      * is really a disk, qemu can read and write to it. */
     if (def->os.loader && def->os.loader->nvram &&
+        def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE &&
         secdef && secdef->imagelabel &&
-        virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram,
+        virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram->path,
                                      secdef->imagelabel) < 0)
         return -1;
 
-- 
1.8.1.2




More information about the libvir-list mailing list