os-xenapi: Add utils to support HIMN configure
Add utils to do HIMN configuration. If the local HIMN interface is up and gets IP address allocated, we can get the interface via checking if the local interface has an IP belong to the same network as the dom0's HIMN IP which should be supplied. Otherwise read xenstore to get mac address and find the interface via mac. After identified the interface, we populate the ifcfg file to ensure this interface will be up in the future across boots. Change-Id: I5f8cd53710edb714f0c4c1dc50c1d4472f2e365f Depends-on: Ia363afc1fc932bf44a7ac956a5bc27978bb47868
This commit is contained in:
parent
99ea3ef3fa
commit
7b6aa0ad9b
77
os_xenapi/utils/common_function.py
Normal file
77
os_xenapi/utils/common_function.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright 2017 Citrix Systems
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""The common functions for XenAPI utils
|
||||
|
||||
It contains the common functions used by XenAPI utils."""
|
||||
|
||||
import logging
|
||||
import netifaces
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from os_xenapi.client import exception
|
||||
|
||||
|
||||
LOG = logging.getLogger('XenAPI_utils')
|
||||
|
||||
|
||||
def detailed_execute(*cmd, **kwargs):
|
||||
cmd = map(str, cmd)
|
||||
_env = kwargs.get('env')
|
||||
env_prefix = ''
|
||||
if _env:
|
||||
env_prefix = ''.join(['%s=%s ' % (k, _env[k]) for k in _env])
|
||||
|
||||
env = dict(os.environ)
|
||||
env.update(_env)
|
||||
else:
|
||||
env = None
|
||||
LOG.info(env_prefix + ' '.join(cmd))
|
||||
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, # nosec
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, env=env)
|
||||
|
||||
prompt = kwargs.get('prompt')
|
||||
if prompt:
|
||||
(out, err) = proc.communicate(prompt)
|
||||
else:
|
||||
(out, err) = proc.communicate()
|
||||
|
||||
if out:
|
||||
# Truncate "\n" if it is the last char
|
||||
out = out.strip()
|
||||
LOG.debug(out)
|
||||
if err:
|
||||
LOG.info(err)
|
||||
|
||||
if proc.returncode is not None and proc.returncode != 0:
|
||||
if proc.returncode in kwargs.get('allowed_return_codes', [0]):
|
||||
LOG.info('Swallowed acceptable return code of %d',
|
||||
proc.returncode)
|
||||
else:
|
||||
LOG.warn('proc.returncode: %s', proc.returncode)
|
||||
raise exception(err)
|
||||
|
||||
return proc.returncode, out, err
|
||||
|
||||
|
||||
def execute(*cmd, **kwargs):
|
||||
_, out, _ = detailed_execute(*cmd, **kwargs)
|
||||
return out
|
||||
|
||||
|
||||
def get_eth_mac(eth):
|
||||
# Get eth's mac address.
|
||||
return netifaces.ifaddresses(eth).get(netifaces.AF_LINK)[0]['addr']
|
97
os_xenapi/utils/himn.py
Normal file
97
os_xenapi/utils/himn.py
Normal file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright 2017 Citrix Systems
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""HIMN utils
|
||||
|
||||
It contains the utiles relative to HIMN(Host Internal Management Network."""
|
||||
|
||||
import ipaddress
|
||||
import netifaces
|
||||
import sys
|
||||
|
||||
from os_xenapi.client import exception
|
||||
from os_xenapi.utils import common_function
|
||||
|
||||
|
||||
def get_local_himn_eth_via_xenstore():
|
||||
# Find HIMN eth by querying xenstore.
|
||||
domid = common_function.execute('xenstore-read', 'domid')
|
||||
himn_mac = common_function.execute(
|
||||
'xenstore-read',
|
||||
'/local/domain/%s/vm-data/himn_mac' % domid)
|
||||
|
||||
eths = [eth for eth in netifaces.interfaces()
|
||||
if common_function.get_eth_mac(eth) == himn_mac]
|
||||
if len(eths) != 1:
|
||||
raise exception('Cannot find eth matches himn_mac')
|
||||
|
||||
return eths[0]
|
||||
|
||||
|
||||
def get_local_himn_eth_via_ip(ip_in_himn, eths=None):
|
||||
# Get the local interface which is connected to HIMN by searching
|
||||
# an eth whose IP address is in the same network as `ip_in_himn`.
|
||||
# By default search all available interfaces. The parameter of
|
||||
# `eths` can be used to specify a list of interfaces, so that
|
||||
# it will only search interfaces belong to the list.
|
||||
if eths is None:
|
||||
eths = netifaces.interfaces()
|
||||
for eth in eths:
|
||||
ipv4s = netifaces.ifaddresses(eth).get(netifaces.AF_INET, [])
|
||||
for ipv4 in ipv4s:
|
||||
net = ipaddress.ip_network(ipv4['netmask'])
|
||||
hint_himn_ipaddr = ipaddress.ip_address(unicode(ip_in_himn))
|
||||
if hint_himn_ipaddr in net:
|
||||
# Got the interface which has an IP address belong to HIMN.
|
||||
return eth
|
||||
return None
|
||||
|
||||
|
||||
def get_local_himn_eth(himn_dom0_ip):
|
||||
eth = get_local_himn_eth_via_ip(himn_dom0_ip)
|
||||
if eth:
|
||||
return eth
|
||||
# the local HIMN interfae has not got IP address: e.g. the interface
|
||||
# is not up or has not requested DHCP address; then try to get eth
|
||||
# via xenstore.
|
||||
return get_local_himn_eth_via_xenstore()
|
||||
|
||||
|
||||
def persist_eth_cfg(eth, bootproto='dhcp', defroute='no', onboot='yes'):
|
||||
# Persist eth configure into ifcfg-eth file.
|
||||
ifcfg_file = '/etc/sysconfig/network-scripts/ifcfg-%s' % eth
|
||||
with open(ifcfg_file, 'w') as ifcfg:
|
||||
ifcfg.write('DEVICE="%s\n"' % eth)
|
||||
ifcfg.write('IPV6INIT="no"')
|
||||
ifcfg.write('BOOTPROTO="%s\n"' % bootproto)
|
||||
ifcfg.write('DEFROUTE="%s\n"' % defroute)
|
||||
ifcfg.write('ONBOOT="%s\n"' % onboot)
|
||||
|
||||
|
||||
def config_himn(himn_dom0_ip):
|
||||
eth = get_local_himn_eth(himn_dom0_ip)
|
||||
# populate the ifcfg file for HIMN interface, so that it will always get ip
|
||||
# in the future.
|
||||
if not eth:
|
||||
raise exception("can't find eth on %s" % himn_dom0_ip)
|
||||
persist_eth_cfg(eth)
|
||||
# Force a restart on this interface by using the configure file.
|
||||
# It will ensure the interface up and refresh IP via DHCP.
|
||||
# NOTE(jianghuaw): use ifconfig to activate interface firstly.
|
||||
common_function.execute('ifconfig', eth, 'up')
|
||||
common_function.execute('ifdown', eth)
|
||||
common_function.execute('ifup', eth)
|
||||
|
||||
if __name__ == '__main__':
|
||||
config_himn(sys.argv[1])
|
Loading…
x
Reference in New Issue
Block a user