[libvirt] [PATCH v2 02/12] qemu: Introduce qemuDomainSecretPrepare and Destroy

Cole Robinson crobinso at redhat.com
Wed Apr 27 22:49:09 UTC 2016


On 04/16/2016 10:17 AM, John Ferlan wrote:
> Rather than needing to pass the conn parameter to various command
> line building API's, add qemuDomainSecretPrepare just prior to the
> qemuProcessLaunch which calls qemuBuilCommandLine. The function
> must be called after qemuProcessPrepareHost since it's expected
> to eventually need the domain masterKey generated during the prepare
> host call. Additionally, future patches may require device aliases
> (assigned during the prepare domain call) in order to associate
> the secret objects.
> 
> The qemuDomainSecretDestroy is called after the qemuProcessLaunch
> finishes in order to clear and free memory used by the secrets
> that were recently prepared, so they are not kept around in memory
> too long.
> 
> Placing the setup here is beneficial for future patches which will
> need the domain masterKey in order to generate an encrypted secret
> along with an initialization vector to be saved and passed (since
> the masterKey shouldn't be passed around).
> 
> Finally, since the secret is not added during command line build,
> the hotplug code will need to get the secret into the private disk data.
> 
> Signed-off-by: John Ferlan <jferlan at redhat.com>
> ---
>  src/qemu/qemu_command.c |  45 ++++-----------
>  src/qemu/qemu_command.h |   5 +-
>  src/qemu/qemu_domain.c  | 150 ++++++++++++++++++++++++++++++++++++++++++++++--
>  src/qemu/qemu_domain.h  |  15 ++++-
>  src/qemu/qemu_driver.c  |  10 ++--
>  src/qemu/qemu_hotplug.c |  26 +++++----
>  src/qemu/qemu_hotplug.h |   1 -
>  src/qemu/qemu_process.c |   8 +++
>  8 files changed, 202 insertions(+), 58 deletions(-)
> 
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 26c19ff..24ed8ed 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -832,7 +832,7 @@ qemuBuildNetworkDriveURI(virStorageSourcePtr src,
>  
>  int
>  qemuGetDriveSourceString(virStorageSourcePtr src,
> -                         virConnectPtr conn,
> +                         qemuDomainSecretInfoPtr secinfo,
>                           char **source)
>  {
>      int actualType = virStorageSourceGetActualType(src);
> @@ -846,31 +846,6 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
>      if (virStorageSourceIsEmpty(src))
>          return 1;
>  
> -    if (conn) {
> -        if (actualType == VIR_STORAGE_TYPE_NETWORK &&
> -            src->auth &&
> -            (src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI ||
> -             src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD)) {
> -            bool encode = false;
> -            int secretType = VIR_SECRET_USAGE_TYPE_ISCSI;
> -            const char *protocol = virStorageNetProtocolTypeToString(src->protocol);
> -            username = src->auth->username;
> -
> -            if (src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
> -                /* qemu requires the secret to be encoded for RBD */
> -                encode = true;
> -                secretType = VIR_SECRET_USAGE_TYPE_CEPH;
> -            }
> -
> -            if (!(secret = virSecretGetSecretString(conn,
> -                                                    protocol,
> -                                                    encode,
> -                                                    src->auth,
> -                                                    secretType)))
> -                goto cleanup;
> -        }
> -    }
> -
>      switch ((virStorageType) actualType) {
>      case VIR_STORAGE_TYPE_BLOCK:
>      case VIR_STORAGE_TYPE_FILE:
> @@ -881,6 +856,11 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
>          break;
>  
>      case VIR_STORAGE_TYPE_NETWORK:
> +        if (secinfo) {
> +            username = secinfo->s.plain.username;
> +            secret = secinfo->s.plain.secret;
> +        }
> +
>          if (!(*source = qemuBuildNetworkDriveURI(src, username, secret)))
>              goto cleanup;
>          break;
> @@ -894,7 +874,6 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
>      ret = 0;
>  
>   cleanup:
> -    VIR_FREE(secret);
>      return ret;
>  }
>  
> @@ -1033,8 +1012,7 @@ qemuCheckFips(void)
>  
>  
>  char *
> -qemuBuildDriveStr(virConnectPtr conn,
> -                  virDomainDiskDefPtr disk,
> +qemuBuildDriveStr(virDomainDiskDefPtr disk,
>                    bool bootable,
>                    virQEMUCapsPtr qemuCaps)
>  {
> @@ -1046,6 +1024,7 @@ qemuBuildDriveStr(virConnectPtr conn,
>      int busid = -1, unitid = -1;
>      char *source = NULL;
>      int actualType = virStorageSourceGetActualType(disk->src);
> +    qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
>  
>      if (idx < 0) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -1127,7 +1106,7 @@ qemuBuildDriveStr(virConnectPtr conn,
>          break;
>      }
>  
> -    if (qemuGetDriveSourceString(disk->src, conn, &source) < 0)
> +    if (qemuGetDriveSourceString(disk->src, diskPriv->secinfo, &source) < 0)
>          goto error;
>  
>      if (source &&
> @@ -1816,7 +1795,6 @@ qemuBuildDriveDevStr(const virDomainDef *def,
>  
>  static int
>  qemuBuildDiskDriveCommandLine(virCommandPtr cmd,
> -                              virConnectPtr conn,
>                                const virDomainDef *def,
>                                virQEMUCapsPtr qemuCaps,
>                                bool emitBootindex)
> @@ -1910,7 +1888,7 @@ qemuBuildDiskDriveCommandLine(virCommandPtr cmd,
>                  deviceFlagMasked = true;
>              }
>          }
> -        optstr = qemuBuildDriveStr(conn, disk,
> +        optstr = qemuBuildDriveStr(disk,
>                                     emitBootindex ? false : !!bootindex,
>                                     qemuCaps);
>          if (deviceFlagMasked)
> @@ -9363,8 +9341,7 @@ qemuBuildCommandLine(virConnectPtr conn,
>      if (qemuBuildHubCommandLine(cmd, def, qemuCaps) < 0)
>          goto error;
>  
> -    if (qemuBuildDiskDriveCommandLine(cmd, conn, def, qemuCaps,
> -                                      emitBootindex) < 0)
> +    if (qemuBuildDiskDriveCommandLine(cmd, def, qemuCaps, emitBootindex) < 0)
>          goto error;
>  
>      if (qemuBuildFSDevCommandLine(cmd, def, qemuCaps) < 0)
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 2e2f133..2662d9b 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -99,8 +99,7 @@ char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
>                                 virQEMUCapsPtr qemuCaps);
>  
>  /* Both legacy & current support */
> -char *qemuBuildDriveStr(virConnectPtr conn,
> -                        virDomainDiskDefPtr disk,
> +char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
>                          bool bootable,
>                          virQEMUCapsPtr qemuCaps);
>  
> @@ -177,7 +176,7 @@ char *qemuBuildRedirdevDevStr(const virDomainDef *def,
>  int qemuNetworkPrepareDevices(virDomainDefPtr def);
>  
>  int qemuGetDriveSourceString(virStorageSourcePtr src,
> -                             virConnectPtr conn,
> +                             qemuDomainSecretInfoPtr secinfo,
>                               char **source);
>  
>  int qemuCheckDiskConfig(virDomainDiskDefPtr disk);
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 55cb30f..93033d9 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -46,6 +46,7 @@
>  #include "viratomic.h"
>  #include "virprocess.h"
>  #include "virrandom.h"
> +#include "secret_util.h"
>  #include "base64.h"
>  #ifdef WITH_GNUTLS
>  # include <gnutls/gnutls.h>
> @@ -791,6 +792,146 @@ qemuDomainDiskPrivateDispose(void *obj)
>  }
>  
>  
> +/* qemuDomainSecretPlainSetup:
> + * @conn: Pointer to connection
> + * @secinfo: Pointer to secret info
> + * @protocol: Protocol for secret
> + * @authdef: Pointer to auth data
> + *
> + * Taking a secinfo, fill in the plaintext information
> + *
> + * Returns 0 on success, -1 on failure with error message
> + */
> +static int
> +qemuDomainSecretPlainSetup(virConnectPtr conn,
> +                           qemuDomainSecretInfoPtr secinfo,
> +                           virStorageNetProtocol protocol,
> +                           virStorageAuthDefPtr authdef)
> +{
> +    bool encode = false;
> +    int secretType = VIR_SECRET_USAGE_TYPE_ISCSI;
> +    const char *protocolstr = virStorageNetProtocolTypeToString(protocol);
> +
> +    secinfo->type = VIR_DOMAIN_SECRET_INFO_PLAIN;
> +    if (VIR_STRDUP(secinfo->s.plain.username, authdef->username) < 0)
> +        return -1;
> +
> +    if (protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
> +        /* qemu requires the secret to be encoded for RBD */
> +        encode = true;
> +        secretType = VIR_SECRET_USAGE_TYPE_CEPH;
> +    }
> +
> +    if (!(secinfo->s.plain.secret =
> +          virSecretGetSecretString(conn, protocolstr, encode,
> +                                   authdef, secretType)))
> +        return -1;
> +
> +    return 0;
> +}
> +
> +
> +/* qemuDomainSecretDiskDestroy:
> + * @disk: Pointer to a disk definition
> + *
> + * Clear and destroy memory associated with the secret
> + */
> +void
> +qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk)
> +{
> +    qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
> +
> +    if (!diskPriv->secinfo)
> +        return;
> +
> +    qemuDomainSecretInfoFree(&diskPriv->secinfo);
> +}
> +
> +
> +/* qemuDomainSecretDiskPrepare:
> + * @conn: Pointer to connection
> + * @disk: Pointer to a disk definition
> + *
> + * For the right disk, generate the qemuDomainSecretInfo structure.
> + *
> + * Returns 0 on success, -1 on failure
> + */
> +int
> +qemuDomainSecretDiskPrepare(virConnectPtr conn,
> +                            virDomainDiskDefPtr disk)
> +{
> +    virStorageSourcePtr src = disk->src;
> +    qemuDomainSecretInfoPtr secinfo = NULL;
> +
> +    if (conn && !virStorageSourceIsEmpty(src) &&
> +        virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_NETWORK &&
> +        src->auth &&
> +        (src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI ||
> +         src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD)) {
> +

Is conn ever going to be NULL here?

> +        qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
> +
> +        if (VIR_ALLOC(secinfo) < 0)
> +            return -1;
> +
> +        if (qemuDomainSecretPlainSetup(conn, secinfo, src->protocol,
> +                                       src->auth) < 0)
> +            goto error;
> +
> +        diskPriv->secinfo = secinfo;
> +    }
> +
> +    return 0;
> +
> + error:
> +    qemuDomainSecretInfoFree(&secinfo);
> +    return -1;
> +}
> +
> +
> +/* qemuDomainSecretDestroy:
> + * @vm: Domain object
> + *
> + * Once completed with the generation of the command line it is
> + * expect to remove the secrets
> + */
> +void
> +qemuDomainSecretDestroy(virDomainObjPtr vm)
> +{
> +    size_t i;
> +
> +    for (i = 0; i < vm->def->ndisks; i++)
> +        qemuDomainSecretDiskDestroy(vm->def->disks[i]);
> +}
> +
> +
> +/* qemuDomainSecretPrepare:
> + * @conn: Pointer to connection
> + * @vm: Domain object
> + *
> + * For any objects that may require an auth/secret setup, create a
> + * qemuDomainSecretInfo and save it in the approriate place within
> + * the private structures. This will be used by command line build
> + * code in order to pass the secret along to qemu in order to provide
> + * the necessary authentication data.
> + *
> + * Returns 0 on success, -1 on failure with error message set
> + */
> +int
> +qemuDomainSecretPrepare(virConnectPtr conn,
> +                        virDomainObjPtr vm)
> +{
> +    size_t i;
> +
> +    for (i = 0; i < vm->def->ndisks; i++) {
> +        if (qemuDomainSecretDiskPrepare(conn, vm->def->disks[i]) < 0)
> +            return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +
>  /* This is the old way of setting up per-domain directories */
>  static int
>  qemuDomainSetPrivatePathsOld(virQEMUDriverPtr driver,
> @@ -3782,8 +3923,7 @@ qemuDomainDiskChainElementPrepare(virQEMUDriverPtr driver,
>  
>  
>  bool
> -qemuDomainDiskSourceDiffers(virConnectPtr conn,
> -                            virDomainDiskDefPtr disk,
> +qemuDomainDiskSourceDiffers(virDomainDiskDefPtr disk,
>                              virDomainDiskDefPtr origDisk)
>  {
>      char *diskSrc = NULL, *origDiskSrc = NULL;
> @@ -3799,8 +3939,10 @@ qemuDomainDiskSourceDiffers(virConnectPtr conn,
>      if (diskEmpty ^ origDiskEmpty)
>          return true;
>  
> -    if (qemuGetDriveSourceString(disk->src, conn, &diskSrc) < 0 ||
> -        qemuGetDriveSourceString(origDisk->src, conn, &origDiskSrc) < 0)
> +    /* This won't be a network storage, so no need to get the diskPriv
> +     * in order to fetch the secret, thus NULL for param2 */
> +    if (qemuGetDriveSourceString(disk->src, NULL, &diskSrc) < 0 ||
> +        qemuGetDriveSourceString(origDisk->src, NULL, &origDiskSrc) < 0)
>          goto cleanup;
>  
>      /* So far in qemu disk sources are considered different
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 9cfe3e4..bde71a4 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -497,8 +497,7 @@ int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
>                                   bool force_probe,
>                                   bool report_broken);
>  
> -bool qemuDomainDiskSourceDiffers(virConnectPtr conn,
> -                                 virDomainDiskDefPtr disk,
> +bool qemuDomainDiskSourceDiffers(virDomainDiskDefPtr disk,
>                                   virDomainDiskDefPtr origDisk);
>  
>  bool qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk,
> @@ -616,4 +615,16 @@ int qemuDomainMasterKeyCreate(virQEMUDriverPtr driver,
>  
>  void qemuDomainMasterKeyRemove(qemuDomainObjPrivatePtr priv);
>  
> +void qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk)
> +    ATTRIBUTE_NONNULL(1);
> +
> +int qemuDomainSecretDiskPrepare(virConnectPtr conn, virDomainDiskDefPtr disk)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
> +void qemuDomainSecretDestroy(virDomainObjPtr vm)
> +    ATTRIBUTE_NONNULL(1);
> +
> +int qemuDomainSecretPrepare(virConnectPtr conn, virDomainObjPtr vm)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
>  #endif /* __QEMU_DOMAIN_H__ */
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 1ba8ab9..bb55b7d 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7710,14 +7710,16 @@ qemuDomainChangeDiskLive(virConnectPtr conn,
>  
>          orig_disk->startupPolicy = dev->data.disk->startupPolicy;
>  
> -        if (qemuDomainDiskSourceDiffers(conn, disk, orig_disk)) {
> +        if (qemuDomainDiskSourceDiffers(disk, orig_disk)) {
>              /* Add the new disk src into shared disk hash table */
>              if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
>                  goto cleanup;
>  
> -            if (qemuDomainChangeEjectableMedia(driver, conn, vm,
> -                                               orig_disk, dev->data.disk->src, force) < 0) {
> -                ignore_value(qemuRemoveSharedDisk(driver, dev->data.disk, vm->def->name));
> +            if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
> +                                               dev->data.disk->src,
> +                                               force) < 0) {
> +                ignore_value(qemuRemoveSharedDisk(driver, dev->data.disk,
> +                                                  vm->def->name));
>                  goto rollback;
>              }
>  
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index ef8696b..692e3e7 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -148,7 +148,6 @@ qemuDomainPrepareDisk(virQEMUDriverPtr driver,
>  /**
>   * qemuDomainChangeEjectableMedia:
>   * @driver: qemu driver structure
> - * @conn: connection structure
>   * @vm: domain definition
>   * @disk: disk definition to change the source of
>   * @newsrc: new disk source to change to
> @@ -163,7 +162,6 @@ qemuDomainPrepareDisk(virQEMUDriverPtr driver,
>   */
>  int
>  qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
> -                               virConnectPtr conn,
>                                 virDomainObjPtr vm,
>                                 virDomainDiskDefPtr disk,
>                                 virStorageSourcePtr newsrc,
> @@ -223,7 +221,8 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
>      } while (rc < 0);
>  
>      if (!virStorageSourceIsEmpty(newsrc)) {
> -        if (qemuGetDriveSourceString(newsrc, conn, &sourcestr) < 0)
> +        /* cdrom/floppy won't have secret */
> +        if (qemuGetDriveSourceString(newsrc, NULL, &sourcestr) < 0)
>              goto error;
>  

Why not? Can't you have an rbd backed cdrom device?

ACK otherwise

- Cole




More information about the libvir-list mailing list