From dd9b8be8f47638f9149f3b577f1c38e36cd3e0db Mon Sep 17 00:00:00 2001
From: AlexChen <alex.chen@huawei.com>
Date: Tue, 19 Oct 2021 14:50:32 +0800
Subject: [PATCH] Hotpatch: introduce DomainHotpatchManage API

Signed-off-by: Hao Wang <wanghao232@huawei.com>
Signed-off-by: Bihong Yu <yubihong@huawei.com>
Signed-off-by: AlexChen <alex.chen@huawei.com>
---
 include/libvirt/libvirt-domain.h | 23 +++++++++++++
 scripts/check-aclrules.py        |  1 +
 src/driver-hypervisor.h          |  8 +++++
 src/libvirt-domain.c             | 59 ++++++++++++++++++++++++++++++++
 src/libvirt_public.syms          |  5 +++
 src/remote/remote_driver.c       |  1 +
 src/remote/remote_protocol.x     | 19 +++++++++-
 7 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index a1902546bb..f8def59032 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -6416,6 +6416,29 @@ int virDomainAuthorizedSSHKeysGet(virDomainPtr domain,
                                   char ***keys,
                                   unsigned int flags);
 
+/**
+ * virDomainHotpatchAction:
+ *
+ * Since: 6.2.0
+ */
+typedef enum {
+    VIR_DOMAIN_HOTPATCH_NONE = 0, /* No action */
+    VIR_DOMAIN_HOTPATCH_APPLY,    /* Apply hotpatch */
+    VIR_DOMAIN_HOTPATCH_UNAPPLY,  /* Unapply hotpatch */
+    VIR_DOMAIN_HOTPATCH_QUERY,    /* Query hotpatch */
+
+# ifdef VIR_ENUM_SENTINELS
+    VIR_DOMAIN_HOTPATCH_LAST
+# endif
+} virDomainHotpatchAction;
+
+char *
+virDomainHotpatchManage(virDomainPtr domain,
+                        int action,
+                        const char *patch,
+                        const char *id,
+                        unsigned int flags);
+
 /**
  * virDomainAuthorizedSSHKeysSetFlags:
  *
diff --git a/scripts/check-aclrules.py b/scripts/check-aclrules.py
index ed6805058b..e39dbd2ba8 100755
--- a/scripts/check-aclrules.py
+++ b/scripts/check-aclrules.py
@@ -53,6 +53,7 @@ permitted = {
     "connectURIProbe": True,
     "localOnly": True,
     "domainQemuAttach": True,
+    "domainHotpatchManage": True,
 }
 
 # XXX this vzDomainMigrateConfirm3Params looks
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 5219344b72..e54af0515f 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1448,6 +1448,13 @@ typedef int
                            int *fds,
                            unsigned int flags);
 
+typedef char *
+(*virDrvDomainHotpatchManage)(virDomainPtr domain,
+                              int action,
+                              const char *patch,
+                              const char *id,
+                              unsigned int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 
 /**
@@ -1720,4 +1727,5 @@ struct _virHypervisorDriver {
     virDrvDomainGetMessages domainGetMessages;
     virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
     virDrvDomainFDAssociate domainFDAssociate;
+    virDrvDomainHotpatchManage domainHotpatchManage;
 };
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 77a9682ecb..26833efd0e 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -13784,6 +13784,65 @@ virDomainBackupGetXMLDesc(virDomainPtr domain,
     return NULL;
 }
 
+/**
+ * virDomainHotpatchManage:
+ * @domain: a domain object
+ * @action: the action type from virDomainHotpatchAction
+ * @patch: the target hotpatch file
+ * @id: the patch id of the target hotpatch
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Manage hotpatch for the current domain according to @action.
+ *
+ * If the @action is set to VIR_DOMAIN_HOTPATCH_APPLY, apply hotpatch
+ * @patch to the current domain.
+ *
+ * If the @action is set to VIR_DOMAIN_HOTPATCH_UNAPPLY, unapply the
+ * hotpatch which is matched with @id from the current domain.
+ *
+ * If the @action is set to VIR_DOMAIN_HOTPATCH_QUERY, query infomations
+ * of the applied hotpatch of the current domain.
+ *
+ * Returns success messages in case of success, NULL otherwise.
+ *
+ * Since: 6.10.0
+ */
+char *
+virDomainHotpatchManage(virDomainPtr domain,
+                        int action,
+                        const char *patch,
+                        const char *id,
+                        unsigned int flags)
+{
+    virConnectPtr conn;
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (action == VIR_DOMAIN_HOTPATCH_APPLY)
+        virCheckNonNullArgGoto(patch, error);
+
+    if (action == VIR_DOMAIN_HOTPATCH_UNAPPLY)
+        virCheckNonNullArgGoto(id, error);
+
+    if (conn->driver->domainHotpatchManage) {
+        char *ret;
+        ret = conn->driver->domainHotpatchManage(domain, action, patch, id, flags);
+        if (!ret)
+            goto error;
+
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
 
 /**
  * virDomainAuthorizedSSHKeysGet:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index bd1e916d2a..52a5d03240 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -873,6 +873,11 @@ LIBVIRT_6.0.0 {
         virDomainBackupGetXMLDesc;
 } LIBVIRT_5.10.0;
 
+LIBVIRT_6.2.0 {
+    global:
+        virDomainHotpatchManage;
+} LIBVIRT_6.0.0;
+
 LIBVIRT_6.10.0 {
     global:
         virDomainAuthorizedSSHKeysGet;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index c4831db6cd..25fae1cad6 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7842,6 +7842,7 @@ static virHypervisorDriver hypervisor_driver = {
     .domainAgentSetResponseTimeout = remoteDomainAgentSetResponseTimeout, /* 5.10.0 */
     .domainBackupBegin = remoteDomainBackupBegin, /* 6.0.0 */
     .domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */
+    .domainHotpatchManage = remoteDomainHotpatchManage, /* 6.2.0 */
     .domainAuthorizedSSHKeysGet = remoteDomainAuthorizedSSHKeysGet, /* 6.10.0 */
     .domainAuthorizedSSHKeysSet = remoteDomainAuthorizedSSHKeysSet, /* 6.10.0 */
     .domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index e295b0acc3..eea11df2ea 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3956,6 +3956,17 @@ struct remote_domain_event_memory_device_size_change_msg {
     unsigned hyper size;
 };
 
+struct remote_domain_hotpatch_manage_args {
+    remote_nonnull_domain dom;
+    int action;
+    remote_string patch;
+    remote_string id;
+    unsigned int flags;
+};
+
+struct remote_domain_hotpatch_manage_ret {
+    remote_string info;
+};
 
 struct remote_domain_fd_associate_args {
     remote_nonnull_domain dom;
@@ -7021,5 +7032,11 @@ enum remote_procedure {
      * @generate: both
      * @acl: none
      */
-    REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446
+    REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446,
+
+    /**
+     * @generate: both
+     * @acl: domain:read
+     */
+    REMOTE_PROC_DOMAIN_HOTPATCH_MANAGE = 800
 };
-- 
2.27.0

