From 2721c0ce65045c90e54fcab383d4af83415bd3f3 Mon Sep 17 00:00:00 2001 From: AlexChen Date: Tue, 19 Oct 2021 14:50:32 +0800 Subject: [PATCH] hotpatch: Implement qemuDomainHotpatchManage Signed-off-by: Hao Wang Signed-off-by: Bihong Yu Signed-off-by: AlexChen --- include/libvirt/libvirt-domain.h | 10 +- src/libvirt-domain.c | 2 +- src/libvirt_public.syms | 2 +- src/qemu/meson.build | 1 + src/qemu/qemu_driver.c | 48 ++++++++ src/qemu/qemu_hotpatch.c | 182 +++++++++++++++++++++++++++++++ src/qemu/qemu_hotpatch.h | 36 ++++++ 7 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 src/qemu/qemu_hotpatch.c create mode 100644 src/qemu/qemu_hotpatch.h diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index f8def59032..e786ecfab2 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -6422,13 +6422,13 @@ int virDomainAuthorizedSSHKeysGet(virDomainPtr domain, * 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 */ + VIR_DOMAIN_HOTPATCH_NONE = 0, /* No action (Since: 6.2.0) */ + VIR_DOMAIN_HOTPATCH_APPLY, /* Apply hotpatch (Since: 6.2.0) */ + VIR_DOMAIN_HOTPATCH_UNAPPLY, /* Unapply hotpatch (Since: 6.2.0) */ + VIR_DOMAIN_HOTPATCH_QUERY, /* Query hotpatch (Since: 6.2.0) */ # ifdef VIR_ENUM_SENTINELS - VIR_DOMAIN_HOTPATCH_LAST + VIR_DOMAIN_HOTPATCH_LAST /* Last index (Since: 6.2.0) */ # endif } virDomainHotpatchAction; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 26833efd0e..21b01110fe 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -13805,7 +13805,7 @@ virDomainBackupGetXMLDesc(virDomainPtr domain, * * Returns success messages in case of success, NULL otherwise. * - * Since: 6.10.0 + * Since: 6.2.0 */ char * virDomainHotpatchManage(virDomainPtr domain, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 52a5d03240..8b38fe9a5f 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -882,7 +882,7 @@ LIBVIRT_6.10.0 { global: virDomainAuthorizedSSHKeysGet; virDomainAuthorizedSSHKeysSet; -} LIBVIRT_6.0.0; +} LIBVIRT_6.2.0; LIBVIRT_7.1.0 { global: diff --git a/src/qemu/meson.build b/src/qemu/meson.build index 2279fef2ca..9d5b4da35d 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -42,6 +42,7 @@ qemu_driver_sources = [ 'qemu_vhost_user.c', 'qemu_vhost_user_gpu.c', 'qemu_virtiofs.c', + 'qemu_hotpatch.c', ] driver_source_files += files(qemu_driver_sources) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d00d2a27c6..3dd82d6f12 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -105,6 +105,7 @@ #include "virdomaincheckpointobjlist.h" #include "virutil.h" #include "backup_conf.h" +#include "qemu_hotpatch.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -19934,6 +19935,52 @@ qemuDomainFDAssociate(virDomainPtr domain, return ret; } +static char * +qemuDomainHotpatchManage(virDomainPtr domain, + int action, + const char *patch, + const char *id, + unsigned int flags) +{ + virDomainObjPtr vm; + char *ret = NULL; + size_t len; + + virCheckFlags(0, NULL); + + if (!(vm = qemuDomainObjFromDomain(domain))) + goto cleanup; + + switch (action) { + case VIR_DOMAIN_HOTPATCH_APPLY: + ret = qemuDomainHotpatchApply(vm, patch); + break; + + case VIR_DOMAIN_HOTPATCH_UNAPPLY: + ret = qemuDomainHotpatchUnapply(vm, id); + break; + + case VIR_DOMAIN_HOTPATCH_QUERY: + ret = qemuDomainHotpatchQuery(vm); + break; + + default: + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Unknow hotpatch action")); + } + + if (!ret) + goto endjob; + + /* Wipeout redundant empty line */ + len = strlen(ret); + if (len > 0) + ret[len - 1] = '\0'; + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, @@ -20178,6 +20225,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainAgentSetResponseTimeout = qemuDomainAgentSetResponseTimeout, /* 5.10.0 */ .domainBackupBegin = qemuDomainBackupBegin, /* 6.0.0 */ .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */ + .domainHotpatchManage = qemuDomainHotpatchManage, /* 6.2.0 */ .domainAuthorizedSSHKeysGet = qemuDomainAuthorizedSSHKeysGet, /* 6.10.0 */ .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */ .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */ diff --git a/src/qemu/qemu_hotpatch.c b/src/qemu/qemu_hotpatch.c new file mode 100644 index 0000000000..c1a4ab7aca --- /dev/null +++ b/src/qemu/qemu_hotpatch.c @@ -0,0 +1,182 @@ +/* + * huawei_qemu_hotpatch.h: huawei qemu hotpatch functions + * + * Copyright (C) 2021-2021 HUAWEI, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + + +#include +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" +#include "vircommand.h" +#include "qemu/qemu_domain.h" +#include "qemu_hotpatch.h" + +#define LIBCARE_CTL "libcare-ctl" +#define LIBCARE_ERROR_NUMBER 255 +#define MAX_PATCHID_LEN 8 + +#define VIR_FROM_THIS VIR_FROM_QEMU + +VIR_LOG_INIT("qemu_hotpatch"); + +char * +qemuDomainHotpatchQuery(virDomainObj *vm) +{ + g_autoptr(virCommand) cmd = NULL; + g_autofree char *binary = NULL; + char *output = NULL; + int ret = -1; + + if (!(binary = virFindFileInPath(LIBCARE_CTL))) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Failed to find libcare-ctl command.")); + return NULL; + } + + cmd = virCommandNewArgList(binary, "info", "-p", NULL); + virCommandAddArgFormat(cmd, "%d", vm->pid); + virCommandSetOutputBuffer(cmd, &output); + + VIR_DEBUG("Querying hotpatch for domain %s. (%s info -p %d)", + vm->def->name, binary, vm->pid); + + if (virCommandRun(cmd, &ret) < 0) + goto error; + + if (ret == LIBCARE_ERROR_NUMBER) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Failed to execute libcare-ctl command.")); + goto error; + } + return output; + + error: + VIR_FREE(output); + return NULL; +} + +char * +qemuDomainHotpatchApply(virDomainObj *vm, + const char *patch) +{ + g_autoptr(virCommand) cmd = NULL; + g_autofree char *binary = NULL; + char *output = NULL; + int ret = -1; + + if (!patch || !virFileExists(patch)) { + virReportError(VIR_ERR_INVALID_ARG, + "%s", _("Invalid hotpatch file.")); + return NULL; + } + + if (!(binary = virFindFileInPath(LIBCARE_CTL))) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Failed to find libcare-ctl command.")); + return NULL; + } + + cmd = virCommandNewArgList(binary, "patch", "-p", NULL); + virCommandAddArgFormat(cmd, "%d", vm->pid); + virCommandAddArgList(cmd, patch, NULL); + virCommandSetOutputBuffer(cmd, &output); + + VIR_DEBUG("Applying hotpatch for domain %s. (%s patch -p %d %s)", + vm->def->name, binary, vm->pid, patch); + + if (virCommandRun(cmd, &ret) < 0) + goto error; + + if (ret == LIBCARE_ERROR_NUMBER) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Failed to execute libcare-ctl command.")); + goto error; + } + return output; + + error: + VIR_FREE(output); + return NULL; +} + +static bool +qemuDomainHotpatchIsPatchidValid(const char *id) +{ + size_t len, i; + + if (!id) + return false; + + len = strlen(id); + if (len > MAX_PATCHID_LEN - 1) + return false; + + for (i = 0; i < len; i++) { + if (!g_ascii_isalnum(*(id + i))) + return false; + } + + return true; +} + +char * +qemuDomainHotpatchUnapply(virDomainObj *vm, + const char *id) +{ + g_autoptr(virCommand) cmd = NULL; + g_autofree char *binary = NULL; + char *output = NULL; + int ret = -1; + + if (!id || !qemuDomainHotpatchIsPatchidValid(id)) { + virReportError(VIR_ERR_INVALID_ARG, + "%s", _("Invalid hotpatch id.")); + return NULL; + } + + if (!(binary = virFindFileInPath(LIBCARE_CTL))) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Failed to find libcare-ctl command.")); + return NULL; + } + + cmd = virCommandNewArgList(binary, "unpatch", "-p", NULL); + virCommandAddArgFormat(cmd, "%d", vm->pid); + virCommandAddArgList(cmd, "-i", id, NULL); + virCommandSetOutputBuffer(cmd, &output); + + VIR_DEBUG("Unapplying hotpatch for domain %s. (%s unpatch -p %d -i %s)", + vm->def->name, binary, vm->pid, id); + + if (virCommandRun(cmd, &ret) < 0) + goto error; + + if (ret == LIBCARE_ERROR_NUMBER) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Failed to execute libcare-ctl command.")); + goto error; + } + return output; + + error: + VIR_FREE(output); + return NULL; +} diff --git a/src/qemu/qemu_hotpatch.h b/src/qemu/qemu_hotpatch.h new file mode 100644 index 0000000000..3cf22f7fc4 --- /dev/null +++ b/src/qemu/qemu_hotpatch.h @@ -0,0 +1,36 @@ +/* + * huawei_qemu_hotpatch.h: huawei qemu hotpatch functions + * + * Copyright (C) 2021-2021 HUAWEI, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#pragma once + +#include +#include "qemu/qemu_conf.h" + +char * +qemuDomainHotpatchQuery(virDomainObj *vm); + +char * +qemuDomainHotpatchApply(virDomainObj *vm, + const char *patch); + +char * +qemuDomainHotpatchUnapply(virDomainObj *vm, + const char *id); -- 2.27.0