[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