]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: support recording ports against virNetworkObjPtr
authorDaniel P. Berrangé <berrange@redhat.com>
Wed, 19 Dec 2018 14:24:53 +0000 (14:24 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Mon, 17 Jun 2019 14:41:31 +0000 (15:41 +0100)
The virNetworkObjPtr state will need to maintain a record of all
virNetworkPortDefPtr objects associated with the network. Record these
in a hash and add APIs for manipulating them.

Reviewed-by: Laine Stump <laine@laine.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/conf/virnetworkobj.c
src/conf/virnetworkobj.h
src/libvirt_private.syms

index c9336e04726f9f447c0df1470c0df8a127a53148..47c142998ed4bd4b010f08fe90a4ba357b8da347 100644 (file)
@@ -58,6 +58,8 @@ struct _virNetworkObj {
 
     /* Immutable pointer, self locking APIs */
     virMacMapPtr macmap;
+
+    virHashTablePtr ports; /* uuid -> virNetworkPortDefPtr */
 };
 
 struct _virNetworkObjList {
@@ -86,6 +88,17 @@ virNetworkObjOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(virNetworkObj);
 
+static int
+virNetworkObjLoadAllPorts(virNetworkObjPtr net,
+                          const char *stateDir);
+
+
+static void
+virNetworkObjPortFree(void *val, const void *key ATTRIBUTE_UNUSED)
+{
+    virNetworkPortDefFree(val);
+}
+
 virNetworkObjPtr
 virNetworkObjNew(void)
 {
@@ -106,6 +119,10 @@ virNetworkObjNew(void)
         virBitmapSetBitExpand(obj->classIdMap, 2) < 0)
         goto error;
 
+    if (!(obj->ports = virHashCreate(10,
+                                     virNetworkObjPortFree)))
+        goto error;
+
     virObjectLock(obj);
 
     return obj;
@@ -458,6 +475,7 @@ virNetworkObjDispose(void *opaque)
 {
     virNetworkObjPtr obj = opaque;
 
+    virHashFree(obj->ports);
     virNetworkDefFree(obj->def);
     virNetworkDefFree(obj->newDef);
     virBitmapFree(obj->classIdMap);
@@ -1072,9 +1090,16 @@ virNetworkObjLoadAllState(virNetworkObjListPtr nets,
             continue;
 
         obj = virNetworkLoadState(nets, stateDir, entry->d_name);
+
+        if (obj &&
+            virNetworkObjLoadAllPorts(obj, stateDir) < 0) {
+            virNetworkObjEndAPI(&obj);
+            goto cleanup;
+        }
         virNetworkObjEndAPI(&obj);
     }
 
+ cleanup:
     VIR_DIR_CLOSE(dir);
     return ret;
 }
@@ -1584,3 +1609,281 @@ virNetworkObjListPrune(virNetworkObjListPtr nets,
     virHashRemoveSet(nets->objs, virNetworkObjListPruneHelper, &data);
     virObjectRWUnlock(nets);
 }
+
+
+char *
+virNetworkObjGetPortStatusDir(virNetworkObjPtr net,
+                              const char *stateDir)
+{
+    char *ret;
+    ignore_value(virAsprintf(&ret, "%s/%s/ports", stateDir, net->def->name));
+    return ret;
+}
+
+int
+virNetworkObjAddPort(virNetworkObjPtr net,
+                     virNetworkPortDefPtr portdef,
+                     const char *stateDir)
+{
+    int ret = -1;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    char *dir = NULL;
+
+    virUUIDFormat(portdef->uuid, uuidstr);
+
+    if (virHashLookup(net->ports, uuidstr)) {
+        virReportError(VIR_ERR_NETWORK_PORT_EXIST,
+                       _("Network port with UUID %s already exists"),
+                       uuidstr);
+        goto cleanup;
+    }
+
+    if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+        goto cleanup;
+
+    if (virHashAddEntry(net->ports, uuidstr, portdef) < 0)
+        goto cleanup;
+
+    if (virNetworkPortDefSaveStatus(portdef, dir) < 0) {
+        virHashRemoveEntry(net->ports, uuidstr);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+
+virNetworkPortDefPtr
+virNetworkObjLookupPort(virNetworkObjPtr net,
+                        const unsigned char *uuid)
+{
+    virNetworkPortDefPtr ret = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    virUUIDFormat(uuid, uuidstr);
+
+    if (!(ret = virHashLookup(net->ports, uuidstr))) {
+        virReportError(VIR_ERR_NO_NETWORK_PORT,
+                       _("Network port with UUID %s does not exist"),
+                       uuidstr);
+        goto cleanup;
+    }
+
+ cleanup:
+    return ret;
+}
+
+
+int
+virNetworkObjDeletePort(virNetworkObjPtr net,
+                        const unsigned char *uuid,
+                        const char *stateDir)
+{
+    int ret = -1;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    char *dir = NULL;
+    virNetworkPortDefPtr portdef;
+
+    virUUIDFormat(uuid, uuidstr);
+
+    if (!(portdef = virHashLookup(net->ports, uuidstr))) {
+        virReportError(VIR_ERR_NO_NETWORK_PORT,
+                       _("Network port with UUID %s does not exist"),
+                       uuidstr);
+        goto cleanup;
+    }
+
+    if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+        goto cleanup;
+
+    if (virNetworkPortDefDeleteStatus(portdef, dir) < 0)
+        goto cleanup;
+
+    if (virHashRemoveEntry(net->ports, uuidstr) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(dir);
+    return ret;
+}
+
+
+int
+virNetworkObjDeleteAllPorts(virNetworkObjPtr net,
+                            const char *stateDir)
+{
+    char *dir;
+    DIR *dh;
+    struct dirent *de;
+    int rc;
+    int ret = -1;
+
+    if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+        goto cleanup;
+
+    if ((rc = virDirOpenIfExists(&dh, dir)) <= 0) {
+        ret = rc;
+        goto cleanup;
+    }
+
+    while ((rc = virDirRead(dh, &de, dir)) > 0) {
+        char *file = NULL;
+
+        if (!virStringStripSuffix(de->d_name, ".xml"))
+            continue;
+
+        if (virAsprintf(&file, "%s/%s.xml", dir, de->d_name) < 0)
+            goto cleanup;
+
+        if (unlink(file) < 0 && errno != ENOENT)
+            VIR_WARN("Unable to delete %s", file);
+
+        VIR_FREE(file);
+    }
+
+    virHashRemoveAll(net->ports);
+
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+
+typedef struct _virNetworkObjPortListExportData virNetworkObjPortListExportData;
+typedef virNetworkObjPortListExportData *virNetworkObjPortListExportDataPtr;
+struct _virNetworkObjPortListExportData {
+    virNetworkPtr net;
+    virNetworkDefPtr def;
+    virNetworkPortPtr *ports;
+    virNetworkPortListFilter filter;
+    int nports;
+    bool error;
+};
+
+static int
+virNetworkObjPortListExportCallback(void *payload,
+                                    const void *name ATTRIBUTE_UNUSED,
+                                    void *opaque)
+{
+    virNetworkObjPortListExportDataPtr data = opaque;
+    virNetworkPortDefPtr def = payload;
+    virNetworkPortPtr port;
+
+    if (data->error)
+        return 0;
+
+    if (data->filter &&
+        !data->filter(data->net->conn, data->def, def))
+        goto cleanup;
+
+    if (!data->ports) {
+        data->nports++;
+        goto cleanup;
+    }
+
+    if (!(port = virGetNetworkPort(data->net, def->uuid))) {
+        data->error = true;
+        goto cleanup;
+    }
+
+    data->ports[data->nports++] = port;
+
+ cleanup:
+    return 0;
+}
+
+
+int
+virNetworkObjPortListExport(virNetworkPtr net,
+                            virNetworkObjPtr obj,
+                            virNetworkPortPtr **ports,
+                            virNetworkPortListFilter filter)
+{
+    virNetworkObjPortListExportData data = {
+        net, obj->def, NULL, filter, 0, false,
+    };
+    int ret = -1;
+
+    *ports = NULL;
+
+    if (ports && VIR_ALLOC_N(data.ports, virHashSize(obj->ports) + 1) < 0)
+        goto cleanup;
+
+    virHashForEach(obj->ports, virNetworkObjPortListExportCallback, &data);
+
+    if (data.error)
+        goto cleanup;
+
+    if (data.ports) {
+        /* trim the array to the final size */
+        ignore_value(VIR_REALLOC_N(data.ports, data.nports + 1));
+        *ports = data.ports;
+        data.ports = NULL;
+    }
+
+    ret = data.nports;
+ cleanup:
+    while (data.ports && data.nports)
+        virObjectUnref(data.ports[--data.nports]);
+
+    VIR_FREE(data.ports);
+    return ret;
+}
+
+
+static int
+virNetworkObjLoadAllPorts(virNetworkObjPtr net,
+                          const char *stateDir)
+{
+    char *dir;
+    DIR *dh = NULL;
+    struct dirent *de;
+    int ret = -1;
+    int rc;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    virNetworkPortDefPtr portdef = NULL;
+
+    if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+        goto cleanup;
+
+    if ((rc = virDirOpenIfExists(&dh, dir)) <= 0) {
+        ret = rc;
+        goto cleanup;
+    }
+
+    while ((rc = virDirRead(dh, &de, dir)) > 0) {
+        char *file = NULL;
+
+        if (!virStringStripSuffix(de->d_name, ".xml"))
+            continue;
+
+        if (virAsprintf(&file, "%s/%s.xml", dir, de->d_name) < 0)
+            goto cleanup;
+
+        portdef = virNetworkPortDefParseFile(file);
+        VIR_FREE(file);
+        file = NULL;
+
+        if (!portdef) {
+            VIR_WARN("Cannot parse port %s", file);
+            continue;
+        }
+
+        virUUIDFormat(portdef->uuid, uuidstr);
+        if (virHashAddEntry(net->ports, uuidstr, portdef) < 0)
+            goto cleanup;
+
+        portdef = NULL;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_DIR_CLOSE(dh);
+    virNetworkPortDefFree(portdef);
+    return ret;
+}
index 3b296a10b38f36edcaeb06659359794fe1102dce..e649b6b3502ec9445757c7a057387b300751a5ba 100644 (file)
@@ -22,6 +22,7 @@
 #include "internal.h"
 
 #include "network_conf.h"
+#include "virnetworkportdef.h"
 
 typedef struct _virNetworkObj virNetworkObj;
 typedef virNetworkObj *virNetworkObjPtr;
@@ -155,6 +156,39 @@ void
 virNetworkObjRemoveInactive(virNetworkObjListPtr nets,
                             virNetworkObjPtr net);
 
+int
+virNetworkObjAddPort(virNetworkObjPtr net,
+                     virNetworkPortDefPtr portdef,
+                     const char *stateDir);
+
+char *
+virNetworkObjGetPortStatusDir(virNetworkObjPtr net,
+                              const char *stateDir);
+
+virNetworkPortDefPtr
+virNetworkObjLookupPort(virNetworkObjPtr net,
+                        const unsigned char *uuid);
+
+int
+virNetworkObjDeletePort(virNetworkObjPtr net,
+                        const unsigned char *uuid,
+                        const char *stateDir);
+
+int
+virNetworkObjDeleteAllPorts(virNetworkObjPtr net,
+                            const char *stateDir);
+
+typedef bool
+(*virNetworkPortListFilter)(virConnectPtr conn,
+                            virNetworkDefPtr def,
+                            virNetworkPortDefPtr portdef);
+
+int
+virNetworkObjPortListExport(virNetworkPtr net,
+                            virNetworkObjPtr obj,
+                            virNetworkPortPtr **ports,
+                            virNetworkPortListFilter filter);
+
 int
 virNetworkObjSaveStatus(const char *statusDir,
                         virNetworkObjPtr net) ATTRIBUTE_RETURN_CHECK;
index 2bf15cf8037c46158ddfab7c731268bfc3bdc0dd..81b1cbdcf45cd6d5c471ac552a9e6da06e680673 100644 (file)
@@ -1031,9 +1031,12 @@ virInterfaceObjSetActive;
 
 
 # conf/virnetworkobj.h
+virNetworkObjAddPort;
 virNetworkObjAssignDef;
 virNetworkObjBridgeInUse;
+virNetworkObjDeleteAllPorts;
 virNetworkObjDeleteConfig;
+virNetworkObjDeletePort;
 virNetworkObjEndAPI;
 virNetworkObjFindByName;
 virNetworkObjFindByUUID;
@@ -1044,6 +1047,7 @@ virNetworkObjGetFloorSum;
 virNetworkObjGetMacMap;
 virNetworkObjGetNewDef;
 virNetworkObjGetPersistentDef;
+virNetworkObjGetPortStatusDir;
 virNetworkObjGetRadvdPid;
 virNetworkObjIsActive;
 virNetworkObjIsAutostart;
@@ -1056,9 +1060,11 @@ virNetworkObjListNumOfNetworks;
 virNetworkObjListPrune;
 virNetworkObjLoadAllConfigs;
 virNetworkObjLoadAllState;
+virNetworkObjLookupPort;
 virNetworkObjMacMgrAdd;
 virNetworkObjMacMgrDel;
 virNetworkObjNew;
+virNetworkObjPortListExport;
 virNetworkObjRemoveInactive;
 virNetworkObjReplacePersistentDef;
 virNetworkObjSaveStatus;