From b255a024007eb236745b703586a2fed8bdedae6c Mon Sep 17 00:00:00 2001 From: AlexChen Date: Tue, 19 Oct 2021 22:11:45 +0800 Subject: [PATCH] hotpatch: Implement qemuDomainHotpatchManage Signed-off-by: Hao Wang Signed-off-by: Bihong Yu Signed-off-by: AlexChen --- src/qemu/Makefile.inc.am | 2 + src/qemu/qemu_driver.c | 48 +++++++++++ src/qemu/qemu_hotpatch.c | 182 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_hotpatch.h | 36 ++++++++ 4 files changed, 268 insertions(+) create mode 100644 src/qemu/qemu_hotpatch.c create mode 100644 src/qemu/qemu_hotpatch.h diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am index 51cd79879d..a1a8bfa17c 100644 --- a/src/qemu/Makefile.inc.am +++ b/src/qemu/Makefile.inc.am @@ -73,6 +73,8 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_checkpoint.h \ qemu/qemu_backup.c \ qemu/qemu_backup.h \ + qemu/qemu_hotpatch.c \ + qemu/qemu_hotpatch.h \ $(NULL) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5901f922bf..f6d99957a5 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -50,6 +50,7 @@ #include "qemu_security.h" #include "qemu_checkpoint.h" #include "qemu_backup.h" +#include "qemu_hotpatch.h" #include "virerror.h" #include "virlog.h" @@ -23171,6 +23172,52 @@ qemuDomainAgentSetResponseTimeout(virDomainPtr dom, 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, @@ -23411,6 +23458,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainAgentSetResponseTimeout = qemuDomainAgentSetResponseTimeout, /* 5.10.0 */ .domainBackupBegin = qemuDomainBackupBegin, /* 6.0.0 */ .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */ + .domainHotpatchManage = qemuDomainHotpatchManage, /* 6.2.0 */ }; diff --git a/src/qemu/qemu_hotpatch.c b/src/qemu/qemu_hotpatch.c new file mode 100644 index 0000000000..45796b3f24 --- /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(virDomainObjPtr 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(virDomainObjPtr 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(virDomainObjPtr 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..4c84a57950 --- /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(virDomainObjPtr vm); + +char * +qemuDomainHotpatchApply(virDomainObjPtr vm, + const char *patch); + +char * +qemuDomainHotpatchUnapply(virDomainObjPtr vm, + const char *id); -- 2.27.0