[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 1/2] Add virsh iface-* commands for virInterface* functions



Commands all start with "iface-", for example, iface-list,
iface-dumpxml, etc.
---
 src/virsh.c |  536 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 536 insertions(+), 0 deletions(-)

diff --git a/src/virsh.c b/src/virsh.c
index 5623499..1ba4e37 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -228,6 +228,7 @@ static int vshCommandOptBool(const vshCmd *cmd, const char *name);
 #define VSH_BYID     (1 << 1)
 #define VSH_BYUUID   (1 << 2)
 #define VSH_BYNAME   (1 << 3)
+#define VSH_BYMAC    (1 << 4)
 
 static virDomainPtr vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
                                           char **name, int flag);
@@ -244,6 +245,14 @@ static virNetworkPtr vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
     vshCommandOptNetworkBy(_ctl, _cmd, _name,                      \
                            VSH_BYUUID|VSH_BYNAME)
 
+static virInterfacePtr vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
+                                                char **name, int flag);
+
+/* default is lookup by Name and MAC */
+#define vshCommandOptInterface(_ctl, _cmd, _name)                    \
+    vshCommandOptInterfaceBy(_ctl, _cmd, _name,                      \
+                           VSH_BYMAC|VSH_BYNAME)
+
 static virStoragePoolPtr vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd,
                             const char *optname, char **name, int flag);
 
@@ -275,6 +284,10 @@ static const char *vshDomainVcpuStateToString(int state);
 static int vshConnectionUsability(vshControl *ctl, virConnectPtr conn,
                                   int showerror);
 
+static char *editWriteToTempFile (vshControl *ctl, const char *doc);
+static int   editFile (vshControl *ctl, const char *filename);
+static char *editReadBackFile (vshControl *ctl, const char *filename);
+
 static void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
 #define vshMalloc(_ctl, _sz)    _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
 
@@ -2692,6 +2705,106 @@ cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd)
 
 
 /*
+ * "iface-edit" command
+ */
+static const vshCmdInfo info_interface_edit[] = {
+    {"help", gettext_noop("edit XML configuration for a physical host interface")},
+    {"desc", gettext_noop("Edit the XML configuration for a physical host interface.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_edit[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name or MAC address")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd)
+{
+    int ret = FALSE;
+    virInterfacePtr iface = NULL;
+    char *tmp = NULL;
+    char *doc = NULL;
+    char *doc_edited = NULL;
+    char *doc_reread = NULL;
+    int flags = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        goto cleanup;
+
+    iface = vshCommandOptInterface (ctl, cmd, NULL);
+    if (iface == NULL)
+        goto cleanup;
+
+    /* Get the XML configuration of the interface. */
+    doc = virInterfaceGetXMLDesc (iface, flags);
+    if (!doc)
+        goto cleanup;
+
+    /* Create and open the temporary file. */
+    tmp = editWriteToTempFile (ctl, doc);
+    if (!tmp) goto cleanup;
+
+    /* Start the editor. */
+    if (editFile (ctl, tmp) == -1) goto cleanup;
+
+    /* Read back the edited file. */
+    doc_edited = editReadBackFile (ctl, tmp);
+    if (!doc_edited) goto cleanup;
+
+    unlink (tmp);
+    tmp = NULL;
+
+    /* Compare original XML with edited.  Has it changed at all? */
+    if (STREQ (doc, doc_edited)) {
+        vshPrint (ctl, _("Interface %s XML configuration not changed.\n"),
+                  virInterfaceGetName (iface));
+        ret = TRUE;
+        goto cleanup;
+    }
+
+    /* Now re-read the interface XML.  Did someone else change it while
+     * it was being edited?  This also catches problems such as us
+     * losing a connection or the interface going away.
+     */
+    doc_reread = virInterfaceGetXMLDesc (iface, flags);
+    if (!doc_reread)
+        goto cleanup;
+
+    if (STRNEQ (doc, doc_reread)) {
+        vshError (ctl, FALSE,
+                  "%s", _("ERROR: the XML configuration was changed by another user"));
+        goto cleanup;
+    }
+
+    /* Everything checks out, so redefine the interface. */
+    virInterfaceFree (iface);
+    iface = virInterfaceDefineXML (ctl->conn, doc_edited, 0);
+    if (!iface)
+        goto cleanup;
+
+    vshPrint (ctl, _("Interface %s XML configuration edited.\n"),
+              virInterfaceGetName(iface));
+
+    ret = TRUE;
+
+cleanup:
+    if (iface)
+        virInterfaceFree (iface);
+
+    free (doc);
+    free (doc_edited);
+    free (doc_reread);
+
+    if (tmp) {
+        unlink (tmp);
+        free (tmp);
+    }
+
+    return ret;
+}
+
+/*
  * "net-list" command
  */
 static const vshCmdInfo info_network_list[] = {
@@ -2957,6 +3070,378 @@ cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd)
 }
 
 
+/**************************************************************************/
+/*
+ * "iface-list" command
+ */
+static const vshCmdInfo info_interface_list[] = {
+    {"help", gettext_noop("list physical host interfaces")},
+    {"desc", gettext_noop("Returns list of physical host interfaces.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_list[] = {
+    {"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive interfaces")},
+    {"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active interfaces")},
+    {NULL, 0, 0, NULL}
+};
+static int
+cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    int inactive = vshCommandOptBool(cmd, "inactive");
+    int all = vshCommandOptBool(cmd, "all");
+    int active = !inactive || all ? 1 : 0;
+    int maxactive = 0, maxinactive = 0, i;
+    char **activeNames = NULL, **inactiveNames = NULL;
+    inactive |= all;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (active) {
+        maxactive = virConnectNumOfInterfaces(ctl->conn);
+        if (maxactive < 0) {
+            vshError(ctl, FALSE, "%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, FALSE, "%s", _("Failed to list active interfaces"));
+                free(activeNames);
+                return FALSE;
+            }
+
+            qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
+        }
+    }
+    if (inactive) {
+        maxinactive = virConnectNumOfDefinedInterfaces(ctl->conn);
+        if (maxinactive < 0) {
+            vshError(ctl, FALSE, "%s", _("Failed to list inactive interfaces"));
+            free(activeNames);
+            return FALSE;
+        }
+        if (maxinactive) {
+            inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
+
+            if ((maxinactive = virConnectListDefinedInterfaces(ctl->conn, inactiveNames, maxinactive)) < 0) {
+                vshError(ctl, FALSE, "%s", _("Failed to list inactive interfaces"));
+                free(activeNames);
+                free(inactiveNames);
+                return FALSE;
+            }
+
+            qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
+        }
+    }
+    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]);
+        const char *autostartStr;
+        int autostart = 0;
+
+        /* this kind of work with interfaces is not atomic */
+        if (!iface) {
+            free(activeNames[i]);
+            continue;
+        }
+
+        vshPrint(ctl, "%-20s %-10s %s\n",
+                 virInterfaceGetName(iface),
+                 _("active"),
+                 virInterfaceGetMACString(iface));
+        virInterfaceFree(iface);
+        free(activeNames[i]);
+    }
+    for (i = 0; i < maxinactive; i++) {
+        virInterfacePtr iface = virInterfaceLookupByName(ctl->conn, inactiveNames[i]);
+        const char *autostartStr;
+        int autostart = 0;
+
+        /* this kind of work with interfaces is not atomic */
+        if (!iface) {
+            free(inactiveNames[i]);
+            continue;
+        }
+
+        vshPrint(ctl, "%-20s %-10s %s\n",
+                 virInterfaceGetName(iface),
+                 _("inactive"),
+                 virInterfaceGetMACString(iface));
+        virInterfaceFree(iface);
+        free(inactiveNames[i]);
+    }
+    free(activeNames);
+    free(inactiveNames);
+    return TRUE;
+
+}
+
+/*
+ * "iface-name" command
+ */
+static const vshCmdInfo info_interface_name[] = {
+    {"help", gettext_noop("convert an interface MAC address to interface name")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_name[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface mac")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+    if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, 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", gettext_noop("convert an interface name to interface MAC address")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_mac[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+    if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, 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", gettext_noop("interface information in XML")},
+    {"desc", gettext_noop("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, gettext_noop("interface name or MAC address")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+    int ret = TRUE;
+    char *dump;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
+        return FALSE;
+
+    dump = virInterfaceGetXMLDesc(iface, 0);
+    if (dump != NULL) {
+        printf("%s", dump);
+        free(dump);
+    } else {
+        ret = FALSE;
+    }
+
+    virInterfaceFree(iface);
+    return ret;
+}
+
+/*
+ * "iface-define" command
+ */
+static const vshCmdInfo info_interface_define[] = {
+    {"help", gettext_noop("define (but don't start) a physical host interface from an XML file")},
+    {"desc", gettext_noop("Define a physical host interface.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_define[] = {
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML interface description")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr interface;
+    char *from;
+    int found;
+    int ret = TRUE;
+    char *buffer;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    from = vshCommandOptString(cmd, "file", &found);
+    if (!found)
+        return FALSE;
+
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
+        return FALSE;
+
+    interface = virInterfaceDefineXML(ctl->conn, buffer, 0);
+    free (buffer);
+
+    if (interface != NULL) {
+        vshPrint(ctl, _("Interface %s defined from %s\n"),
+                 virInterfaceGetName(interface), from);
+    } else {
+        vshError(ctl, FALSE, _("Failed to define interface from %s"), from);
+        ret = FALSE;
+    }
+    return ret;
+}
+
+/*
+ * "iface-undefine" command
+ */
+static const vshCmdInfo info_interface_undefine[] = {
+    {"help", gettext_noop("undefine a physical host interface (remove it from configuration)")},
+    {"desc", gettext_noop("undefine an interface.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_undefine[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name or MAC address")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
+        return FALSE;
+
+    if (virInterfaceUndefine(iface) == 0) {
+        vshPrint(ctl, _("Interface %s undefined\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to undefine interface %s"), name);
+        ret = FALSE;
+    }
+
+    virInterfaceFree(iface);
+    return ret;
+}
+
+/*
+ * "iface-start" command
+ */
+static const vshCmdInfo info_interface_start[] = {
+    {"help", gettext_noop("start a physical host interface (enable it / \"if-up\")")},
+    {"desc", gettext_noop("start a physical host interface.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_start[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name or MAC address")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        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, FALSE, _("Failed to start interface %s"), name);
+        ret = FALSE;
+    }
+
+    virInterfaceFree(iface);
+    return ret;
+}
+
+/*
+ * "iface-destroy" command
+ */
+static const vshCmdInfo info_interface_destroy[] = {
+    {"help", gettext_noop("destroy a physical host interface (disable it / \"if-down\")")},
+    {"desc", gettext_noop("destroy a physical host interface.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_destroy[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name or MAC address")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        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, FALSE, _("Failed to destroy interface %s"), name);
+        ret = FALSE;
+    }
+
+    virInterfaceFree(iface);
+    return ret;
+}
+
+/**************************************************************************/
 /*
  * "pool-autostart" command
  */
@@ -6249,6 +6734,17 @@ static const vshCmdDef commands[] = {
     {"net-start", cmdNetworkStart, opts_network_start, info_network_start},
     {"net-undefine", cmdNetworkUndefine, opts_network_undefine, info_network_undefine},
     {"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid},
+
+    {"iface-list", cmdInterfaceList, opts_interface_list, info_interface_list},
+    {"iface-name", cmdInterfaceName, opts_interface_name, info_interface_name},
+    {"iface-mac", cmdInterfaceMAC, opts_interface_mac, info_interface_mac},
+    {"iface-dumpxml", cmdInterfaceDumpXML, opts_interface_dumpxml, info_interface_dumpxml},
+    {"iface-define", cmdInterfaceDefine, opts_interface_define, info_interface_define},
+    {"iface-undefine", cmdInterfaceUndefine, opts_interface_undefine, info_interface_undefine},
+    {"iface-edit", cmdInterfaceEdit, opts_interface_edit, info_interface_edit},
+    {"iface-start", cmdInterfaceStart, opts_interface_start, info_interface_start},
+    {"iface-destroy", cmdInterfaceDestroy, opts_interface_destroy, info_interface_destroy},
+
     {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
 
     {"nodedev-list", cmdNodeListDevices, opts_node_list_devices, info_node_list_devices},
@@ -6700,6 +7196,46 @@ vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
     return network;
 }
 
+static virInterfacePtr
+vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
+                         char **name, int flag)
+{
+    virInterfacePtr iface = NULL;
+    char *n;
+    const char *optname = "interface";
+    if (!cmd_has_option (ctl, cmd, optname))
+        return NULL;
+
+    if (!(n = vshCommandOptString(cmd, optname, NULL))) {
+        vshError(ctl, FALSE, "%s", _("undefined interface identifier"));
+        return NULL;
+    }
+
+    vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
+             cmd->def->name, optname, n);
+
+    if (name)
+        *name = n;
+
+    /* try it by NAME */
+    if ((iface == NULL) && (flag & VSH_BYNAME)) {
+        vshDebug(ctl, 5, "%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, 5, "%s: <%s> trying as interface MAC\n",
+                 cmd->def->name, optname);
+        iface = virInterfaceLookupByMACString(ctl->conn, n);
+    }
+
+    if (!iface)
+        vshError(ctl, FALSE, _("failed to get interface '%s'"), n);
+
+    return iface;
+}
+
 static virStoragePoolPtr
 vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
                     char **name, int flag)
-- 
1.6.3.3.353.g4f2b1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]