Fix node extract when no network-isolation

When network isolation is not enabled by
environments/network-isolation.yaml the networks in the default
networks file is not created. But the RoleNetIpMap still have
entries for each network all with the ctlplane IP address.

This change re-factors the code to ignore RoleNetIpMap entries
when the network is not found/does not exist.

Change-Id: If35ff8a1b3d9b4e93e6151c9c28d8e9c707bc64a
Closes-Bug: #2027580
This commit is contained in:
Harald Jensås 2023-09-04 19:57:09 +02:00
parent 2e31655f5b
commit b6fb1e58b1
No known key found for this signature in database
GPG Key ID: 693852E00DCEA408
2 changed files with 142 additions and 7 deletions

View File

@ -1247,3 +1247,133 @@ class TestExtractProvisionedNode(test_utils.TestCommand):
self.cmd.take_action(parsed_args)
result = self.cmd.app.stdout.make_string()
self.assertIsNone(yaml.safe_load(result))
@mock.patch('tripleoclient.utils.run_command_and_log', autospec=True)
def test_extract_no_network_isolation(self, mock_run_cmd):
controller_ips = ['192.168.25.21', '192.168.25.25', '192.168.25.28']
compute_ips = ['192.168.26.11']
roles_data = [
{'name': 'Controller',
'default_route_networks': ['External'],
'networks_skip_config': ['Tenant']},
{'name': 'Compute'}
]
networks_data = []
stack_dict = {
'parameters': {
'ComputeHostnameFormat': '%stackname%-novacompute-%index%',
'ControllerHostnameFormat': '%stackname%-controller-%index%',
},
'outputs': [{
'output_key': 'TripleoHeatTemplatesJinja2RenderingDataSources',
'output_value': {
'roles_data': roles_data,
'networks_data': networks_data,
}
}, {
'output_key': 'AnsibleHostVarsMap',
'output_value': {
'Compute': [
'overcloud-novacompute-0'
],
'Controller': [
'overcloud-controller-0',
'overcloud-controller-1',
'overcloud-controller-2'
],
}
}, {
'output_key': 'RoleNetIpMap',
'output_value': {
'Compute': {
'ctlplane': compute_ips,
'internal_api': compute_ips,
},
'Controller': {
'ctlplane': controller_ips,
'external': controller_ips,
'internal_api': controller_ips,
}
}
}]
}
stack = mock.Mock()
stack.stack_name = 'overcloud'
stack.to_dict.return_value = stack_dict
stack.environment.return_value = {}
self.orchestration.stacks.get.return_value = stack
self.baremetal.node.list.return_value = self.nodes
self.network.find_network.side_effect = [
self.ctlplane_net, None,
# controller-0
self.ctlplane_net, None, None,
# controller-1
self.ctlplane_net, None, None,
# controller-2
self.ctlplane_net, None, None,
]
self.network.get_subnet.side_effect = [
# compute-0
self.ctlplane_a, self.ctlplane_b,
# controller-0
self.ctlplane_a,
# controller-1
self.ctlplane_a,
# controller-2
self.ctlplane_a,
]
mock_run_cmd.return_value = 0
argslist = ['--output', self.extract_file.name,
'--yes']
self.app.command_options = argslist
verifylist = [('output', self.extract_file.name),
('yes', True)]
parsed_args = self.check_parser(self.cmd,
argslist, verifylist)
self.cmd.take_action(parsed_args)
result = self.cmd.app.stdout.make_string()
self.assertEqual([{
'name': 'Compute',
'count': 1,
'hostname_format': '%stackname%-novacompute-%index%',
'defaults': {
'network_config': {'network_config_update': False,
'physical_bridge_name': 'br-ex',
'public_interface_name': 'nic1',
'template': None},
'networks': [{'network': 'ctlplane', 'vif': True}]
},
'instances': [{
'hostname': 'overcloud-novacompute-0',
'name': 'bm-3-uuid',
'resource_class': 'compute',
}],
}, {
'name': 'Controller',
'count': 3,
'hostname_format': '%stackname%-controller-%index%',
'defaults': {
'network_config': {'default_route_network': ['External'],
'network_config_update': False,
'networks_skip_config': ['Tenant'],
'physical_bridge_name': 'br-ex',
'public_interface_name': 'nic1',
'template': None},
'networks': [{'network': 'ctlplane', 'vif': True}],
},
'instances': [{
'hostname': 'overcloud-controller-0',
'name': 'bm-0-uuid',
'resource_class': 'controller',
}, {
'hostname': 'overcloud-controller-1',
'name': 'bm-1-uuid',
'resource_class': 'controller',
}, {
'hostname': 'overcloud-controller-2',
'name': 'bm-2-uuid',
}],
}], yaml.safe_load(result))

View File

@ -508,7 +508,7 @@ class ExtractProvisionedNode(command.Command):
'"$HOME/overcloud-deploy/<stack>"'))
return parser
def _get_subnet_from_net_name_and_ip(self, net_name, ip_addr):
def _get_network_from_net_name(self, net_name):
try:
network = self.network_client.find_network(net_name)
except openstack_exc.DuplicateResource:
@ -516,10 +516,9 @@ class ExtractProvisionedNode(command.Command):
"Unable to extract role networks. Duplicate network resources "
"with name %s detected." % net_name)
if network is None:
raise oscexc.CommandError("Unable to extract role networks. "
"Network %s not found." % net_name)
return network
def _get_subnet_from_ip(self, network, ip_addr):
for subnet_id in network.subnet_ids:
subnet = self.network_client.get_subnet(subnet_id)
if (ipaddress.ip_address(ip_addr)
@ -530,7 +529,7 @@ class ExtractProvisionedNode(command.Command):
raise oscexc.CommandError("Unable to extract role networks. Could not "
"find subnet for IP address %(ip)s on "
"network %(net)s." % {'ip': ip_addr,
'net': net_name})
'net': network.name})
def _convert_heat_nic_conf_to_j2(self, stack, role_name, network_data,
resource_registry, parsed_args):
@ -676,8 +675,14 @@ class ExtractProvisionedNode(command.Command):
# Add networks to the role default section
role_networks = defaults['networks'] = []
for net_name, ips in role_net_ip_map[role_name].items():
subnet_name = self._get_subnet_from_net_name_and_ip(net_name,
ips[0])
network = self._get_network_from_net_name(net_name)
# NOTE(hjensas): If network is not found (None)
# network-isolation is not enabled i.e ignore default
# network-data networks when not enabled.
if network is None:
continue
subnet_name = self._get_subnet_from_ip(network, ips[0])
if net_name == constants.CTLPLANE_NET_NAME:
role_networks.append({'network': net_name,
'vif': True})