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:
parent
1b4550b0b8
commit
3a5672beb3
@ -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():
|
def args():
|
||||||
"""Setup argument Parsing."""
|
"""Setup argument Parsing."""
|
||||||
parser = argparse.ArgumentParser(
|
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):
|
def _check_config_settings(cidr_networks, config, container_skel):
|
||||||
"""check preciseness of config settings
|
"""check preciseness of config settings
|
||||||
|
|
||||||
@ -896,6 +932,8 @@ def _check_config_settings(cidr_networks, config, container_skel):
|
|||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
"can't find " + q_name + " in cidr_networks"
|
"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):
|
def load_environment(config_path):
|
||||||
|
@ -329,8 +329,8 @@ class TestIps(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestConfigChecks(unittest.TestCase):
|
class TestConfigChecks(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.config_changed = False
|
||||||
self.user_defined_config = dict()
|
self.user_defined_config = dict()
|
||||||
with open(USER_CONFIG_FILE, 'rb') as f:
|
with open(USER_CONFIG_FILE, 'rb') as f:
|
||||||
self.user_defined_config.update(yaml.safe_load(f.read()) or {})
|
self.user_defined_config.update(yaml.safe_load(f.read()) or {})
|
||||||
@ -351,6 +351,7 @@ class TestConfigChecks(unittest.TestCase):
|
|||||||
self.write_config()
|
self.write_config()
|
||||||
|
|
||||||
def write_config(self):
|
def write_config(self):
|
||||||
|
self.config_changed = True
|
||||||
# rename temporarily our user_config_file so we can use the new one
|
# rename temporarily our user_config_file so we can use the new one
|
||||||
os.rename(USER_CONFIG_FILE, USER_CONFIG_FILE + ".tmp")
|
os.rename(USER_CONFIG_FILE, USER_CONFIG_FILE + ".tmp")
|
||||||
# Save new user_config_file
|
# Save new user_config_file
|
||||||
@ -380,6 +381,14 @@ class TestConfigChecks(unittest.TestCase):
|
|||||||
expectedLog = "No container CIDR specified in user config"
|
expectedLog = "No container CIDR specified in user config"
|
||||||
self.assertEqual(context.exception.message, expectedLog)
|
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):
|
def test_provider_networks_check(self):
|
||||||
# create config file without provider networks
|
# create config file without provider networks
|
||||||
self.delete_config_key(self.user_defined_config, '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"
|
expectedLog = "global_overrides can't be found in user config"
|
||||||
self.assertEqual(context.exception.message, expectedLog)
|
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):
|
def tearDown(self):
|
||||||
# get back our initial user config file
|
if self.config_changed:
|
||||||
os.remove(USER_CONFIG_FILE)
|
# get back our initial user config file
|
||||||
os.rename(USER_CONFIG_FILE + ".tmp", USER_CONFIG_FILE)
|
os.remove(USER_CONFIG_FILE)
|
||||||
|
os.rename(USER_CONFIG_FILE + ".tmp", USER_CONFIG_FILE)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user