Check for IP addresses assigned to multiple hosts

added a check in dynamic_inventory to discover
ip addresses assigned to more than one host in
openstack_user_config and warn users in case of any.

Change-Id: I5fc9c6441e82ccd37ab23ba2e194e30ae7918f00
This commit is contained in:
Ala Raddaoui 2016-04-21 05:30:57 +00:00
parent 1b4550b0b8
commit 3a5672beb3
2 changed files with 83 additions and 4 deletions

View File

@ -49,6 +49,22 @@ REQUIRED_HOSTVARS = [
]
class MultipleHostsWithOneIPError(Exception):
def __init__(self, ip, assigned_host, new_host):
self.ip = ip
self.assigned_host = assigned_host
self.new_host = new_host
error_msg = ("ip address:{} has already been "
"assigned to host:{}, cannot "
"assign same ip to host:{}")
self.message = error_msg.format(ip, assigned_host, new_host)
def __str__(self):
return self.message
def args():
"""Setup argument Parsing."""
parser = argparse.ArgumentParser(
@ -855,6 +871,26 @@ def _extra_config(user_defined_config, base_dir):
)
def _check_same_ip_to_multiple_host(config):
"""Check for IPs assigned to multiple hosts
: param: config: ``dict`` User provided configuration
"""
ips_to_hostnames_mapping = dict()
for key, value in config.iteritems():
if key.endswith('hosts'):
for _key, _value in value.iteritems():
hostname = _key
ip = _value['ip']
if not (ip in ips_to_hostnames_mapping):
ips_to_hostnames_mapping[ip] = hostname
else:
if ips_to_hostnames_mapping[ip] != hostname:
info = (ip, ips_to_hostnames_mapping[ip], hostname)
raise MultipleHostsWithOneIPError(*info)
def _check_config_settings(cidr_networks, config, container_skel):
"""check preciseness of config settings
@ -896,6 +932,8 @@ def _check_config_settings(cidr_networks, config, container_skel):
raise SystemExit(
"can't find " + q_name + " in cidr_networks"
)
# look for same ip address assigned to different hosts
_check_same_ip_to_multiple_host(config)
def load_environment(config_path):

View File

@ -329,8 +329,8 @@ class TestIps(unittest.TestCase):
class TestConfigChecks(unittest.TestCase):
def setUp(self):
self.config_changed = False
self.user_defined_config = dict()
with open(USER_CONFIG_FILE, 'rb') as f:
self.user_defined_config.update(yaml.safe_load(f.read()) or {})
@ -351,6 +351,7 @@ class TestConfigChecks(unittest.TestCase):
self.write_config()
def write_config(self):
self.config_changed = True
# rename temporarily our user_config_file so we can use the new one
os.rename(USER_CONFIG_FILE, USER_CONFIG_FILE + ".tmp")
# Save new user_config_file
@ -380,6 +381,14 @@ class TestConfigChecks(unittest.TestCase):
expectedLog = "No container CIDR specified in user config"
self.assertEqual(context.exception.message, expectedLog)
def set_new_hostname(self, user_defined_config, group,
old_hostname, new_hostname):
self.config_changed = True
# set a new name for the specified hostname
old_hostname_settings = user_defined_config[group].pop(old_hostname)
user_defined_config[group][new_hostname] = old_hostname_settings
self.write_config()
def test_provider_networks_check(self):
# create config file without provider networks
self.delete_config_key(self.user_defined_config, 'provider_networks')
@ -398,10 +407,42 @@ class TestConfigChecks(unittest.TestCase):
expectedLog = "global_overrides can't be found in user config"
self.assertEqual(context.exception.message, expectedLog)
def test_two_hosts_same_ip(self):
# Use an OrderedDict to be certain our testing order is preserved
# Even with the same hash seed, different OSes get different results,
# eg. local OS X vs gate's Linux
config = collections.OrderedDict()
config['infra_hosts'] = {
'host1': {
'ip': '192.168.1.1'
}
}
config['compute_hosts'] = {
'host2': {
'ip': '192.168.1.1'
}
}
with self.assertRaises(di.MultipleHostsWithOneIPError) as context:
di._check_same_ip_to_multiple_host(config)
self.assertEqual(context.exception.ip, '192.168.1.1')
self.assertEqual(context.exception.assigned_host, 'host1')
self.assertEqual(context.exception.new_host, 'host2')
def test_two_hosts_same_ip_externally(self):
self.set_new_hostname(self.user_defined_config, "haproxy_hosts",
"aio1", "hap")
with self.assertRaises(di.MultipleHostsWithOneIPError) as context:
get_inventory()
expectedLog = ("ip address:172.29.236.100 has already been assigned"
" to host:aio1, cannot assign same ip to host:hap")
self.assertEqual(context.exception.message, expectedLog)
def tearDown(self):
# get back our initial user config file
os.remove(USER_CONFIG_FILE)
os.rename(USER_CONFIG_FILE + ".tmp", USER_CONFIG_FILE)
if self.config_changed:
# get back our initial user config file
os.remove(USER_CONFIG_FILE)
os.rename(USER_CONFIG_FILE + ".tmp", USER_CONFIG_FILE)
if __name__ == '__main__':