From 268a2708c42322808f19f080653911373a7743f2 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Thu, 6 Oct 2022 16:29:32 +0200 Subject: [PATCH] virsh: Add --model option for hypervisor-cpu-baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This option can be used as a shortcut for creating a single XML with just a CPU model name and no features: $ virsh hypervisor-cpu-baseline --model Skylake-Server Skylake-Server Signed-off-by: Jiri Denemark Reviewed-by: Ján Tomko --- docs/manpages/virsh.rst | 14 +++++++++++--- tools/virsh-host.c | 23 +++++++++++++++++++---- tools/virsh.h | 7 +++++-- tools/vsh.h | 27 +++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 5d11c48803..61fcb2e9ca 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -962,13 +962,18 @@ hypervisor-cpu-baseline :: - hypervisor-cpu-baseline FILE [virttype] [emulator] [arch] [machine] [--features] [--migratable] + hypervisor-cpu-baseline [FILE] [virttype] [emulator] [arch] [machine] + [--features] [--migratable] [model] Compute a baseline CPU which will be compatible with all CPUs defined in an XML *file* and with the CPU the hypervisor is able to provide on the host. (This is different from ``cpu-baseline`` which does not consider any hypervisor abilities when computing the baseline CPU.) +As an alternative for *FILE* in case the XML would only contain a CPU model +with no additional features the CPU model name itself can be passed as *model*. +Exactly one of *FILE* and *model* must be used. + The XML *FILE* may contain either host or guest CPU definitions describing the host CPU model. The host CPU definition is the element and its contents as printed by ``capabilities`` command. The guest CPU definition may be created @@ -981,10 +986,13 @@ fail or provide unexpected results. When *FILE* contains only a single CPU definition, the command will print the same CPU with restrictions imposed by the capabilities of the hypervisor. -Specifically, running th ``virsh hypervisor-cpu-baseline`` command with no +Specifically, running the ``virsh hypervisor-cpu-baseline`` command with no additional options on the result of ``virsh domcapabilities`` will transform the host CPU model from domain capabilities XML to a form directly usable in domain -XML. +XML. Running the command with *model* (or *FILE* containing just a single CPU +definition with model and no feature elements) which is marked as unusable in +``virsh domcapabilities`` will provide a list of features that block this CPU +model from being usable. The *virttype* option specifies the virtualization type (usable in the 'type' attribute of the top level element from the domain XML). *emulator* diff --git a/tools/virsh-host.c b/tools/virsh-host.c index ead966b500..16c3585a1a 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -1689,7 +1689,8 @@ static const vshCmdInfo info_hypervisor_cpu_baseline[] = { }; static const vshCmdOptDef opts_hypervisor_cpu_baseline[] = { - VIRSH_COMMON_OPT_FILE(N_("file containing XML CPU descriptions")), + VIRSH_COMMON_OPT_FILE_FULL(N_("file containing XML CPU descriptions"), + false), {.name = "virttype", .type = VSH_OT_STRING, .completer = virshDomainVirtTypeCompleter, @@ -1716,6 +1717,11 @@ static const vshCmdOptDef opts_hypervisor_cpu_baseline[] = { .type = VSH_OT_BOOL, .help = N_("Do not include features that block migration") }, + {.name = "model", + .type = VSH_OT_STRING, + .help = N_("Shortcut for calling the command with a single CPU model " + "and no additional features") + }, {.name = NULL} }; @@ -1728,6 +1734,7 @@ cmdHypervisorCPUBaseline(vshControl *ctl, const char *emulator = NULL; const char *arch = NULL; const char *machine = NULL; + const char *model = NULL; bool ret = false; g_autofree char *result = NULL; g_auto(GStrv) list = NULL; @@ -1743,11 +1750,19 @@ cmdHypervisorCPUBaseline(vshControl *ctl, vshCommandOptStringReq(ctl, cmd, "virttype", &virttype) < 0 || vshCommandOptStringReq(ctl, cmd, "emulator", &emulator) < 0 || vshCommandOptStringReq(ctl, cmd, "arch", &arch) < 0 || - vshCommandOptStringReq(ctl, cmd, "machine", &machine) < 0) + vshCommandOptStringReq(ctl, cmd, "machine", &machine) < 0 || + vshCommandOptStringReq(ctl, cmd, "model", &model) < 0) return false; - if (!(list = vshExtractCPUDefXMLs(ctl, from))) - return false; + VSH_ALTERNATIVE_OPTIONS_EXPR("file", from, "model", model); + + if (from) { + if (!(list = vshExtractCPUDefXMLs(ctl, from))) + return false; + } else { + list = g_new0(char *, 2); + list[0] = g_strdup_printf("%s", model); + } result = virConnectBaselineHypervisorCPU(priv->conn, emulator, arch, machine, virttype, diff --git a/tools/virsh.h b/tools/virsh.h index f9841c8da2..6acefa7f9d 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -96,9 +96,12 @@ /* Use this only for files which are existing and used locally by virsh */ #define VIRSH_COMMON_OPT_FILE(_helpstr) \ + VIRSH_COMMON_OPT_FILE_FULL(_helpstr, true) + +#define VIRSH_COMMON_OPT_FILE_FULL(_helpstr, required) \ {.name = "file", \ - .type = VSH_OT_DATA, \ - .flags = VSH_OFLAG_REQ, \ + .type = required ? VSH_OT_DATA : VSH_OT_STRING, \ + .flags = required ? VSH_OFLAG_REQ : VSH_OFLAG_NONE, \ .completer = virshCompletePathLocalExisting, \ .help = _helpstr \ } diff --git a/tools/vsh.h b/tools/vsh.h index a43660b63d..657a1e7a93 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -520,6 +520,33 @@ void vshReadlineHistoryAdd(const char *cmd); #define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \ VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2) +/* Macros to help dealing with alternative mutually exclusive options. */ + +/* VSH_ALTERNATIVE_OPTIONS_EXPR: + * + * @NAME1: String containing the name of the option. + * @EXPR1: Expression to validate the variable (must evaluate to bool). + * @NAME2: String containing the name of the option. + * @EXPR2: Expression to validate the variable (must evaluate to bool). + * + * Require exactly one of the command options in virsh. Use the provided + * expression to check the variables. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +#define VSH_ALTERNATIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \ + do { \ + bool _expr1 = EXPR1; \ + bool _expr2 = EXPR2; \ + VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, _expr1, NAME2, _expr2); \ + if (!_expr1 && !_expr2) { \ + vshError(ctl, _("Either --%s or --%s must be provided"), \ + NAME1, NAME2); \ + return false; \ + } \ + } while (0) + /* Macros to help dealing with required options. */ /* VSH_REQUIRE_OPTION_EXPR: