]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Generate pr cmd line at startup
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 18 Apr 2018 14:55:14 +0000 (16:55 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 11 May 2018 07:02:56 +0000 (09:02 +0200)
For command line we need two things:

1) -object pr-manager-helper,id=$alias,path=$socketPath
2) -drive file.pr-manager=$alias

In -object pr-manager-helper we tell qemu which socket to connect
to, then in -drive file-pr-manager we just reference the object
the drive in question should use.

For managed PR helper the alias is always "pr-helper0" and socket
path "${vm->priv->libDir}/pr-helper0.sock".

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
12 files changed:
src/libvirt_private.syms
src/qemu/qemu_alias.c
src/qemu/qemu_alias.h
src/qemu/qemu_command.c
src/qemu/qemu_command.h
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_process.h
src/util/virstoragefile.c
src/util/virstoragefile.h
tests/qemuxml2argvdata/disk-virtio-scsi-reservations.args [new file with mode: 0644]
tests/qemuxml2argvtest.c

index 7b93b42264575b1e008aa34742b010466bd9611f..5fea1bca41d9a58eb8002664be1c26995ddcd143 100644 (file)
@@ -2803,7 +2803,9 @@ virStorageNetHostTransportTypeToString;
 virStorageNetProtocolTypeToString;
 virStoragePRDefFormat;
 virStoragePRDefFree;
+virStoragePRDefIsEnabled;
 virStoragePRDefIsEqual;
+virStoragePRDefIsManaged;
 virStoragePRDefParseXML;
 virStorageSourceBackingStoreClear;
 virStorageSourceClear;
index 9b49f9c1e1632abf83489a4c2c7a40717dd6d435..bd714f7aee09010fd88517f9359d4f120c9fdc48 100644 (file)
@@ -773,3 +773,21 @@ qemuAliasChardevFromDevAlias(const char *devAlias)
 
     return ret;
 }
+
+
+const char *
+qemuDomainGetManagedPRAlias(void)
+{
+    return "pr-helper0";
+}
+
+
+char *
+qemuDomainGetUnmanagedPRAlias(const virDomainDiskDef *disk)
+{
+    char *ret;
+
+    ignore_value(virAsprintf(&ret, "pr-helper-%s", disk->info.alias));
+
+    return ret;
+}
index 8c744138cef7b64647b32f81e01a1016d546893e..76678658c0f2736c224182828dfb941c584a1049 100644 (file)
@@ -92,4 +92,8 @@ char *qemuAliasTLSObjFromSrcAlias(const char *srcAlias)
 char *qemuAliasChardevFromDevAlias(const char *devAlias)
     ATTRIBUTE_NONNULL(1);
 
+const char *qemuDomainGetManagedPRAlias(void);
+
+char *qemuDomainGetUnmanagedPRAlias(const virDomainDiskDef *disk);
+
 #endif /* __QEMU_ALIAS_H__*/
index 08f67a44b91c2b4f6a3cc8e5705485316d3e3cbe..81a9811d14d63873f23848dc5e13aa3aa75d4c25 100644 (file)
@@ -1470,6 +1470,28 @@ qemuDiskSourceGetProps(virStorageSourcePtr src)
 }
 
 
+static int
+qemuBuildDriveSourcePR(virBufferPtr buf,
+                       virDomainDiskDefPtr disk)
+{
+    char *alias = NULL;
+    const char *defaultAlias = NULL;
+
+    if (!virStoragePRDefIsEnabled(disk->src->pr))
+        return 0;
+
+    if (virStoragePRDefIsManaged(disk->src->pr))
+        defaultAlias = qemuDomainGetManagedPRAlias();
+    else if (!(alias = qemuDomainGetUnmanagedPRAlias(disk)))
+        return -1;
+
+
+    virBufferAsprintf(buf, ",file.pr-manager=%s", alias ? alias : defaultAlias);
+    VIR_FREE(alias);
+    return 0;
+}
+
+
 static int
 qemuBuildDriveSourceStr(virDomainDiskDefPtr disk,
                         virQEMUCapsPtr qemuCaps,
@@ -1533,6 +1555,9 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk,
 
         if (disk->src->debug)
             virBufferAsprintf(buf, ",file.debug=%d", disk->src->debugLevel);
+
+        if (qemuBuildDriveSourcePR(buf, disk) < 0)
+            goto cleanup;
     } else {
         if (!(source = virQEMUBuildDriveCommandlineFromJSON(srcprops)))
             goto cleanup;
@@ -9619,6 +9644,112 @@ qemuBuildPanicCommandLine(virCommandPtr cmd,
 }
 
 
+/**
+ * qemuBuildPRManagerInfoProps:
+ * @prd: disk PR runtime info
+ * @propsret: JSON properties to return
+ *
+ * Build the JSON properties for the pr-manager object.
+ *
+ * Returns: 0 on success (@propsret is NULL if no properties are needed),
+ *         -1 on failure (with error message set).
+ */
+int
+qemuBuildPRManagerInfoProps(virDomainObjPtr vm,
+                            const virDomainDiskDef *disk,
+                            virJSONValuePtr *propsret,
+                            char **aliasret)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    char *socketPath = NULL;
+    char *alias = NULL;
+    int ret = -1;
+
+    *propsret = NULL;
+    *aliasret = NULL;
+
+    if (!virStoragePRDefIsEnabled(disk->src->pr))
+        return 0;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_PR_MANAGER_HELPER)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("reservations not supported with this QEMU binary"));
+        return ret;
+    }
+
+    if (!(socketPath = qemuDomainGetPRSocketPath(vm, disk->src->pr)))
+        return ret;
+
+    if (virStoragePRDefIsManaged(disk->src->pr)) {
+        if (VIR_STRDUP(alias, qemuDomainGetManagedPRAlias()) < 0)
+            goto cleanup;
+    } else {
+        if (!(alias = qemuDomainGetUnmanagedPRAlias(disk)))
+            goto cleanup;
+    }
+
+    if (virJSONValueObjectCreate(propsret,
+                                 "s:path", socketPath,
+                                 NULL) < 0)
+        goto cleanup;
+
+    VIR_STEAL_PTR(*aliasret, alias);
+    ret = 0;
+ cleanup:
+    VIR_FREE(alias);
+    VIR_FREE(socketPath);
+    return ret;
+}
+
+
+static int
+qemuBuildMasterPRCommandLine(virDomainObjPtr vm,
+                             virCommandPtr cmd,
+                             const virDomainDef *def)
+{
+    size_t i;
+    bool managedAdded = false;
+    virJSONValuePtr props = NULL;
+    char *alias = NULL;
+    char *tmp = NULL;
+    int ret = -1;
+
+    for (i = 0; i < def->ndisks; i++) {
+        const virDomainDiskDef *disk = def->disks[i];
+
+        if (virStoragePRDefIsManaged(disk->src->pr)) {
+            if (managedAdded)
+                continue;
+
+            managedAdded = true;
+        }
+
+        if (qemuBuildPRManagerInfoProps(vm, disk, &props, &alias) < 0)
+            goto cleanup;
+
+        if (!props)
+            continue;
+
+        if (!(tmp = virQEMUBuildObjectCommandlineFromJSON("pr-manager-helper",
+                                                          alias,
+                                                          props)))
+            goto cleanup;
+        VIR_FREE(alias);
+        virJSONValueFree(props);
+        props = NULL;
+
+        virCommandAddArgList(cmd, "-object", tmp, NULL);
+        VIR_FREE(tmp);
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(alias);
+    virJSONValueFree(props);
+    return ret;
+}
+
+
 /**
  * qemuBuildCommandLineValidate:
  *
@@ -9787,6 +9918,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0)
         goto error;
 
+    if (qemuBuildMasterPRCommandLine(vm, cmd, def) < 0)
+        goto error;
+
     if (enableFips)
         virCommandAddArg(cmd, "-enable-fips");
 
index 31c9da673ca4f4d4bcb580b4370d27f974b2c448..da1fe679fed7021b32ebce1a99af462fc3a8df51 100644 (file)
@@ -54,6 +54,11 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
                                    size_t *nnicindexes,
                                    int **nicindexes);
 
+/* Generate the object properties for pr-manager */
+int qemuBuildPRManagerInfoProps(virDomainObjPtr vm,
+                                const virDomainDiskDef *disk,
+                                virJSONValuePtr *propsret,
+                                char **alias);
 
 /* Generate the object properties for a secret */
 int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo,
index c14615fa7364447b5068f82c6dc251949cf6ec51..f43b8602ae3462ef3740859e81ad9b5db922b8d4 100644 (file)
@@ -12001,3 +12001,25 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
     }
     VIR_FREE(event);
 }
+
+
+char *
+qemuDomainGetPRSocketPath(virDomainObjPtr vm,
+                          virStoragePRDefPtr pr)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    const char *defaultAlias = NULL;
+    char *ret = NULL;
+
+    if (!virStoragePRDefIsEnabled(pr))
+        return NULL;
+
+    if (virStoragePRDefIsManaged(pr)) {
+        defaultAlias = qemuDomainGetManagedPRAlias();
+        ignore_value(virAsprintf(&ret, "%s/%s.sock", priv->libDir, defaultAlias));
+    } else {
+        ignore_value(VIR_STRDUP(ret, pr->path));
+    }
+
+    return ret;
+}
index 2dccec264b104aa7e8869222e094a63260678e3d..fbbbcf208fc92e4126c6878d63b78e455a4e4291 100644 (file)
@@ -1003,4 +1003,7 @@ qemuDomainDiskCachemodeFlags(int cachemode,
                              bool *direct,
                              bool *noflush);
 
+char * qemuDomainGetPRSocketPath(virDomainObjPtr vm,
+                                 virStoragePRDefPtr pr);
+
 #endif /* __QEMU_DOMAIN_H__ */
index 9dd5c97642dbdf692abb81aa792537a1a9c760e4..3bf66f71b74741d84560f37daff51b24eed65dc6 100644 (file)
@@ -24,6 +24,7 @@
 
 # include "qemu_conf.h"
 # include "qemu_domain.h"
+# include "virstoragefile.h"
 
 int qemuProcessPrepareMonitorChr(virDomainChrSourceDefPtr monConfig,
                                  const char *domainDir);
index 46ae1ba8fb51fa074dc07a9df4a2db914a6dd9da..87c34995614d825888f9e83c8f0d121c91bf0d53 100644 (file)
@@ -2041,6 +2041,20 @@ virStoragePRDefIsEqual(virStoragePRDefPtr a,
 }
 
 
+bool
+virStoragePRDefIsEnabled(virStoragePRDefPtr prd)
+{
+    return prd && prd->enabled == VIR_TRISTATE_BOOL_YES;
+}
+
+
+bool
+virStoragePRDefIsManaged(virStoragePRDefPtr prd)
+{
+    return prd && prd->managed == VIR_TRISTATE_BOOL_YES;
+}
+
+
 virSecurityDeviceLabelDefPtr
 virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src,
                                     const char *model)
index 7240a20fd60058ce8e1b4d1460b1c51f11688dd7..0bba016e4ebb7af3fecf27f55fe8fb85d26fe375 100644 (file)
@@ -397,6 +397,8 @@ void virStoragePRDefFormat(virBufferPtr buf,
                            virStoragePRDefPtr prd);
 bool virStoragePRDefIsEqual(virStoragePRDefPtr a,
                             virStoragePRDefPtr b);
+bool virStoragePRDefIsEnabled(virStoragePRDefPtr prd);
+bool virStoragePRDefIsManaged(virStoragePRDefPtr prd);
 
 virSecurityDeviceLabelDefPtr
 virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src,
diff --git a/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.args b/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.args
new file mode 100644 (file)
index 0000000..dce3fc4
--- /dev/null
@@ -0,0 +1,38 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-i686 \
+-name QEMUGuest1 \
+-S \
+-object pr-manager-helper,id=pr-helper0,\
+path=/tmp/lib/domain--1-QEMUGuest1/pr-helper0.sock \
+-object pr-manager-helper,id=pr-helper-scsi0-0-0-1,\
+path=/path/to/qemu-pr-helper.sock \
+-machine pc,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-smp 8,sockets=8,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot c \
+-device virtio-scsi-pci,id=scsi0,num_queues=8,bus=pci.0,addr=0x3 \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,file.pr-manager=pr-helper0,format=raw,\
+if=none,id=drive-scsi0-0-0-0,boot=on \
+-device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=0,\
+drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
+-drive file=/dev/HostVG/QEMUGuest2,file.pr-manager=pr-helper-scsi0-0-0-1,\
+format=raw,if=none,id=drive-scsi0-0-0-1 \
+-device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=1,\
+drive=drive-scsi0-0-0-1,id=scsi0-0-0-1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
index ddf567b62238a0a5afaeaeeaf2e65c76d3f0a76d..8da2f17f4fa5e643b58cbe370794703161de3a21 100644 (file)
@@ -2801,6 +2801,10 @@ mymain(void)
             QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4,
             QEMU_CAPS_ICH9_USB_EHCI1);
 
+    DO_TEST("disk-virtio-scsi-reservations",
+            QEMU_CAPS_DRIVE_BOOT, QEMU_CAPS_VIRTIO_SCSI,
+            QEMU_CAPS_SCSI_BLOCK, QEMU_CAPS_PR_MANAGER_HELPER);
+
     /* Test disks with format probing enabled for legacy reasons.
      * New tests should not go in this section. */
     driver.config->allowDiskFormatProbing = true;