From 8c0fc507499360bce22bd30a1edb1d0c81ffe1f9 Mon Sep 17 00:00:00 2001
From: Jacek Kowalski <Jacek@jacekk.info>
Date: Mon, 04 May 2020 23:08:58 +0000
Subject: [PATCH] Persist NetworkDriverData.networks on disk

---
 lib/NetworkDriver.py     |  159 ++++++++++++++++++++++++----------------------------
 lib/NetworkDriverData.py |   13 +++
 2 files changed, 84 insertions(+), 88 deletions(-)

diff --git a/lib/NetworkDriver.py b/lib/NetworkDriver.py
index 6e42b70..6fa4a0d 100644
--- a/lib/NetworkDriver.py
+++ b/lib/NetworkDriver.py
@@ -15,81 +15,10 @@
     return ''.join([random.choice(chars) for _ in range(size)])
 
 
-@app.route('/NetworkDriver.GetCapabilities', methods=['POST'])
-def GetCapabilities():
-    return {
-        'Scope': 'local',
-        'ConnectivityScope': 'global',
-    }
-
-
-@app.route('/NetworkDriver.CreateNetwork', methods=['POST'])
-def CreateNetwork():
-    network = NetworkCreateEntity(**flask.request.get_json(force=True))
-    try:
-        for option, value in network.Options['com.docker.network.generic'].items():
-            if option not in network.Options:
-                network.Options[option] = value
-    except KeyError:
-        pass
-    networks[network.NetworkID] = network
-    return {}
-
-
-@app.route('/NetworkDriver.DeleteNetwork', methods=['POST'])
-def DeleteNetwork():
-    network = NetworkDeleteEntity(**flask.request.get_json(force=True))
-    del networks[network.NetworkID]
-    return {}
-
-
-@app.route('/NetworkDriver.CreateEndpoint', methods=['POST'])
-def CreateEndpoint():
-    endpoint = EndpointCreateEntity(**flask.request.get_json(force=True))
-
-    endpoints['{}-{}'.format(endpoint.NetworkID, endpoint.EndpointID)] = endpoint
-    return {
-        'Interface': {
-        }
-    }
-
-
-@app.route('/NetworkDriver.EndpointOperInfo', methods=['POST'])
-def EndpointOperInfo():
-    endpoint = EndpointOperInfoEntity(**flask.request.get_json(force=True))
-    return {
-        'Value': {
-        }
-    }
-
-
-@app.route('/NetworkDriver.DeleteEndpoint', methods=['POST'])
-def DeleteEndpoint():
-    entity = EndpointDeleteEntity(**flask.request.get_json(force=True))
-    endpoint = endpoints['{}-{}'.format(entity.NetworkID, entity.EndpointID)]
-
-    try:
-        with pyroute2.IPRoute() as ip:
-            iface = ip.link_lookup(ifname=endpoint.Interface.Peer)[0]
-            if iface:
-                ip.link('del', index=iface)
-        del endpoint.Interface.Name
-        del endpoint.Interface.Peer
-    except AttributeError:
-        pass
-
-    del endpoints['{}-{}'.format(endpoint.NetworkID, endpoint.EndpointID)]
-    return {}
-
-
-@app.route('/NetworkDriver.Join', methods=['POST'])
-def Join():
-    join = JoinEntity(**flask.request.get_json(force=True))
-    network = networks[join.NetworkID]
-    endpoint = endpoints['{}-{}'.format(join.NetworkID, join.EndpointID)]
-
+def create_interface(endpoint, network) -> str:
     ifname0 = 'veth{}'.format(genid())
     ifname1 = 'veth{}'.format(genid())
+
     with pyroute2.IPRoute() as ip:
         ip.link('add', ifname=ifname0, peer=ifname1, kind='veth')
         idx = ip.link_lookup(ifname=ifname0)[0]
@@ -111,6 +40,76 @@
             print(ip.link("set", index=idx, master=id_parent))
         endpoint.Interface.Peer = ifname1
 
+    return ifname0
+
+
+@app.route('/NetworkDriver.GetCapabilities', methods=['POST'])
+def GetCapabilities():
+    return {
+        'Scope': 'local',
+        'ConnectivityScope': 'global',
+    }
+
+
+@app.route('/NetworkDriver.CreateNetwork', methods=['POST'])
+def CreateNetwork():
+    network = NetworkCreateEntity(**flask.request.get_json(force=True))
+    try:
+        for option, value in network.Options['com.docker.network.generic'].items():
+            if option not in network.Options:
+                network.Options[option] = value
+    except KeyError:
+        pass
+    networks[network.NetworkID] = network
+    networks_sync()
+    return {}
+
+
+@app.route('/NetworkDriver.DeleteNetwork', methods=['POST'])
+def DeleteNetwork():
+    network = NetworkDeleteEntity(**flask.request.get_json(force=True))
+    if network.NetworkID in networks:
+        del networks[network.NetworkID]
+        networks_sync()
+    return {}
+
+
+@app.route('/NetworkDriver.CreateEndpoint', methods=['POST'])
+def CreateEndpoint():
+    endpoint = EndpointCreateEntity(**flask.request.get_json(force=True))
+    endpoints['{}-{}'.format(endpoint.NetworkID, endpoint.EndpointID)] = endpoint
+    return {
+        'Interface': {
+        }
+    }
+
+
+@app.route('/NetworkDriver.EndpointOperInfo', methods=['POST'])
+def EndpointOperInfo():
+    endpoint = EndpointOperInfoEntity(**flask.request.get_json(force=True))
+    return {
+        'Value': {
+        }
+    }
+
+
+@app.route('/NetworkDriver.DeleteEndpoint', methods=['POST'])
+def DeleteEndpoint():
+    entity = EndpointDeleteEntity(**flask.request.get_json(force=True))
+    endpoint_id = '{}-{}'.format(entity.NetworkID, entity.EndpointID)
+    if endpoint_id in endpoints:
+        del endpoints['{}-{}'.format(entity.NetworkID, entity.EndpointID)]
+    return {}
+
+
+@app.route('/NetworkDriver.Join', methods=['POST'])
+def Join():
+    join = JoinEntity(**flask.request.get_json(force=True))
+    network = networks[join.NetworkID]
+    endpoint = endpoints['{}-{}'.format(join.NetworkID, join.EndpointID)]
+
+    interface = create_interface(endpoint, network)
+
     gw4 = None
     for net4 in network.IPv4:
         try:
@@ -128,7 +127,7 @@
 
     result = {
         'InterfaceName': {
-            'SrcName': ifname0,
+            'SrcName': interface,
             'DstPrefix': 'eth',
         },
     }
@@ -142,18 +141,6 @@
 @app.route('/NetworkDriver.Leave', methods=['POST'])
 def Leave():
     leave = LeaveEntity(**flask.request.get_json(force=True))
-    endpoint = endpoints['{}-{}'.format(leave.NetworkID, leave.EndpointID)]
-
-    try:
-        with pyroute2.IPRoute() as ip:
-            iface = ip.link_lookup(ifname=endpoint.Interface.Peer)[0]
-            if iface:
-                ip.link('del', index=iface)
-        del endpoint.Interface.Name
-        del endpoint.Interface.Peer
-    except AttributeError:
-        pass
-
     return {}
 
 
diff --git a/lib/NetworkDriverData.py b/lib/NetworkDriverData.py
index 3359851..909a034 100644
--- a/lib/NetworkDriverData.py
+++ b/lib/NetworkDriverData.py
@@ -1,6 +1,15 @@
+import shelve
 from typing import Dict
 
 from docker_plugin_api.NetworkDriverEntities import NetworkCreateEntity, EndpointCreateEntity
 
-networks : Dict[str, NetworkCreateEntity] = {}
-endpoints : Dict[str, EndpointCreateEntity] = {}
+
+networks_store = shelve.open('networks', writeback=True)
+networks: Dict[str, NetworkCreateEntity] = networks_store
+
+
+def networks_sync():
+    networks_store.sync()
+
+
+endpoints: Dict[str, EndpointCreateEntity] = {}

--
Gitblit v1.9.1