|
|
@@ -25,10 +25,19 @@ logger = logging.getLogger('net-dhcp')
|
|
|
|
|
|
interface.InitializeLibrary(LIBRARY)
|
|
|
|
|
|
-client = docker.from_env()
|
|
|
+dockerClient = None
|
|
|
+
|
|
|
+def get_docker_client():
|
|
|
+ global dockerClient
|
|
|
+ if dockerClient is None:
|
|
|
+ dockerClient = docker.from_env()
|
|
|
+
|
|
|
@atexit.register
|
|
|
-def close_docker():
|
|
|
- client.close()
|
|
|
+def close_docker_client():
|
|
|
+ global dockerClient
|
|
|
+ if dockerClient is not None:
|
|
|
+ dockerClient.close()
|
|
|
+ dockerClient = None
|
|
|
|
|
|
gateway_hints = {}
|
|
|
container_dhcp_clients = {}
|
|
|
@@ -43,28 +52,34 @@ def veth_pair(e):
|
|
|
|
|
|
def iface_addrs(iface):
|
|
|
return list(map(lambda a: ipaddress.ip_interface((a['address'], a['prefixlen'])), iface.ipaddr))
|
|
|
+
|
|
|
def iface_nets(iface):
|
|
|
return list(map(lambda n: n.network, iface_addrs(iface)))
|
|
|
|
|
|
def get_bridges():
|
|
|
+ get_docker_client()
|
|
|
reserved_nets = set(map(ipaddress.ip_network, map(lambda c: c['Subnet'], \
|
|
|
itertools.chain.from_iterable(map(lambda i: i['Config'], filter(lambda i: i['Driver'] != 'net-dhcp', \
|
|
|
- map(lambda n: n.attrs['IPAM'], client.networks.list())))))))
|
|
|
+ map(lambda n: n.attrs['IPAM'], dockerClient.networks.list())))))))
|
|
|
|
|
|
return dict(map(lambda i: (i['ifname'], i), filter(lambda i: i['kind'] == 'bridge' and not \
|
|
|
set(iface_nets(i)).intersection(reserved_nets), map(lambda i: interface.GetInterface(LIBRARY, i['ifname']), \
|
|
|
interface.GetInterfaces(LIBRARY)))))
|
|
|
|
|
|
def net_bridge(n):
|
|
|
- return interface.GetInterface(LIBRARY, client.networks.get(n).attrs['Options'][OPT_BRIDGE])
|
|
|
+ get_docker_client()
|
|
|
+ return interface.GetInterface(LIBRARY, dockerClient.networks.get(n).attrs['Options'][OPT_BRIDGE])
|
|
|
+
|
|
|
def ipv6_enabled(n):
|
|
|
- options = client.networks.get(n).attrs['Options']
|
|
|
+ get_docker_client()
|
|
|
+ options = dockerClient.networks.get(n).attrs['Options']
|
|
|
return OPT_IPV6 in options and options[OPT_IPV6] == 'true'
|
|
|
|
|
|
def endpoint_container_iface(n, e):
|
|
|
- for cid, info in client.networks.get(n).attrs['Containers'].items():
|
|
|
+ get_docker_client()
|
|
|
+ for cid, info in dockerClient.networks.get(n).attrs['Containers'].items():
|
|
|
if info['EndpointID'] == e:
|
|
|
- container = client.containers.get(cid)
|
|
|
+ container = dockerClient.containers.get(cid)
|
|
|
netns = f'/proc/{container.attrs["State"]["Pid"]}/ns/net'
|
|
|
|
|
|
with pyroute2.NetNS(netns) as rtnl:
|
|
|
@@ -91,9 +106,10 @@ def await_endpoint_container_iface(n, e, timeout=5):
|
|
|
return iface
|
|
|
|
|
|
def endpoint_container_hostname(n, e):
|
|
|
- for cid, info in client.networks.get(n).attrs['Containers'].items():
|
|
|
+ get_docker_client()
|
|
|
+ for cid, info in dockerClient.networks.get(n).attrs['Containers'].items():
|
|
|
if info['EndpointID'] == e:
|
|
|
- return client.containers.get(cid).attrs['Config']['Hostname']
|
|
|
+ return dockerClient.containers.get(cid).attrs['Config']['Hostname']
|
|
|
return None
|
|
|
|
|
|
@app.route('/NetworkDriver.GetCapabilities', methods=['POST'])
|
|
|
@@ -378,6 +394,6 @@ class ContainerDHCPManager:
|
|
|
self._thread.join()
|
|
|
|
|
|
# we have to do this since the docker client leaks sockets...
|
|
|
- global client
|
|
|
- client.close()
|
|
|
- client = docker.from_env()
|
|
|
+ close_docker_client()
|
|
|
+ get_docker_client()
|
|
|
+
|