[libvirt] [PATCH v4 23/29] virsh: add support for network port APIs

Daniel P. Berrangé berrange at redhat.com
Wed Apr 17 17:19:23 UTC 2019


Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 tools/virsh-completer.c |  50 +++++
 tools/virsh-completer.h |   4 +
 tools/virsh-network.c   | 399 +++++++++++++++++++++++++++++++++++++++-
 tools/virsh-network.h   |   5 +
 4 files changed, 457 insertions(+), 1 deletion(-)

diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c
index 918e409890..7d5cf8cb90 100644
--- a/tools/virsh-completer.c
+++ b/tools/virsh-completer.c
@@ -408,6 +408,56 @@ virshNetworkEventNameCompleter(vshControl *ctl ATTRIBUTE_UNUSED,
 }
 
 
+char **
+virshNetworkPortUUIDCompleter(vshControl *ctl,
+                              const vshCmd *cmd ATTRIBUTE_UNUSED,
+                              unsigned int flags)
+{
+    virshControlPtr priv = ctl->privData;
+    virNetworkPtr net = NULL;
+    virNetworkPortPtr *ports = NULL;
+    int nports = 0;
+    size_t i = 0;
+    char **ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
+        return NULL;
+
+    if (!(net = virshCommandOptNetwork(ctl, cmd, NULL)))
+        return false;
+
+    if ((nports = virNetworkListAllPorts(net, &ports, flags)) < 0)
+        return NULL;
+
+    if (VIR_ALLOC_N(ret, nports + 1) < 0)
+        goto error;
+
+    for (i = 0; i < nports; i++) {
+        char uuid[VIR_UUID_STRING_BUFLEN];
+
+        if (virNetworkPortGetUUIDString(ports[i], uuid) < 0 ||
+            VIR_STRDUP(ret[i], uuid) < 0)
+            goto error;
+
+        virNetworkPortFree(ports[i]);
+    }
+    VIR_FREE(ports);
+
+    return ret;
+
+ error:
+    for (; i < nports; i++)
+        virNetworkPortFree(ports[i]);
+    VIR_FREE(ports);
+    for (i = 0; i < nports; i++)
+        VIR_FREE(ret[i]);
+    VIR_FREE(ret);
+    return NULL;
+}
+
+
 char **
 virshNodeDeviceNameCompleter(vshControl *ctl,
                              const vshCmd *cmd ATTRIBUTE_UNUSED,
diff --git a/tools/virsh-completer.h b/tools/virsh-completer.h
index ed37a26cc9..cd3cc9ecae 100644
--- a/tools/virsh-completer.h
+++ b/tools/virsh-completer.h
@@ -59,6 +59,10 @@ char ** virshNetworkEventNameCompleter(vshControl *ctl,
                                        const vshCmd *cmd,
                                        unsigned int flags);
 
+char ** virshNetworkPortUUIDCompleter(vshControl *ctl,
+                                      const vshCmd *cmd,
+                                      unsigned int flags);
+
 char ** virshNodeDeviceNameCompleter(vshControl *ctl,
                                      const vshCmd *cmd,
                                      unsigned int flags);
diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 14bf9a144f..af08441842 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1,7 +1,7 @@
 /*
  * virsh-network.c: Commands to manage network
  *
- * Copyright (C) 2005, 2007-2016 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2019 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
@@ -54,6 +54,16 @@
 #define VIRSH_COMMON_OPT_NETWORK_OT_STRING_FULL(cflags) \
     VIRSH_COMMON_OPT_NETWORK_OT_STRING(N_("network name or uuid"), cflags)
 
+#define VIRSH_COMMON_OPT_NETWORK_PORT(cflags) \
+    {.name = "port", \
+     .type = VSH_OT_DATA, \
+     .flags = VSH_OFLAG_REQ, \
+     .help = N_("port UUID"), \
+     .completer = virshNetworkPortUUIDCompleter, \
+     .completer_flags = cflags, \
+    }
+
+
 virNetworkPtr
 virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
                          const char **name, unsigned int flags)
@@ -92,6 +102,35 @@ virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
     return network;
 }
 
+
+virNetworkPortPtr
+virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd,
+                           virNetworkPtr net,
+                           const char **name)
+{
+    virNetworkPortPtr port = NULL;
+    const char *n = NULL;
+    const char *optname = "port";
+
+    if (vshCommandOptStringReq(ctl, 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;
+
+    vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n",
+             cmd->def->name, optname);
+    port = virNetworkPortLookupByUUIDString(net, n);
+
+    if (!port)
+        vshError(ctl, _("failed to get network port '%s'"), n);
+
+    return port;
+}
+
 /*
  * "net-autostart" command
  */
@@ -1437,6 +1476,340 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
     return ret;
 }
 
+/*
+ * "net-port-create" command
+ */
+static const vshCmdInfo info_network_port_create[] = {
+    {.name = "help",
+     .data = N_("create a network port from an XML file")
+    },
+    {.name = "desc",
+     .data = N_("Create a network port.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_port_create[] = {
+    VIRSH_COMMON_OPT_NETWORK_FULL(0),
+    VIRSH_COMMON_OPT_FILE(N_("file containing an XML network port description")),
+    {.name = NULL}
+};
+
+static bool
+cmdNetworkPortCreate(vshControl *ctl, const vshCmd *cmd)
+{
+    virNetworkPortPtr port = NULL;
+    const char *from = NULL;
+    bool ret = false;
+    char *buffer = NULL;
+    virNetworkPtr network = NULL;
+
+    network = virshCommandOptNetwork(ctl, cmd, NULL);
+    if (network == NULL)
+        goto cleanup;
+
+    if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
+        goto cleanup;
+
+    if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
+        goto cleanup;
+
+    port = virNetworkPortCreateXML(network, buffer, 0);
+
+    if (port != NULL) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virNetworkPortGetUUIDString(port, uuidstr);
+        vshPrintExtra(ctl, _("Network port %s created from %s\n"),
+                      uuidstr, from);
+    } else {
+        vshError(ctl, _("Failed to create network from %s"), from);
+        goto cleanup;
+    }
+
+    ret = true;
+ cleanup:
+    VIR_FREE(buffer);
+    if (port)
+        virNetworkPortFree(port);
+    if (network)
+        virNetworkFree(network);
+    return ret;
+}
+
+/*
+ * "net-port-dumpxml" command
+ */
+static const vshCmdInfo info_network_port_dumpxml[] = {
+    {.name = "help",
+     .data = N_("network port information in XML")
+    },
+    {.name = "desc",
+     .data = N_("Output the network port information as an XML dump to stdout.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_port_dumpxml[] = {
+    VIRSH_COMMON_OPT_NETWORK_FULL(0),
+    VIRSH_COMMON_OPT_NETWORK_PORT(0),
+    {.name = NULL}
+};
+
+static bool
+cmdNetworkPortDumpXML(vshControl *ctl, const vshCmd *cmd)
+{
+    virNetworkPtr network;
+    virNetworkPortPtr port = NULL;
+    bool ret = true;
+    char *dump;
+    unsigned int flags = 0;
+
+    if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
+        goto cleanup;
+
+    if (!(port = virshCommandOptNetworkPort(ctl, cmd, network, NULL)))
+        goto cleanup;
+
+    dump = virNetworkPortGetXMLDesc(port, flags);
+
+    if (dump != NULL) {
+        vshPrint(ctl, "%s", dump);
+        VIR_FREE(dump);
+    } else {
+        ret = false;
+    }
+
+ cleanup:
+    if (port)
+        virNetworkPortFree(port);
+    if (network)
+        virNetworkFree(network);
+    return ret;
+}
+
+
+/*
+ * "net-port-delete" command
+ */
+static const vshCmdInfo info_network_port_delete[] = {
+    {.name = "help",
+     .data = N_("network port information in XML")
+    },
+    {.name = "desc",
+     .data = N_("Output the network port information as an XML dump to stdout.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_port_delete[] = {
+    VIRSH_COMMON_OPT_NETWORK_FULL(0),
+    VIRSH_COMMON_OPT_NETWORK_PORT(0),
+    {.name = NULL}
+};
+
+static bool
+cmdNetworkPortDelete(vshControl *ctl, const vshCmd *cmd)
+{
+    virNetworkPtr network = NULL;
+    virNetworkPortPtr port = NULL;
+    bool ret = true;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
+        goto cleanup;
+
+    if (!(port = virshCommandOptNetworkPort(ctl, cmd, network, NULL)))
+        goto cleanup;
+
+    if (virNetworkPortGetUUIDString(port, uuidstr) < 0)
+        goto cleanup;
+
+    if (virNetworkPortDelete(port, 0) < 0) {
+        vshError(ctl, _("Failed to delete network port %s"), uuidstr);
+        goto cleanup;
+    } else {
+        vshPrintExtra(ctl, _("Network port %s deleted\n"), uuidstr);
+    }
+
+    ret = true;
+ cleanup:
+    if (port)
+        virNetworkPortFree(port);
+    if (network)
+        virNetworkFree(network);
+    return ret;
+}
+
+
+static int
+virshNetworkPortSorter(const void *a, const void *b)
+{
+    virNetworkPortPtr *na = (virNetworkPortPtr *) a;
+    virNetworkPortPtr *nb = (virNetworkPortPtr *) b;
+    unsigned char uuida[VIR_UUID_BUFLEN];
+    unsigned char uuidb[VIR_UUID_BUFLEN];
+
+    if (*na && !*nb)
+        return -1;
+
+    if (!*na)
+        return *nb != NULL;
+
+    if (virNetworkPortGetUUID(*na, uuida) < 0 ||
+        virNetworkPortGetUUID(*nb, uuidb) < 0)
+        return -1;
+
+    return memcmp(uuida, uuidb, VIR_UUID_BUFLEN);
+}
+
+struct virshNetworkPortList {
+    virNetworkPortPtr *ports;
+    size_t nports;
+};
+typedef struct virshNetworkPortList *virshNetworkPortListPtr;
+
+static void
+virshNetworkPortListFree(virshNetworkPortListPtr list)
+{
+    size_t i;
+
+    if (list && list->ports) {
+        for (i = 0; i < list->nports; i++) {
+            if (list->ports[i])
+                virNetworkPortFree(list->ports[i]);
+        }
+        VIR_FREE(list->ports);
+    }
+    VIR_FREE(list);
+}
+
+static virshNetworkPortListPtr
+virshNetworkPortListCollect(vshControl *ctl,
+                            const vshCmd *cmd,
+                            unsigned int flags)
+{
+    virshNetworkPortListPtr list = vshMalloc(ctl, sizeof(*list));
+    int ret;
+    virNetworkPtr network = NULL;
+    bool success = false;
+
+    if (!(network = virshCommandOptNetwork(ctl, cmd, NULL)))
+        goto cleanup;
+
+    /* try the list with flags support (0.10.2 and later) */
+    if ((ret = virNetworkListAllPorts(network,
+                                      &list->ports,
+                                      flags)) < 0)
+        goto cleanup;
+
+    list->nports = ret;
+
+    /* sort the list */
+    if (list->ports && list->nports)
+        qsort(list->ports, list->nports,
+              sizeof(*list->ports), virshNetworkPortSorter);
+
+    success = true;
+
+ cleanup:
+    if (!success) {
+        virshNetworkPortListFree(list);
+        list = NULL;
+    }
+
+    if (network)
+        virNetworkFree(network);
+
+    return list;
+}
+
+/*
+ * "net-list" command
+ */
+static const vshCmdInfo info_network_port_list[] = {
+    {.name = "help",
+     .data = N_("list network ports")
+    },
+    {.name = "desc",
+     .data = N_("Returns list of network ports.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_port_list[] = {
+    VIRSH_COMMON_OPT_NETWORK_FULL(0),
+    {.name = "uuid",
+     .type = VSH_OT_BOOL,
+     .help = N_("list uuid's only")
+    },
+    {.name = "table",
+     .type = VSH_OT_BOOL,
+     .help = N_("list table (default)")
+    },
+    {.name = NULL}
+};
+
+#define FILTER(NAME, FLAG) \
+    if (vshCommandOptBool(cmd, NAME)) \
+        flags |= (FLAG)
+static bool
+cmdNetworkPortList(vshControl *ctl, const vshCmd *cmd)
+{
+    virshNetworkPortListPtr list = NULL;
+    size_t i;
+    bool ret = false;
+    bool optTable = vshCommandOptBool(cmd, "table");
+    bool optUUID = vshCommandOptBool(cmd, "uuid");
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    unsigned int flags = 0;
+    vshTablePtr table = NULL;
+
+    if (optTable + optUUID > 1) {
+        vshError(ctl, "%s",
+                 _("Only one argument from --table and --uuid "
+                   "may be specified."));
+        return false;
+    }
+
+    if (!optUUID)
+        optTable = true;
+
+    if (!(list = virshNetworkPortListCollect(ctl, cmd, flags)))
+        return false;
+
+    if (optTable) {
+        table = vshTableNew(_("UUID"), NULL);
+        if (!table)
+            goto cleanup;
+    }
+
+    for (i = 0; i < list->nports; i++) {
+        virNetworkPortPtr port = list->ports[i];
+
+        if (virNetworkPortGetUUIDString(port, uuid) < 0) {
+            vshError(ctl, "%s", _("Failed to get network's UUID"));
+            goto cleanup;
+        }
+        if (optTable) {
+            if (vshTableRowAppend(table, uuid, NULL) < 0)
+                goto cleanup;
+        } else if (optUUID) {
+            vshPrint(ctl, "%s\n", uuid);
+        }
+    }
+
+    if (optTable)
+        vshTablePrintToStdout(table, ctl);
+
+    ret = true;
+ cleanup:
+    vshTableFree(table);
+    virshNetworkPortListFree(list);
+    return ret;
+}
+#undef FILTER
+
+
 const vshCmdDef networkCmds[] = {
     {.name = "net-autostart",
      .handler = cmdNetworkAutostart,
@@ -1528,5 +1901,29 @@ const vshCmdDef networkCmds[] = {
      .info = info_network_uuid,
      .flags = 0
     },
+    {.name = "net-port-list",
+     .handler = cmdNetworkPortList,
+     .opts = opts_network_port_list,
+     .info = info_network_port_list,
+     .flags = 0
+    },
+    {.name = "net-port-create",
+     .handler = cmdNetworkPortCreate,
+     .opts = opts_network_port_create,
+     .info = info_network_port_create,
+     .flags = 0
+    },
+    {.name = "net-port-dumpxml",
+     .handler = cmdNetworkPortDumpXML,
+     .opts = opts_network_port_dumpxml,
+     .info = info_network_port_dumpxml,
+     .flags = 0
+    },
+    {.name = "net-port-delete",
+     .handler = cmdNetworkPortDelete,
+     .opts = opts_network_port_delete,
+     .info = info_network_port_delete,
+     .flags = 0
+    },
     {.name = NULL}
 };
diff --git a/tools/virsh-network.h b/tools/virsh-network.h
index 9c86eb5bc9..18b8e4365f 100644
--- a/tools/virsh-network.h
+++ b/tools/virsh-network.h
@@ -27,6 +27,11 @@ virNetworkPtr
 virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
                          const char **name, unsigned int flags);
 
+virNetworkPortPtr
+virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd,
+                           virNetworkPtr net,
+                           const char **name);
+
 /* default is lookup by Name and UUID */
 # define virshCommandOptNetwork(_ctl, _cmd, _name) \
     virshCommandOptNetworkBy(_ctl, _cmd, _name, \
-- 
2.20.1




More information about the libvir-list mailing list