[libvirt] [PATCH v4 24/29] conf: support recording ports against virNetworkObjPtr

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


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.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/conf/virnetworkobj.c | 303 +++++++++++++++++++++++++++++++++++++++
 src/conf/virnetworkobj.h |  34 +++++
 src/libvirt_private.syms |   6 +
 3 files changed, 343 insertions(+)

diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c
index c9336e0472..47c142998e 100644
--- a/src/conf/virnetworkobj.c
+++ b/src/conf/virnetworkobj.c
@@ -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;
+}
diff --git a/src/conf/virnetworkobj.h b/src/conf/virnetworkobj.h
index 9c8f141cd9..9d9b29fc25 100644
--- a/src/conf/virnetworkobj.h
+++ b/src/conf/virnetworkobj.h
@@ -23,6 +23,7 @@
 # include "internal.h"
 
 # include "network_conf.h"
+# include "virnetworkportdef.h"
 
 typedef struct _virNetworkObj virNetworkObj;
 typedef virNetworkObj *virNetworkObjPtr;
@@ -156,6 +157,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;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bcd49904b2..ca81b2c4fc 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1030,9 +1030,12 @@ virInterfaceObjSetActive;
 
 
 # conf/virnetworkobj.h
+virNetworkObjAddPort;
 virNetworkObjAssignDef;
 virNetworkObjBridgeInUse;
+virNetworkObjDeleteAllPorts;
 virNetworkObjDeleteConfig;
+virNetworkObjDeletePort;
 virNetworkObjEndAPI;
 virNetworkObjFindByName;
 virNetworkObjFindByUUID;
@@ -1043,6 +1046,7 @@ virNetworkObjGetFloorSum;
 virNetworkObjGetMacMap;
 virNetworkObjGetNewDef;
 virNetworkObjGetPersistentDef;
+virNetworkObjGetPortStatusDir;
 virNetworkObjGetRadvdPid;
 virNetworkObjIsActive;
 virNetworkObjIsAutostart;
@@ -1055,9 +1059,11 @@ virNetworkObjListNumOfNetworks;
 virNetworkObjListPrune;
 virNetworkObjLoadAllConfigs;
 virNetworkObjLoadAllState;
+virNetworkObjLookupPort;
 virNetworkObjMacMgrAdd;
 virNetworkObjMacMgrDel;
 virNetworkObjNew;
+virNetworkObjPortListExport;
 virNetworkObjRemoveInactive;
 virNetworkObjReplacePersistentDef;
 virNetworkObjSaveStatus;
-- 
2.20.1




More information about the libvir-list mailing list