From nobody Sun Feb 8 12:37:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1557848950; cv=none; d=zoho.com; s=zohoarc; b=EJE+Nj6axT3PsACSSFJn2+iknSvnc3F1CddtCgC2zWLt86AppkN0K8e+HRIo7G/yBicjcVvqwfXFnzAugPlNqfO1KRO7Ps1IXn0CPgpbY4b0kwL1qAGdrA12AosKqqAs701RZiHF7Pm8E1fiYbw/Fkl2D4kl2RN//XkcbyqaE14= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557848950; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=wNLuvi+DzTAmxclnY6waRpJwLBvHhA3wAyx2OpE7mKs=; b=THPe3sQg6rJUJ8D4z54f5uE364JQpfk70VzLGFUPZPuVX9ewrcSXE36jzNAlI4TyWDUUie1taasA+naT3s1JfQVsmk//YzNR7G/GuYS7Mi04Rf6WUvVJmbVKOeDyZ61UZ1RAPeZSgzGwKFXaNScxj3B7owP0vO+w6IQOlEzbgn0= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1557848950314538.0590433883489; Tue, 14 May 2019 08:49:10 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C3C1C821CC; Tue, 14 May 2019 15:49:08 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9386E61995; Tue, 14 May 2019 15:49:08 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 5736F3FA4F; Tue, 14 May 2019 15:49:08 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x4EFn1jf031909 for ; Tue, 14 May 2019 11:49:01 -0400 Received: by smtp.corp.redhat.com (Postfix) id 9AE251981E; Tue, 14 May 2019 15:49:01 +0000 (UTC) Received: from dhcp-17-248.lcy.redhat.com (unknown [10.42.17.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id E360C2B9F0; Tue, 14 May 2019 15:49:00 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Tue, 14 May 2019 16:48:29 +0100 Message-Id: <20190514154836.6427-18-berrange@redhat.com> In-Reply-To: <20190514154836.6427-1-berrange@redhat.com> References: <20190514154836.6427-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: Laine Stump Subject: [libvirt] [PATCH v5 17/24] virsh: add support for network port APIs X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 14 May 2019 15:49:09 +0000 (UTC) Signed-off-by: Daniel P. Berrang=C3=A9 --- 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 ATTRIBU= TE_UNUSED, } =20 =20 +char ** +virshNetworkPortUUIDCompleter(vshControl *ctl, + const vshCmd *cmd ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virshControlPtr priv =3D ctl->privData; + virNetworkPtr net =3D NULL; + virNetworkPortPtr *ports =3D NULL; + int nports =3D 0; + size_t i =3D 0; + char **ret =3D NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <=3D 0) + return NULL; + + if (!(net =3D virshCommandOptNetwork(ctl, cmd, NULL))) + return false; + + if ((nports =3D virNetworkListAllPorts(net, &ports, flags)) < 0) + return NULL; + + if (VIR_ALLOC_N(ret, nports + 1) < 0) + goto error; + + for (i =3D 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 =3D 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); =20 +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) =20 +#define VIRSH_COMMON_OPT_NETWORK_PORT(cflags) \ + {.name =3D "port", \ + .type =3D VSH_OT_DATA, \ + .flags =3D VSH_OFLAG_REQ, \ + .help =3D N_("port UUID"), \ + .completer =3D virshNetworkPortUUIDCompleter, \ + .completer_flags =3D 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; } =20 + +virNetworkPortPtr +virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd, + virNetworkPtr net, + const char **name) +{ + virNetworkPortPtr port =3D NULL; + const char *n =3D NULL; + const char *optname =3D "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 =3D n; + + vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n", + cmd->def->name, optname); + port =3D 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; } =20 +/* + * "net-port-create" command + */ +static const vshCmdInfo info_network_port_create[] =3D { + {.name =3D "help", + .data =3D N_("create a network port from an XML file") + }, + {.name =3D "desc", + .data =3D N_("Create a network port.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_port_create[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_FILE(N_("file containing an XML network port descript= ion")), + {.name =3D NULL} +}; + +static bool +cmdNetworkPortCreate(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPortPtr port =3D NULL; + const char *from =3D NULL; + bool ret =3D false; + char *buffer =3D NULL; + virNetworkPtr network =3D NULL; + + network =3D virshCommandOptNetwork(ctl, cmd, NULL); + if (network =3D=3D NULL) + goto cleanup; + + if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) + goto cleanup; + + if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + goto cleanup; + + port =3D virNetworkPortCreateXML(network, buffer, 0); + + if (port !=3D 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 =3D 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[] =3D { + {.name =3D "help", + .data =3D N_("network port information in XML") + }, + {.name =3D "desc", + .data =3D N_("Output the network port information as an XML dump to s= tdout.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_port_dumpxml[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_NETWORK_PORT(0), + {.name =3D NULL} +}; + +static bool +cmdNetworkPortDumpXML(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPtr network; + virNetworkPortPtr port =3D NULL; + bool ret =3D true; + char *dump; + unsigned int flags =3D 0; + + if (!(network =3D virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + if (!(port =3D virshCommandOptNetworkPort(ctl, cmd, network, NULL))) + goto cleanup; + + dump =3D virNetworkPortGetXMLDesc(port, flags); + + if (dump !=3D NULL) { + vshPrint(ctl, "%s", dump); + VIR_FREE(dump); + } else { + ret =3D false; + } + + cleanup: + if (port) + virNetworkPortFree(port); + if (network) + virNetworkFree(network); + return ret; +} + + +/* + * "net-port-delete" command + */ +static const vshCmdInfo info_network_port_delete[] =3D { + {.name =3D "help", + .data =3D N_("network port information in XML") + }, + {.name =3D "desc", + .data =3D N_("Output the network port information as an XML dump to s= tdout.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_port_delete[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_NETWORK_PORT(0), + {.name =3D NULL} +}; + +static bool +cmdNetworkPortDelete(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPtr network =3D NULL; + virNetworkPortPtr port =3D NULL; + bool ret =3D true; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + if (!(network =3D virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + if (!(port =3D 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 =3D true; + cleanup: + if (port) + virNetworkPortFree(port); + if (network) + virNetworkFree(network); + return ret; +} + + +static int +virshNetworkPortSorter(const void *a, const void *b) +{ + virNetworkPortPtr *na =3D (virNetworkPortPtr *) a; + virNetworkPortPtr *nb =3D (virNetworkPortPtr *) b; + unsigned char uuida[VIR_UUID_BUFLEN]; + unsigned char uuidb[VIR_UUID_BUFLEN]; + + if (*na && !*nb) + return -1; + + if (!*na) + return *nb !=3D 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 =3D 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 =3D vshMalloc(ctl, sizeof(*list)); + int ret; + virNetworkPtr network =3D NULL; + bool success =3D false; + + if (!(network =3D virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + /* try the list with flags support (0.10.2 and later) */ + if ((ret =3D virNetworkListAllPorts(network, + &list->ports, + flags)) < 0) + goto cleanup; + + list->nports =3D ret; + + /* sort the list */ + if (list->ports && list->nports) + qsort(list->ports, list->nports, + sizeof(*list->ports), virshNetworkPortSorter); + + success =3D true; + + cleanup: + if (!success) { + virshNetworkPortListFree(list); + list =3D NULL; + } + + if (network) + virNetworkFree(network); + + return list; +} + +/* + * "net-list" command + */ +static const vshCmdInfo info_network_port_list[] =3D { + {.name =3D "help", + .data =3D N_("list network ports") + }, + {.name =3D "desc", + .data =3D N_("Returns list of network ports.") + }, + {.name =3D NULL} +}; + +static const vshCmdOptDef opts_network_port_list[] =3D { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + {.name =3D "uuid", + .type =3D VSH_OT_BOOL, + .help =3D N_("list uuid's only") + }, + {.name =3D "table", + .type =3D VSH_OT_BOOL, + .help =3D N_("list table (default)") + }, + {.name =3D NULL} +}; + +#define FILTER(NAME, FLAG) \ + if (vshCommandOptBool(cmd, NAME)) \ + flags |=3D (FLAG) +static bool +cmdNetworkPortList(vshControl *ctl, const vshCmd *cmd) +{ + virshNetworkPortListPtr list =3D NULL; + size_t i; + bool ret =3D false; + bool optTable =3D vshCommandOptBool(cmd, "table"); + bool optUUID =3D vshCommandOptBool(cmd, "uuid"); + char uuid[VIR_UUID_STRING_BUFLEN]; + unsigned int flags =3D 0; + vshTablePtr table =3D NULL; + + if (optTable + optUUID > 1) { + vshError(ctl, "%s", + _("Only one argument from --table and --uuid " + "may be specified.")); + return false; + } + + if (!optUUID) + optTable =3D true; + + if (!(list =3D virshNetworkPortListCollect(ctl, cmd, flags))) + return false; + + if (optTable) { + table =3D vshTableNew(_("UUID"), NULL); + if (!table) + goto cleanup; + } + + for (i =3D 0; i < list->nports; i++) { + virNetworkPortPtr port =3D 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 =3D true; + cleanup: + vshTableFree(table); + virshNetworkPortListFree(list); + return ret; +} +#undef FILTER + + const vshCmdDef networkCmds[] =3D { {.name =3D "net-autostart", .handler =3D cmdNetworkAutostart, @@ -1528,5 +1901,29 @@ const vshCmdDef networkCmds[] =3D { .info =3D info_network_uuid, .flags =3D 0 }, + {.name =3D "net-port-list", + .handler =3D cmdNetworkPortList, + .opts =3D opts_network_port_list, + .info =3D info_network_port_list, + .flags =3D 0 + }, + {.name =3D "net-port-create", + .handler =3D cmdNetworkPortCreate, + .opts =3D opts_network_port_create, + .info =3D info_network_port_create, + .flags =3D 0 + }, + {.name =3D "net-port-dumpxml", + .handler =3D cmdNetworkPortDumpXML, + .opts =3D opts_network_port_dumpxml, + .info =3D info_network_port_dumpxml, + .flags =3D 0 + }, + {.name =3D "net-port-delete", + .handler =3D cmdNetworkPortDelete, + .opts =3D opts_network_port_delete, + .info =3D info_network_port_delete, + .flags =3D 0 + }, {.name =3D 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); =20 +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, \ --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list