1 ##############################################################################
2 # Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat)
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
15 from mock import patch
16 from mock import MagicMock
17 from mock import mock_open
18 from io import StringIO
20 from apex.common import constants as con
21 from apex.common.exceptions import ApexDeployException
22 from apex.overcloud.deploy import build_sdn_env_list
23 from apex.overcloud.deploy import create_deploy_cmd
24 from apex.overcloud.deploy import prep_image
25 from apex.overcloud.deploy import make_ssh_key
26 from apex.overcloud.deploy import prep_env
27 from apex.overcloud.deploy import generate_ceph_key
28 from apex.overcloud.deploy import prep_storage_env
29 from apex.overcloud.deploy import prep_sriov_env
30 from apex.overcloud.deploy import external_network_cmds
31 from apex.overcloud.deploy import create_congress_cmds
32 from apex.overcloud.deploy import SDN_FILE_MAP
33 from apex.overcloud.deploy import get_docker_sdn_files
35 from nose.tools import (
36 assert_regexp_matches,
44 class TestOvercloudDeploy(unittest.TestCase):
47 """This method is run once for each class before any tests are run"""
50 def teardown_class(cls):
51 """This method is run once for each class _after_ all tests are run"""
54 """This method is run once before _each_ test method is executed"""
57 """This method is run once after _each_ test method is executed"""
59 def test_build_sdn_env_list(self):
60 ds = {'sdn_controller': 'opendaylight'}
61 sdn_map = {'opendaylight': 'test'}
62 res = '/usr/share/openstack-tripleo-heat-templates/environments/test'
63 assert_equal(build_sdn_env_list(ds, sdn_map), [res])
65 def test_build_sdn_env_list_dict(self):
66 ds = {'opendaylight': True,
67 'sdn_controller': None}
68 sdn_map = {'opendaylight': {}}
69 assert_equal(build_sdn_env_list(ds, sdn_map), [])
71 def test_build_sdn_env_list_tuple(self):
72 ds = {'opendaylight': 'test',
73 'sdn_controller': None}
74 sdn_map = {'opendaylight': ('test', 'test')}
75 res = '/usr/share/openstack-tripleo-heat-templates/environments/test'
76 assert_equal(build_sdn_env_list(ds, sdn_map), [res])
78 def test_build_sdn_env_list_with_string(self):
79 ds = {'sdn_controller': 'opendaylight',
81 prefix = '/usr/share/openstack-tripleo-heat-templates/environments'
82 res = [os.path.join(prefix, 'neutron-opendaylight.yaml'),
83 os.path.join(prefix, 'neutron-opendaylight-sriov.yaml')]
84 assert_equal(build_sdn_env_list(ds, SDN_FILE_MAP), res)
86 def test_build_sdn_env_list_with_default(self):
87 ds = {'sdn_controller': 'opendaylight',
89 prefix = '/usr/share/openstack-tripleo-heat-templates/environments'
90 res = [os.path.join(prefix, 'neutron-opendaylight.yaml'),
91 os.path.join(prefix, 'neutron-bgpvpn-opendaylight.yaml')]
92 assert_equal(build_sdn_env_list(ds, SDN_FILE_MAP), res)
94 @patch('apex.overcloud.deploy.prep_sriov_env')
95 @patch('apex.overcloud.deploy.prep_storage_env')
96 @patch('apex.overcloud.deploy.build_sdn_env_list')
97 @patch('builtins.open', mock_open())
98 def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage,
100 mock_sdn_list.return_value = []
101 ds = {'deploy_options':
111 'global_params': MagicMock()}
113 ns = {'ntp': ['ntp']}
115 inv.get_node_counts.return_value = (3, 2)
117 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
118 assert_in('--ntp-server ntp', result_cmd)
119 assert_in('enable_tacker.yaml', result_cmd)
120 assert_in('enable_congress.yaml', result_cmd)
121 assert_in('enable_barometer.yaml', result_cmd)
122 assert_in('virtual-environment.yaml', result_cmd)
123 assert_in('--control-scale 3', result_cmd)
124 assert_in('--compute-scale 2', result_cmd)
126 @patch('apex.overcloud.deploy.prep_sriov_env')
127 @patch('apex.overcloud.deploy.prep_storage_env')
128 @patch('builtins.open', mock_open())
129 def test_create_deploy_cmd_containers_sdn(self, mock_prep_storage,
131 ds = {'deploy_options':
139 'sdn_controller': 'opendaylight',
141 'os_version': 'queens',
144 'global_params': MagicMock()}
146 ns = {'ntp': ['ntp']}
148 inv.get_node_counts.return_value = (3, 2)
150 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
151 assert_in('--ntp-server ntp', result_cmd)
152 assert_not_in('enable_tacker.yaml', result_cmd)
153 assert_not_in('enable_congress.yaml', result_cmd)
154 assert_not_in('enable_barometer.yaml', result_cmd)
155 assert_in('virtual-environment.yaml', result_cmd)
156 assert_in('--control-scale 3', result_cmd)
157 assert_in('--compute-scale 2', result_cmd)
158 assert_in('docker-images.yaml', result_cmd)
159 assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
160 '/docker.yaml', result_cmd)
161 assert_in('/usr/share/openstack-tripleo-heat-templates/environments/'
162 'storage-environment.yaml', result_cmd)
163 assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
164 '/services/neutron-opendaylight.yaml', result_cmd)
165 ds['deploy_options']['os_version'] = 'master'
166 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
167 assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
168 '/services/neutron-opendaylight.yaml', result_cmd)
170 @patch('apex.overcloud.deploy.prep_sriov_env')
171 @patch('apex.overcloud.deploy.prep_storage_env')
172 @patch('apex.overcloud.deploy.build_sdn_env_list')
173 @patch('builtins.open', mock_open())
174 def test_create_deploy_cmd_no_ha_bm(self, mock_sdn_list,
175 mock_prep_storage, mock_prep_sriov):
176 mock_sdn_list.return_value = []
177 ds = {'deploy_options': MagicMock(),
178 'global_params': MagicMock()}
179 ds['global_params'].__getitem__.side_effect = \
180 lambda i: False if i == 'ha_enabled' else MagicMock()
181 ds['deploy_options'].__getitem__.side_effect = \
182 lambda i: 'master' if i == 'os_version' else MagicMock()
183 ns = {'ntp': ['ntp']}
185 inv.get_node_counts.return_value = (3, 2)
187 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
188 assert_in('--ntp-server ntp', result_cmd)
189 assert_in('--control-scale 1', result_cmd)
190 assert_in('--compute-scale 2', result_cmd)
191 assert_in('baremetal-environment.yaml', result_cmd)
192 assert_not_in('enable_tacker.yaml', result_cmd)
193 assert_not_in('enable_congress.yaml', result_cmd)
194 assert_not_in('enable_barometer.yaml', result_cmd)
196 @patch('apex.builders.overcloud_builder.inject_opendaylight')
197 @patch('apex.overcloud.deploy.virt_utils')
198 @patch('apex.overcloud.deploy.shutil')
199 @patch('apex.overcloud.deploy.os.path.isfile')
200 @patch('builtins.open', mock_open())
201 def test_prep_image(self, mock_is_file, mock_shutil, mock_virt_utils,
203 mock_is_file.return_value = True
204 ds_opts = {'dataplane': 'fdio',
205 'sdn_controller': 'opendaylight',
206 'odl_version': 'master',
209 ds = {'deploy_options': MagicMock(),
210 'global_params': MagicMock()}
211 ds['deploy_options'].__getitem__.side_effect = \
212 lambda i: ds_opts.get(i, MagicMock())
214 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
215 mock_virt_utils.virt_customize.assert_called()
216 mock_inject_odl.assert_called()
218 @patch('apex.overcloud.deploy.virt_utils')
219 @patch('apex.overcloud.deploy.shutil')
220 @patch('apex.overcloud.deploy.os.path.isfile')
221 @patch('builtins.open', mock_open())
222 def test_prep_image_sdn_false(self, mock_is_file, mock_shutil,
224 mock_is_file.return_value = True
225 ds_opts = {'dataplane': 'fdio',
227 'sdn_controller': False}
228 ds = {'deploy_options': MagicMock(),
229 'global_params': MagicMock()}
230 ds['deploy_options'].__getitem__.side_effect = \
231 lambda i: ds_opts.get(i, MagicMock())
233 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
234 mock_virt_utils.virt_customize.assert_called()
236 @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
237 @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
238 @patch('apex.builders.overcloud_builder.inject_opendaylight')
239 @patch('apex.overcloud.deploy.virt_utils')
240 @patch('apex.overcloud.deploy.shutil')
241 @patch('apex.overcloud.deploy.os.path.isfile')
242 @patch('builtins.open', mock_open())
243 def test_prep_image_sdn_odl(self, mock_is_file, mock_shutil,
244 mock_virt_utils, mock_inject_odl,
245 mock_fetch, mock_ovs_nsh):
246 mock_is_file.return_value = True
247 ds_opts = {'dataplane': 'ovs',
248 'sdn_controller': 'opendaylight',
251 'odl_version': con.DEFAULT_ODL_VERSION,
252 'odl_vpp_netvirt': True}
253 ds = {'deploy_options': MagicMock(),
254 'global_params': MagicMock()}
255 ds['deploy_options'].__getitem__.side_effect = \
256 lambda i: ds_opts.get(i, MagicMock())
257 ds['deploy_options'].__contains__.side_effect = \
258 lambda i: True if i in ds_opts else MagicMock()
260 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
261 mock_virt_utils.virt_customize.assert_called()
262 mock_inject_odl.assert_called()
263 mock_ovs_nsh.assert_called()
265 @patch('apex.overcloud.deploy.c_builder')
266 @patch('apex.overcloud.deploy.oc_builder')
267 @patch('apex.overcloud.deploy.virt_utils')
268 @patch('apex.overcloud.deploy.shutil')
269 @patch('apex.overcloud.deploy.os.path.isfile')
270 @patch('builtins.open', mock_open())
271 def test_prep_image_sdn_odl_upstream_containers_patches(
272 self, mock_is_file, mock_shutil, mock_virt_utils,
273 mock_oc_builder, mock_c_builder):
274 mock_is_file.return_value = True
275 ds_opts = {'dataplane': 'ovs',
276 'sdn_controller': 'opendaylight',
277 'odl_version': con.DEFAULT_ODL_VERSION,
278 'odl_vpp_netvirt': True}
279 ds = {'deploy_options': MagicMock(),
280 'global_params': MagicMock()}
281 ds['deploy_options'].__getitem__.side_effect = \
282 lambda i: ds_opts.get(i, MagicMock())
283 ds['deploy_options'].__contains__.side_effect = \
284 lambda i: True if i in ds_opts else MagicMock()
286 mock_c_builder.add_upstream_patches.return_value = ['nova-api']
287 patches = ['dummy_nova_patch']
288 rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
289 docker_tag='latest', patches=patches)
290 mock_oc_builder.inject_opendaylight.assert_called()
291 mock_virt_utils.virt_customize.assert_called()
292 mock_c_builder.add_upstream_patches.assert_called()
293 self.assertListEqual(sorted(rv), ['nova-api', 'opendaylight'])
295 @patch('apex.overcloud.deploy.c_builder')
296 @patch('apex.overcloud.deploy.oc_builder')
297 @patch('apex.overcloud.deploy.virt_utils')
298 @patch('apex.overcloud.deploy.shutil')
299 @patch('apex.overcloud.deploy.os.path.isfile')
300 @patch('builtins.open', mock_open())
301 def test_prep_image_nosdn_upstream_containers_patches(
302 self, mock_is_file, mock_shutil, mock_virt_utils,
303 mock_oc_builder, mock_c_builder):
304 mock_is_file.return_value = True
305 ds_opts = {'dataplane': 'ovs',
306 'sdn_controller': False,
307 'odl_version': con.DEFAULT_ODL_VERSION,
308 'odl_vpp_netvirt': False}
309 ds = {'deploy_options': MagicMock(),
310 'global_params': MagicMock()}
311 ds['deploy_options'].__getitem__.side_effect = \
312 lambda i: ds_opts.get(i, MagicMock())
313 ds['deploy_options'].__contains__.side_effect = \
314 lambda i: True if i in ds_opts else MagicMock()
316 mock_c_builder.add_upstream_patches.return_value = ['nova-api']
317 patches = ['dummy_nova_patch']
318 rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
319 docker_tag='latest', patches=patches)
320 mock_virt_utils.virt_customize.assert_called()
321 mock_c_builder.add_upstream_patches.assert_called()
322 self.assertListEqual(sorted(rv), ['nova-api'])
324 @patch('apex.overcloud.deploy.oc_builder')
325 @patch('apex.overcloud.deploy.virt_utils')
326 @patch('apex.overcloud.deploy.shutil')
327 @patch('apex.overcloud.deploy.os.path.isfile')
328 @patch('builtins.open', mock_open())
329 def test_prep_image_sdn_odl_not_def(self, mock_is_file,
330 mock_shutil, mock_virt_utils,
332 mock_is_file.return_value = True
333 ds_opts = {'dataplane': 'ovs',
334 'sdn_controller': 'opendaylight',
335 'odl_version': 'uncommon'}
336 ds = {'deploy_options': MagicMock(),
337 'global_params': MagicMock()}
338 ds['deploy_options'].__getitem__.side_effect = \
339 lambda i: ds_opts.get(i, MagicMock())
341 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
342 mock_virt_utils.virt_customize.assert_called()
343 mock_oc_builder.inject_opendaylight.assert_called()
345 @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
346 @patch('apex.overcloud.deploy.virt_utils')
347 @patch('apex.overcloud.deploy.shutil')
348 @patch('apex.overcloud.deploy.os.path.isfile')
349 @patch('builtins.open', mock_open())
350 def test_prep_image_sdn_ovn(self, mock_is_file, mock_shutil,
351 mock_virt_utils, mock_ovs_nsh):
352 mock_is_file.return_value = True
353 ds_opts = {'dataplane': 'ovs',
356 'sdn_controller': 'ovn'}
357 ds = {'deploy_options': MagicMock(),
358 'global_params': MagicMock()}
359 ds['deploy_options'].__getitem__.side_effect = \
360 lambda i: ds_opts.get(i, MagicMock())
362 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
363 mock_virt_utils.virt_customize.assert_called()
364 mock_ovs_nsh.assert_called()
366 @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
367 @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
368 @patch('apex.builders.overcloud_builder.inject_quagga')
369 @patch('apex.builders.overcloud_builder.inject_opendaylight')
370 @patch('apex.overcloud.deploy.virt_utils')
371 @patch('apex.overcloud.deploy.shutil')
372 @patch('apex.overcloud.deploy.os.path.isfile')
373 @patch('builtins.open', mock_open())
374 def test_prep_image_sdn_odl_vpn(self, mock_is_file, mock_shutil,
375 mock_virt_utils, mock_inject_odl,
376 mock_inject_quagga, mock_fetch,
378 mock_is_file.return_value = True
379 ds_opts = {'dataplane': 'ovs',
380 'sdn_controller': 'opendaylight',
383 'odl_version': con.DEFAULT_ODL_VERSION,
384 'odl_vpp_netvirt': True}
385 ds = {'deploy_options': MagicMock(),
386 'global_params': MagicMock()}
387 ds['deploy_options'].__getitem__.side_effect = \
388 lambda i: ds_opts.get(i, MagicMock())
389 ds['deploy_options'].__contains__.side_effect = \
390 lambda i: True if i in ds_opts else MagicMock()
392 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
393 mock_virt_utils.virt_customize.assert_called()
394 mock_inject_odl.assert_called()
395 mock_inject_quagga.assert_called()
396 mock_ovs_nsh.assert_called()
398 @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
399 @patch('apex.builders.overcloud_builder.inject_opendaylight')
400 @patch('apex.overcloud.deploy.virt_utils')
401 @patch('apex.overcloud.deploy.shutil')
402 @patch('apex.overcloud.deploy.os.path.isfile')
403 @patch('builtins.open', mock_open())
404 def test_prep_image_sdn_odl_sfc(self, mock_is_file, mock_shutil,
405 mock_virt_utils, mock_inject_odl,
406 mock_inject_ovs_nsh):
407 mock_is_file.return_value = True
408 ds_opts = {'dataplane': 'ovs',
409 'sdn_controller': 'opendaylight',
412 'odl_version': con.DEFAULT_ODL_VERSION,
413 'odl_vpp_netvirt': True}
414 ds = {'deploy_options': MagicMock(),
415 'global_params': MagicMock()}
416 ds['deploy_options'].__getitem__.side_effect = \
417 lambda i: ds_opts.get(i, MagicMock())
418 ds['deploy_options'].__contains__.side_effect = \
419 lambda i: True if i in ds_opts else MagicMock()
421 prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
422 mock_virt_utils.virt_customize.assert_called()
423 mock_inject_odl.assert_called()
424 mock_inject_ovs_nsh.assert_called()
426 @patch('apex.overcloud.deploy.os.path.isfile')
427 def test_prep_image_no_image(self, mock_isfile):
428 mock_isfile.return_value = False
429 assert_raises(ApexDeployException, prep_image,
430 {}, {}, 'undercloud.qcow2', '/tmp')
432 def test_make_ssh_key(self):
433 priv, pub = make_ssh_key()
434 assert_in('-----BEGIN PRIVATE KEY-----', priv)
435 assert_in('ssh-rsa', pub)
437 @patch('apex.overcloud.deploy.yaml')
438 @patch('apex.overcloud.deploy.fileinput')
439 @patch('apex.overcloud.deploy.shutil')
440 @patch('builtins.open', mock_open())
441 def test_prep_env(self, mock_shutil, mock_fileinput, mock_yaml):
442 mock_fileinput.input.return_value = \
443 ['CloudDomain', 'replace_private_key', 'replace_public_key',
444 'opendaylight::vpp_routing_node', 'ControllerExtraConfig',
445 'NovaComputeExtraConfig', 'ComputeKernelArgs', 'HostCpusList',
446 'ComputeExtraConfigPre', 'resource_registry',
447 'NovaSchedulerDefaultFilters']
448 mock_yaml.safe_load.return_value = {
449 'parameter_defaults': {
450 'ControllerServices': [1, 2, 3],
451 'ComputeServices': [3, 4, 5]
453 ds = {'global_params': {'ha_enabled': False},
455 {'sdn_controller': 'opendaylight',
456 'odl_vpp_routing_node': 'test',
457 'dataplane': 'ovs_dpdk',
459 'performance': {'Compute': {'vpp': {'main-core': 'test',
460 'corelist-workers': 'test'},
461 'ovs': {'dpdk_cores': 'test'},
462 'kernel': {'test': 'test'}},
463 'Controller': {'vpp': 'test'}}}}
464 ns_dict = {'domain_name': 'test.domain',
467 {'nic_mapping': {'controller':
468 {'members': ['tenant_nic']},
470 {'members': ['tenant_nic']}}},
472 [{'nic_mapping': {'controller':
473 {'members': ['ext_nic']},
475 {'members': ['ext_nic']}}}]}}
477 inv.get_node_counts.return_value = (1, 0)
480 saved_stdout = sys.stdout
484 ns.enabled_network_list = ['external', 'tenant']
485 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
487 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
488 output = out.getvalue().strip()
489 assert_in('CloudDomain: test.domain', output)
490 assert_in('ssh-rsa', output)
491 assert_in('ComputeKernelArgs: \'test=test \'', output)
492 assert_in('fdio::vpp_cpu_main_core: \'test\'', output)
493 mock_yaml.safe_dump.assert_called_with(
494 {'parameter_defaults': {
495 'ControllerServices': [1, 2, 3, 4, 5],
497 mock.ANY, default_flow_style=False
501 sys.stdout = saved_stdout
503 @patch('apex.overcloud.deploy.fileinput')
504 @patch('apex.overcloud.deploy.shutil')
505 @patch('builtins.open', mock_open())
506 def test_prep_env_round_two(self, mock_shutil, mock_fileinput):
507 mock_fileinput.input.return_value = \
508 ['NeutronVPPAgentPhysnets']
509 ds = {'global_params': {'ha_enabled': False},
511 {'sdn_controller': False,
514 'performance': {'Compute': {},
516 ns_dict = {'domain_name': 'test.domain',
519 {'nic_mapping': {'controller':
520 {'members': ['tenant_nic']},
522 {'members': ['tenant_nic']}}},
524 [{'nic_mapping': {'controller':
525 {'members': ['ext_nic']},
527 {'members': ['ext_nic']}}}]}}
529 inv.get_node_counts.return_value = (3, 2)
532 saved_stdout = sys.stdout
536 ns.enabled_network_list = ['external', 'tenant']
537 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
539 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
540 output = out.getvalue().strip()
541 assert_in('NeutronVPPAgentPhysnets: '
542 '\'datacentre:tenant_nic,external:tap0\'',
544 assert_in('NeutronVPPAgentPhysnets', output)
547 sys.stdout = saved_stdout
549 @patch('apex.overcloud.deploy.fileinput')
550 @patch('apex.overcloud.deploy.shutil')
551 @patch('builtins.open', mock_open())
552 def test_prep_env_round_three(self, mock_shutil, mock_fileinput):
553 mock_fileinput.input.return_value = \
554 ['OS::TripleO::Services::NeutronDhcpAgent',
555 'NeutronDhcpAgentsPerNetwork', 'ComputeServices']
556 ds = {'global_params': {'ha_enabled': False},
558 {'sdn_controller': 'opendaylight',
562 ns_dict = {'domain_name': 'test.domain',
565 {'nic_mapping': {'controller':
566 {'members': ['tenant_nic']},
568 {'members': ['tenant_nic']}}},
570 [{'nic_mapping': {'controller':
571 {'members': ['ext_nic']},
573 {'members': ['ext_nic']}}}]}}
575 inv.get_node_counts.return_value = (3, 2)
578 saved_stdout = sys.stdout
582 ns.enabled_network_list = ['external', 'tenant']
583 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
585 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
586 output = out.getvalue().strip()
587 assert_in('NeutronDhcpAgentsPerNetwork: 2', output)
590 sys.stdout = saved_stdout
592 @patch('apex.overcloud.deploy.fileinput')
593 @patch('apex.overcloud.deploy.shutil')
594 @patch('builtins.open', mock_open())
595 def test_prep_env_tenant_vlan(self, mock_shutil, mock_fileinput):
596 mock_fileinput.input.return_value = \
597 ['NeutronNetworkVLANRanges',
598 'NeutronNetworkType', 'NeutronBridgeMappings']
599 ds = {'global_params': {'ha_enabled': False},
601 {'sdn_controller': False,
605 ns_dict = {'domain_name': 'test.domain',
608 {'nic_mapping': {'controller':
609 {'members': ['tenant_nic']},
611 {'members': ['tenant_nic']}},
612 'segmentation_type': 'vlan',
613 'overlay_id_range': 'vlan:500:600'
616 [{'nic_mapping': {'controller':
617 {'members': ['ext_nic']},
619 {'members': ['ext_nic']}}}]}}
621 inv.get_node_counts.return_value = (3, 2)
624 saved_stdout = sys.stdout
628 ns.enabled_network_list = ['external', 'tenant']
629 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
631 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
632 output = out.getvalue().strip()
633 assert_in('NeutronNetworkVLANRanges: '
634 'vlan:500:600,datacentre:1:1000', output)
635 assert_in('NeutronNetworkType: vlan', output)
636 assert_in('NeutronBridgeMappings: '
637 'vlan:br-vlan,datacentre:br-ex', output)
638 assert_not_in('OpenDaylightProviderMappings', output)
641 sys.stdout = saved_stdout
643 @patch('apex.overcloud.deploy.fileinput')
644 @patch('apex.overcloud.deploy.shutil')
645 @patch('builtins.open', mock_open())
646 def test_prep_env_tenant_vlan_odl(self, mock_shutil, mock_fileinput):
647 mock_fileinput.input.return_value = \
648 ['NeutronNetworkVLANRanges',
649 'NeutronNetworkType',
650 'NeutronBridgeMappings',
651 'OpenDaylightProviderMappings']
652 ds = {'global_params': {'ha_enabled': False},
654 {'sdn_controller': 'opendaylight',
658 ns_dict = {'domain_name': 'test.domain',
661 {'nic_mapping': {'controller':
662 {'members': ['tenant_nic']},
664 {'members': ['tenant_nic']}},
665 'segmentation_type': 'vlan',
666 'overlay_id_range': 'vlan:500:600'
669 [{'nic_mapping': {'controller':
670 {'members': ['ext_nic']},
672 {'members': ['ext_nic']}}}]}}
674 inv.get_node_counts.return_value = (3, 2)
677 saved_stdout = sys.stdout
681 ns.enabled_network_list = ['external', 'tenant']
682 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
684 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
685 output = out.getvalue().strip()
686 assert_in('NeutronNetworkVLANRanges: '
687 'vlan:500:600,datacentre:1:1000', output)
688 assert_in('NeutronNetworkType: vlan', output)
689 assert_in('NeutronBridgeMappings: '
690 'vlan:br-vlan,datacentre:br-ex', output)
691 assert_in('OpenDaylightProviderMappings: '
692 'vlan:br-vlan,datacentre:br-ex', output)
695 sys.stdout = saved_stdout
697 def test_generate_ceph_key(self):
698 assert_equal(len(generate_ceph_key()), 40)
700 @patch('apex.overcloud.deploy.generate_ceph_key')
701 @patch('apex.overcloud.deploy.fileinput')
702 @patch('apex.overcloud.deploy.os.path.isfile')
703 @patch('builtins.open', mock_open())
704 def test_prep_storage_env(self, mock_isfile, mock_fileinput,
706 mock_fileinput.input.return_value = \
707 ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
708 ds = {'deploy_options': {
709 'ceph_device': '/dev/sdx',
713 prep_storage_env(ds, ns, virtual=False, tmp_dir='/tmp')
715 @patch('apex.overcloud.deploy.utils.edit_tht_env')
716 @patch('apex.overcloud.deploy.generate_ceph_key')
717 @patch('apex.overcloud.deploy.fileinput')
718 @patch('apex.overcloud.deploy.os.path.isfile')
719 @patch('builtins.open', mock_open())
720 def test_prep_storage_env_containers(self, mock_isfile, mock_fileinput,
721 mock_ceph_key, mock_edit_tht):
722 mock_fileinput.input.return_value = \
723 ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
724 ds = {'deploy_options': {
725 'ceph_device': '/dev/sdx',
727 'os_version': 'master'
728 }, 'global_params': {'ha_enabled': False}}
729 ns = {'networks': {con.ADMIN_NETWORK: {'installer_vm':
730 {'ip': '192.0.2.1'}}}
732 prep_storage_env(ds, ns, virtual=True, tmp_dir='/tmp')
734 'CephPoolDefaultSize': 2,
735 'CephAnsibleExtraConfig': {
736 'centos_package_dependencies': [],
737 'ceph_osd_docker_memory_limit': '1g',
738 'ceph_mds_docker_memory_limit': '1g'
740 'CephPoolDefaultPgNum': 32,
741 'CephAnsibleDisksConfig': {
742 'devices': ['/dev/sdx'],
744 'osd_scenario': 'collocated'
747 mock_edit_tht.assert_called_with('/tmp/storage-environment.yaml',
748 'parameter_defaults',
751 @patch('apex.overcloud.deploy.os.path.isfile')
752 @patch('builtins.open', mock_open())
753 def test_prep_storage_env_raises(self, mock_isfile):
754 mock_isfile.return_value = False
755 ds = {'deploy_options': MagicMock()}
757 assert_raises(ApexDeployException, prep_storage_env, ds,
758 ns, virtual=False, tmp_dir='/tmp')
760 @patch('apex.overcloud.deploy.generate_ceph_key')
761 @patch('apex.overcloud.deploy.fileinput')
762 @patch('apex.overcloud.deploy.os.path.isfile')
763 @patch('builtins.open', mock_open())
764 def test_prep_sriov_env(self, mock_isfile, mock_fileinput, mock_ceph_key):
765 ds = {'deploy_options':
766 {'sdn_controller': 'opendaylight',
770 saved_stdout = sys.stdout
774 mock_fileinput.input.return_value = \
775 ['# NovaSchedulerDefaultFilters',
776 '# NovaSchedulerAvailableFilters',
777 '#NeutronPhysicalDevMappings: "datacentre:ens20f2"',
778 '#NeutronSriovNumVFs: \"ens20f2:5\"',
779 '#NovaPCIPassthrough:',
780 '# - devname: \"ens20f2\"',
781 '# physical_network: \"datacentre\"']
782 prep_sriov_env(ds, '/tmp')
783 output = out.getvalue().strip()
784 assert_in('NovaSchedulerDefaultFilters', output)
785 assert_in('NovaSchedulerAvailableFilters', output)
786 assert_in('NeutronPhysicalDevMappings: \"nfv_sriov:xxx\"', output)
787 assert_in('NeutronSriovNumVFs: \"xxx:8\"', output)
788 assert_in('NovaPCIPassthrough:', output)
789 assert_in('- devname: \"xxx\"', output)
790 assert_in('physical_network: \"nfv_sriov\"', output)
793 sys.stdout = saved_stdout
795 @patch('apex.overcloud.deploy.os.path.isfile')
796 @patch('builtins.open', mock_open())
797 def test_prep_sriov_env_raises(self, mock_isfile):
798 ds_opts = {'sriov': True}
799 ds = {'deploy_options': MagicMock()}
800 ds['deploy_options'].__getitem__.side_effect = \
801 lambda i: ds_opts.get(i, MagicMock())
802 mock_isfile.return_value = False
803 ds = {'deploy_options': MagicMock()}
804 assert_raises(ApexDeployException, prep_sriov_env, ds, '/tmp')
806 def test_external_network_cmds(self):
807 ds = {'deploy_options':
808 {'sdn_controller': 'opendaylight',
813 ns_dict = {'networks':
814 {'external': [{'floating_ip_range': (0, 1),
816 {'compute': {'vlan': 'native'}},
820 ns.enabled_network_list = ['external']
821 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
822 cmds = ' '.join(external_network_cmds(ns, ds))
823 assert_in('--external', cmds)
824 assert_in('--allocation-pool start=0,end=1', cmds)
825 assert_in('--gateway gw', cmds)
826 assert_in('--network external', cmds)
827 assert_in('--provider-physical-network datacentre', cmds)
829 def test_external_network_cmds_nosdn_fdio(self):
830 ds = {'deploy_options':
831 {'sdn_controller': False,
832 'dataplane': 'fdio'}}
836 ns_dict = {'networks':
837 {'external': [{'floating_ip_range': (0, 1),
839 {'compute': {'vlan': 'native'}},
843 ns.enabled_network_list = ['external']
844 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
845 cmds = ' '.join(external_network_cmds(ns, ds))
846 assert_in('--external', cmds)
847 assert_in('--allocation-pool start=0,end=1', cmds)
848 assert_in('--gateway gw', cmds)
849 assert_in('--network external', cmds)
850 assert_in('--provider-physical-network external', cmds)
852 def test_external_network_cmds_no_ext(self):
853 ds = {'deploy_options':
854 {'sdn_controller': 'opendaylight',
862 {'introspection_range': (0, 1),
864 {'compute': {'vlan': '123'}},
868 ns.enabled_network_list = ['admin']
869 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
870 cmds = ' '.join(external_network_cmds(ns, ds))
871 assert_in('--external', cmds)
872 assert_in('--allocation-pool start=0,end=1', cmds)
873 assert_in('--network external', cmds)
874 assert_in('--provider-network-type vlan', cmds)
876 @patch('apex.overcloud.deploy.parsers')
877 def test_create_congress_cmds(self, mock_parsers):
878 assert_greater(len(create_congress_cmds('overcloud_file')), 0)
880 @patch('apex.overcloud.deploy.parsers.parse_overcloudrc')
881 def test_create_congress_cmds_raises(self, mock_parsers):
882 mock_parsers.return_value.__getitem__.side_effect = KeyError()
883 assert_raises(KeyError, create_congress_cmds, 'overcloud_file')
885 def test_get_docker_sdn_files(self):
886 ds_opts = {'ha_enabled': True,
893 'sdn_controller': 'opendaylight',
894 'os_version': 'queens'
896 output = get_docker_sdn_files(ds_opts)
897 compare = ['/usr/share/openstack-tripleo-heat-templates/'
898 'environments/services/neutron-opendaylight.yaml',
899 '/usr/share/openstack-tripleo-heat-templates/environments'
900 '/services/neutron-bgpvpn-opendaylight.yaml']
901 self.assertEqual(output, compare)