[PATCH] Introduce a new virDomainReloadTlsCertificates API

Han Han hhan at redhat.com
Mon May 10 13:22:21 UTC 2021


On Sat, May 8, 2021 at 2:43 PM Zheng Yan <yanzheng759 at huawei.com> wrote:

> The new virDomainReloadTlsCertificates API is used to notify domain reload
> its certificates without restart, and avoid service interruption.
>
> Currently, only QEMU VNC TLS certificates are supported, but parameters and
> flags are also reserved for subsequent scenarios.
>
> Take reload QEMU VNC TLS certificates as an example, we can call:
>
>   virDomainReloadTlsCertificates(domain,
>                                  VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC,
>                                  NULL, 0, 0);
>
> Then the specified QMP message would be send to QEMU:
> {"execute": "display-reload", "arguments":{"type": "vnc", "tls-certs":
> true}}
>
> Refers:
>
> https://gitlab.com/qemu-project/qemu/-/commit/9cc07651655ee86eca41059f5ead8c4e5607c734

The qmp is introduced in QEMU 6.0. A qemu compatibility flag should be
added to check if target qemu supports
this qmp. See a former example:
https://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=adb9f7123a

>
> ---
>  include/libvirt/libvirt-domain.h | 20 +++++++++++
>  src/driver-hypervisor.h          |  8 +++++
>  src/libvirt-domain.c             | 58 ++++++++++++++++++++++++++++++++
>  src/libvirt_public.syms          |  5 +++
>  src/qemu/qemu_driver.c           | 40 ++++++++++++++++++++++
>  src/qemu/qemu_hotplug.c          | 17 ++++++++++
>  src/qemu/qemu_hotplug.h          |  4 +++
>  src/qemu/qemu_monitor.c          | 27 +++++++++++++++
>  src/qemu/qemu_monitor.h          |  3 ++
>  src/qemu/qemu_monitor_json.c     | 27 +++++++++++++++
>  src/qemu/qemu_monitor_json.h     |  4 +++
>  src/remote/remote_driver.c       |  1 +
>  src/remote/remote_protocol.x     | 15 ++++++++-
>  src/remote_protocol-structs      | 10 ++++++
>  14 files changed, 238 insertions(+), 1 deletion(-)
>
Please add a virsh sub-command for this new API.

It's better to split the big patch info pieces, for example:
- A patch for qemu compatibilities
- A patch for qemu driver internal
- A patch for remote driver
- A patch for libvirt pub API
- A patch for virsh
At last, a patch for news after these above are merged.

>
> diff --git a/include/libvirt/libvirt-domain.h
> b/include/libvirt/libvirt-domain.h
> index e99bfb7654..357d3598a6 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -5152,4 +5152,24 @@ int virDomainStartDirtyRateCalc(virDomainPtr domain,
>                                  int seconds,
>                                  unsigned int flags);
>
> +/**
> + * virDomainTlsCertificateType:
> + * the used scene of TLS certificates for doamin
> + */
> +typedef enum {
> +    VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC      = 0,
> +    VIR_DOMAIN_TLS_CERT_GRAPHICS_SPICE    = 1,
> +
> +# ifdef VIR_ENUM_SENTINELS
> +    VIR_DOMAIN_TLS_CERT_LAST
> +# endif
> +} virDomainTlsCertificateType;
> +
> +int
> +virDomainReloadTlsCertificates(virDomainPtr domain,
> +                               unsigned int type,
> +                               virTypedParameterPtr params,
> +                               int nparams,
> +                               unsigned int flags);
> +
>  #endif /* LIBVIRT_DOMAIN_H */
> diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
> index d642af8a37..d0d4976441 100644
> --- a/src/driver-hypervisor.h
> +++ b/src/driver-hypervisor.h
> @@ -1410,6 +1410,13 @@ typedef int
>                                    int seconds,
>                                    unsigned int flags);
>
> +typedef int
> +(*virDrvDomainReloadTlsCertificates)(virDomainPtr domain,
> +                                     unsigned int type,
> +                                     virTypedParameterPtr params,
> +                                     int nparams,
> +                                     unsigned int flags);
> +
>  typedef struct _virHypervisorDriver virHypervisorDriver;
>
>  /**
> @@ -1676,4 +1683,5 @@ struct _virHypervisorDriver {
>      virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet;
>      virDrvDomainGetMessages domainGetMessages;
>      virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
> +    virDrvDomainReloadTlsCertificates domainReloadTlsCertificates;
>  };
> diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
> index 42c75f6cc5..1b6889ab49 100644
> --- a/src/libvirt-domain.c
> +++ b/src/libvirt-domain.c
> @@ -13218,3 +13218,61 @@ virDomainStartDirtyRateCalc(virDomainPtr domain,
>      virDispatchError(conn);
>      return -1;
>  }
> +
> +/**
> + * virDomainReloadTlsCertificates:
> + * @domain: a domain object.
> + * @type: a value of virDomainTlsCertificateType
> + * @params: pointer to TLS Certs parameter objects, must be NULL if not
> used
> + * @nparams: number of TLS Certs parameter objects, must be 0 if not used
> + * @flags: extra flags; not used yet, so callers should always pass 0
> + *
> + * Notify domain reload its certificates with specified 'type'
> + *
> + * Returns 0 in case of success, -1 otherwise.
> + */
> +int
> +virDomainReloadTlsCertificates(virDomainPtr domain,
> +                               unsigned int type,
> +                               virTypedParameterPtr params,
> +                               int nparams,
> +                               unsigned int flags)
> +{
> +    virConnectPtr conn;
> +
> +    VIR_DOMAIN_DEBUG(domain, "certificate type=%u, params=%p, nparams=%d,
> flags=%x",
> +                     type, params, nparams, flags);
> +
> +    virResetLastError();
> +
> +    virCheckDomainReturn(domain, -1);
> +    conn = domain->conn;
> +
> +    virCheckReadOnlyGoto(conn->flags, error);
> +    virCheckNonNegativeArgGoto(nparams, error);
> +
> +    if (type >= VIR_DOMAIN_TLS_CERT_LAST) {
> +        virReportInvalidArg(type,
> +                            _("type must be less than %d"),
> +                            VIR_DOMAIN_TLS_CERT_LAST);
> +        goto error;
> +    }
> +
> +    if (conn->driver->domainReloadTlsCertificates) {
> +        int ret;
> +        ret = conn->driver->domainReloadTlsCertificates(domain,
> +                                                        type,
> +                                                        params,
> +                                                        nparams,
> +                                                        flags);
> +        if (ret < 0)
> +            goto error;
> +        return ret;
> +    }
> +
> +    virReportUnsupportedError();
> +
> + error:
> +    virDispatchError(domain->conn);
> +    return -1;
> +}
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index 5678a13cda..30ff012958 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -896,4 +896,9 @@ LIBVIRT_7.3.0 {
>          virNodeDeviceCreate;
>  } LIBVIRT_7.2.0;
>
> +LIBVIRT_7.4.0 {
> +    global:
> +        virDomainReloadTlsCertificates;
> +} LIBVIRT_7.3.0;
> +
>  # .... define new API here using predicted next version number ....
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index c90d52edc0..422a350c65 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -20449,6 +20449,45 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom,
>      return ret;
>  }
>
> +static int
> +qemuDomainReloadTlsCertificates(virDomainPtr domain,
> +                                unsigned int type,
> +                                virTypedParameterPtr params,
> +                                int nparams,
> +                                unsigned int flags)
> +{
> +    int ret = -1;
> +    virQEMUDriver *driver = domain->conn->privateData;
> +    virDomainObj *vm = qemuDomObjFromDomain(domain);
> +
> +    if (!vm)
> +        goto cleanup;
> +
> +    virCheckNonNullArgGoto(params, cleanup);
> +    if (nparams != 0) {
> +        virReportInvalidZeroArg(nparams);
> +        goto cleanup;
> +    }
> +    virCheckFlagsGoto(0, cleanup);
> +
> +    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
> +        goto cleanup;
> +
> +     if (!virDomainObjIsActive(vm)) {
> +        virReportError(VIR_ERR_OPERATION_INVALID,
> +                       "%s", _("domain is not running"));
> +        goto endjob;
> +    }
> +
> +    ret = qemuDomainReloadTLSCerts(driver, vm, type);
> +
> + endjob:
> +    qemuDomainObjEndJob(driver, vm);
> +
> + cleanup:
> +    virDomainObjEndAPI(&vm);
> +    return ret;
> +}
>
>  static virHypervisorDriver qemuHypervisorDriver = {
>      .name = QEMU_DRIVER_NAME,
> @@ -20693,6 +20732,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
>      .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /*
> 6.10.0 */
>      .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
>      .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
> +    .domainReloadTlsCertificates = qemuDomainReloadTlsCertificates, /*
> 7.4.0 */
>  };
>
>
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index a64cddb9e7..34dc035d73 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -6704,3 +6704,20 @@ qemuDomainSetVcpuInternal(virQEMUDriver *driver,
>      virBitmapFree(livevcpus);
>      return ret;
>  }
> +
> +int qemuDomainReloadTLSCerts(virQEMUDriverPtr driver,
> +                             virDomainObjPtr vm,
> +                             unsigned int type)
> +{
> +    int ret = -1;
> +    qemuDomainObjPrivate *priv = vm->privateData;
> +
> +    qemuDomainObjEnterMonitor(driver, vm);
> +
> +    ret = qemuMonitorDisplayReloadTLSCerts(priv->mon, type);
> +
> +    if (qemuDomainObjExitMonitor(driver, vm) < 0)
> +        ret = -1;
> +
> +    return ret;
> +}
> diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
> index df8f76f8d6..411741a688 100644
> --- a/src/qemu/qemu_hotplug.h
> +++ b/src/qemu/qemu_hotplug.h
> @@ -160,3 +160,7 @@ int qemuHotplugAttachDBusVMState(virQEMUDriver *driver,
>  int qemuHotplugRemoveDBusVMState(virQEMUDriver *driver,
>                                   virDomainObj *vm,
>                                   qemuDomainAsyncJob asyncJob);
> +
> +int qemuDomainReloadTLSCerts(virQEMUDriverPtr driver,
> +                             virDomainObjPtr vm,
> +                             unsigned int type);
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 1e6f892e08..11f8cc8670 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -4746,3 +4746,30 @@ qemuMonitorQueryDirtyRate(qemuMonitor *mon,
>
>      return qemuMonitorJSONQueryDirtyRate(mon, info);
>  }
> +
> +static const char *
> +qemuMonitorTLSCertificateTypeToString(unsigned int type)
> +{
> +    switch (type) {
> +    /* for now, only VNC is supported */
> +    case VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC:
> +        return "vnc";
> +    default:
> +        virReportError(VIR_ERR_INVALID_ARG,
> +                       _("unsupported qemu certificate type %u"),
> +                       type);
> +        return NULL;
> +    }
> +}
> +
> +int
> +qemuMonitorDisplayReloadTLSCerts(qemuMonitorPtr mon, unsigned int type)
> +{
> +    const char *certType = qemuMonitorTLSCertificateTypeToString(type);
> +    if (!certType)
> +        return -1;
> +
> +    QEMU_CHECK_MONITOR(mon);
> +
> +    return qemuMonitorJSONDisplayReload(mon, certType, true);
> +}
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 6a25def78b..f26f92fb51 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -1496,3 +1496,6 @@ struct _qemuMonitorDirtyRateInfo {
>  int
>  qemuMonitorQueryDirtyRate(qemuMonitor *mon,
>                            qemuMonitorDirtyRateInfo *info);
> +
> +int qemuMonitorDisplayReloadTLSCerts(qemuMonitorPtr mon,
> +                                     unsigned int type);
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 46aa3330a8..9934613cc2 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -9446,3 +9446,30 @@ qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,
>
>      return qemuMonitorJSONExtractDirtyRateInfo(data, info);
>  }
> +
> +int qemuMonitorJSONDisplayReload(qemuMonitorPtr mon,
> +                                 const char *type,
> +                                 bool tlsCerts)
> +{
> +    int ret = -1;
> +    virJSONValuePtr reply = NULL;
> +    virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("display-reload",
> +                                                     "s:type", type,
> +                                                     "b:tls-certs",
> tlsCerts,
> +                                                     NULL);
> +    if (!cmd)
> +        return -1;
> +
> +    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(cmd);
> +    virJSONValueFree(reply);
> +    return ret;
> +}
> diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
> index 01a3ba25f1..73761d54f8 100644
> --- a/src/qemu/qemu_monitor_json.h
> +++ b/src/qemu/qemu_monitor_json.h
> @@ -706,3 +706,7 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon,
>  int
>  qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,
>                                qemuMonitorDirtyRateInfo *info);
> +
> +int qemuMonitorJSONDisplayReload(qemuMonitorPtr mon,
> +                                 const char *type,
> +                                 bool tlsCerts);
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 0c72d69933..0e6e4e3007 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -8566,6 +8566,7 @@ static virHypervisorDriver hypervisor_driver = {
>      .domainAuthorizedSSHKeysSet = remoteDomainAuthorizedSSHKeysSet, /*
> 6.10.0 */
>      .domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
>      .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0
> */
> +    .domainReloadTlsCertificates = remoteDomainReloadTlsCertificates, /*
> 7.4.0 */
>  };
>
>  static virNetworkDriver network_driver = {
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index de69704b68..c13b3e1f5c 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -286,6 +286,8 @@ const REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX = 2048;
>  /* Upper limit on number of messages */
>  const REMOTE_DOMAIN_MESSAGES_MAX = 2048;
>
> +/* Upper limit on list of TLS certificate parameters */
> +const REMOTE_DOMAIN_RELOAD_TLS_CERT_PARAMETERS_MAX = 16;
>
>  /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
>  typedef opaque remote_uuid[VIR_UUID_BUFLEN];
> @@ -3836,6 +3838,12 @@ struct remote_domain_start_dirty_rate_calc_args {
>      unsigned int flags;
>  };
>
> +struct remote_domain_reload_tls_certificates_args {
> +    remote_nonnull_domain dom;
> +    unsigned int type;
> +    remote_typed_param
> params<REMOTE_DOMAIN_RELOAD_TLS_CERT_PARAMETERS_MAX>;
> +    unsigned int flags;
> +};
>
>  /*----- Protocol. -----*/
>
> @@ -6784,6 +6792,11 @@ enum remote_procedure {
>       * @priority: high
>       * @acl: node_device:start
>       */
> -    REMOTE_PROC_NODE_DEVICE_CREATE = 430
> +    REMOTE_PROC_NODE_DEVICE_CREATE = 430,
>
> +        /**
> +     * @generate: both
> +     * @acl: domain:write
> +     */
> +    REMOTE_PROC_DOMAIN_RELOAD_TLS_CERTIFICATES = 431
>  };
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index 6b46328adc..799a8596ea 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -3192,6 +3192,15 @@ struct remote_domain_start_dirty_rate_calc_args {
>          int                        seconds;
>          u_int                      flags;
>  };
> +struct remote_domain_reload_tls_certificates_args {
> +        remote_nonnull_domain      dom;
> +        u_int                      type;
> +        struct {
> +                u_int              params_len;
> +                remote_typed_param * params_val;
> +        } params;
> +        u_int                      flags;
> +};
>  enum remote_procedure {
>          REMOTE_PROC_CONNECT_OPEN = 1,
>          REMOTE_PROC_CONNECT_CLOSE = 2,
> @@ -3623,4 +3632,5 @@ enum remote_procedure {
>          REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428,
>          REMOTE_PROC_NODE_DEVICE_UNDEFINE = 429,
>          REMOTE_PROC_NODE_DEVICE_CREATE = 430,
> +        REMOTE_PROC_DOMAIN_RELOAD_TLS_CERTIFICATES = 431,
>  };
> --
> 2.25.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20210510/6662dd23/attachment-0001.htm>


More information about the libvir-list mailing list