Merge "overcloud node extract provisioned - fixed_ips"

This commit is contained in:
Zuul 2021-12-21 09:07:50 +00:00 committed by Gerrit Code Review
commit 2dea5787c0
2 changed files with 216 additions and 78 deletions

View File

@ -745,25 +745,7 @@ class TestExtractProvisionedNode(test_utils.TestCommand):
self.cmd = overcloud_node.ExtractProvisionedNode(self.app, None) self.cmd = overcloud_node.ExtractProvisionedNode(self.app, None)
self.extract_file = tempfile.NamedTemporaryFile( self.stack_dict = {
mode='w', delete=False, suffix='.yaml')
self.extract_file.close()
roles_data = [
{'name': 'Controller',
'default_route_networks': ['External'],
'networks_skip_config': ['Tenant']},
{'name': 'Compute'}
]
self.roles_file = tempfile.NamedTemporaryFile(
mode='w', delete=False, suffix='.yaml')
self.roles_file.write(yaml.safe_dump(roles_data))
self.roles_file.close()
self.addCleanup(os.unlink, self.extract_file.name)
self.addCleanup(os.unlink, self.roles_file.name)
def test_extract(self):
stack_dict = {
'parameters': { 'parameters': {
'ComputeHostnameFormat': '%stackname%-novacompute-%index%', 'ComputeHostnameFormat': '%stackname%-novacompute-%index%',
'ControllerHostnameFormat': '%stackname%-controller-%index%', 'ControllerHostnameFormat': '%stackname%-controller-%index%',
@ -803,93 +785,125 @@ class TestExtractProvisionedNode(test_utils.TestCommand):
} }
}] }]
} }
stack = mock.Mock()
stack.to_dict.return_value = stack_dict
self.orchestration.stacks.get.return_value = stack
nodes = [ self.nodes = [
mock.Mock(), mock.Mock(),
mock.Mock(), mock.Mock(),
mock.Mock(), mock.Mock(),
mock.Mock() mock.Mock()
] ]
nodes[0].name = 'bm-0' self.nodes[0].name = 'bm-0'
nodes[1].name = 'bm-1' self.nodes[1].name = 'bm-1'
nodes[2].name = 'bm-2' self.nodes[2].name = 'bm-2'
nodes[3].name = 'bm-3' self.nodes[3].name = 'bm-3'
nodes[0].instance_info = {'display_name': 'overcloud-controller-0'} self.nodes[0].instance_info = {
nodes[1].instance_info = {'display_name': 'overcloud-controller-1'} 'display_name': 'overcloud-controller-0'}
nodes[2].instance_info = {'display_name': 'overcloud-controller-2'} self.nodes[1].instance_info = {
nodes[3].instance_info = {'display_name': 'overcloud-novacompute-0'} 'display_name': 'overcloud-controller-1'}
self.nodes[2].instance_info = {
'display_name': 'overcloud-controller-2'}
self.nodes[3].instance_info = {
'display_name': 'overcloud-novacompute-0'}
self.baremetal.node.list.return_value = nodes self.networks = [
networks = [
mock.Mock(), # ctlplane mock.Mock(), # ctlplane
mock.Mock(), # external mock.Mock(), # external
mock.Mock(), # internal_api mock.Mock(), # internal_api
] ]
ctlplane_net = networks[0] self.ctlplane_net = self.networks[0]
external_net = networks[1] self.external_net = self.networks[1]
internal_api_net = networks[2] self.internal_api_net = self.networks[2]
ctlplane_net.id = 'ctlplane_id' self.ctlplane_net.id = 'ctlplane_id'
ctlplane_net.name = 'ctlplane' self.ctlplane_net.name = 'ctlplane'
ctlplane_net.subnet_ids = ['ctlplane_a_id', self.ctlplane_net.subnet_ids = ['ctlplane_a_id',
'ctlplane_b_id'] 'ctlplane_b_id']
external_net.id = 'external_id' self.external_net.id = 'external_id'
external_net.name = 'external' self.external_net.name = 'external'
external_net.subnet_ids = ['external_a_id'] self.external_net.subnet_ids = ['external_a_id']
internal_api_net.id = 'internal_api_id' self.internal_api_net.id = 'internal_api_id'
internal_api_net.name = 'internal_api' self.internal_api_net.name = 'internal_api'
internal_api_net.subnet_ids = ['internal_api_a_id', self.internal_api_net.subnet_ids = ['internal_api_a_id',
'internal_api_b_id'] 'internal_api_b_id']
subnets = [ self.subnets = [
mock.Mock(), # ctlplane_a mock.Mock(), # ctlplane_a
mock.Mock(), # ctlplane_b mock.Mock(), # ctlplane_b
mock.Mock(), # external_a mock.Mock(), # external_a
mock.Mock(), # internal_api_a mock.Mock(), # internal_api_a
mock.Mock(), # internal_api_b mock.Mock(), # internal_api_b
] ]
ctlplane_a = subnets[0] self.ctlplane_a = self.subnets[0]
ctlplane_b = subnets[1] self.ctlplane_b = self.subnets[1]
external_a = subnets[2] self.external_a = self.subnets[2]
int_api_a = subnets[3] self.int_api_a = self.subnets[3]
int_api_b = subnets[4] self.int_api_b = self.subnets[4]
ctlplane_a.id = 'ctlplane_a_id' self.ctlplane_a.id = 'ctlplane_a_id'
ctlplane_a.name = 'ctlplane_a' self.ctlplane_a.name = 'ctlplane_a'
ctlplane_a.cidr = '192.168.25.0/24' self.ctlplane_a.cidr = '192.168.25.0/24'
ctlplane_b.id = 'ctlplane_b_id' self.ctlplane_b.id = 'ctlplane_b_id'
ctlplane_b.name = 'ctlplane_b' self.ctlplane_b.name = 'ctlplane_b'
ctlplane_b.cidr = '192.168.26.0/24' self.ctlplane_b.cidr = '192.168.26.0/24'
external_a.id = 'external_a_id' self.external_a.id = 'external_a_id'
external_a.name = 'external_a' self.external_a.name = 'external_a'
external_a.cidr = '10.0.0.0/24' self.external_a.cidr = '10.0.0.0/24'
int_api_a.id = 'internal_api_a_id' self.int_api_a.id = 'internal_api_a_id'
int_api_a.name = 'internal_api_a' self.int_api_a.name = 'internal_api_a'
int_api_a.cidr = '172.17.0.0/24' self.int_api_a.cidr = '172.17.0.0/24'
int_api_b.id = 'internal_api_b_id' self.int_api_b.id = 'internal_api_b_id'
int_api_b.name = 'internal_api_b' self.int_api_b.name = 'internal_api_b'
int_api_b.cidr = '172.17.1.0/24' self.int_api_b.cidr = '172.17.1.0/24'
self.network.find_network.side_effect = [ self.network.find_network.side_effect = [
ctlplane_net, internal_api_net, # compute-0 # compute-0
ctlplane_net, external_net, internal_api_net, # controller-0 self.ctlplane_net, self.internal_api_net,
ctlplane_net, external_net, internal_api_net, # controller-1 # controller-0
ctlplane_net, external_net, internal_api_net, # controller-2 self.ctlplane_net, self.external_net, self.internal_api_net,
# controller-1
self.ctlplane_net, self.external_net, self.internal_api_net,
# controller-2
self.ctlplane_net, self.external_net, self.internal_api_net,
] ]
self.network.get_subnet.side_effect = [ self.network.get_subnet.side_effect = [
ctlplane_a, ctlplane_b, int_api_a, int_api_b, # compute-0 # compute-0
ctlplane_a, external_a, int_api_a, # controller-0, self.ctlplane_a, self.ctlplane_b, self.int_api_a, self.int_api_b,
ctlplane_a, external_a, int_api_a, # controller-1, # controller-0
ctlplane_a, external_a, int_api_a, # controller-2, self.ctlplane_a, self.external_a, self.int_api_a,
# controller-1
self.ctlplane_a, self.external_a, self.int_api_a,
# controller-2
self.ctlplane_a, self.external_a, self.int_api_a,
] ]
self.extract_file = tempfile.NamedTemporaryFile(
mode='w', delete=False, suffix='.yaml')
self.extract_file.close()
roles_data = [
{'name': 'Controller',
'default_route_networks': ['External'],
'networks_skip_config': ['Tenant']},
{'name': 'Compute'}
]
self.roles_file = tempfile.NamedTemporaryFile(
mode='w', delete=False, suffix='.yaml')
self.roles_file.write(yaml.safe_dump(roles_data))
self.roles_file.close()
self.addCleanup(os.unlink, self.extract_file.name)
self.addCleanup(os.unlink, self.roles_file.name)
def test_extract(self):
stack = mock.Mock()
stack.to_dict.return_value = self.stack_dict
stack.environment.return_value = {}
self.orchestration.stacks.get.return_value = stack
self.baremetal.node.list.return_value = self.nodes
argslist = ['--roles-file', self.roles_file.name, argslist = ['--roles-file', self.roles_file.name,
'--output', self.extract_file.name, '--output', self.extract_file.name,
'--yes'] '--yes']
@ -954,6 +968,118 @@ class TestExtractProvisionedNode(test_utils.TestCommand):
with open(self.extract_file.name) as f: with open(self.extract_file.name) as f:
self.assertEqual(yaml.safe_load(result), yaml.safe_load(f)) self.assertEqual(yaml.safe_load(result), yaml.safe_load(f))
def test_extract_ips_from_pool(self):
stack = mock.Mock()
stack.to_dict.return_value = self.stack_dict
stack.environment.return_value = {
'parameter_defaults': {
'ComputeIPs':
self.stack_dict['outputs'][1]['output_value']['Compute'],
'ControllerIPs':
self.stack_dict['outputs'][1]['output_value']['Controller']
}
}
self.orchestration.stacks.get.return_value = stack
self.baremetal.node.list.return_value = self.nodes
argslist = ['--roles-file', self.roles_file.name,
'--output', self.extract_file.name,
'--yes']
self.app.command_options = argslist
verifylist = [('roles_file', self.roles_file.name),
('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': 'templates/compute.j2'},
'networks': [{'network': 'ctlplane',
'vif': True},
{'network': 'internal_api',
'subnet': 'internal_api_b'}]
},
'instances': [{
'hostname': 'overcloud-novacompute-0',
'name': 'bm-3',
'networks': [{'fixed_ip': '192.168.26.11',
'network': 'ctlplane',
'vif': True},
{'fixed_ip': '172.17.1.23',
'network': 'internal_api',
'subnet': 'internal_api_b'}],
}],
}, {
'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': 'templates/controller.j2'},
'networks': [{'network': 'ctlplane',
'vif': True},
{'network': 'external',
'subnet': 'external_a'},
{'network': 'internal_api',
'subnet': 'internal_api_a'}],
},
'instances': [{
'hostname': 'overcloud-controller-0',
'name': 'bm-0',
'networks': [{'fixed_ip': '192.168.25.21',
'network': 'ctlplane',
'vif': True},
{'fixed_ip': '10.0.0.199',
'network': 'external',
'subnet': 'external_a'},
{'fixed_ip': '172.17.0.37',
'network': 'internal_api',
'subnet': 'internal_api_a'}],
}, {
'hostname': 'overcloud-controller-1',
'name': 'bm-1',
'networks': [{'fixed_ip': '192.168.25.25',
'network': 'ctlplane',
'vif': True},
{'fixed_ip': '10.0.0.197',
'network': 'external',
'subnet': 'external_a'},
{'fixed_ip': '172.17.0.33',
'network': 'internal_api',
'subnet': 'internal_api_a'}],
}, {
'hostname': 'overcloud-controller-2',
'name': 'bm-2',
'networks': [{'fixed_ip': '192.168.25.28',
'network': 'ctlplane',
'vif': True},
{'fixed_ip': '10.0.0.191',
'network': 'external',
'subnet': 'external_a'},
{'fixed_ip': '172.17.0.39',
'network': 'internal_api',
'subnet': 'internal_api_a'}],
}],
}], yaml.safe_load(result))
with open(self.extract_file.name) as f:
self.assertEqual(yaml.safe_load(result), yaml.safe_load(f))
def test_extract_empty(self): def test_extract_empty(self):
stack_dict = { stack_dict = {
'parameters': {}, 'parameters': {},

View File

@ -14,6 +14,7 @@
# #
import collections import collections
import copy
import datetime import datetime
from io import StringIO from io import StringIO
import ipaddress import ipaddress
@ -531,6 +532,7 @@ class ExtractProvisionedNode(command.Command):
role_net_ip_map = oooutils.get_stack_output_item( role_net_ip_map = oooutils.get_stack_output_item(
stack, 'RoleNetIpMap') or {} stack, 'RoleNetIpMap') or {}
parameters = stack.to_dict().get('parameters', {}) parameters = stack.to_dict().get('parameters', {})
parameter_defaults = stack.environment().get('parameter_defaults', {})
# list all baremetal nodes and map hostname to node name # list all baremetal nodes and map hostname to node name
node_details = self.baremetal_client.node.list(detail=True) node_details = self.baremetal_client.node.list(detail=True)
@ -615,11 +617,21 @@ class ExtractProvisionedNode(command.Command):
'networks_skip_config') 'networks_skip_config')
# Add individual instances # Add individual instances
ips_from_pool = parameter_defaults.get(
'{}IPs'.format(role_name), {})
instances = role['instances'] = [] instances = role['instances'] = []
for entry in sorted(entries): for idx, entry in enumerate(sorted(entries)):
instance = {'hostname': entry} instance = {'hostname': entry}
if entry in hostname_node_map: if entry in hostname_node_map:
instance['name'] = hostname_node_map[entry] instance['name'] = hostname_node_map[entry]
if ips_from_pool:
instance['networks'] = copy.deepcopy(role_networks)
for net in instance['networks']:
net['fixed_ip'] = (
role_net_ip_map[role_name][net['network']][idx])
instances.append(instance) instances.append(instance)
data.append(role) data.append(role)