Add a straightforward implementation for using the new APIs.
---
tools/virsh-domain.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 10 ++++++
2 files changed, 103 insertions(+)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index bd6db47..ff2305f 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6762,6 +6762,93 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+
+/*
+ * "guestvcpus" command
+ */
+static const vshCmdInfo info_guestvcpus[] = {
+ {.name = "help",
+ .data = N_("query or modify state of vcpu in the guest (via agent)")
+ },
+ {.name = "desc",
+ .data = N_("Use the guest agent to query or set cpu state from guest's
"
+ "point of view")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_guestvcpus[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL,
+ {.name = "cpumap",
+ .type = VSH_OT_STRING,
+ .help = N_("number of virtual CPUs")
+ },
+ {.name = "enable",
+ .type = VSH_OT_BOOL,
+ .help = N_("enable cpus specified by cpumap")
+ },
+ {.name = "disable",
+ .type = VSH_OT_BOOL,
+ .help = N_("disable cpus specified by cpumap")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdGuestvcpus(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ bool enable = vshCommandOptBool(cmd, "enable");
+ bool disable = vshCommandOptBool(cmd, "disable");
+ virTypedParameterPtr params = NULL;
+ unsigned int nparams = 0;
+ const char *cpumap = NULL;
+ int state = 0;
+ size_t i;
+ bool ret = false;
+
+ VSH_EXCLUSIVE_OPTIONS_VAR(enable, disable);
+ VSH_REQUIRE_OPTION("enable", "cpumap");
+ VSH_REQUIRE_OPTION("disable", "cpumap");
+
+ if (vshCommandOptStringReq(ctl, cmd, "cpumap", &cpumap))
+ return false;
+
+ if (cpumap && !(enable | disable)) {
+ vshError(ctl, _("One of options --enable or --disable is required by "
+ "option --cpumap"));
+ return false;
+ }
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (enable)
+ state = 1;
+
+ if (cpumap) {
+ if (virDomainSetGuestVcpus(dom, cpumap, state, 0) < 0)
+ goto cleanup;
+ } else {
+ if (virDomainGetGuestVcpus(dom, ¶ms, &nparams, 0) < 0)
+ goto cleanup;
+
+ for (i = 0; i < nparams; i++) {
+ char *str = vshGetTypedParamValue(ctl, ¶ms[i]);
+ vshPrint(ctl, "%-15s: %s\n", params[i].field, str);
+ VIR_FREE(str);
+ }
+ }
+
+ ret = true;
+
+ cleanup:
+ virTypedParamsFree(params, nparams);
+ virDomainFree(dom);
+ return ret;
+}
+
+
/*
* "iothreadinfo" command
*/
@@ -13602,5 +13689,11 @@ const vshCmdDef domManagementCmds[] = {
.info = info_vncdisplay,
.flags = 0
},
+ {.name = "guestvcpus",
+ .handler = cmdGuestvcpus,
+ .opts = opts_guestvcpus,
+ .info = info_guestvcpus,
+ .flags = 0
+ },
{.name = NULL}
};
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 8e3ba69..6af1328 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2501,6 +2501,16 @@ Both I<--live> and I<--config> flags may be given if
I<cpulist> is present,
but I<--current> is exclusive.
If no flag is specified, behavior is different depending on hypervisor.
+=item B<guestvcpus> I<domain> [[I<--enable>] | [I<--disable>]]
[I<cpumap>]
+
+Query or change state of vCPUs from guest's point of view using the guest agent.
+When invoked without I<cpumap> the guest is queried for available guest vCPUs,
+their state and possibility to be offlined.
+
+If I<cpumap> is provided then one of I<--enable> or I<--disable> must
be
+provided too. The desired operation is then executed on the domain.
+
+See B<vcpupin> for I<cpumap> (as I<cpulist>).
=item B<vncdisplay> I<domain>
--
2.8.3