Use gateway from DHCP

pull/8/head
Jack O'Sullivan 5 years ago
parent 05aec4b0f8
commit 02d5109ced

@ -27,6 +27,17 @@ client = docker.from_env()
def close_docker(): def close_docker():
client.close() client.close()
host_dhcp_clients = {}
container_dhcp_clients = {}
@atexit.register
def cleanup_dhcp():
for endpoint, dhcp in host_dhcp_clients.items():
logger.warning('cleaning up orphaned host DHCP client (endpoint "%s")', endpoint)
dhcp.finish(timeout=1)
for endpoint, dhcp in container_dhcp_clients.items():
logger.warning('cleaning up orphaned container DHCP client (endpoint "%s")', endpoint)
dhcp.finish(timeout=1)
def veth_pair(e): def veth_pair(e):
return f'dh-{e[:12]}', f'{e[:12]}-dh' return f'dh-{e[:12]}', f'{e[:12]}-dh'
@ -114,10 +125,10 @@ def create_endpoint():
if addr.ip == bridge_addr.ip: if addr.ip == bridge_addr.ip:
raise NetDhcpError(400, f'Address {addr} is already in use on bridge {bridge["ifname"]}') raise NetDhcpError(400, f'Address {addr} is already in use on bridge {bridge["ifname"]}')
elif type_ == 'v4': elif type_ == 'v4':
dhcp = udhcpc.DHCPClient(if_container['ifname'], once=True) dhcp = udhcpc.DHCPClient(if_container['ifname'])
dhcp.finish() addr = dhcp.await_ip(timeout=10)
addr = dhcp.ip
res_iface['Address'] = str(addr) res_iface['Address'] = str(addr)
host_dhcp_clients[req['EndpointID']] = dhcp
else: else:
raise NetDhcpError(400, f'DHCPv6 is currently unsupported') raise NetDhcpError(400, f'DHCPv6 is currently unsupported')
logger.info('Adding address %s to %s', addr, if_container['ifname']) logger.info('Adding address %s to %s', addr, if_container['ifname'])
@ -180,6 +191,7 @@ def delete_endpoint():
@app.route('/NetworkDriver.Join', methods=['POST']) @app.route('/NetworkDriver.Join', methods=['POST'])
def join(): def join():
req = request.get_json(force=True) req = request.get_json(force=True)
endpoint = req['EndpointID']
bridge = net_bridge(req['NetworkID']) bridge = net_bridge(req['NetworkID'])
_if_host, if_container = veth_pair(req['EndpointID']) _if_host, if_container = veth_pair(req['EndpointID'])
@ -191,6 +203,13 @@ def join():
}, },
'StaticRoutes': [] 'StaticRoutes': []
} }
if endpoint in host_dhcp_clients:
dhcp = host_dhcp_clients[endpoint]
logger.info('Setting IPv4 gateway from DHCP (%s)', dhcp.gateway)
res['Gateway'] = str(dhcp.gateway)
dhcp.finish(timeout=1)
del host_dhcp_clients[endpoint]
ipv6 = ipv6_enabled(req['NetworkID']) ipv6 = ipv6_enabled(req['NetworkID'])
for route in bridge.routes: for route in bridge.routes:
if route['type'] != rtypes['RTN_UNICAST'] or (route['family'] == socket.AF_INET6 and not ipv6): if route['type'] != rtypes['RTN_UNICAST'] or (route['family'] == socket.AF_INET6 and not ipv6):

@ -1,6 +1,7 @@
from enum import Enum from enum import Enum
import ipaddress import ipaddress
from os import path from os import path
import time
import threading import threading
import subprocess import subprocess
import logging import logging
@ -9,6 +10,7 @@ from pyroute2.netns.process.proxy import NSPopen
INFO_PREFIX = '__info' INFO_PREFIX = '__info'
HANDLER_SCRIPT = path.join(path.dirname(__file__), 'udhcpc_handler.py') HANDLER_SCRIPT = path.join(path.dirname(__file__), 'udhcpc_handler.py')
AWAIT_INTERVAL = 0.1
class EventType(Enum): class EventType(Enum):
BOUND = 'bound' BOUND = 'bound'
@ -62,12 +64,22 @@ class DHCPClient:
logger.debug('[udhcp event] %s %s %s %s', event_type, self.ip, self.gateway, self.domain) logger.debug('[udhcp event] %s %s %s %s', event_type, self.ip, self.gateway, self.domain)
self.event_listener(event_type, self.ip, self.gateway, self.domain) self.event_listener(event_type, self.ip, self.gateway, self.domain)
def finish(self): def await_ip(self, timeout=5):
# TODO: this bad
waited = 0
while not self.ip:
if waited >= timeout:
raise DHCPClientError('Timed out waiting for dhcp lease')
time.sleep(AWAIT_INTERVAL)
waited += AWAIT_INTERVAL
return self.ip
def finish(self, timeout=5):
if not self.once: if not self.once:
self.proc.terminate() self.proc.terminate()
if self.proc.wait(timeout=10) != 0: if self.proc.wait(timeout=timeout) != 0:
raise DHCPClientError(f'udhcpc exited with non-zero exit code {self.proc.returncode}') raise DHCPClientError(f'udhcpc exited with non-zero exit code {self.proc.returncode}')
self._event_thread.join() self._event_thread.join()
if self.once and not self.ip: if self.once and not self.ip:
raise DHCPClientError(f'failed to obtain lease') raise DHCPClientError(f'Timed out waiting for dhcp lease')

Loading…
Cancel
Save