Introduce a new virDomainReloadTLSCertificates API for notify domain

reload its certificates without restart, and avoid service interruption.

 

Take reload QEMU VNC TLS certificates as an example, we can call:

 

  virDomainReloadTLSCertificates(dom, VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC)

 

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

---

include/libvirt/libvirt-domain.h | 17 ++++++++++++++++

src/driver-hypervisor.h          |  5 +++++

src/libvirt-domain.c             | 33 ++++++++++++++++++++++++++++++++

src/qemu/qemu_driver.c           | 11 +++++++++++

src/qemu/qemu_hotplug.c          | 21 ++++++++++++++++++++

src/qemu/qemu_hotplug.h          |  4 ++++

src/qemu/qemu_monitor.c          | 10 ++++++++++

src/qemu/qemu_monitor.h          |  3 +++

src/qemu/qemu_monitor_json.c     | 22 +++++++++++++++++++++

src/qemu/qemu_monitor_json.h     |  3 +++

10 files changed, 129 insertions(+)

 

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h

index e99bfb7654..aeb33d69d9 100644

--- a/include/libvirt/libvirt-domain.h

+++ b/include/libvirt/libvirt-domain.h

@@ -5152,4 +5152,21 @@ int virDomainStartDirtyRateCalc(virDomainPtr domain,

                                 int seconds,

                                 unsigned int flags);

+/**

+ * virDomainTLSCertificaType:

+ *

+ * the used scene of TLS certificates for doamin.

+ */

+typedef enum {

+    VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC      = 0,

+    VIR_DOMAIN_TLS_CERT_GRAPHICS_SPICE    = 1,

+

+    VIR_DOMAIN_TLS_CERT_LAST

+} virDomainTLSCertificaType;

+

+int

+virDomainReloadTLSCertificates(virDomainPtr domain,

+                               unsigned int type);

+

+

#endif /* LIBVIRT_DOMAIN_H */

diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h

index d642af8a37..8de2bc4137 100644

--- a/src/driver-hypervisor.h

+++ b/src/driver-hypervisor.h

@@ -1410,6 +1410,10 @@ typedef int

                                   int seconds,

                                   unsigned int flags);

+typedef int

+(*virDrvDomainReloadTLSCertificates)(virDomainPtr domain,

+                                     unsigned int type);

+

typedef struct _virHypervisorDriver virHypervisorDriver;

 /**

@@ -1676,4 +1680,5 @@ struct _virHypervisorDriver {

     virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet;

     virDrvDomainGetMessages domainGetMessages;

     virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;

+    virDrvDomainReloadTLSCertificates domainiReloadTLSCertificates;

};

diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c

index 42c75f6cc5..fb9e5ec2d1 100644

--- a/src/libvirt-domain.c

+++ b/src/libvirt-domain.c

@@ -13218,3 +13218,36 @@ virDomainStartDirtyRateCalc(virDomainPtr domain,

     virDispatchError(conn);

     return -1;

}

+

+/**

+ * virDomainReloadTLSCertificates:

+ * @domain: a domain object.

+ * @type: a value of virDomainTLSCertificaType

+ *

+ * Notify domain reload its certificates with specified 'type'.

+ *

+ * Returns 0 in case of success, -1 otherwise .

+ */

+int

+virDomainReloadTLSCertificates(virDomainPtr domain,

+                               unsigned int type)

+{

+    virConnectPtr conn;

+    VIR_DOMAIN_DEBUG(domain, "certificate type=%d", type);

+    virResetLastError();

+    virCheckDomainReturn(domain, -1);

+    conn = domain->conn;

+    if (type >= VIR_DOMAIN_TLS_CERT_LAST)

+        goto error;

+    if (conn->driver->domainiReloadTLSCertificates) {

+        int ret;

+        ret = conn->driver->domainiReloadTLSCertificates(domain, type);

+        if (ret < 0)

+            goto error;

+        return ret;

+    }

+    virReportUnsupportedError();

+ error:

+    virDispatchError(domain->conn);

+    return -1;

+}

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c

index c90d52edc0..61cd8cfa24 100644

--- a/src/qemu/qemu_driver.c

+++ b/src/qemu/qemu_driver.c

@@ -20449,6 +20449,16 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom,

     return ret;

}

+static int

+qemuDomainReloadTLSCertificates(virDomainPtr domain,

+                                unsigned int type)

+{

+    virQEMUDriver *driver = domain->conn->privateData;

+    virDomainObj *vm = qemuDomainObjFromDomain(domain);

+    if (!driver || !vm)

+        return -1;

+    return qemuDomainReloadTLSCerts(driver, vm, type);

+}

 static virHypervisorDriver qemuHypervisorDriver = {

     .name = QEMU_DRIVER_NAME,

@@ -20693,6 +20703,7 @@ static virHypervisorDriver qemuHypervisorDriver = {

     .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */

     .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */

     .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */

+    .domainiReloadTLSCertificates = qemuDomainReloadTLSCertificates, /* 7.2.0 */

};

 

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c

index 444d89d64a..013d8728a0 100644

--- a/src/qemu/qemu_hotplug.c

+++ b/src/qemu/qemu_hotplug.c

@@ -6704,3 +6704,24 @@ qemuDomainSetVcpuInternal(virQEMUDriver *driver,

     virBitmapFree(livevcpus);

     return ret;

}

+

+int qemuDomainReloadTLSCerts(virQEMUDriverPtr driver,

+                             virDomainObjPtr vm,

+                             int type)

+{

+    int ret = -1;

+    qemuDomainObjPrivate *priv = vm->privateData;

+    /* for now, only VNC is supported */

+    if (type != VIR_DOMAIN_TLS_CERT_GRAPHICS_VNC)

+        virReportError(VIR_ERR_INVALID_ARG,

+                       _("invalid certificate type=%d, only support VNC"),

+                       type);

+        return ret;

+    }

+    if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)

+        return ret;

+    ret = qemuMonitorReloadTLSCerts(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..44afe23f0a 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,

+                             int type);

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c

index 3a7f231ce0..952ef87a6b 100644

--- a/src/qemu/qemu_monitor.c

+++ b/src/qemu/qemu_monitor.c

@@ -4746,3 +4746,13 @@ qemuMonitorQueryDirtyRate(qemuMonitor *mon,

     return qemuMonitorJSONQueryDirtyRate(mon, info);

}

+

+int

+qemuMonitorReloadTLSCerts(qemuMonitorPtr mon, int type)

+{

+    const char *protocol = qemuMonitorTypeToProtocol(type);

+    if (!protocol)

+        return -1;

+    VIR_DEBUG("protocol=%s", protocol);

+    return qemuMonitorJSONReloadTLSCerts(mon, protocol);

+}

diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h

index 6a25def78b..a5b702b023 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 qemuMonitorReloadTLSCerts(qemuMonitorPtr mon,

+                              int type);

diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c

index 46aa3330a8..d2b06c4703 100644

--- a/src/qemu/qemu_monitor_json.c

+++ b/src/qemu/qemu_monitor_json.c

@@ -9446,3 +9446,25 @@ qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,

     return qemuMonitorJSONExtractDirtyRateInfo(data, info);

}

+

+int qemuMonitorJSONReloadTLSCerts(qemuMonitorPtr mon,

+                                  const char *protocol)

+{

+    int ret = -1;

+    virJSONValuePtr reply = NULL;

+    virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("display-reload",

+                                                     "s:type", protocol,

+                                                     "b:tls-certs", 1,

+                                                     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..d9ad77e873 100644

--- a/src/qemu/qemu_monitor_json.h

+++ b/src/qemu/qemu_monitor_json.h

@@ -706,3 +706,6 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon,

int

qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,

                               qemuMonitorDirtyRateInfo *info);

+

+int qemuMonitorJSONReloadTLSCerts(qemuMonitorPtr mon,

+                                  const char *protocol);

--

2.25.1