Check for HIMN using dhcp discovery

A future plan for this plugin is to not require the HIMN XC
plugin but to support adding the network just in XenCenter
(with hidden objects displayed). Therefore the fuel plugin
should try to auto detect the HIMN as the MAC would not be
written to XenStore.

Change-Id: I7bb120ab79b486fa5ee201385e91c3c450454527
This commit is contained in:
Bob Ball 2016-09-05 17:12:59 +01:00
parent b772bc52ef
commit 01402e857c
1 changed files with 82 additions and 25 deletions

View File

@ -60,7 +60,11 @@ def execute(*cmd, **kwargs):
logging.error(err)
if proc.returncode is not None and proc.returncode != 0:
raise ExecutionError(err)
if proc.returncode in kwargs.get('allowed_return_codes', [0]):
logging.info('Swallowed acceptable return code of %d',
proc.returncode)
else:
raise ExecutionError(err)
return out
@ -114,6 +118,57 @@ def get_options(astute, astute_section=ASTUTE_SECTION):
options['install_xapi']
def eth_to_mac(eth):
return netifaces.ifaddresses(eth).get(netifaces.AF_LINK)[0]['addr']
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',
'/local/domain/%s/vm-data/himn_mac' % domid)
logging.info('himn_mac: %s' % 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')
return eths[0]
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
@ -121,26 +176,23 @@ def init_eth():
the IP addresses of local host and hypervisor.
"""
def _mac(eth):
return netifaces.ifaddresses(eth).get(netifaces.AF_LINK)[0]['addr']
domid = execute('xenstore-read', 'domid')
himn_mac = execute(
'xenstore-read',
'/local/domain/%s/vm-data/himn_mac' % domid)
logging.info('himn_mac: %s' % himn_mac)
eths = [eth for eth in netifaces.interfaces() if _mac(eth) == himn_mac]
if len(eths) != 1:
reportError('Cannot find eth matches himn_mac')
eth = eths[0]
logging.info('himn_eth: %s' % eth)
ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET)
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'
@ -151,13 +203,18 @@ def init_eth():
logging.info('%s created' % fname)
execute('ifdown', eth)
execute('ifup', eth)
ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET)
if ip:
ip = netifaces.ifaddresses(eth).get(netifaces.AF_INET)
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 Hypervisor')
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']