Add --network_details to build-nodes-json

This is useful as a general way to easily retrieve the assigned
network addresses for all the deployed nodes.  This also deprecates
the --add_undercloud parameter as those details will be included
in the network_details data.
This commit is contained in:
Ben Nemec 2017-10-18 13:16:57 -05:00
parent cc36441e2f
commit 2e4dd517d1
2 changed files with 65 additions and 31 deletions

View File

@ -56,7 +56,13 @@ def _parse_args():
parser.add_argument('--add_undercloud',
dest='add_undercloud',
action='store_true',
help='Adds the undercloud details to the json file.')
help='DEPRECATED: Use --network_details instead. '
'Adds the undercloud details to the json file.')
parser.add_argument('--network_details',
dest='network_details',
action='store_true',
help='Include addresses for all nodes on all networks '
'in a network_details key')
args = parser.parse_args()
return args
@ -69,13 +75,12 @@ def _get_from_env(env, name):
def _get_names(args):
undercloud_name = None
if args.env is None:
bmc_base = args.bmc_prefix
baremetal_base = args.baremetal_prefix
provision_net = args.provision_net
if args.add_undercloud:
undercloud_name = 'undercloud'
# FIXME: This is not necessarily true.
undercloud_name = 'undercloud'
else:
with open(args.env) as f:
e = yaml.safe_load(f)
@ -85,8 +90,7 @@ def _get_names(args):
role = e.get('parameter_defaults', {}).get('role')
if role and baremetal_base.endswith('-' + role):
baremetal_base = baremetal_base[:-len(role) - 1]
if args.add_undercloud:
undercloud_name = e['parameter_defaults']['undercloud_name']
undercloud_name = e.get('parameter_defaults', {}).get('undercloud_name')
return bmc_base, baremetal_base, provision_net, undercloud_name
@ -130,8 +134,12 @@ def _build_nodes(nova, glance, bmc_ports, bm_ports, provision_net,
nodes = []
bmc_bm_pairs = []
cache = {}
network_details = {}
for bmc_port, baremetal_port in zip(bmc_ports, bm_ports):
baremetal = nova.servers.get(baremetal_port['device_id'])
network_details[baremetal.name] = {}
network_details[baremetal.name]['id'] = baremetal.id
network_details[baremetal.name]['ips'] = baremetal.addresses
node = dict(node_template)
node['pm_addr'] = bmc_port['fixed_ips'][0]['ip_address']
bmc_bm_pairs.append((node['pm_addr'], baremetal.name))
@ -176,21 +184,27 @@ def _build_nodes(nova, glance, bmc_ports, bm_ports, provision_net,
undercloud_instance = nova.servers.list(
search_opts={'name': undercloud_name})[0]
except IndexError:
raise RuntimeError(
'undercloud %s specified in the environment file is not '
'available in nova' % undercloud_name)
undercloud_node_template['id'] = undercloud_instance.id
undercloud_node_template['ips'] = nova.servers.ips(undercloud_instance)
print ('Undercloud %s specified in the environment file is not '
'available in nova. No undercloud details will be '
'included in the output.' % undercloud_name)
else:
undercloud_node_template['id'] = undercloud_instance.id
undercloud_node_template['ips'] = nova.servers.ips(undercloud_instance)
extra_nodes.append(undercloud_node_template)
return nodes, bmc_bm_pairs, extra_nodes
extra_nodes.append(undercloud_node_template)
network_details[undercloud_name] = {}
network_details[undercloud_name]['id'] = undercloud_instance.id
network_details[undercloud_name]['ips'] = undercloud_instance.addresses
return nodes, bmc_bm_pairs, extra_nodes, network_details
def _write_nodes(nodes, extra_nodes, args):
def _write_nodes(nodes, extra_nodes, network_details, args):
with open(args.nodes_json, 'w') as node_file:
resulting_json = {'nodes': nodes}
if extra_nodes:
if args.add_undercloud and extra_nodes:
resulting_json['extra_nodes'] = extra_nodes
if args.network_details:
resulting_json['network_details'] = network_details
contents = json.dumps(resulting_json, indent=2)
node_file.write(contents)
print(contents)
@ -246,12 +260,13 @@ def main():
bmc_base, baremetal_base, provision_net, undercloud_name = _get_names(args)
nova, neutron, glance = _get_clients()
bmc_ports, bm_ports = _get_ports(neutron, bmc_base, baremetal_base)
nodes, bmc_bm_pairs, extra_nodes = _build_nodes(nova, glance, bmc_ports,
bm_ports,
provision_net,
baremetal_base,
undercloud_name)
_write_nodes(nodes, extra_nodes, args)
(nodes,
bmc_bm_pairs,
extra_nodes,
network_details) = _build_nodes(nova, glance, bmc_ports, bm_ports,
provision_net, baremetal_base,
undercloud_name)
_write_nodes(nodes, extra_nodes, network_details, args)
_write_role_nodes(nodes, args)
_write_pairs(bmc_bm_pairs)

View File

@ -74,7 +74,7 @@ class TestBuildNodesJson(testtools.TestCase):
self.assertEqual('bmc-foo', bmc_base)
self.assertEqual('baremetal-foo', baremetal_base)
self.assertEqual('provision-foo', provision_net)
self.assertIsNone(undercloud_name)
self.assertEqual('undercloud', undercloud_name)
def test_get_names_no_env_w_undercloud(self):
args = mock.Mock()
@ -245,13 +245,17 @@ class TestBuildNodesJson(testtools.TestCase):
servers[0].name = 'bm_0'
servers[0].flavor = {'id': '1'}
servers[0].addresses = {'provision': [{'OS-EXT-IPS-MAC:mac_addr':
'aa:aa:aa:aa:aa:aa'}]}
'aa:aa:aa:aa:aa:aa',
'addr': '2.1.1.1'}]}
servers[0].image = {'id': 'f00'}
servers[0].id = '123abc'
servers[1].name = 'bm_1'
servers[1].flavor = {'id': '1'}
servers[1].addresses = {'provision': [{'OS-EXT-IPS-MAC:mac_addr':
'aa:aa:aa:aa:aa:ab'}]}
'aa:aa:aa:aa:aa:ab',
'addr': '2.1.1.2'}]}
servers[1].image = {'id': 'f00'}
servers[1].id = '456def'
mock_flavor = mock.Mock()
mock_flavor.vcpus = 128
mock_flavor.ram = 145055
@ -277,7 +281,10 @@ class TestBuildNodesJson(testtools.TestCase):
glance = mock.Mock()
nodes, bmc_bm_pairs, extra_nodes = build_nodes_json._build_nodes(
(nodes,
bmc_bm_pairs,
extra_nodes,
network_details) = build_nodes_json._build_nodes(
nova, glance, bmc_ports, bm_ports, 'provision', 'bm', 'undercloud')
expected_nodes = TEST_NODES
self.assertEqual(expected_nodes, nodes)
@ -285,6 +292,10 @@ class TestBuildNodesJson(testtools.TestCase):
bmc_bm_pairs)
self.assertEqual(1, len(extra_nodes))
self.assertEqual('undercloud', extra_nodes[0]['name'])
self.assertEqual('2.1.1.1',
network_details['bm_0']['ips']['provision'][0]['addr'])
self.assertEqual('2.1.1.2',
network_details['bm_1']['ips']['provision'][0]['addr'])
def test_build_nodes_role_uefi(self):
bmc_ports = [{'fixed_ips': [{'ip_address': '1.1.1.1'}]},
@ -304,7 +315,7 @@ class TestBuildNodesJson(testtools.TestCase):
mock_image_get.get.return_value = 'uefi'
glance.images.get.return_value = mock_image_get
nodes, bmc_bm_pairs, extra_nodes = build_nodes_json._build_nodes(
nodes, bmc_bm_pairs, extra_nodes, _ = build_nodes_json._build_nodes(
nova, glance, bmc_ports, bm_ports, 'provision', 'bm-foo', None)
expected_nodes = copy.deepcopy(TEST_NODES)
expected_nodes[0]['name'] = 'bm-foo-control-0'
@ -326,8 +337,9 @@ class TestBuildNodesJson(testtools.TestCase):
args = mock.Mock()
mock_open.return_value = mock.MagicMock()
args.nodes_json = 'test.json'
args.network_details = False
extra_nodes = []
build_nodes_json._write_nodes(TEST_NODES, extra_nodes, args)
build_nodes_json._write_nodes(TEST_NODES, extra_nodes, {}, args)
data = json.dumps({'nodes': TEST_NODES}, indent=2)
f = mock_open.return_value.__enter__.return_value
f.write.assert_called_once_with(data)
@ -338,10 +350,14 @@ class TestBuildNodesJson(testtools.TestCase):
args = mock.Mock()
mock_open.return_value = mock.MagicMock()
args.nodes_json = 'test.json'
args.network_details = True
extra_nodes = [{'foo': 'bar'}]
build_nodes_json._write_nodes(TEST_NODES, extra_nodes, args)
network_details = {'bar': 'baz'}
build_nodes_json._write_nodes(TEST_NODES, extra_nodes,
network_details, args)
data = json.dumps({'nodes': TEST_NODES,
'extra_nodes': extra_nodes}, indent=2)
'extra_nodes': extra_nodes,
'network_details': network_details}, indent=2)
f = mock_open.return_value.__enter__.return_value
f.write.assert_called_once_with(data)
@ -418,7 +434,9 @@ class TestBuildNodesJson(testtools.TestCase):
nodes = mock.Mock()
pairs = mock.Mock()
extra_nodes = mock.Mock()
mock_build_nodes.return_value = (nodes, pairs, extra_nodes)
network_details = mock.Mock()
mock_build_nodes.return_value = (nodes, pairs, extra_nodes,
network_details)
build_nodes_json.main()
@ -431,7 +449,8 @@ class TestBuildNodesJson(testtools.TestCase):
bm_ports, provision_net,
baremetal_base,
undercloud_name)
mock_write_nodes.assert_called_once_with(nodes, extra_nodes, args)
mock_write_nodes.assert_called_once_with(nodes, extra_nodes,
network_details, args)
mock_write_role_nodes.assert_called_once_with(nodes, args)
mock_write_pairs.assert_called_once_with(pairs)