Commands to manage host interface are moved from virsh.c to
virsh-interface.c, with a few helpers for interface command use.
* virsh.c: Remove interface commands and a few helpers.
(vshCommandOptInterface, vshCommandOptInterfaceBy)
* virsh-interface.c: New file, filled with interface commands its helpers.
---
tools/virsh-interface.c | 1000 +++++++++++++++++++++++++++++++++++
tools/virsh.c | 1333 +++++++----------------------------------------
2 files changed, 1177 insertions(+), 1156 deletions(-)
create mode 100644 tools/virsh-interface.c
diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c
new file mode 100644
index 0000000..6a43bb1
--- /dev/null
+++ b/tools/virsh-interface.c
@@ -0,0 +1,1000 @@
+/*
+ * virsh-interface.c: Commands to manage host interface
+ *
+ * Copyright (C) 2005, 2007-2012 Red Hat, 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
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Daniel Veillard <veillard(a)redhat.com>
+ * Karel Zak <kzak(a)redhat.com>
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ *
+ */
+
+/* default is lookup by Name and MAC */
+#define vshCommandOptInterface(_ctl, _cmd, _name) \
+ vshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \
+ VSH_BYMAC|VSH_BYNAME)
+
+static virInterfacePtr
+vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
+ const char *optname,
+ const char **name, int flag)
+{
+ virInterfacePtr iface = NULL;
+ const char *n = NULL;
+
+ if (!optname)
+ optname = "interface";
+ if (!cmd_has_option(ctl, cmd, optname))
+ return NULL;
+
+ if (vshCommandOptString(cmd, optname, &n) <= 0)
+ return NULL;
+
+ vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
+ cmd->def->name, optname, n);
+
+ if (name)
+ *name = n;
+
+ /* try it by NAME */
+ if (flag & VSH_BYNAME) {
+ vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface
NAME\n",
+ cmd->def->name, optname);
+ iface = virInterfaceLookupByName(ctl->conn, n);
+ }
+ /* try it by MAC */
+ if (iface == NULL && (flag & VSH_BYMAC)) {
+ vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface
MAC\n",
+ cmd->def->name, optname);
+ iface = virInterfaceLookupByMACString(ctl->conn, n);
+ }
+
+ if (!iface)
+ vshError(ctl, _("failed to get interface '%s'"), n);
+
+ return iface;
+}
+
+/*
+ * "iface-edit" command
+ */
+static const vshCmdInfo info_interface_edit[] = {
+ {"help", N_("edit XML configuration for a physical host
interface")},
+ {"desc", N_("Edit the XML configuration for a physical host
interface.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_edit[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd)
+{
+ bool ret = false;
+ virInterfacePtr iface = NULL;
+ virInterfacePtr iface_edited = NULL;
+ unsigned int flags = VIR_INTERFACE_XML_INACTIVE;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ iface = vshCommandOptInterface(ctl, cmd, NULL);
+ if (iface == NULL)
+ goto cleanup;
+
+#define EDIT_GET_XML virInterfaceGetXMLDesc(iface, flags)
+#define EDIT_NOT_CHANGED \
+ vshPrint(ctl, _("Interface %s XML configuration not changed.\n"), \
+ virInterfaceGetName(iface)); \
+ ret = true; goto edit_cleanup;
+#define EDIT_DEFINE \
+ (iface_edited = virInterfaceDefineXML(ctl->conn, doc_edited, 0))
+#define EDIT_FREE \
+ if (iface_edited) \
+ virInterfaceFree(iface_edited);
+#include "virsh-edit.c"
+
+ vshPrint(ctl, _("Interface %s XML configuration edited.\n"),
+ virInterfaceGetName(iface_edited));
+
+ ret = true;
+
+cleanup:
+ if (iface)
+ virInterfaceFree(iface);
+ if (iface_edited)
+ virInterfaceFree(iface_edited);
+
+ return ret;
+}
+
+/*
+ * "iface-list" command
+ */
+static const vshCmdInfo info_interface_list[] = {
+ {"help", N_("list physical host interfaces")},
+ {"desc", N_("Returns list of physical host interfaces.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_list[] = {
+ {"inactive", VSH_OT_BOOL, 0, N_("list inactive interfaces")},
+ {"all", VSH_OT_BOOL, 0, N_("list inactive & active
interfaces")},
+ {NULL, 0, 0, NULL}
+};
+static bool
+cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ bool inactive = vshCommandOptBool(cmd, "inactive");
+ bool all = vshCommandOptBool(cmd, "all");
+ bool active = !inactive || all;
+ int maxactive = 0, maxinactive = 0, i;
+ char **activeNames = NULL, **inactiveNames = NULL;
+ inactive |= all;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (active) {
+ maxactive = virConnectNumOfInterfaces(ctl->conn);
+ if (maxactive < 0) {
+ vshError(ctl, "%s", _("Failed to list active
interfaces"));
+ return false;
+ }
+ if (maxactive) {
+ activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
+
+ if ((maxactive = virConnectListInterfaces(ctl->conn, activeNames,
+ maxactive)) < 0) {
+ vshError(ctl, "%s", _("Failed to list active
interfaces"));
+ VIR_FREE(activeNames);
+ return false;
+ }
+
+ qsort(&activeNames[0], maxactive, sizeof(char *), vshNameSorter);
+ }
+ }
+ if (inactive) {
+ maxinactive = virConnectNumOfDefinedInterfaces(ctl->conn);
+ if (maxinactive < 0) {
+ vshError(ctl, "%s", _("Failed to list inactive
interfaces"));
+ VIR_FREE(activeNames);
+ return false;
+ }
+ if (maxinactive) {
+ inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
+
+ if ((maxinactive =
+ virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
+ maxinactive)) < 0) {
+ vshError(ctl, "%s", _("Failed to list inactive
interfaces"));
+ VIR_FREE(activeNames);
+ VIR_FREE(inactiveNames);
+ return false;
+ }
+
+ qsort(&inactiveNames[0], maxinactive, sizeof(char*), vshNameSorter);
+ }
+ }
+ vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"),
_("State"),
+ _("MAC Address"));
+ vshPrintExtra(ctl, "--------------------------------------------\n");
+
+ for (i = 0; i < maxactive; i++) {
+ virInterfacePtr iface =
+ virInterfaceLookupByName(ctl->conn, activeNames[i]);
+
+ /* this kind of work with interfaces is not atomic */
+ if (!iface) {
+ VIR_FREE(activeNames[i]);
+ continue;
+ }
+
+ vshPrint(ctl, "%-20s %-10s %s\n",
+ virInterfaceGetName(iface),
+ _("active"),
+ virInterfaceGetMACString(iface));
+ virInterfaceFree(iface);
+ VIR_FREE(activeNames[i]);
+ }
+ for (i = 0; i < maxinactive; i++) {
+ virInterfacePtr iface =
+ virInterfaceLookupByName(ctl->conn, inactiveNames[i]);
+
+ /* this kind of work with interfaces is not atomic */
+ if (!iface) {
+ VIR_FREE(inactiveNames[i]);
+ continue;
+ }
+
+ vshPrint(ctl, "%-20s %-10s %s\n",
+ virInterfaceGetName(iface),
+ _("inactive"),
+ virInterfaceGetMACString(iface));
+ virInterfaceFree(iface);
+ VIR_FREE(inactiveNames[i]);
+ }
+ VIR_FREE(activeNames);
+ VIR_FREE(inactiveNames);
+ return true;
+
+}
+
+/*
+ * "iface-name" command
+ */
+static const vshCmdInfo info_interface_name[] = {
+ {"help", N_("convert an interface MAC address to interface
name")},
+ {"desc", ""},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_name[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface mac")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+ if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+ VSH_BYMAC)))
+ return false;
+
+ vshPrint(ctl, "%s\n", virInterfaceGetName(iface));
+ virInterfaceFree(iface);
+ return true;
+}
+
+/*
+ * "iface-mac" command
+ */
+static const vshCmdInfo info_interface_mac[] = {
+ {"help", N_("convert an interface name to interface MAC
address")},
+ {"desc", ""},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_mac[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+ if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+ VSH_BYNAME)))
+ return false;
+
+ vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface));
+ virInterfaceFree(iface);
+ return true;
+}
+
+/*
+ * "iface-dumpxml" command
+ */
+static const vshCmdInfo info_interface_dumpxml[] = {
+ {"help", N_("interface information in XML")},
+ {"desc", N_("Output the physical host interface information as an XML
dump to stdout.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_dumpxml[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
+ {"inactive", VSH_OT_BOOL, 0, N_("show inactive defined XML")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+ bool ret = true;
+ char *dump;
+ unsigned int flags = 0;
+ bool inactive = vshCommandOptBool(cmd, "inactive");
+
+ if (inactive)
+ flags |= VIR_INTERFACE_XML_INACTIVE;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
+ return false;
+
+ dump = virInterfaceGetXMLDesc(iface, flags);
+ if (dump != NULL) {
+ vshPrint(ctl, "%s", dump);
+ VIR_FREE(dump);
+ } else {
+ ret = false;
+ }
+
+ virInterfaceFree(iface);
+ return ret;
+}
+
+/*
+ * "iface-define" command
+ */
+static const vshCmdInfo info_interface_define[] = {
+ {"help", N_("define (but don't start) a physical host interface
from an XML file")},
+ {"desc", N_("Define a physical host interface.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_define[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML
interface description")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+ const char *from = NULL;
+ bool ret = true;
+ char *buffer;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptString(cmd, "file", &from) <= 0)
+ return false;
+
+ if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
+ return false;
+
+ iface = virInterfaceDefineXML(ctl->conn, buffer, 0);
+ VIR_FREE(buffer);
+
+ if (iface != NULL) {
+ vshPrint(ctl, _("Interface %s defined from %s\n"),
+ virInterfaceGetName(iface), from);
+ virInterfaceFree(iface);
+ } else {
+ vshError(ctl, _("Failed to define interface from %s"), from);
+ ret = false;
+ }
+ return ret;
+}
+
+/*
+ * "iface-undefine" command
+ */
+static const vshCmdInfo info_interface_undefine[] = {
+ {"help", N_("undefine a physical host interface (remove it from
configuration)")},
+ {"desc", N_("undefine an interface.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_undefine[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+ bool ret = true;
+ const char *name;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ return false;
+
+ if (virInterfaceUndefine(iface) == 0) {
+ vshPrint(ctl, _("Interface %s undefined\n"), name);
+ } else {
+ vshError(ctl, _("Failed to undefine interface %s"), name);
+ ret = false;
+ }
+
+ virInterfaceFree(iface);
+ return ret;
+}
+
+/*
+ * "iface-start" command
+ */
+static const vshCmdInfo info_interface_start[] = {
+ {"help", N_("start a physical host interface (enable it /
\"if-up\")")},
+ {"desc", N_("start a physical host interface.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_start[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+ bool ret = true;
+ const char *name;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ return false;
+
+ if (virInterfaceCreate(iface, 0) == 0) {
+ vshPrint(ctl, _("Interface %s started\n"), name);
+ } else {
+ vshError(ctl, _("Failed to start interface %s"), name);
+ ret = false;
+ }
+
+ virInterfaceFree(iface);
+ return ret;
+}
+
+/*
+ * "iface-destroy" command
+ */
+static const vshCmdInfo info_interface_destroy[] = {
+ {"help", N_("destroy a physical host interface (disable it /
\"if-down\")")},
+ {"desc", N_("forcefully stop a physical host interface.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_destroy[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd)
+{
+ virInterfacePtr iface;
+ bool ret = true;
+ const char *name;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+ return false;
+
+ if (virInterfaceDestroy(iface, 0) == 0) {
+ vshPrint(ctl, _("Interface %s destroyed\n"), name);
+ } else {
+ vshError(ctl, _("Failed to destroy interface %s"), name);
+ ret = false;
+ }
+
+ virInterfaceFree(iface);
+ return ret;
+}
+
+/*
+ * "iface-begin" command
+ */
+static const vshCmdInfo info_interface_begin[] = {
+ {"help", N_("create a snapshot of current interfaces settings, "
+ "which can be later committed (iface-commit) or "
+ "restored (iface-rollback)")},
+ {"desc", N_("Create a restore point for interfaces settings")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_begin[] = {
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceBegin(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (virInterfaceChangeBegin(ctl->conn, 0) < 0) {
+ vshError(ctl, "%s", _("Failed to begin network config change
transaction"));
+ return false;
+ }
+
+ vshPrint(ctl, "%s", _("Network config change transaction
started\n"));
+ return true;
+}
+
+/*
+ * "iface-commit" command
+ */
+static const vshCmdInfo info_interface_commit[] = {
+ {"help", N_("commit changes made since iface-begin and free restore
point")},
+ {"desc", N_("commit changes and free restore point")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_commit[] = {
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceCommit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (virInterfaceChangeCommit(ctl->conn, 0) < 0) {
+ vshError(ctl, "%s", _("Failed to commit network config change
transaction"));
+ return false;
+ }
+
+ vshPrint(ctl, "%s", _("Network config change transaction
committed\n"));
+ return true;
+}
+
+/*
+ * "iface-rollback" command
+ */
+static const vshCmdInfo info_interface_rollback[] = {
+ {"help", N_("rollback to previous saved configuration created via
iface-begin")},
+ {"desc", N_("rollback to previous restore point")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_rollback[] = {
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceRollback(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (virInterfaceChangeRollback(ctl->conn, 0) < 0) {
+ vshError(ctl, "%s", _("Failed to rollback network config change
transaction"));
+ return false;
+ }
+
+ vshPrint(ctl, "%s", _("Network config change transaction rolled
back\n"));
+ return true;
+}
+
+/*
+ * "iface-bridge" command
+ */
+static const vshCmdInfo info_interface_bridge[] = {
+ {"help", N_("create a bridge device and attach an existing network
device to it")},
+ {"desc", N_("bridge an existing network device")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_bridge[] = {
+ {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("existing interface
name")},
+ {"bridge", VSH_OT_DATA, VSH_OFLAG_REQ, N_("new bridge device
name")},
+ {"no-stp", VSH_OT_BOOL, 0, N_("do not enable STP for this
bridge")},
+ {"delay", VSH_OT_INT, 0,
+ N_("number of seconds to squelch traffic on newly connected ports")},
+ {"no-start", VSH_OT_BOOL, 0, N_("don't start the bridge
immediately")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd)
+{
+ bool ret = false;
+ virInterfacePtr if_handle = NULL, br_handle = NULL;
+ const char *if_name, *br_name;
+ char *if_type = NULL, *if2_name = NULL, *delay_str = NULL;
+ bool stp = false, nostart = false;
+ unsigned int delay = 0;
+ char *if_xml = NULL;
+ xmlChar *br_xml = NULL;
+ int br_xml_size;
+ xmlDocPtr xml_doc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr top_node, br_node, if_node, cur;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ /* Get a handle to the original device */
+ if (!(if_handle = vshCommandOptInterfaceBy(ctl, cmd, "interface",
+ &if_name, VSH_BYNAME))) {
+ goto cleanup;
+ }
+
+ /* Name for new bridge device */
+ if (vshCommandOptString(cmd, "bridge", &br_name) <= 0) {
+ vshError(ctl, "%s", _("Missing bridge device name in
command"));
+ goto cleanup;
+ }
+
+ /* make sure "new" device doesn't already exist */
+ if ((br_handle = virInterfaceLookupByName(ctl->conn, br_name))) {
+ vshError(ctl, _("Network device %s already exists"), br_name);
+ goto cleanup;
+ }
+
+ /* use "no-stp" because we want "stp" to default true */
+ stp = !vshCommandOptBool(cmd, "no-stp");
+
+ if (vshCommandOptUInt(cmd, "delay", &delay) < 0) {
+ vshError(ctl, "%s", _("Unable to parse delay parameter"));
+ goto cleanup;
+ }
+
+ nostart = vshCommandOptBool(cmd, "no-start");
+
+ /* Get the original interface into an xmlDoc */
+ if (!(if_xml = virInterfaceGetXMLDesc(if_handle, VIR_INTERFACE_XML_INACTIVE)))
+ goto cleanup;
+ if (!(xml_doc = virXMLParseStringCtxt(if_xml,
+ _("(interface definition)"),
&ctxt))) {
+ vshError(ctl, _("Failed to parse configuration of %s"), if_name);
+ goto cleanup;
+ }
+ top_node = ctxt->node;
+
+ /* Verify that the original device isn't already a bridge. */
+ if (!(if_type = virXMLPropString(top_node, "type"))) {
+ vshError(ctl, _("Existing device %s has no type"), if_name);
+ goto cleanup;
+ }
+
+ if (STREQ(if_type, "bridge")) {
+ vshError(ctl, _("Existing device %s is already a bridge"), if_name);
+ goto cleanup;
+ }
+
+ /* verify the name in the XML matches the device name */
+ if (!(if2_name = virXMLPropString(top_node, "name")) ||
+ STRNEQ(if2_name, if_name)) {
+ vshError(ctl, _("Interface name from config %s doesn't match given
supplied name %s"),
+ if2_name, if_name);
+ goto cleanup;
+ }
+
+ /* Create a <bridge> node under <interface>. */
+ if (!(br_node = xmlNewChild(top_node, NULL, BAD_CAST "bridge", NULL))) {
+ vshError(ctl, "%s", _("Failed to create bridge node in xml
document"));
+ goto cleanup;
+ }
+
+ /* Set stp and delay attributes in <bridge> according to the
+ * commandline options.
+ */
+ if (!xmlSetProp(br_node, BAD_CAST "stp", BAD_CAST (stp ? "on" :
"off"))) {
+ vshError(ctl, "%s", _("Failed to set stp attribute in xml
document"));
+ goto cleanup;
+ }
+
+ if ((delay || stp) &&
+ ((virAsprintf(&delay_str, "%d", delay) < 0) ||
+ !xmlSetProp(br_node, BAD_CAST "delay", BAD_CAST delay_str))) {
+ vshError(ctl, _("Failed to set bridge delay %d in xml document"),
delay);
+ goto cleanup;
+ }
+
+ /* Change the type of the outer/master interface to "bridge" and the
+ * name to the provided bridge name.
+ */
+ if (!xmlSetProp(top_node, BAD_CAST "type", BAD_CAST "bridge")) {
+ vshError(ctl, "%s", _("Failed to set bridge interface type to
'bridge' in xml document"));
+ goto cleanup;
+ }
+
+ if (!xmlSetProp(top_node, BAD_CAST "name", BAD_CAST br_name)) {
+ vshError(ctl, _("Failed to set master bridge interface name to '%s'
in xml document"),
+ br_name);
+ goto cleanup;
+ }
+
+ /* Create an <interface> node under <bridge> that uses the
+ * original interface's type and name.
+ */
+ if (!(if_node = xmlNewChild(br_node, NULL, BAD_CAST "interface", NULL))) {
+ vshError(ctl, "%s", _("Failed to create interface node under
bridge node in xml document"));
+ goto cleanup;
+ }
+
+ /* set the type of the inner/slave interface to the original
+ * if_type, and the name to the original if_name.
+ */
+ if (!xmlSetProp(if_node, BAD_CAST "type", BAD_CAST if_type)) {
+ vshError(ctl, _("Failed to set new slave interface type to '%s' in
xml document"),
+ if_name);
+ goto cleanup;
+ }
+
+ if (!xmlSetProp(if_node, BAD_CAST "name", BAD_CAST if_name)) {
+ vshError(ctl, _("Failed to set new slave interface name to '%s' in
xml document"),
+ br_name);
+ goto cleanup;
+ }
+
+ /* Cycle through all the nodes under the original <interface>,
+ * moving all <mac>, <bond> and <vlan> nodes down into the new
+ * lower level <interface>.
+ */
+ cur = top_node->children;
+ while (cur) {
+ xmlNodePtr old = cur;
+
+ cur = cur->next;
+ if ((old->type == XML_ELEMENT_NODE) &&
+ (xmlStrEqual(old->name, BAD_CAST "mac") || /* ethernet stuff to
move down */
+ xmlStrEqual(old->name, BAD_CAST "bond") || /* bond stuff to
move down */
+ xmlStrEqual(old->name, BAD_CAST "vlan"))) { /* vlan stuff to
move down */
+ xmlUnlinkNode(old);
+ if (!xmlAddChild(if_node, old)) {
+ vshError(ctl, _("Failed to move '%s' element in xml
document"), old->name);
+ xmlFreeNode(old);
+ goto cleanup;
+ }
+ }
+ }
+
+ /* The document should now be fully converted; write it out to a string. */
+ xmlDocDumpMemory(xml_doc, &br_xml, &br_xml_size);
+
+ if (!br_xml || br_xml_size <= 0) {
+ vshError(ctl, _("Failed to format new xml document for bridge %s"),
br_name);
+ goto cleanup;
+ }
+
+
+ /* br_xml is the new interface to define. It will automatically undefine the
+ * independent original interface.
+ */
+ if (!(br_handle = virInterfaceDefineXML(ctl->conn, (char *) br_xml, 0))) {
+ vshError(ctl, _("Failed to define new bridge interface %s"),
+ br_name);
+ goto cleanup;
+ }
+
+ vshPrint(ctl, _("Created bridge %s with attached device %s\n"),
+ br_name, if_name);
+
+ /* start it up unless requested not to */
+ if (!nostart) {
+ if (virInterfaceCreate(br_handle, 0) < 0) {
+ vshError(ctl, _("Failed to start bridge interface %s"), br_name);
+ goto cleanup;
+ }
+ vshPrint(ctl, _("Bridge interface %s started\n"), br_name);
+ }
+
+ ret = true;
+ cleanup:
+ if (if_handle)
+ virInterfaceFree(if_handle);
+ if (br_handle)
+ virInterfaceFree(br_handle);
+ VIR_FREE(if_xml);
+ VIR_FREE(br_xml);
+ VIR_FREE(if_type);
+ VIR_FREE(if2_name);
+ VIR_FREE(delay_str);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml_doc);
+ return ret;
+}
+
+/*
+ * "iface-unbridge" command
+ */
+static const vshCmdInfo info_interface_unbridge[] = {
+ {"help", N_("undefine a bridge device after detaching its slave
device")},
+ {"desc", N_("unbridge a network device")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_unbridge[] = {
+ {"bridge", VSH_OT_DATA, VSH_OFLAG_REQ, N_("current bridge device
name")},
+ {"no-start", VSH_OT_BOOL, 0,
+ N_("don't start the un-slaved interface immediately (not
recommended)")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceUnbridge(vshControl *ctl, const vshCmd *cmd)
+{
+ bool ret = false;
+ virInterfacePtr if_handle = NULL, br_handle = NULL;
+ const char *br_name;
+ char *if_type = NULL, *if_name = NULL;
+ bool nostart = false;
+ char *br_xml = NULL;
+ xmlChar *if_xml = NULL;
+ int if_xml_size;
+ xmlDocPtr xml_doc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr top_node, br_node, if_node, cur;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ /* Get a handle to the original device */
+ if (!(br_handle = vshCommandOptInterfaceBy(ctl, cmd, "bridge",
+ &br_name, VSH_BYNAME))) {
+ goto cleanup;
+ }
+
+ nostart = vshCommandOptBool(cmd, "no-start");
+
+ /* Get the bridge xml into an xmlDoc */
+ if (!(br_xml = virInterfaceGetXMLDesc(br_handle, VIR_INTERFACE_XML_INACTIVE)))
+ goto cleanup;
+ if (!(xml_doc = virXMLParseStringCtxt(br_xml,
+ _("(bridge interface definition)"),
+ &ctxt))) {
+ vshError(ctl, _("Failed to parse configuration of %s"), br_name);
+ goto cleanup;
+ }
+ top_node = ctxt->node;
+
+ /* Verify that the device really is a bridge. */
+ if (!(if_type = virXMLPropString(top_node, "type"))) {
+ vshError(ctl, _("Existing device %s has no type"), br_name);
+ goto cleanup;
+ }
+
+ if (STRNEQ(if_type, "bridge")) {
+ vshError(ctl, _("Device %s is not a bridge"), br_name);
+ goto cleanup;
+ }
+ VIR_FREE(if_type);
+
+ /* verify the name in the XML matches the device name */
+ if (!(if_name = virXMLPropString(top_node, "name")) ||
+ STRNEQ(if_name, br_name)) {
+ vshError(ctl, _("Interface name from config %s doesn't match given
supplied name %s"),
+ if_name, br_name);
+ goto cleanup;
+ }
+ VIR_FREE(if_name);
+
+ /* Find the <bridge> node under <interface>. */
+ if (!(br_node = virXPathNode("./bridge", ctxt))) {
+ vshError(ctl, "%s", _("No bridge node in xml document"));
+ goto cleanup;
+ }
+
+ if ((if_node = virXPathNode("./bridge/interface[2]", ctxt))) {
+ vshError(ctl, "%s", _("Multiple interfaces attached to
bridge"));
+ goto cleanup;
+ }
+
+ if (!(if_node = virXPathNode("./bridge/interface", ctxt))) {
+ vshError(ctl, "%s", _("No interface attached to bridge"));
+ goto cleanup;
+ }
+
+ /* Change the type and name of the outer/master interface to
+ * the type/name of the attached slave interface.
+ */
+ if (!(if_name = virXMLPropString(if_node, "name"))) {
+ vshError(ctl, _("Device attached to bridge %s has no name"), br_name);
+ goto cleanup;
+ }
+
+ if (!(if_type = virXMLPropString(if_node, "type"))) {
+ vshError(ctl, _("Attached device %s has no type"), if_name);
+ goto cleanup;
+ }
+
+ if (!xmlSetProp(top_node, BAD_CAST "type", BAD_CAST if_type)) {
+ vshError(ctl, _("Failed to set interface type to '%s' in xml
document"),
+ if_type);
+ goto cleanup;
+ }
+
+ if (!xmlSetProp(top_node, BAD_CAST "name", BAD_CAST if_name)) {
+ vshError(ctl, _("Failed to set interface name to '%s' in xml
document"),
+ if_name);
+ goto cleanup;
+ }
+
+ /* Cycle through all the nodes under the attached <interface>,
+ * moving all <mac>, <bond> and <vlan> nodes up into the toplevel
+ * <interface>.
+ */
+ cur = if_node->children;
+ while (cur) {
+ xmlNodePtr old = cur;
+
+ cur = cur->next;
+ if ((old->type == XML_ELEMENT_NODE) &&
+ (xmlStrEqual(old->name, BAD_CAST "mac") || /* ethernet stuff to
move down */
+ xmlStrEqual(old->name, BAD_CAST "bond") || /* bond stuff to
move down */
+ xmlStrEqual(old->name, BAD_CAST "vlan"))) { /* vlan stuff to
move down */
+ xmlUnlinkNode(old);
+ if (!xmlAddChild(top_node, old)) {
+ vshError(ctl, _("Failed to move '%s' element in xml
document"), old->name);
+ xmlFreeNode(old);
+ goto cleanup;
+ }
+ }
+ }
+
+ /* The document should now be fully converted; write it out to a string. */
+ xmlDocDumpMemory(xml_doc, &if_xml, &if_xml_size);
+
+ if (!if_xml || if_xml_size <= 0) {
+ vshError(ctl, _("Failed to format new xml document for un-enslaved interface
%s"),
+ if_name);
+ goto cleanup;
+ }
+
+ /* Destroy and Undefine the bridge device, since we otherwise
+ * can't safely define the unattached device.
+ */
+ if (virInterfaceDestroy(br_handle, 0) < 0) {
+ vshError(ctl, _("Failed to destroy bridge interface %s"), br_name);
+ goto cleanup;
+ }
+ if (virInterfaceUndefine(br_handle) < 0) {
+ vshError(ctl, _("Failed to undefine bridge interface %s"), br_name);
+ goto cleanup;
+ }
+
+ /* if_xml is the new interface to define.
+ */
+ if (!(if_handle = virInterfaceDefineXML(ctl->conn, (char *) if_xml, 0))) {
+ vshError(ctl, _("Failed to define new interface %s"), if_name);
+ goto cleanup;
+ }
+
+ vshPrint(ctl, _("Device %s un-attached from bridge %s\n"),
+ if_name, br_name);
+
+ /* unless requested otherwise, undefine the bridge device */
+ if (!nostart) {
+ if (virInterfaceCreate(if_handle, 0) < 0) {
+ vshError(ctl, _("Failed to start interface %s"), if_name);
+ goto cleanup;
+ }
+ vshPrint(ctl, _("Interface %s started\n"), if_name);
+ }
+
+ ret = true;
+ cleanup:
+ if (if_handle)
+ virInterfaceFree(if_handle);
+ if (br_handle)
+ virInterfaceFree(br_handle);
+ VIR_FREE(if_xml);
+ VIR_FREE(br_xml);
+ VIR_FREE(if_type);
+ VIR_FREE(if_name);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml_doc);
+ return ret;
+}
diff --git a/tools/virsh.c b/tools/virsh.c
index 220aa1d..23b2ec9 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -347,15 +347,6 @@ static virNWFilterPtr vshCommandOptNWFilterBy(vshControl *ctl, const
vshCmd *cmd
vshCommandOptNWFilterBy(_ctl, _cmd, _name, \
VSH_BYUUID|VSH_BYNAME)
-static virInterfacePtr vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char **name, int flag);
-
-/* default is lookup by Name and MAC */
-#define vshCommandOptInterface(_ctl, _cmd, _name) \
- vshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \
- VSH_BYMAC|VSH_BYNAME)
-
static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd,
const char **name);
@@ -1019,1180 +1010,249 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptInt(cmd, "cpu", &cpuNum) < 0) {
vshError(ctl, "%s", _("Invalid value of cpuNum"));
- return false;
- }
-
- if (virNodeGetCPUStats(ctl->conn, cpuNum, NULL, &nparams, 0) != 0) {
- vshError(ctl, "%s",
- _("Unable to get number of cpu stats"));
- return false;
- }
- if (nparams == 0) {
- /* nothing to output */
- return true;
- }
-
- memset(cpu_stats, 0, sizeof(cpu_stats));
- params = vshCalloc(ctl, nparams, sizeof(*params));
-
- for (i = 0; i < 2; i++) {
- if (i > 0)
- sleep(1);
-
- if (virNodeGetCPUStats(ctl->conn, cpuNum, params, &nparams, 0) != 0) {
- vshError(ctl, "%s", _("Unable to get node cpu stats"));
- goto cleanup;
- }
-
- for (j = 0; j < nparams; j++) {
- unsigned long long value = params[j].value;
-
- if (STREQ(params[j].field, VIR_NODE_CPU_STATS_KERNEL)) {
- cpu_stats[i].sys = value;
- } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_USER)) {
- cpu_stats[i].user = value;
- } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IDLE)) {
- cpu_stats[i].idle = value;
- } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IOWAIT)) {
- cpu_stats[i].iowait = value;
- } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_UTILIZATION)) {
- cpu_stats[i].util = value;
- flag_utilization = true;
- }
- }
-
- if (flag_utilization || !flag_percent)
- break;
- }
-
- if (!flag_percent) {
- if (!flag_utilization) {
- vshPrint(ctl, "%-15s %20llu\n", _("user:"),
cpu_stats[0].user);
- vshPrint(ctl, "%-15s %20llu\n", _("system:"),
cpu_stats[0].sys);
- vshPrint(ctl, "%-15s %20llu\n", _("idle:"),
cpu_stats[0].idle);
- vshPrint(ctl, "%-15s %20llu\n", _("iowait:"),
cpu_stats[0].iowait);
- }
- } else {
- if (flag_utilization) {
- usage = cpu_stats[0].util;
-
- vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage);
- vshPrint(ctl, "%-15s %5.1lf%%\n", _("idle:"), 100 -
usage);
- } else {
- user_time = cpu_stats[1].user - cpu_stats[0].user;
- sys_time = cpu_stats[1].sys - cpu_stats[0].sys;
- idle_time = cpu_stats[1].idle - cpu_stats[0].idle;
- iowait_time = cpu_stats[1].iowait - cpu_stats[0].iowait;
- total_time = user_time + sys_time + idle_time + iowait_time;
-
- usage = (user_time + sys_time) / total_time * 100;
-
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("usage:"), usage);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("user:"), user_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("system:"), sys_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("idle:"), idle_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("iowait:"), iowait_time / total_time * 100);
- }
- }
-
- ret = true;
-
- cleanup:
- VIR_FREE(params);
- return ret;
-}
-
-/*
- * "nodememstats" command
- */
-static const vshCmdInfo info_nodememstats[] = {
- {"help", N_("Prints memory stats of the node.")},
- {"desc", N_("Returns memory stats of the node, in kilobytes.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_node_memstats[] = {
- {"cell", VSH_OT_INT, 0, N_("prints specified cell statistics
only.")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd)
-{
- int nparams = 0;
- unsigned int i = 0;
- int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS;
- virNodeMemoryStatsPtr params = NULL;
- bool ret = false;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (vshCommandOptInt(cmd, "cell", &cellNum) < 0) {
- vshError(ctl, "%s", _("Invalid value of cellNum"));
- return false;
- }
-
- /* get the number of memory parameters */
- if (virNodeGetMemoryStats(ctl->conn, cellNum, NULL, &nparams, 0) != 0) {
- vshError(ctl, "%s",
- _("Unable to get number of memory stats"));
- goto cleanup;
- }
-
- if (nparams == 0) {
- /* nothing to output */
- ret = true;
- goto cleanup;
- }
-
- /* now go get all the memory parameters */
- params = vshCalloc(ctl, nparams, sizeof(*params));
- if (virNodeGetMemoryStats(ctl->conn, cellNum, params, &nparams, 0) != 0) {
- vshError(ctl, "%s", _("Unable to get memory stats"));
- goto cleanup;
- }
-
- for (i = 0; i < nparams; i++)
- vshPrint(ctl, "%-7s: %20llu KiB\n", params[i].field, params[i].value);
-
- ret = true;
-
- cleanup:
- VIR_FREE(params);
- return ret;
-}
-
-/*
- * "nodesuspend" command
- */
-static const vshCmdInfo info_nodesuspend[] = {
- {"help", N_("suspend the host node for a given time duration")},
- {"desc", N_("Suspend the host node for a given time duration "
- "and attempt to resume thereafter.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_node_suspend[] = {
- {"target", VSH_OT_DATA, VSH_OFLAG_REQ, N_("mem(Suspend-to-RAM),
"
- "disk(Suspend-to-Disk),
hybrid(Hybrid-Suspend)")},
- {"duration", VSH_OT_INT, VSH_OFLAG_REQ, N_("Suspend duration in
seconds")},
- {"flags", VSH_OT_INT, VSH_OFLAG_NONE, N_("Suspend flags, 0 for
default")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd)
-{
- const char *target = NULL;
- unsigned int suspendTarget;
- long long duration;
- unsigned int flags = 0;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (vshCommandOptString(cmd, "target", &target) < 0) {
- vshError(ctl, _("Invalid target argument"));
- return false;
- }
-
- if (vshCommandOptLongLong(cmd, "duration", &duration) < 0) {
- vshError(ctl, _("Invalid duration argument"));
- return false;
- }
-
- if (vshCommandOptUInt(cmd, "flags", &flags) < 0) {
- vshError(ctl, _("Invalid flags argument"));
- return false;
- }
-
- if (STREQ(target, "mem"))
- suspendTarget = VIR_NODE_SUSPEND_TARGET_MEM;
- else if (STREQ(target, "disk"))
- suspendTarget = VIR_NODE_SUSPEND_TARGET_DISK;
- else if (STREQ(target, "hybrid"))
- suspendTarget = VIR_NODE_SUSPEND_TARGET_HYBRID;
- else {
- vshError(ctl, "%s", _("Invalid target"));
- return false;
- }
-
- if (duration <= 0) {
- vshError(ctl, "%s", _("Invalid duration"));
- return false;
- }
-
- if (virNodeSuspendForDuration(ctl->conn, suspendTarget, duration,
- flags) < 0) {
- vshError(ctl, "%s", _("The host was not suspended"));
- return false;
- }
- return true;
-}
-
-
-/*
- * "capabilities" command
- */
-static const vshCmdInfo info_capabilities[] = {
- {"help", N_("capabilities")},
- {"desc", N_("Returns capabilities of hypervisor/driver.")},
- {NULL, NULL}
-};
-
-static bool
-cmdCapabilities(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- char *caps;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if ((caps = virConnectGetCapabilities(ctl->conn)) == NULL) {
- vshError(ctl, "%s", _("failed to get capabilities"));
- return false;
- }
- vshPrint(ctl, "%s\n", caps);
- VIR_FREE(caps);
-
- return true;
-}
-
-/*
- * "iface-edit" command
- */
-static const vshCmdInfo info_interface_edit[] = {
- {"help", N_("edit XML configuration for a physical host
interface")},
- {"desc", N_("Edit the XML configuration for a physical host
interface.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_edit[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd)
-{
- bool ret = false;
- virInterfacePtr iface = NULL;
- virInterfacePtr iface_edited = NULL;
- unsigned int flags = VIR_INTERFACE_XML_INACTIVE;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- goto cleanup;
-
- iface = vshCommandOptInterface(ctl, cmd, NULL);
- if (iface == NULL)
- goto cleanup;
-
-#define EDIT_GET_XML virInterfaceGetXMLDesc(iface, flags)
-#define EDIT_NOT_CHANGED \
- vshPrint(ctl, _("Interface %s XML configuration not changed.\n"), \
- virInterfaceGetName(iface)); \
- ret = true; goto edit_cleanup;
-#define EDIT_DEFINE \
- (iface_edited = virInterfaceDefineXML(ctl->conn, doc_edited, 0))
-#define EDIT_FREE \
- if (iface_edited) \
- virInterfaceFree(iface_edited);
-#include "virsh-edit.c"
-
- vshPrint(ctl, _("Interface %s XML configuration edited.\n"),
- virInterfaceGetName(iface_edited));
-
- ret = true;
-
-cleanup:
- if (iface)
- virInterfaceFree(iface);
- if (iface_edited)
- virInterfaceFree(iface_edited);
-
- return ret;
-}
-
-/**************************************************************************/
-/*
- * "iface-list" command
- */
-static const vshCmdInfo info_interface_list[] = {
- {"help", N_("list physical host interfaces")},
- {"desc", N_("Returns list of physical host interfaces.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_list[] = {
- {"inactive", VSH_OT_BOOL, 0, N_("list inactive interfaces")},
- {"all", VSH_OT_BOOL, 0, N_("list inactive & active
interfaces")},
- {NULL, 0, 0, NULL}
-};
-static bool
-cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- bool inactive = vshCommandOptBool(cmd, "inactive");
- bool all = vshCommandOptBool(cmd, "all");
- bool active = !inactive || all;
- int maxactive = 0, maxinactive = 0, i;
- char **activeNames = NULL, **inactiveNames = NULL;
- inactive |= all;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (active) {
- maxactive = virConnectNumOfInterfaces(ctl->conn);
- if (maxactive < 0) {
- vshError(ctl, "%s", _("Failed to list active
interfaces"));
- return false;
- }
- if (maxactive) {
- activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
-
- if ((maxactive = virConnectListInterfaces(ctl->conn, activeNames,
- maxactive)) < 0) {
- vshError(ctl, "%s", _("Failed to list active
interfaces"));
- VIR_FREE(activeNames);
- return false;
- }
-
- qsort(&activeNames[0], maxactive, sizeof(char *), vshNameSorter);
- }
- }
- if (inactive) {
- maxinactive = virConnectNumOfDefinedInterfaces(ctl->conn);
- if (maxinactive < 0) {
- vshError(ctl, "%s", _("Failed to list inactive
interfaces"));
- VIR_FREE(activeNames);
- return false;
- }
- if (maxinactive) {
- inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
-
- if ((maxinactive =
- virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
- maxinactive)) < 0) {
- vshError(ctl, "%s", _("Failed to list inactive
interfaces"));
- VIR_FREE(activeNames);
- VIR_FREE(inactiveNames);
- return false;
- }
-
- qsort(&inactiveNames[0], maxinactive, sizeof(char*), vshNameSorter);
- }
- }
- vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"),
_("State"),
- _("MAC Address"));
- vshPrintExtra(ctl, "--------------------------------------------\n");
-
- for (i = 0; i < maxactive; i++) {
- virInterfacePtr iface =
- virInterfaceLookupByName(ctl->conn, activeNames[i]);
-
- /* this kind of work with interfaces is not atomic */
- if (!iface) {
- VIR_FREE(activeNames[i]);
- continue;
- }
-
- vshPrint(ctl, "%-20s %-10s %s\n",
- virInterfaceGetName(iface),
- _("active"),
- virInterfaceGetMACString(iface));
- virInterfaceFree(iface);
- VIR_FREE(activeNames[i]);
- }
- for (i = 0; i < maxinactive; i++) {
- virInterfacePtr iface =
- virInterfaceLookupByName(ctl->conn, inactiveNames[i]);
-
- /* this kind of work with interfaces is not atomic */
- if (!iface) {
- VIR_FREE(inactiveNames[i]);
- continue;
- }
-
- vshPrint(ctl, "%-20s %-10s %s\n",
- virInterfaceGetName(iface),
- _("inactive"),
- virInterfaceGetMACString(iface));
- virInterfaceFree(iface);
- VIR_FREE(inactiveNames[i]);
- }
- VIR_FREE(activeNames);
- VIR_FREE(inactiveNames);
- return true;
-
-}
-
-/*
- * "iface-name" command
- */
-static const vshCmdInfo info_interface_name[] = {
- {"help", N_("convert an interface MAC address to interface
name")},
- {"desc", ""},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_name[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface mac")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
- if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
- VSH_BYMAC)))
- return false;
-
- vshPrint(ctl, "%s\n", virInterfaceGetName(iface));
- virInterfaceFree(iface);
- return true;
-}
-
-/*
- * "iface-mac" command
- */
-static const vshCmdInfo info_interface_mac[] = {
- {"help", N_("convert an interface name to interface MAC
address")},
- {"desc", ""},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_mac[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
- if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
- VSH_BYNAME)))
- return false;
-
- vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface));
- virInterfaceFree(iface);
- return true;
-}
-
-/*
- * "iface-dumpxml" command
- */
-static const vshCmdInfo info_interface_dumpxml[] = {
- {"help", N_("interface information in XML")},
- {"desc", N_("Output the physical host interface information as an XML
dump to stdout.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_dumpxml[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
- {"inactive", VSH_OT_BOOL, 0, N_("show inactive defined XML")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
- bool ret = true;
- char *dump;
- unsigned int flags = 0;
- bool inactive = vshCommandOptBool(cmd, "inactive");
-
- if (inactive)
- flags |= VIR_INTERFACE_XML_INACTIVE;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
- return false;
-
- dump = virInterfaceGetXMLDesc(iface, flags);
- if (dump != NULL) {
- vshPrint(ctl, "%s", dump);
- VIR_FREE(dump);
- } else {
- ret = false;
- }
-
- virInterfaceFree(iface);
- return ret;
-}
-
-/*
- * "iface-define" command
- */
-static const vshCmdInfo info_interface_define[] = {
- {"help", N_("define (but don't start) a physical host interface
from an XML file")},
- {"desc", N_("Define a physical host interface.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_define[] = {
- {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML
interface description")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
- const char *from = NULL;
- bool ret = true;
- char *buffer;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (vshCommandOptString(cmd, "file", &from) <= 0)
- return false;
-
- if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
- return false;
-
- iface = virInterfaceDefineXML(ctl->conn, buffer, 0);
- VIR_FREE(buffer);
-
- if (iface != NULL) {
- vshPrint(ctl, _("Interface %s defined from %s\n"),
- virInterfaceGetName(iface), from);
- virInterfaceFree(iface);
- } else {
- vshError(ctl, _("Failed to define interface from %s"), from);
- ret = false;
- }
- return ret;
-}
-
-/*
- * "iface-undefine" command
- */
-static const vshCmdInfo info_interface_undefine[] = {
- {"help", N_("undefine a physical host interface (remove it from
configuration)")},
- {"desc", N_("undefine an interface.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_undefine[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
- bool ret = true;
- const char *name;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
- return false;
-
- if (virInterfaceUndefine(iface) == 0) {
- vshPrint(ctl, _("Interface %s undefined\n"), name);
- } else {
- vshError(ctl, _("Failed to undefine interface %s"), name);
- ret = false;
- }
-
- virInterfaceFree(iface);
- return ret;
-}
-
-/*
- * "iface-start" command
- */
-static const vshCmdInfo info_interface_start[] = {
- {"help", N_("start a physical host interface (enable it /
\"if-up\")")},
- {"desc", N_("start a physical host interface.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_start[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
- bool ret = true;
- const char *name;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
- return false;
-
- if (virInterfaceCreate(iface, 0) == 0) {
- vshPrint(ctl, _("Interface %s started\n"), name);
- } else {
- vshError(ctl, _("Failed to start interface %s"), name);
- ret = false;
- }
-
- virInterfaceFree(iface);
- return ret;
-}
-
-/*
- * "iface-destroy" command
- */
-static const vshCmdInfo info_interface_destroy[] = {
- {"help", N_("destroy a physical host interface (disable it /
\"if-down\")")},
- {"desc", N_("forcefully stop a physical host interface.")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_destroy[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC
address")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd)
-{
- virInterfacePtr iface;
- bool ret = true;
- const char *name;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
- return false;
-
- if (virInterfaceDestroy(iface, 0) == 0) {
- vshPrint(ctl, _("Interface %s destroyed\n"), name);
- } else {
- vshError(ctl, _("Failed to destroy interface %s"), name);
- ret = false;
- }
-
- virInterfaceFree(iface);
- return ret;
-}
-
-/*
- * "iface-begin" command
- */
-static const vshCmdInfo info_interface_begin[] = {
- {"help", N_("create a snapshot of current interfaces settings, "
- "which can be later committed (iface-commit) or "
- "restored (iface-rollback)")},
- {"desc", N_("Create a restore point for interfaces settings")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_begin[] = {
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceBegin(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (virInterfaceChangeBegin(ctl->conn, 0) < 0) {
- vshError(ctl, "%s", _("Failed to begin network config change
transaction"));
- return false;
- }
-
- vshPrint(ctl, "%s", _("Network config change transaction
started\n"));
- return true;
-}
-
-/*
- * "iface-commit" command
- */
-static const vshCmdInfo info_interface_commit[] = {
- {"help", N_("commit changes made since iface-begin and free restore
point")},
- {"desc", N_("commit changes and free restore point")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_commit[] = {
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceCommit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (virInterfaceChangeCommit(ctl->conn, 0) < 0) {
- vshError(ctl, "%s", _("Failed to commit network config change
transaction"));
- return false;
- }
-
- vshPrint(ctl, "%s", _("Network config change transaction
committed\n"));
- return true;
-}
-
-/*
- * "iface-rollback" command
- */
-static const vshCmdInfo info_interface_rollback[] = {
- {"help", N_("rollback to previous saved configuration created via
iface-begin")},
- {"desc", N_("rollback to previous restore point")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_rollback[] = {
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceRollback(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
- if (!vshConnectionUsability(ctl, ctl->conn))
- return false;
-
- if (virInterfaceChangeRollback(ctl->conn, 0) < 0) {
- vshError(ctl, "%s", _("Failed to rollback network config change
transaction"));
- return false;
- }
-
- vshPrint(ctl, "%s", _("Network config change transaction rolled
back\n"));
- return true;
-}
-
-/*
- * "iface-bridge" command
- */
-static const vshCmdInfo info_interface_bridge[] = {
- {"help", N_("create a bridge device and attach an existing network
device to it")},
- {"desc", N_("bridge an existing network device")},
- {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_interface_bridge[] = {
- {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("existing interface
name")},
- {"bridge", VSH_OT_DATA, VSH_OFLAG_REQ, N_("new bridge device
name")},
- {"no-stp", VSH_OT_BOOL, 0, N_("do not enable STP for this
bridge")},
- {"delay", VSH_OT_INT, 0,
- N_("number of seconds to squelch traffic on newly connected ports")},
- {"no-start", VSH_OT_BOOL, 0, N_("don't start the bridge
immediately")},
- {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd)
-{
- bool ret = false;
- virInterfacePtr if_handle = NULL, br_handle = NULL;
- const char *if_name, *br_name;
- char *if_type = NULL, *if2_name = NULL, *delay_str = NULL;
- bool stp = false, nostart = false;
- unsigned int delay = 0;
- char *if_xml = NULL;
- xmlChar *br_xml = NULL;
- int br_xml_size;
- xmlDocPtr xml_doc = NULL;
- xmlXPathContextPtr ctxt = NULL;
- xmlNodePtr top_node, br_node, if_node, cur;
-
- if (!vshConnectionUsability(ctl, ctl->conn))
- goto cleanup;
-
- /* Get a handle to the original device */
- if (!(if_handle = vshCommandOptInterfaceBy(ctl, cmd, "interface",
- &if_name, VSH_BYNAME))) {
- goto cleanup;
- }
-
- /* Name for new bridge device */
- if (vshCommandOptString(cmd, "bridge", &br_name) <= 0) {
- vshError(ctl, "%s", _("Missing bridge device name in
command"));
- goto cleanup;
- }
-
- /* make sure "new" device doesn't already exist */
- if ((br_handle = virInterfaceLookupByName(ctl->conn, br_name))) {
- vshError(ctl, _("Network device %s already exists"), br_name);
- goto cleanup;
- }
-
- /* use "no-stp" because we want "stp" to default true */
- stp = !vshCommandOptBool(cmd, "no-stp");
-
- if (vshCommandOptUInt(cmd, "delay", &delay) < 0) {
- vshError(ctl, "%s", _("Unable to parse delay parameter"));
- goto cleanup;
- }
-
- nostart = vshCommandOptBool(cmd, "no-start");
-
- /* Get the original interface into an xmlDoc */
- if (!(if_xml = virInterfaceGetXMLDesc(if_handle, VIR_INTERFACE_XML_INACTIVE)))
- goto cleanup;
- if (!(xml_doc = virXMLParseStringCtxt(if_xml,
- _("(interface definition)"),
&ctxt))) {
- vshError(ctl, _("Failed to parse configuration of %s"), if_name);
- goto cleanup;
- }
- top_node = ctxt->node;
-
- /* Verify that the original device isn't already a bridge. */
- if (!(if_type = virXMLPropString(top_node, "type"))) {
- vshError(ctl, _("Existing device %s has no type"), if_name);
- goto cleanup;
- }
-
- if (STREQ(if_type, "bridge")) {
- vshError(ctl, _("Existing device %s is already a bridge"), if_name);
- goto cleanup;
- }
-
- /* verify the name in the XML matches the device name */
- if (!(if2_name = virXMLPropString(top_node, "name")) ||
- STRNEQ(if2_name, if_name)) {
- vshError(ctl, _("Interface name from config %s doesn't match given
supplied name %s"),
- if2_name, if_name);
- goto cleanup;
- }
-
- /* Create a <bridge> node under <interface>. */
- if (!(br_node = xmlNewChild(top_node, NULL, BAD_CAST "bridge", NULL))) {
- vshError(ctl, "%s", _("Failed to create bridge node in xml
document"));
- goto cleanup;
- }
-
- /* Set stp and delay attributes in <bridge> according to the
- * commandline options.
- */
- if (!xmlSetProp(br_node, BAD_CAST "stp", BAD_CAST (stp ? "on" :
"off"))) {
- vshError(ctl, "%s", _("Failed to set stp attribute in xml
document"));
- goto cleanup;
- }
-
- if ((delay || stp) &&
- ((virAsprintf(&delay_str, "%d", delay) < 0) ||
- !xmlSetProp(br_node, BAD_CAST "delay", BAD_CAST delay_str))) {
- vshError(ctl, _("Failed to set bridge delay %d in xml document"),
delay);
- goto cleanup;
- }
-
- /* Change the type of the outer/master interface to "bridge" and the
- * name to the provided bridge name.
- */
- if (!xmlSetProp(top_node, BAD_CAST "type", BAD_CAST "bridge")) {
- vshError(ctl, "%s", _("Failed to set bridge interface type to
'bridge' in xml document"));
- goto cleanup;
+ return false;
}
- if (!xmlSetProp(top_node, BAD_CAST "name", BAD_CAST br_name)) {
- vshError(ctl, _("Failed to set master bridge interface name to '%s'
in xml document"),
- br_name);
- goto cleanup;
+ if (virNodeGetCPUStats(ctl->conn, cpuNum, NULL, &nparams, 0) != 0) {
+ vshError(ctl, "%s",
+ _("Unable to get number of cpu stats"));
+ return false;
}
-
- /* Create an <interface> node under <bridge> that uses the
- * original interface's type and name.
- */
- if (!(if_node = xmlNewChild(br_node, NULL, BAD_CAST "interface", NULL))) {
- vshError(ctl, "%s", _("Failed to create interface node under
bridge node in xml document"));
- goto cleanup;
+ if (nparams == 0) {
+ /* nothing to output */
+ return true;
}
- /* set the type of the inner/slave interface to the original
- * if_type, and the name to the original if_name.
- */
- if (!xmlSetProp(if_node, BAD_CAST "type", BAD_CAST if_type)) {
- vshError(ctl, _("Failed to set new slave interface type to '%s' in
xml document"),
- if_name);
- goto cleanup;
- }
+ memset(cpu_stats, 0, sizeof(cpu_stats));
+ params = vshCalloc(ctl, nparams, sizeof(*params));
- if (!xmlSetProp(if_node, BAD_CAST "name", BAD_CAST if_name)) {
- vshError(ctl, _("Failed to set new slave interface name to '%s' in
xml document"),
- br_name);
- goto cleanup;
- }
+ for (i = 0; i < 2; i++) {
+ if (i > 0)
+ sleep(1);
- /* Cycle through all the nodes under the original <interface>,
- * moving all <mac>, <bond> and <vlan> nodes down into the new
- * lower level <interface>.
- */
- cur = top_node->children;
- while (cur) {
- xmlNodePtr old = cur;
-
- cur = cur->next;
- if ((old->type == XML_ELEMENT_NODE) &&
- (xmlStrEqual(old->name, BAD_CAST "mac") || /* ethernet stuff to
move down */
- xmlStrEqual(old->name, BAD_CAST "bond") || /* bond stuff to
move down */
- xmlStrEqual(old->name, BAD_CAST "vlan"))) { /* vlan stuff to
move down */
- xmlUnlinkNode(old);
- if (!xmlAddChild(if_node, old)) {
- vshError(ctl, _("Failed to move '%s' element in xml
document"), old->name);
- xmlFreeNode(old);
- goto cleanup;
- }
+ if (virNodeGetCPUStats(ctl->conn, cpuNum, params, &nparams, 0) != 0) {
+ vshError(ctl, "%s", _("Unable to get node cpu stats"));
+ goto cleanup;
}
- }
- /* The document should now be fully converted; write it out to a string. */
- xmlDocDumpMemory(xml_doc, &br_xml, &br_xml_size);
+ for (j = 0; j < nparams; j++) {
+ unsigned long long value = params[j].value;
- if (!br_xml || br_xml_size <= 0) {
- vshError(ctl, _("Failed to format new xml document for bridge %s"),
br_name);
- goto cleanup;
+ if (STREQ(params[j].field, VIR_NODE_CPU_STATS_KERNEL)) {
+ cpu_stats[i].sys = value;
+ } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_USER)) {
+ cpu_stats[i].user = value;
+ } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IDLE)) {
+ cpu_stats[i].idle = value;
+ } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IOWAIT)) {
+ cpu_stats[i].iowait = value;
+ } else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_UTILIZATION)) {
+ cpu_stats[i].util = value;
+ flag_utilization = true;
+ }
+ }
+
+ if (flag_utilization || !flag_percent)
+ break;
}
+ if (!flag_percent) {
+ if (!flag_utilization) {
+ vshPrint(ctl, "%-15s %20llu\n", _("user:"),
cpu_stats[0].user);
+ vshPrint(ctl, "%-15s %20llu\n", _("system:"),
cpu_stats[0].sys);
+ vshPrint(ctl, "%-15s %20llu\n", _("idle:"),
cpu_stats[0].idle);
+ vshPrint(ctl, "%-15s %20llu\n", _("iowait:"),
cpu_stats[0].iowait);
+ }
+ } else {
+ if (flag_utilization) {
+ usage = cpu_stats[0].util;
- /* br_xml is the new interface to define. It will automatically undefine the
- * independent original interface.
- */
- if (!(br_handle = virInterfaceDefineXML(ctl->conn, (char *) br_xml, 0))) {
- vshError(ctl, _("Failed to define new bridge interface %s"),
- br_name);
- goto cleanup;
- }
+ vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage);
+ vshPrint(ctl, "%-15s %5.1lf%%\n", _("idle:"), 100 -
usage);
+ } else {
+ user_time = cpu_stats[1].user - cpu_stats[0].user;
+ sys_time = cpu_stats[1].sys - cpu_stats[0].sys;
+ idle_time = cpu_stats[1].idle - cpu_stats[0].idle;
+ iowait_time = cpu_stats[1].iowait - cpu_stats[0].iowait;
+ total_time = user_time + sys_time + idle_time + iowait_time;
- vshPrint(ctl, _("Created bridge %s with attached device %s\n"),
- br_name, if_name);
+ usage = (user_time + sys_time) / total_time * 100;
- /* start it up unless requested not to */
- if (!nostart) {
- if (virInterfaceCreate(br_handle, 0) < 0) {
- vshError(ctl, _("Failed to start bridge interface %s"), br_name);
- goto cleanup;
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("usage:"), usage);
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("user:"), user_time / total_time * 100);
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("system:"), sys_time / total_time * 100);
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("idle:"), idle_time / total_time * 100);
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("iowait:"), iowait_time / total_time * 100);
}
- vshPrint(ctl, _("Bridge interface %s started\n"), br_name);
}
ret = true;
- cleanup:
- if (if_handle)
- virInterfaceFree(if_handle);
- if (br_handle)
- virInterfaceFree(br_handle);
- VIR_FREE(if_xml);
- VIR_FREE(br_xml);
- VIR_FREE(if_type);
- VIR_FREE(if2_name);
- VIR_FREE(delay_str);
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(xml_doc);
+
+ cleanup:
+ VIR_FREE(params);
return ret;
}
/*
- * "iface-unbridge" command
+ * "nodememstats" command
*/
-static const vshCmdInfo info_interface_unbridge[] = {
- {"help", N_("undefine a bridge device after detaching its slave
device")},
- {"desc", N_("unbridge a network device")},
+static const vshCmdInfo info_nodememstats[] = {
+ {"help", N_("Prints memory stats of the node.")},
+ {"desc", N_("Returns memory stats of the node, in kilobytes.")},
{NULL, NULL}
};
-static const vshCmdOptDef opts_interface_unbridge[] = {
- {"bridge", VSH_OT_DATA, VSH_OFLAG_REQ, N_("current bridge device
name")},
- {"no-start", VSH_OT_BOOL, 0,
- N_("don't start the un-slaved interface immediately (not
recommended)")},
+static const vshCmdOptDef opts_node_memstats[] = {
+ {"cell", VSH_OT_INT, 0, N_("prints specified cell statistics
only.")},
{NULL, 0, 0, NULL}
};
static bool
-cmdInterfaceUnbridge(vshControl *ctl, const vshCmd *cmd)
+cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd)
{
+ int nparams = 0;
+ unsigned int i = 0;
+ int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS;
+ virNodeMemoryStatsPtr params = NULL;
bool ret = false;
- virInterfacePtr if_handle = NULL, br_handle = NULL;
- const char *br_name;
- char *if_type = NULL, *if_name = NULL;
- bool nostart = false;
- char *br_xml = NULL;
- xmlChar *if_xml = NULL;
- int if_xml_size;
- xmlDocPtr xml_doc = NULL;
- xmlXPathContextPtr ctxt = NULL;
- xmlNodePtr top_node, br_node, if_node, cur;
if (!vshConnectionUsability(ctl, ctl->conn))
- goto cleanup;
+ return false;
- /* Get a handle to the original device */
- if (!(br_handle = vshCommandOptInterfaceBy(ctl, cmd, "bridge",
- &br_name, VSH_BYNAME))) {
- goto cleanup;
+ if (vshCommandOptInt(cmd, "cell", &cellNum) < 0) {
+ vshError(ctl, "%s", _("Invalid value of cellNum"));
+ return false;
}
- nostart = vshCommandOptBool(cmd, "no-start");
-
- /* Get the bridge xml into an xmlDoc */
- if (!(br_xml = virInterfaceGetXMLDesc(br_handle, VIR_INTERFACE_XML_INACTIVE)))
- goto cleanup;
- if (!(xml_doc = virXMLParseStringCtxt(br_xml,
- _("(bridge interface definition)"),
- &ctxt))) {
- vshError(ctl, _("Failed to parse configuration of %s"), br_name);
+ /* get the number of memory parameters */
+ if (virNodeGetMemoryStats(ctl->conn, cellNum, NULL, &nparams, 0) != 0) {
+ vshError(ctl, "%s",
+ _("Unable to get number of memory stats"));
goto cleanup;
}
- top_node = ctxt->node;
- /* Verify that the device really is a bridge. */
- if (!(if_type = virXMLPropString(top_node, "type"))) {
- vshError(ctl, _("Existing device %s has no type"), br_name);
+ if (nparams == 0) {
+ /* nothing to output */
+ ret = true;
goto cleanup;
}
- if (STRNEQ(if_type, "bridge")) {
- vshError(ctl, _("Device %s is not a bridge"), br_name);
+ /* now go get all the memory parameters */
+ params = vshCalloc(ctl, nparams, sizeof(*params));
+ if (virNodeGetMemoryStats(ctl->conn, cellNum, params, &nparams, 0) != 0) {
+ vshError(ctl, "%s", _("Unable to get memory stats"));
goto cleanup;
}
- VIR_FREE(if_type);
- /* verify the name in the XML matches the device name */
- if (!(if_name = virXMLPropString(top_node, "name")) ||
- STRNEQ(if_name, br_name)) {
- vshError(ctl, _("Interface name from config %s doesn't match given
supplied name %s"),
- if_name, br_name);
- goto cleanup;
- }
- VIR_FREE(if_name);
+ for (i = 0; i < nparams; i++)
+ vshPrint(ctl, "%-7s: %20llu KiB\n", params[i].field, params[i].value);
- /* Find the <bridge> node under <interface>. */
- if (!(br_node = virXPathNode("./bridge", ctxt))) {
- vshError(ctl, "%s", _("No bridge node in xml document"));
- goto cleanup;
- }
+ ret = true;
- if ((if_node = virXPathNode("./bridge/interface[2]", ctxt))) {
- vshError(ctl, "%s", _("Multiple interfaces attached to
bridge"));
- goto cleanup;
- }
+ cleanup:
+ VIR_FREE(params);
+ return ret;
+}
- if (!(if_node = virXPathNode("./bridge/interface", ctxt))) {
- vshError(ctl, "%s", _("No interface attached to bridge"));
- goto cleanup;
- }
+/*
+ * "nodesuspend" command
+ */
+static const vshCmdInfo info_nodesuspend[] = {
+ {"help", N_("suspend the host node for a given time duration")},
+ {"desc", N_("Suspend the host node for a given time duration "
+ "and attempt to resume thereafter.")},
+ {NULL, NULL}
+};
- /* Change the type and name of the outer/master interface to
- * the type/name of the attached slave interface.
- */
- if (!(if_name = virXMLPropString(if_node, "name"))) {
- vshError(ctl, _("Device attached to bridge %s has no name"), br_name);
- goto cleanup;
- }
+static const vshCmdOptDef opts_node_suspend[] = {
+ {"target", VSH_OT_DATA, VSH_OFLAG_REQ, N_("mem(Suspend-to-RAM),
"
+ "disk(Suspend-to-Disk),
hybrid(Hybrid-Suspend)")},
+ {"duration", VSH_OT_INT, VSH_OFLAG_REQ, N_("Suspend duration in
seconds")},
+ {"flags", VSH_OT_INT, VSH_OFLAG_NONE, N_("Suspend flags, 0 for
default")},
+ {NULL, 0, 0, NULL}
+};
- if (!(if_type = virXMLPropString(if_node, "type"))) {
- vshError(ctl, _("Attached device %s has no type"), if_name);
- goto cleanup;
- }
+static bool
+cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *target = NULL;
+ unsigned int suspendTarget;
+ long long duration;
+ unsigned int flags = 0;
- if (!xmlSetProp(top_node, BAD_CAST "type", BAD_CAST if_type)) {
- vshError(ctl, _("Failed to set interface type to '%s' in xml
document"),
- if_type);
- goto cleanup;
- }
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
- if (!xmlSetProp(top_node, BAD_CAST "name", BAD_CAST if_name)) {
- vshError(ctl, _("Failed to set interface name to '%s' in xml
document"),
- if_name);
- goto cleanup;
+ if (vshCommandOptString(cmd, "target", &target) < 0) {
+ vshError(ctl, _("Invalid target argument"));
+ return false;
}
- /* Cycle through all the nodes under the attached <interface>,
- * moving all <mac>, <bond> and <vlan> nodes up into the toplevel
- * <interface>.
- */
- cur = if_node->children;
- while (cur) {
- xmlNodePtr old = cur;
-
- cur = cur->next;
- if ((old->type == XML_ELEMENT_NODE) &&
- (xmlStrEqual(old->name, BAD_CAST "mac") || /* ethernet stuff to
move down */
- xmlStrEqual(old->name, BAD_CAST "bond") || /* bond stuff to
move down */
- xmlStrEqual(old->name, BAD_CAST "vlan"))) { /* vlan stuff to
move down */
- xmlUnlinkNode(old);
- if (!xmlAddChild(top_node, old)) {
- vshError(ctl, _("Failed to move '%s' element in xml
document"), old->name);
- xmlFreeNode(old);
- goto cleanup;
- }
- }
+ if (vshCommandOptLongLong(cmd, "duration", &duration) < 0) {
+ vshError(ctl, _("Invalid duration argument"));
+ return false;
}
- /* The document should now be fully converted; write it out to a string. */
- xmlDocDumpMemory(xml_doc, &if_xml, &if_xml_size);
-
- if (!if_xml || if_xml_size <= 0) {
- vshError(ctl, _("Failed to format new xml document for un-enslaved interface
%s"),
- if_name);
- goto cleanup;
+ if (vshCommandOptUInt(cmd, "flags", &flags) < 0) {
+ vshError(ctl, _("Invalid flags argument"));
+ return false;
}
- /* Destroy and Undefine the bridge device, since we otherwise
- * can't safely define the unattached device.
- */
- if (virInterfaceDestroy(br_handle, 0) < 0) {
- vshError(ctl, _("Failed to destroy bridge interface %s"), br_name);
- goto cleanup;
+ if (STREQ(target, "mem"))
+ suspendTarget = VIR_NODE_SUSPEND_TARGET_MEM;
+ else if (STREQ(target, "disk"))
+ suspendTarget = VIR_NODE_SUSPEND_TARGET_DISK;
+ else if (STREQ(target, "hybrid"))
+ suspendTarget = VIR_NODE_SUSPEND_TARGET_HYBRID;
+ else {
+ vshError(ctl, "%s", _("Invalid target"));
+ return false;
}
- if (virInterfaceUndefine(br_handle) < 0) {
- vshError(ctl, _("Failed to undefine bridge interface %s"), br_name);
- goto cleanup;
+
+ if (duration <= 0) {
+ vshError(ctl, "%s", _("Invalid duration"));
+ return false;
}
- /* if_xml is the new interface to define.
- */
- if (!(if_handle = virInterfaceDefineXML(ctl->conn, (char *) if_xml, 0))) {
- vshError(ctl, _("Failed to define new interface %s"), if_name);
- goto cleanup;
+ if (virNodeSuspendForDuration(ctl->conn, suspendTarget, duration,
+ flags) < 0) {
+ vshError(ctl, "%s", _("The host was not suspended"));
+ return false;
}
+ return true;
+}
- vshPrint(ctl, _("Device %s un-attached from bridge %s\n"),
- if_name, br_name);
- /* unless requested otherwise, undefine the bridge device */
- if (!nostart) {
- if (virInterfaceCreate(if_handle, 0) < 0) {
- vshError(ctl, _("Failed to start interface %s"), if_name);
- goto cleanup;
- }
- vshPrint(ctl, _("Interface %s started\n"), if_name);
+/*
+ * "capabilities" command
+ */
+static const vshCmdInfo info_capabilities[] = {
+ {"help", N_("capabilities")},
+ {"desc", N_("Returns capabilities of hypervisor/driver.")},
+ {NULL, NULL}
+};
+
+static bool
+cmdCapabilities(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ char *caps;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if ((caps = virConnectGetCapabilities(ctl->conn)) == NULL) {
+ vshError(ctl, "%s", _("failed to get capabilities"));
+ return false;
}
+ vshPrint(ctl, "%s\n", caps);
+ VIR_FREE(caps);
- ret = true;
- cleanup:
- if (if_handle)
- virInterfaceFree(if_handle);
- if (br_handle)
- virInterfaceFree(br_handle);
- VIR_FREE(if_xml);
- VIR_FREE(br_xml);
- VIR_FREE(if_type);
- VIR_FREE(if_name);
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(xml_doc);
- return ret;
+ return true;
}
/*
@@ -6113,47 +5173,6 @@ vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
return nwfilter;
}
-static virInterfacePtr
-vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
- const char *optname,
- const char **name, int flag)
-{
- virInterfacePtr iface = NULL;
- const char *n = NULL;
-
- if (!optname)
- optname = "interface";
- if (!cmd_has_option(ctl, cmd, optname))
- return NULL;
-
- if (vshCommandOptString(cmd, optname, &n) <= 0)
- return NULL;
-
- vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
- cmd->def->name, optname, n);
-
- if (name)
- *name = n;
-
- /* try it by NAME */
- if (flag & VSH_BYNAME) {
- vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface
NAME\n",
- cmd->def->name, optname);
- iface = virInterfaceLookupByName(ctl->conn, n);
- }
- /* try it by MAC */
- if (iface == NULL && (flag & VSH_BYMAC)) {
- vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface
MAC\n",
- cmd->def->name, optname);
- iface = virInterfaceLookupByMACString(ctl->conn, n);
- }
-
- if (!iface)
- vshError(ctl, _("failed to get interface '%s'"), n);
-
- return iface;
-}
-
static virSecretPtr
vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
{
@@ -7717,6 +6736,8 @@ static const vshCmdDef nodedevCmds[] = {
{NULL, NULL, NULL, NULL, 0}
};
+#include "virsh-interface.c"
+
static const vshCmdDef ifaceCmds[] = {
{"iface-begin", cmdInterfaceBegin, opts_interface_begin,
info_interface_begin, 0},
--
1.7.7.3