From 1878defa477812781b78f00f5e389304217de698 Mon Sep 17 00:00:00 2001
From: Jacek Kowalski <Jacek@jacekk.info>
Date: Sun, 03 May 2026 12:45:19 +0000
Subject: [PATCH] Persist IPAM pool data

---
 lib/IpamDriver.py     |    9 ++-------
 lib/Ipam.py           |    7 +++++--
 lib/IpamDriverData.py |   36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/lib/Ipam.py b/lib/Ipam.py
index f1d7659..73f4f67 100644
--- a/lib/Ipam.py
+++ b/lib/Ipam.py
@@ -120,7 +120,10 @@
         check[str(pool)] = pool
         return str(pool)
 
-    def get_pool(self, pool: str) -> Pool:
+    def has_pool(self, pool_id: str) -> bool:
+        return pool_id in self.pools or pool_id in self.pools6
+
+    def get_pool(self, pool: str | Pool) -> Pool:
         pool = str(pool)
         if pool in self.pools:
             return self.pools[pool]
@@ -129,7 +132,7 @@
         else:
             raise InputValidationException('Unknown pool {}'.format(pool))
 
-    def remove_pool(self, pool: str):
+    def remove_pool(self, pool: str | Pool):
         pool = str(pool)
         if pool in self.pools:
             del self.pools[pool]
diff --git a/lib/IpamDriver.py b/lib/IpamDriver.py
index 31a50dc..c0605c2 100644
--- a/lib/IpamDriver.py
+++ b/lib/IpamDriver.py
@@ -1,6 +1,5 @@
 from docker_plugin_api.Plugin import Blueprint
 import flask
-from .Ipam import *
 from .IpamDriverData import *
 from docker_plugin_api.IpamDriverEntities import *
 
@@ -26,10 +25,7 @@
 @app.route('/IpamDriver.RequestPool', methods=['POST'])
 def RequestPool():
     request = RequestPoolEntity(**flask.request.get_json(force=True))
-    space = spaces[request.AddressSpace]
-    pool = Pool(pool=request.Pool, subPool=request.SubPool, options=request.Options, v6=request.V6)
-    pool_id = space.add_pool(pool)
-    full_id = '{}-{}'.format(space.name, pool_id)
+    full_id, pool = create_pool(request)
     return {
         'PoolID': full_id,
         'Pool': str(pool),
@@ -40,8 +36,7 @@
 @app.route('/IpamDriver.ReleasePool', methods=['POST'])
 def ReleasePool():
     request = ReleasePoolEntity(**flask.request.get_json(force=True))
-    space, pool = get_space_pool(request.PoolID)
-    space.remove_pool(pool)
+    remove_pool(request.PoolID)
     return {}
 
 
diff --git a/lib/IpamDriverData.py b/lib/IpamDriverData.py
index 331608b..ea30742 100644
--- a/lib/IpamDriverData.py
+++ b/lib/IpamDriverData.py
@@ -1,15 +1,49 @@
+import shelve
+from typing import Dict
+
+from docker_plugin_api.IpamDriverEntities import *
+
 from .Ipam import *
 
+
+pools_store = shelve.open('pools', writeback=True)
+pools: Dict[str, RequestPoolEntity] = pools_store
+
+
+def pools_sync():
+    pools_store.sync()
+
+
 spaces = {
     'local': Space('local'),
     'global': Space('global'),
 }
 
 
+def create_pool(request: RequestPoolEntity) -> tuple[str, Pool]:
+    space = spaces[request.AddressSpace]
+    pool = Pool(pool=request.Pool, subPool=request.SubPool, options=request.Options, v6=request.V6)
+    pool_id = space.add_pool(pool)
+    full_id = '{}-{}'.format(space.name, pool_id)
+    pools[full_id] = request
+    pools_sync()
+    return full_id, pool
+
+
+def remove_pool(full_id: str):
+    space, pool = get_space_pool(full_id)
+    space.remove_pool(pool)
+    if full_id in pools:
+        del pools[full_id]
+        pools_sync()
+
+
 def get_space_pool(full_id: str):
     space_id, pool_id = full_id.rsplit('-', 2)
     space = spaces[space_id]
+    if not space.has_pool(pool_id) and full_id in pools:
+        create_pool(pools[full_id])
     return space, space.get_pool(pool_id)
 
 
-__all__ = ['spaces', 'get_space_pool']
+__all__ = ['spaces', 'get_space_pool', 'pools', 'pools_sync', 'create_pool', 'remove_pool']

--
Gitblit v1.10.0