Extend ansible inventory from network config file

Some node network_config options defined in the baremetal
deployment yaml definition can't be stored on neutron resources
as tags, because tag strings has a limited max lenght.

In the triple-ansible change https://review.opendev.org/772766
the baremetal deployment workflow put's this data into a config
file. With this change the config in the file source is merged
into the generated ansible inventory.

Partial-Implements: blueprint network-data-v2-ports
Change-Id: I1e339acb21d2acb1c336420af9f04d01f861aa91
This commit is contained in:
Harald Jensås 2021-01-27 23:24:02 +01:00
parent 26f33ce897
commit 34aa73b075
3 changed files with 148 additions and 2 deletions

View File

@ -226,3 +226,5 @@ PER_STEP_TASKS = {
'update_tasks': _PER_STEP_TASK_STRICTNESS,
'post_update_tasks': [False, False, False, False]
}
INVENTORY_NETWORK_CONFIG_FILE = 'inventory-network-config.yaml'

View File

@ -238,7 +238,7 @@ class TripleoInventory(object):
cacert=None, username=None, ansible_ssh_user=None,
host_network=None, ansible_python_interpreter=None,
undercloud_connection=UNDERCLOUD_CONNECTION_LOCAL,
undercloud_key_file=None, serial=1):
undercloud_key_file=None, serial=1, work_dir=None):
self.session = session
self.hclient = hclient
self.host_network = host_network or HOST_NETWORK
@ -253,6 +253,7 @@ class TripleoInventory(object):
self.hostvars = {}
self.undercloud_connection = undercloud_connection
self.serial = serial
self.work_dir = work_dir
@staticmethod
def get_roles_by_service(enabled_services):
@ -578,6 +579,52 @@ class TripleoInventory(object):
allovercloud.setdefault('children',
self._hosts(sorted(children), dynamic))
def _extend_inventory(self, ret, dynamic, data=None):
if not data:
return
for role_name, role_values in data.items():
inventory_role = ret.get(role_name)
if not inventory_role:
continue
inventory_hosts = inventory_role.get('hosts', {})
inventory_vars = inventory_role.get('vars', {})
config_file_hosts = role_values.get('hosts', {})
config_file_vars = role_values.get('vars', {})
for k, v in config_file_vars.items():
inventory_vars.setdefault(k, v)
for config_file_host, host_values in config_file_hosts.items():
inventory_host = inventory_hosts.get(config_file_host, {})
if not inventory_host:
continue
for k, v in host_values.items():
inventory_host.setdefault(k, v)
self.hostvars.update(inventory_hosts)
if dynamic:
hosts_format = [h for h in inventory_hosts.keys()]
hosts_format.sort()
ret[role_name]['hosts'] = hosts_format
def _get_data_from_config_file(self):
if not self.plan_name:
return
if not self.work_dir:
return
data_file_path = os.path.join(self.work_dir,
constants.INVENTORY_NETWORK_CONFIG_FILE)
if not os.path.isfile(data_file_path):
return
with open(data_file_path, 'r') as f:
data = yaml.safe_load(f.read())
return data
def _undercloud_inventory(self, ret, dynamic):
undercloud = ret.setdefault('Undercloud', {})
undercloud.setdefault('hosts', self._hosts(['undercloud'], dynamic))
@ -651,6 +698,8 @@ class TripleoInventory(object):
self._undercloud_inventory(ret, dynamic)
self._inventory_from_neutron_data(ret, children, dynamic)
self._inventory_from_heat_outputs(ret, children, dynamic)
self._extend_inventory(ret, dynamic,
data=self._get_data_from_config_file())
return ret
@ -700,6 +749,9 @@ def generate_tripleo_ansible_inventory(heat, auth_url,
ssh_network='ctlplane',
session=None):
if not work_dir:
work_dir = os.path.join(os.path.expanduser('~'),
'overcloud-deploy-{}'.format(plan))
if not os.path.isdir(work_dir):
work_dir = tempfile.mkdtemp(prefix='tripleo-ansible')
inventory_path = os.path.join(
@ -715,7 +767,8 @@ def generate_tripleo_ansible_inventory(heat, auth_url,
undercloud_key_file=undercloud_key_file,
ansible_python_interpreter=ansible_python_interpreter,
plan_name=plan,
host_network=ssh_network)
host_network=ssh_network,
work_dir=work_dir)
inv.write_static_inventory(inventory_path)
return inventory_path

View File

@ -1161,6 +1161,97 @@ class TestInventory(base.TestCase):
for k in expected:
self.assertEqual(expected[k], inv_list[k])
def test__extend_inventory(self):
dynamic = False
existing_inventory = OrderedDict()
existing_inventory.update({
'RoleA': {
'hosts': {
'host0': {
'existing': 'existing_value'
}
},
'vars': {
'existing': 'existing_value'
},
}
})
extend_data = {
'RoleA': {
'hosts': {
'host0': {
'new': 'new_value',
'existing': 'not_overwritten',
}
},
'vars': {
'new': 'new_var_is_added',
'existing': 'not_overwritten',
},
}
}
expected_inventory = OrderedDict([(
'RoleA', {
'hosts': {
'host0': {
'existing': 'existing_value',
'new': 'new_value'
}
},
'vars': {
'existing': 'existing_value',
'new': 'new_var_is_added'
}
}
)])
self.inventory._extend_inventory(existing_inventory, dynamic,
data=extend_data)
self.assertEqual(expected_inventory, existing_inventory)
def test__extend_inventory_dynamic(self):
dynamic = True
existing_inventory = OrderedDict()
existing_inventory.update({
'RoleA': {
'hosts': {
'host0': {
'existing': 'existing_value'
}
},
'vars': {
'existing': 'existing_value'
},
}
})
extend_data = {
'RoleA': {
'hosts': {
'host0': {
'new': 'new_value',
'existing': 'not_overwritten',
}
},
'vars': {
'new': 'new_var_is_added',
'existing': 'not_overwritten',
},
}
}
expected_inventory = OrderedDict([(
'RoleA', {
'hosts': ['host0'],
'vars':
{'existing': 'existing_value',
'new': 'new_var_is_added'}})])
self.inventory._extend_inventory(existing_inventory, dynamic,
data=extend_data)
self.assertEqual(expected_inventory, existing_inventory)
self.assertEqual(
{'host0': {'existing': 'existing_value',
'new': 'new_value'}}, self.inventory.hostvars)
class TestNeutronData(base.TestCase):
def setUp(self):