From 2682e8ba37fd3ce8bcbb53c399489d44bb33c92f Mon Sep 17 00:00:00 2001 From: Alessandro Pilotti Date: Sat, 26 Jul 2014 02:50:42 +0300 Subject: [PATCH] Adds bind retry option for DHCP client This is necessary in case the DHCP client port is already temporarily bound. --- cloudbaseinit/utils/dhcp.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/cloudbaseinit/utils/dhcp.py b/cloudbaseinit/utils/dhcp.py index 74542377..c9b090cc 100644 --- a/cloudbaseinit/utils/dhcp.py +++ b/cloudbaseinit/utils/dhcp.py @@ -17,6 +17,9 @@ import netifaces import random import socket import struct +import time + +from cloudbaseinit.openstack.common import log as logging _DHCP_COOKIE = b'\x63\x82\x53\x63' _OPTION_END = b'\xff' @@ -24,6 +27,8 @@ _OPTION_END = b'\xff' OPTION_MTU = 26 OPTION_NTP_SERVERS = 42 +LOG = logging.getLogger(__name__) + def _get_dhcp_request_data(id_req, mac_address, requested_options, vendor_id): @@ -97,14 +102,33 @@ def _get_mac_address_by_local_ip(ip_addr): return addrs[netifaces.AF_LINK][0]['addr'] +def _bind_dhcp_client_socket(s, max_bind_attempts, bind_retry_interval): + bind_attempts = 1 + while True: + try: + s.bind(('', 68)) + break + except socket.error, ex: + if (bind_attempts >= max_bind_attempts or + ex.errno not in [48, 10048]): + raise + bind_attempts += 1 + LOG.exception(ex) + LOG.info("Retrying to bind DHCP client port in %s seconds" % + bind_retry_interval) + time.sleep(bind_retry_interval) + + def get_dhcp_options(dhcp_host, requested_options=[], timeout=5.0, - vendor_id='cloudbase-init'): + vendor_id='cloudbase-init', max_bind_attempts=10, + bind_retry_interval=3): id_req = random.randint(0, 2 ** 32 - 1) options = None s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: - s.bind(('', 68)) + _bind_dhcp_client_socket(s, max_bind_attempts, bind_retry_interval) + s.settimeout(timeout) s.connect((dhcp_host, 67))