From 9da9a3b04723cf8f3303255bb7191861540a3e21 Mon Sep 17 00:00:00 2001 From: Hu Tao Date: Tue, 20 Dec 2011 16:35:03 +0800 Subject: [PATCH] add new command numatune to virsh add new command numatune to virsh to get/set numa parameters --- tools/virsh.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 19 ++++++ 2 files changed, 179 insertions(+) diff --git a/tools/virsh.c b/tools/virsh.c index 583ec6df29..0cf51e42b8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -61,6 +61,7 @@ #include "virkeycode.h" #include "virnetdevbandwidth.h" #include "util/bitmap.h" +#include "conf/domain_conf.h" static char *progname; @@ -5125,6 +5126,164 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) return ret; } +/* + * "numatune" command + */ +static const vshCmdInfo info_numatune[] = { + {"help", N_("Get or set numa parameters")}, + {"desc", N_("Get or set the current numa parameters for a guest" \ + " domain.\n" \ + " To get the numa parameters use following command: \n\n" \ + " virsh # numatune ")}, + {NULL, NULL} + +}; + +static const vshCmdOptDef opts_numatune[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"mode", VSH_OT_DATA, VSH_OFLAG_NONE, + N_("NUMA mode, one of strict, preferred and interleave")}, + {"nodeset", VSH_OT_DATA, VSH_OFLAG_NONE, + N_("NUMA node selections to set")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdNumatune(vshControl * ctl, const vshCmd * cmd) +{ + virDomainPtr dom; + int nparams = 0; + unsigned int i = 0; + virTypedParameterPtr params = NULL, temp = NULL; + const char *nodeset = NULL; + bool ret = false; + unsigned int flags = 0; + int current = vshCommandOptBool(cmd, "current"); + int config = vshCommandOptBool(cmd, "config"); + int live = vshCommandOptBool(cmd, "live"); + const char *mode = NULL; + + if (current) { + if (live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return false; + } + flags = VIR_DOMAIN_AFFECT_CURRENT; + } else { + if (config) + flags |= VIR_DOMAIN_AFFECT_CONFIG; + if (live) + flags |= VIR_DOMAIN_AFFECT_LIVE; + } + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (vshCommandOptString(cmd, "nodeset", &nodeset) < 0) { + vshError(ctl, "%s", _("Unable to parse nodeset.")); + virDomainFree(dom); + return false; + } + if (nodeset) + nparams++; + if (vshCommandOptString(cmd, "mode", &mode) < 0) { + vshError(ctl, "%s", _("Unable to parse mode.")); + virDomainFree(dom); + return false; + } + if (mode) + nparams++; + + if (nparams == 0) { + /* get the number of numa parameters */ + if (virDomainGetNumaParameters(dom, NULL, &nparams, flags) != 0) { + vshError(ctl, "%s", + _("Unable to get number of memory parameters")); + goto cleanup; + } + + if (nparams == 0) { + /* nothing to output */ + ret = true; + goto cleanup; + } + + /* now go get all the numa parameters */ + params = vshCalloc(ctl, nparams, sizeof(*params)); + if (virDomainGetNumaParameters(dom, params, &nparams, flags) != 0) { + vshError(ctl, "%s", _("Unable to get numa parameters")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) { + if (params[i].type == VIR_TYPED_PARAM_INT && + STREQ(params[i].field, VIR_DOMAIN_NUMA_MODE)) { + vshPrint(ctl, "%-15s: %s\n", params[i].field, + virDomainNumatuneMemModeTypeToString(params[i].value.i)); + } else { + char *str = vshGetTypedParamValue(ctl, ¶ms[i]); + vshPrint(ctl, "%-15s: %s\n", params[i].field, str); + VIR_FREE(str); + } + } + + ret = true; + } else { + /* set the numa parameters */ + params = vshCalloc(ctl, nparams, sizeof(*params)); + + for (i = 0; i < nparams; i++) { + temp = ¶ms[i]; + + /* + * Some magic here, this is used to fill the params structure with + * the valid arguments passed, after filling the particular + * argument we purposely make them 0, so on the next pass it goes + * to the next valid argument and so on. + */ + if (mode) { + /* Accept string or integer, in case server + * understands newer integer than what strings we were + * compiled with */ + if ((temp->value.i = + virDomainNumatuneMemModeTypeFromString(mode)) < 0 && + virStrToLong_i(mode, NULL, 0, &temp->value.i) < 0) { + vshError(ctl, _("Invalid mode: %s"), mode); + goto cleanup; + } + if (!virStrcpy(temp->field, VIR_DOMAIN_NUMA_MODE, + sizeof(temp->field))) + goto cleanup; + temp->type = VIR_TYPED_PARAM_INT; + mode = NULL; + } else if (nodeset) { + temp->value.s = vshStrdup(ctl, nodeset); + temp->type = VIR_TYPED_PARAM_STRING; + if (!virStrcpy(temp->field, VIR_DOMAIN_NUMA_NODESET, + sizeof(temp->field))) + goto cleanup; + nodeset = NULL; + } + } + if (virDomainSetNumaParameters(dom, params, nparams, flags) != 0) + vshError(ctl, "%s", _("Unable to change numa parameters")); + else + ret = true; + } + + cleanup: + virTypedParameterArrayClear(params, nparams); + VIR_FREE(params); + virDomainFree(dom); + return ret; +} + /* * "nodeinfo" command */ @@ -15237,6 +15396,7 @@ static const vshCmdDef domManagementCmds[] = { opts_migrate_setspeed, info_migrate_setspeed, 0}, {"migrate-getspeed", cmdMigrateGetMaxSpeed, opts_migrate_getspeed, info_migrate_getspeed, 0}, + {"numatune", cmdNumatune, opts_numatune, info_numatune, 0}, {"reboot", cmdReboot, opts_reboot, info_reboot, 0}, {"reset", cmdReset, opts_reset, info_reset, 0}, {"restore", cmdRestore, opts_restore, info_restore, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index dbe5165dfa..3b669b5762 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -832,6 +832,25 @@ migrated to another host. Get the maximum migration bandwidth (in Mbps) for a domain. +=item B I [I<--mode> B] [I<--nodeset> B] +[[I<--config>] [I<--live>] | [I<--current>]] + +Set or get a domain's numa parameters, corresponding to the +element of domain XML. Without flags, the current settings are +displayed. + +I can be one of `strict', `interleave' and `preferred'. For a +running domain, the mode can't be changed, and the nodeset can be +changed only if the domain was started with a mode of `strict'. + +I is a list of numa nodes used by the host for running the domain. +Its syntax is a comma separated list, with '-' for ranges and '^' for +excluding a node. + +If I<--live> is specified, set scheduler information of a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. + =item B I Reboot a domain. This acts just as if the domain had the B