Send hostname with persistent DHCP requests

pull/8/head
Jack O'Sullivan 5 years ago
parent 010e9203a9
commit 7933149acf

@ -91,6 +91,12 @@ def await_endpoint_container_iface(n, e, timeout=5):
raise NetDhcpError('Timed out waiting for container to become availabile') raise NetDhcpError('Timed out waiting for container to become availabile')
return iface return iface
def endpoint_container_name(n, e):
for info in client.networks.get(n).attrs['Containers'].values():
if info['EndpointID'] == e:
return info['Name']
return None
@app.route('/NetworkDriver.GetCapabilities', methods=['POST']) @app.route('/NetworkDriver.GetCapabilities', methods=['POST'])
def net_get_capabilities(): def net_get_capabilities():
return jsonify({ return jsonify({
@ -340,13 +346,14 @@ class ContainerDHCPManager:
def run(self): def run(self):
try: try:
iface = await_endpoint_container_iface(self.network, self.endpoint) iface = await_endpoint_container_iface(self.network, self.endpoint)
hostname = endpoint_container_name(self.network, self.endpoint)
self.dhcp = udhcpc.DHCPClient(iface, event_listener=self._on_event) self.dhcp = udhcpc.DHCPClient(iface, event_listener=self._on_event, hostname=hostname)
logger.info('Starting DHCPv4 client on %s in container namespace %s', iface['ifname'], \ logger.info('Starting DHCPv4 client on %s in container namespace %s', iface['ifname'], \
self.dhcp.netns) self.dhcp.netns)
if self.ipv6: if self.ipv6:
self.dhcp6 = udhcpc.DHCPClient(iface, v6=True, event_listener=self._on_event) self.dhcp6 = udhcpc.DHCPClient(iface, v6=True, event_listener=self._on_event, hostname=hostname)
logger.info('Starting DHCPv6 client on %s in container namespace %s', iface['ifname'], \ logger.info('Starting DHCPv6 client on %s in container namespace %s', iface['ifname'], \
self.dhcp6.netns) self.dhcp6.netns)
except Exception as e: except Exception as e:

@ -1,6 +1,8 @@
from enum import Enum from enum import Enum
import ipaddress import ipaddress
import json import json
import struct
import binascii
import os import os
from os import path from os import path
from select import select from select import select
@ -30,7 +32,7 @@ class DHCPClientError(Exception):
def _nspopen_wrapper(netns): def _nspopen_wrapper(netns):
return lambda *args, **kwargs: NSPopen(netns, *args, **kwargs) return lambda *args, **kwargs: NSPopen(netns, *args, **kwargs)
class DHCPClient: class DHCPClient:
def __init__(self, iface, v6=False, once=False, event_listener=None): def __init__(self, iface, v6=False, once=False, hostname=None, event_listener=None):
self.iface = iface self.iface = iface
self.v6 = v6 self.v6 = v6
self.once = once self.once = once
@ -47,6 +49,18 @@ class DHCPClient:
bin_path = '/usr/bin/udhcpc6' if v6 else '/sbin/udhcpc' bin_path = '/usr/bin/udhcpc6' if v6 else '/sbin/udhcpc'
cmdline = [bin_path, '-s', HANDLER_SCRIPT, '-i', iface['ifname'], '-f'] cmdline = [bin_path, '-s', HANDLER_SCRIPT, '-i', iface['ifname'], '-f']
cmdline.append('-q' if once else '-R') cmdline.append('-q' if once else '-R')
if hostname:
cmdline.append('-x')
if v6:
# TODO: We encode the fqdn for DHCPv6 because udhcpc6 seems to be broken
# flags: S bit set (see RFC4704)
enc_hostname = hostname.encode('utf-8')
enc_hostname = struct.pack('BB', 0b0001, len(enc_hostname)) + enc_hostname
enc_hostname = binascii.hexlify(enc_hostname).decode('ascii')
hostname_opt = f'0x27:{enc_hostname}'
else:
hostname_opt = f'hostname:{hostname}'
cmdline.append(hostname_opt)
if not v6: if not v6:
cmdline += ['-V', VENDOR_ID] cmdline += ['-V', VENDOR_ID]
@ -54,6 +68,8 @@ class DHCPClient:
self._event_queue = posix_ipc.MessageQueue(f'/udhcpc{self._suffix}_{iface["address"].replace(":", "_")}', \ self._event_queue = posix_ipc.MessageQueue(f'/udhcpc{self._suffix}_{iface["address"].replace(":", "_")}', \
flags=os.O_CREAT | os.O_EXCL) flags=os.O_CREAT | os.O_EXCL)
self.proc = Popen(cmdline, env={'EVENT_QUEUE': self._event_queue.name}) self.proc = Popen(cmdline, env={'EVENT_QUEUE': self._event_queue.name})
if hostname:
logger.debug('[udhcpc%s#%d] using hostname "%s"', self._suffix, self.proc.pid, hostname)
self._has_lease = threading.Event() self._has_lease = threading.Event()
self.ip = None self.ip = None
@ -110,7 +126,7 @@ class DHCPClient:
if self._shutdown_event.is_set(): if self._shutdown_event.is_set():
return return
if self.proc.returncode != None and (not self.once or self.proc.returncode != 0): if self.proc.returncode is not None and (not self.once or self.proc.returncode != 0):
raise DHCPClientError(f'udhcpc{self._suffix} exited early with code {self.proc.returncode}') raise DHCPClientError(f'udhcpc{self._suffix} exited early with code {self.proc.returncode}')
if self.once: if self.once:
self.await_ip() self.await_ip()

Loading…
Cancel
Save