diff --git a/deployment_scripts/compute_post_deployment.py b/deployment_scripts/compute_post_deployment.py index 0f47cb2..928a108 100755 --- a/deployment_scripts/compute_post_deployment.py +++ b/deployment_scripts/compute_post_deployment.py @@ -68,7 +68,11 @@ def execute(*cmd, **kwargs): logging.error(err) if proc.returncode is not None and proc.returncode != 0: - raise Exception(err) + if proc.returncode in kwargs.get('allowed_return_codes', [0]): + logging.info('Swallowed acceptable return code of %d', + proc.returncode) + else: + raise Exception(err) return out @@ -161,13 +165,25 @@ def get_endpoints(astute): return endpoints -def init_eth(): - """Initialize the net interface connected to HIMN +def eth_to_mac(eth): + return netifaces.ifaddresses(eth).get(netifaces.AF_LINK)[0]['addr'] - Returns: - the IP addresses of local host and XenServer. - """ +def detect_himn_ip(eths=None): + if eths is None: + eths = netifaces.interfaces() + for eth in eths: + ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET) + if ip is None: + continue + himn_local = ip[0]['addr'] + himn_xs = '.'.join(himn_local.split('.')[:-1] + ['1']) + if HIMN_IP == himn_xs: + return eth, ip + return None, None + + +def find_eth_xenstore(): domid = execute('xenstore-read', 'domid') himn_mac = execute( 'xenstore-read', @@ -176,16 +192,56 @@ def init_eth(): _mac = lambda eth: \ netifaces.ifaddresses(eth).get(netifaces.AF_LINK)[0]['addr'] - eths = [eth for eth in netifaces.interfaces() if _mac(eth) == himn_mac] + eths = [eth for eth in netifaces.interfaces() + if eth_to_mac(eth) == himn_mac] if len(eths) != 1: reportError('Cannot find eth matches himn_mac') - eth = eths[0] - logging.info('himn_eth: %s' % eth) + return eths[0] - ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET) + +def detect_eth_dhclient(): + for eth in netifaces.interfaces(): + # Don't try and dhclient for devices an IP address already + ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET) + if ip: + continue + + # DHCP replies from HIMN should be super fast + execute('timeout', '2s', 'dhclient', eth, + allowed_return_codes=[0, 124]) + try: + _, ip = detect_himn_ip([eth]) + if ip is not None: + return eth + finally: + execute('dhclient', '-r', eth) + + +def init_eth(): + """Initialize the net interface connected to HIMN + + Returns: + the IP addresses of local host and hypervisor. + """ + + eth, ip = detect_himn_ip() if not ip: + eth = None + try: + eth = find_eth_xenstore() + except Exception: + logging.debug('Failed to find MAC through xenstore', exc_info=True) + + if eth is None: + eth = detect_eth_dhclient() + + if eth is None: + reportError('Failed to detect HIMN ethernet device') + + logging.info('himn_eth: %s' % eth) + execute('dhclient', eth) fname = '/etc/network/interfaces.d/ifcfg-' + eth s = ('auto {eth}\n' @@ -196,16 +252,22 @@ def init_eth(): logging.info('%s created' % fname) execute('ifdown', eth) execute('ifup', eth) + ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET) - if ip: himn_local = ip[0]['addr'] himn_xs = '.'.join(himn_local.split('.')[:-1] + ['1']) - if HIMN_IP == himn_xs: - logging.info('himn_local: %s' % himn_local) - return eth, himn_local + if HIMN_IP != himn_xs: + # Not on the HIMN - we failed here. + logging.info('himn_local: DHCP returned incorrect IP %s' % + ip[0]['addr']) + ip = None - reportError('HIMN failed to get IP address from XenServer') + if not ip: + reportError('HIMN failed to get IP address from Hypervisor') + + logging.info('himn_local: %s' % ip[0]['addr']) + return eth, ip[0]['addr'] def check_host_compatibility(himn, username):