402ecebf488eee27fe557e084250e8eb4896c009
[apex.git] / apex / tests / test_apex_overcloud_deploy.py
1 ##############################################################################
2 # Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat)
3 #
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 ##############################################################################
9
10 import mock
11 import os
12 import sys
13 import unittest
14
15 from mock import patch
16 from mock import MagicMock
17 from mock import mock_open
18 from io import StringIO
19
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
34
35 from nose.tools import (
36     assert_regexp_matches,
37     assert_raises,
38     assert_in,
39     assert_not_in,
40     assert_greater,
41     assert_equal)
42
43
44 class TestOvercloudDeploy(unittest.TestCase):
45     @classmethod
46     def setup_class(cls):
47         """This method is run once for each class before any tests are run"""
48
49     @classmethod
50     def teardown_class(cls):
51         """This method is run once for each class _after_ all tests are run"""
52
53     def setup(self):
54         """This method is run once before _each_ test method is executed"""
55
56     def teardown(self):
57         """This method is run once after _each_ test method is executed"""
58
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])
64
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), [])
70
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])
77
78     def test_build_sdn_env_list_with_string(self):
79         ds = {'sdn_controller': 'opendaylight',
80               'sriov': 'xxx'}
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)
85
86     def test_build_sdn_env_list_with_default(self):
87         ds = {'sdn_controller': 'opendaylight',
88               'vpn': True}
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)
93
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,
99                                mock_prep_sriov):
100         mock_sdn_list.return_value = []
101         ds = {'deploy_options':
102               {'ha_enabled': True,
103                'congress': True,
104                'tacker': True,
105                'containers': False,
106                'barometer': True,
107                'ceph': False,
108                'sriov': False,
109                'vim': 'openstack'
110                },
111               'global_params': MagicMock()}
112
113         ns = {'ntp': ['ntp']}
114         inv = MagicMock()
115         inv.get_node_counts.return_value = (3, 2)
116         virt = True
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)
125
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,
130                                               mock_prep_sriov):
131         ds = {'deploy_options':
132               {'ha_enabled': True,
133                'congress': False,
134                'tacker': False,
135                'containers': True,
136                'barometer': False,
137                'vpn': False,
138                'ceph': True,
139                'sdn_controller': 'opendaylight',
140                'sriov': False,
141                'os_version': 'queens',
142                'vim': 'openstack'
143                },
144               'global_params': MagicMock()}
145
146         ns = {'ntp': ['ntp']}
147         inv = MagicMock()
148         inv.get_node_counts.return_value = (3, 2)
149         virt = True
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)
169
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']}
184         inv = MagicMock()
185         inv.get_node_counts.return_value = (3, 2)
186         virt = False
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)
195
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,
202                         mock_inject_odl):
203         mock_is_file.return_value = True
204         ds_opts = {'dataplane': 'fdio',
205                    'sdn_controller': 'opendaylight',
206                    'odl_version': 'master',
207                    'vpn': False,
208                    'sriov': False}
209         ds = {'deploy_options': MagicMock(),
210               'global_params': MagicMock()}
211         ds['deploy_options'].__getitem__.side_effect = \
212             lambda i: ds_opts.get(i, MagicMock())
213         ns = 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()
217
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,
223                                   mock_virt_utils):
224         mock_is_file.return_value = True
225         ds_opts = {'dataplane': 'fdio',
226                    'vpn': False,
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())
232         ns = MagicMock()
233         prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
234         mock_virt_utils.virt_customize.assert_called()
235
236     @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
237     @patch('apex.builders.overcloud_builder.inject_opendaylight')
238     @patch('apex.overcloud.deploy.virt_utils')
239     @patch('apex.overcloud.deploy.shutil')
240     @patch('apex.overcloud.deploy.os.path.isfile')
241     @patch('builtins.open', mock_open())
242     def test_prep_image_sdn_odl(self, mock_is_file, mock_shutil,
243                                 mock_virt_utils, mock_inject_odl, mock_fetch):
244         mock_is_file.return_value = True
245         ds_opts = {'dataplane': 'ovs',
246                    'sdn_controller': 'opendaylight',
247                    'vpn': False,
248                    'sfc': False,
249                    'odl_version': con.DEFAULT_ODL_VERSION,
250                    'odl_vpp_netvirt': True}
251         ds = {'deploy_options': MagicMock(),
252               'global_params': MagicMock()}
253         ds['deploy_options'].__getitem__.side_effect = \
254             lambda i: ds_opts.get(i, MagicMock())
255         ds['deploy_options'].__contains__.side_effect = \
256             lambda i: True if i in ds_opts else MagicMock()
257         ns = MagicMock()
258         prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
259         mock_virt_utils.virt_customize.assert_called()
260         mock_inject_odl.assert_called()
261
262     @patch('apex.overcloud.deploy.c_builder')
263     @patch('apex.overcloud.deploy.oc_builder')
264     @patch('apex.overcloud.deploy.virt_utils')
265     @patch('apex.overcloud.deploy.shutil')
266     @patch('apex.overcloud.deploy.os.path.isfile')
267     @patch('builtins.open', mock_open())
268     def test_prep_image_sdn_odl_upstream_containers_patches(
269             self, mock_is_file, mock_shutil, mock_virt_utils,
270             mock_oc_builder, mock_c_builder):
271         mock_is_file.return_value = True
272         ds_opts = {'dataplane': 'ovs',
273                    'sdn_controller': 'opendaylight',
274                    'odl_version': con.DEFAULT_ODL_VERSION,
275                    'odl_vpp_netvirt': True}
276         ds = {'deploy_options': MagicMock(),
277               'global_params': MagicMock()}
278         ds['deploy_options'].__getitem__.side_effect = \
279             lambda i: ds_opts.get(i, MagicMock())
280         ds['deploy_options'].__contains__.side_effect = \
281             lambda i: True if i in ds_opts else MagicMock()
282         ns = MagicMock()
283         mock_c_builder.add_upstream_patches.return_value = ['nova-api']
284         patches = ['dummy_nova_patch']
285         rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
286                         docker_tag='latest', patches=patches)
287         mock_oc_builder.inject_opendaylight.assert_called()
288         mock_virt_utils.virt_customize.assert_called()
289         mock_c_builder.add_upstream_patches.assert_called()
290         self.assertListEqual(sorted(rv), ['nova-api', 'opendaylight'])
291
292     @patch('apex.overcloud.deploy.c_builder')
293     @patch('apex.overcloud.deploy.oc_builder')
294     @patch('apex.overcloud.deploy.virt_utils')
295     @patch('apex.overcloud.deploy.shutil')
296     @patch('apex.overcloud.deploy.os.path.isfile')
297     @patch('builtins.open', mock_open())
298     def test_prep_image_nosdn_upstream_containers_patches(
299             self, mock_is_file, mock_shutil, mock_virt_utils,
300             mock_oc_builder, mock_c_builder):
301         mock_is_file.return_value = True
302         ds_opts = {'dataplane': 'ovs',
303                    'sdn_controller': False,
304                    'odl_version': con.DEFAULT_ODL_VERSION,
305                    'odl_vpp_netvirt': False}
306         ds = {'deploy_options': MagicMock(),
307               'global_params': MagicMock()}
308         ds['deploy_options'].__getitem__.side_effect = \
309             lambda i: ds_opts.get(i, MagicMock())
310         ds['deploy_options'].__contains__.side_effect = \
311             lambda i: True if i in ds_opts else MagicMock()
312         ns = MagicMock()
313         mock_c_builder.add_upstream_patches.return_value = ['nova-api']
314         patches = ['dummy_nova_patch']
315         rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
316                         docker_tag='latest', patches=patches)
317         mock_virt_utils.virt_customize.assert_called()
318         mock_c_builder.add_upstream_patches.assert_called()
319         self.assertListEqual(sorted(rv), ['nova-api'])
320
321     @patch('apex.overcloud.deploy.oc_builder')
322     @patch('apex.overcloud.deploy.virt_utils')
323     @patch('apex.overcloud.deploy.shutil')
324     @patch('apex.overcloud.deploy.os.path.isfile')
325     @patch('builtins.open', mock_open())
326     def test_prep_image_sdn_odl_not_def(self, mock_is_file,
327                                         mock_shutil, mock_virt_utils,
328                                         mock_oc_builder):
329         mock_is_file.return_value = True
330         ds_opts = {'dataplane': 'ovs',
331                    'sdn_controller': 'opendaylight',
332                    'odl_version': 'uncommon'}
333         ds = {'deploy_options': MagicMock(),
334               'global_params': MagicMock()}
335         ds['deploy_options'].__getitem__.side_effect = \
336             lambda i: ds_opts.get(i, MagicMock())
337         ns = MagicMock()
338         prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
339         mock_virt_utils.virt_customize.assert_called()
340         mock_oc_builder.inject_opendaylight.assert_called()
341
342     @patch('apex.overcloud.deploy.virt_utils')
343     @patch('apex.overcloud.deploy.shutil')
344     @patch('apex.overcloud.deploy.os.path.isfile')
345     @patch('builtins.open', mock_open())
346     def test_prep_image_sdn_ovn(self, mock_is_file, mock_shutil,
347                                 mock_virt_utils):
348         mock_is_file.return_value = True
349         ds_opts = {'dataplane': 'ovs',
350                    'vpn': False,
351                    'sfc': False,
352                    'sdn_controller': 'ovn'}
353         ds = {'deploy_options': MagicMock(),
354               'global_params': MagicMock()}
355         ds['deploy_options'].__getitem__.side_effect = \
356             lambda i: ds_opts.get(i, MagicMock())
357         ns = MagicMock()
358         prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
359         mock_virt_utils.virt_customize.assert_called()
360
361     @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
362     @patch('apex.builders.overcloud_builder.inject_quagga')
363     @patch('apex.builders.overcloud_builder.inject_opendaylight')
364     @patch('apex.overcloud.deploy.virt_utils')
365     @patch('apex.overcloud.deploy.shutil')
366     @patch('apex.overcloud.deploy.os.path.isfile')
367     @patch('builtins.open', mock_open())
368     def test_prep_image_sdn_odl_vpn(self, mock_is_file, mock_shutil,
369                                     mock_virt_utils, mock_inject_odl,
370                                     mock_inject_quagga, mock_fetch):
371         mock_is_file.return_value = True
372         ds_opts = {'dataplane': 'ovs',
373                    'sdn_controller': 'opendaylight',
374                    'vpn': True,
375                    'sfc': False,
376                    'odl_version': con.DEFAULT_ODL_VERSION,
377                    'odl_vpp_netvirt': True}
378         ds = {'deploy_options': MagicMock(),
379               'global_params': MagicMock()}
380         ds['deploy_options'].__getitem__.side_effect = \
381             lambda i: ds_opts.get(i, MagicMock())
382         ds['deploy_options'].__contains__.side_effect = \
383             lambda i: True if i in ds_opts else MagicMock()
384         ns = MagicMock()
385         prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
386         mock_virt_utils.virt_customize.assert_called()
387         mock_inject_odl.assert_called()
388         mock_inject_quagga.assert_called()
389
390         @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
391         @patch('apex.builders.overcloud_builder.inject_opendaylight')
392         @patch('apex.overcloud.deploy.virt_utils')
393         @patch('apex.overcloud.deploy.shutil')
394         @patch('apex.overcloud.deploy.os.path.isfile')
395         @patch('builtins.open', mock_open())
396         def test_prep_image_sdn_odl_sfc(self, mock_is_file, mock_shutil,
397                                         mock_virt_utils, mock_inject_odl,
398                                         mock_inject_ovs_nsh):
399             mock_is_file.return_value = True
400             ds_opts = {'dataplane': 'ovs',
401                        'sdn_controller': 'opendaylight',
402                        'vpn': False,
403                        'sfc': True,
404                        'odl_version': con.DEFAULT_ODL_VERSION,
405                        'odl_vpp_netvirt': True}
406             ds = {'deploy_options': MagicMock(),
407                   'global_params': MagicMock()}
408             ds['deploy_options'].__getitem__.side_effect = \
409                 lambda i: ds_opts.get(i, MagicMock())
410             ds['deploy_options'].__contains__.side_effect = \
411                 lambda i: True if i in ds_opts else MagicMock()
412             ns = MagicMock()
413             prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
414             mock_virt_utils.virt_customize.assert_called()
415             mock_inject_odl.assert_called()
416             mock_inject_ovs_nsh.assert_called()
417
418     @patch('apex.overcloud.deploy.os.path.isfile')
419     def test_prep_image_no_image(self, mock_isfile):
420         mock_isfile.return_value = False
421         assert_raises(ApexDeployException, prep_image,
422                       {}, {}, 'undercloud.qcow2', '/tmp')
423
424     def test_make_ssh_key(self):
425         priv, pub = make_ssh_key()
426         assert_in('-----BEGIN PRIVATE KEY-----', priv)
427         assert_in('ssh-rsa', pub)
428
429     @patch('apex.overcloud.deploy.yaml')
430     @patch('apex.overcloud.deploy.fileinput')
431     @patch('apex.overcloud.deploy.shutil')
432     @patch('builtins.open', mock_open())
433     def test_prep_env(self, mock_shutil, mock_fileinput, mock_yaml):
434         mock_fileinput.input.return_value = \
435             ['CloudDomain', 'replace_private_key', 'replace_public_key',
436              'opendaylight::vpp_routing_node', 'ControllerExtraConfig',
437              'NovaComputeExtraConfig', 'ComputeKernelArgs', 'HostCpusList',
438              'ComputeExtraConfigPre', 'resource_registry',
439              'NovaSchedulerDefaultFilters']
440         mock_yaml.safe_load.return_value = {
441             'parameter_defaults': {
442                 'ControllerServices': [1, 2, 3],
443                 'ComputeServices': [3, 4, 5]
444             }}
445         ds = {'global_params': {'ha_enabled': False},
446               'deploy_options':
447               {'sdn_controller': 'opendaylight',
448                'odl_vpp_routing_node': 'test',
449                'dataplane': 'ovs_dpdk',
450                'sriov': 'xxx',
451                'performance': {'Compute': {'vpp': {'main-core': 'test',
452                                                    'corelist-workers': 'test'},
453                                            'ovs': {'dpdk_cores': 'test'},
454                                            'kernel': {'test': 'test'}},
455                                'Controller': {'vpp': 'test'}}}}
456         ns_dict = {'domain_name': 'test.domain',
457                    'networks':
458                    {'tenant':
459                     {'nic_mapping': {'controller':
460                                      {'members': ['tenant_nic']},
461                                      'compute':
462                                      {'members': ['tenant_nic']}}},
463                     'external':
464                     [{'nic_mapping': {'controller':
465                                       {'members': ['ext_nic']},
466                                       'compute':
467                                       {'members': ['ext_nic']}}}]}}
468         inv = MagicMock()
469         inv.get_node_counts.return_value = (1, 0)
470         try:
471             # Swap stdout
472             saved_stdout = sys.stdout
473             out = StringIO()
474             sys.stdout = out
475             ns = MagicMock()
476             ns.enabled_network_list = ['external', 'tenant']
477             ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
478             # run test
479             prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
480             output = out.getvalue().strip()
481             assert_in('CloudDomain: test.domain', output)
482             assert_in('ssh-rsa', output)
483             assert_in('ComputeKernelArgs: \'test=test \'', output)
484             assert_in('fdio::vpp_cpu_main_core: \'test\'', output)
485             mock_yaml.safe_dump.assert_called_with(
486                 {'parameter_defaults': {
487                     'ControllerServices': [1, 2, 3, 4, 5],
488                 }},
489                 mock.ANY, default_flow_style=False
490             )
491         finally:
492             # put stdout back
493             sys.stdout = saved_stdout
494
495     @patch('apex.overcloud.deploy.fileinput')
496     @patch('apex.overcloud.deploy.shutil')
497     @patch('builtins.open', mock_open())
498     def test_prep_env_round_two(self, mock_shutil, mock_fileinput):
499         mock_fileinput.input.return_value = \
500             ['NeutronVPPAgentPhysnets']
501         ds = {'global_params': {'ha_enabled': False},
502               'deploy_options':
503               {'sdn_controller': False,
504                'dataplane': 'fdio',
505                'sriov': 'xxx',
506                'performance': {'Compute': {},
507                                'Controller': {}}}}
508         ns_dict = {'domain_name': 'test.domain',
509                    'networks':
510                    {'tenant':
511                     {'nic_mapping': {'controller':
512                                      {'members': ['tenant_nic']},
513                                      'compute':
514                                      {'members': ['tenant_nic']}}},
515                     'external':
516                     [{'nic_mapping': {'controller':
517                                       {'members': ['ext_nic']},
518                                       'compute':
519                                       {'members': ['ext_nic']}}}]}}
520         inv = MagicMock()
521         inv.get_node_counts.return_value = (3, 2)
522         try:
523             # Swap stdout
524             saved_stdout = sys.stdout
525             out = StringIO()
526             sys.stdout = out
527             ns = MagicMock()
528             ns.enabled_network_list = ['external', 'tenant']
529             ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
530             # run test
531             prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
532             output = out.getvalue().strip()
533             assert_in('NeutronVPPAgentPhysnets: '
534                       '\'datacentre:tenant_nic,external:tap0\'',
535                       output)
536             assert_in('NeutronVPPAgentPhysnets', output)
537         finally:
538             # put stdout back
539             sys.stdout = saved_stdout
540
541     @patch('apex.overcloud.deploy.fileinput')
542     @patch('apex.overcloud.deploy.shutil')
543     @patch('builtins.open', mock_open())
544     def test_prep_env_round_three(self, mock_shutil, mock_fileinput):
545         mock_fileinput.input.return_value = \
546             ['OS::TripleO::Services::NeutronDhcpAgent',
547              'NeutronDhcpAgentsPerNetwork', 'ComputeServices']
548         ds = {'global_params': {'ha_enabled': False},
549               'deploy_options':
550               {'sdn_controller': 'opendaylight',
551                'dataplane': 'fdio',
552                'sriov': 'xxx',
553                'dvr': True}}
554         ns_dict = {'domain_name': 'test.domain',
555                    'networks':
556                    {'tenant':
557                     {'nic_mapping': {'controller':
558                                      {'members': ['tenant_nic']},
559                                      'compute':
560                                      {'members': ['tenant_nic']}}},
561                     'external':
562                     [{'nic_mapping': {'controller':
563                                       {'members': ['ext_nic']},
564                                       'compute':
565                                       {'members': ['ext_nic']}}}]}}
566         inv = MagicMock()
567         inv.get_node_counts.return_value = (3, 2)
568         try:
569             # Swap stdout
570             saved_stdout = sys.stdout
571             out = StringIO()
572             sys.stdout = out
573             ns = MagicMock()
574             ns.enabled_network_list = ['external', 'tenant']
575             ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
576             # run test
577             prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
578             output = out.getvalue().strip()
579             assert_in('NeutronDhcpAgentsPerNetwork: 2', output)
580         finally:
581             # put stdout back
582             sys.stdout = saved_stdout
583
584     @patch('apex.overcloud.deploy.fileinput')
585     @patch('apex.overcloud.deploy.shutil')
586     @patch('builtins.open', mock_open())
587     def test_prep_env_tenant_vlan(self, mock_shutil, mock_fileinput):
588         mock_fileinput.input.return_value = \
589             ['NeutronNetworkVLANRanges',
590              'NeutronNetworkType', 'NeutronBridgeMappings']
591         ds = {'global_params': {'ha_enabled': False},
592               'deploy_options':
593               {'sdn_controller': False,
594                'dataplane': 'ovs',
595                'sriov': 'xxx',
596                'dvr': True}}
597         ns_dict = {'domain_name': 'test.domain',
598                    'networks':
599                    {'tenant':
600                     {'nic_mapping': {'controller':
601                                      {'members': ['tenant_nic']},
602                                      'compute':
603                                      {'members': ['tenant_nic']}},
604                      'segmentation_type': 'vlan',
605                      'overlay_id_range': 'vlan:500:600'
606                      },
607                     'external':
608                     [{'nic_mapping': {'controller':
609                                       {'members': ['ext_nic']},
610                                       'compute':
611                                       {'members': ['ext_nic']}}}]}}
612         inv = MagicMock()
613         inv.get_node_counts.return_value = (3, 2)
614         try:
615             # Swap stdout
616             saved_stdout = sys.stdout
617             out = StringIO()
618             sys.stdout = out
619             ns = MagicMock()
620             ns.enabled_network_list = ['external', 'tenant']
621             ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
622             # run test
623             prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
624             output = out.getvalue().strip()
625             assert_in('NeutronNetworkVLANRanges: '
626                       'vlan:500:600,datacentre:1:1000', output)
627             assert_in('NeutronNetworkType: vlan', output)
628             assert_in('NeutronBridgeMappings: '
629                       'vlan:br-vlan,datacentre:br-ex', output)
630             assert_not_in('OpenDaylightProviderMappings', output)
631         finally:
632             # put stdout back
633             sys.stdout = saved_stdout
634
635     @patch('apex.overcloud.deploy.fileinput')
636     @patch('apex.overcloud.deploy.shutil')
637     @patch('builtins.open', mock_open())
638     def test_prep_env_tenant_vlan_odl(self, mock_shutil, mock_fileinput):
639         mock_fileinput.input.return_value = \
640             ['NeutronNetworkVLANRanges',
641              'NeutronNetworkType',
642              'NeutronBridgeMappings',
643              'OpenDaylightProviderMappings']
644         ds = {'global_params': {'ha_enabled': False},
645               'deploy_options':
646               {'sdn_controller': 'opendaylight',
647                'dataplane': 'ovs',
648                'sriov': 'xxx',
649                'dvr': True}}
650         ns_dict = {'domain_name': 'test.domain',
651                    'networks':
652                    {'tenant':
653                     {'nic_mapping': {'controller':
654                                      {'members': ['tenant_nic']},
655                                      'compute':
656                                      {'members': ['tenant_nic']}},
657                      'segmentation_type': 'vlan',
658                      'overlay_id_range': 'vlan:500:600'
659                      },
660                     'external':
661                     [{'nic_mapping': {'controller':
662                                       {'members': ['ext_nic']},
663                                       'compute':
664                                       {'members': ['ext_nic']}}}]}}
665         inv = MagicMock()
666         inv.get_node_counts.return_value = (3, 2)
667         try:
668             # Swap stdout
669             saved_stdout = sys.stdout
670             out = StringIO()
671             sys.stdout = out
672             ns = MagicMock()
673             ns.enabled_network_list = ['external', 'tenant']
674             ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
675             # run test
676             prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
677             output = out.getvalue().strip()
678             assert_in('NeutronNetworkVLANRanges: '
679                       'vlan:500:600,datacentre:1:1000', output)
680             assert_in('NeutronNetworkType: vlan', output)
681             assert_in('NeutronBridgeMappings: '
682                       'vlan:br-vlan,datacentre:br-ex', output)
683             assert_in('OpenDaylightProviderMappings: '
684                       'vlan:br-vlan,datacentre:br-ex', output)
685         finally:
686             # put stdout back
687             sys.stdout = saved_stdout
688
689     def test_generate_ceph_key(self):
690         assert_equal(len(generate_ceph_key()), 40)
691
692     @patch('apex.overcloud.deploy.generate_ceph_key')
693     @patch('apex.overcloud.deploy.fileinput')
694     @patch('apex.overcloud.deploy.os.path.isfile')
695     @patch('builtins.open', mock_open())
696     def test_prep_storage_env(self, mock_isfile, mock_fileinput,
697                               mock_ceph_key):
698         mock_fileinput.input.return_value = \
699             ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
700         ds = {'deploy_options': {
701             'ceph_device': '/dev/sdx',
702             'containers': False
703         }}
704         ns = {}
705         prep_storage_env(ds, ns, virtual=False, tmp_dir='/tmp')
706
707     @patch('apex.overcloud.deploy.utils.edit_tht_env')
708     @patch('apex.overcloud.deploy.generate_ceph_key')
709     @patch('apex.overcloud.deploy.fileinput')
710     @patch('apex.overcloud.deploy.os.path.isfile')
711     @patch('builtins.open', mock_open())
712     def test_prep_storage_env_containers(self, mock_isfile, mock_fileinput,
713                                          mock_ceph_key, mock_edit_tht):
714         mock_fileinput.input.return_value = \
715             ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
716         ds = {'deploy_options': {
717               'ceph_device': '/dev/sdx',
718               'containers': True,
719               'os_version': 'master'
720               }, 'global_params': {'ha_enabled': False}}
721         ns = {'networks': {con.ADMIN_NETWORK: {'installer_vm':
722                                                {'ip': '192.0.2.1'}}}
723               }
724         prep_storage_env(ds, ns, virtual=True, tmp_dir='/tmp')
725         ceph_params = {
726             'CephPoolDefaultSize': 2,
727             'CephAnsibleExtraConfig': {
728                 'centos_package_dependencies': [],
729                 'ceph_osd_docker_memory_limit': '1g',
730                 'ceph_mds_docker_memory_limit': '1g'
731             },
732             'CephPoolDefaultPgNum': 32,
733             'CephAnsibleDisksConfig': {
734                 'devices': ['/dev/sdx'],
735                 'journal_size': 512,
736                 'osd_scenario': 'collocated'
737             }
738         }
739         mock_edit_tht.assert_called_with('/tmp/storage-environment.yaml',
740                                          'parameter_defaults',
741                                          ceph_params)
742
743     @patch('apex.overcloud.deploy.os.path.isfile')
744     @patch('builtins.open', mock_open())
745     def test_prep_storage_env_raises(self, mock_isfile):
746         mock_isfile.return_value = False
747         ds = {'deploy_options': MagicMock()}
748         ns = {}
749         assert_raises(ApexDeployException, prep_storage_env, ds,
750                       ns, virtual=False, tmp_dir='/tmp')
751
752     @patch('apex.overcloud.deploy.generate_ceph_key')
753     @patch('apex.overcloud.deploy.fileinput')
754     @patch('apex.overcloud.deploy.os.path.isfile')
755     @patch('builtins.open', mock_open())
756     def test_prep_sriov_env(self, mock_isfile, mock_fileinput, mock_ceph_key):
757         ds = {'deploy_options':
758               {'sdn_controller': 'opendaylight',
759                'sriov': 'xxx'}}
760         try:
761             # Swap stdout
762             saved_stdout = sys.stdout
763             out = StringIO()
764             sys.stdout = out
765             # Run tests
766             mock_fileinput.input.return_value = \
767                 ['#  NovaSchedulerDefaultFilters',
768                  '#  NovaSchedulerAvailableFilters',
769                  '#NeutronPhysicalDevMappings: "datacentre:ens20f2"',
770                  '#NeutronSriovNumVFs: \"ens20f2:5\"',
771                  '#NovaPCIPassthrough:',
772                  '#  - devname: \"ens20f2\"',
773                  '#    physical_network: \"datacentre\"']
774             prep_sriov_env(ds, '/tmp')
775             output = out.getvalue().strip()
776             assert_in('NovaSchedulerDefaultFilters', output)
777             assert_in('NovaSchedulerAvailableFilters', output)
778             assert_in('NeutronPhysicalDevMappings: \"nfv_sriov:xxx\"', output)
779             assert_in('NeutronSriovNumVFs: \"xxx:8\"', output)
780             assert_in('NovaPCIPassthrough:', output)
781             assert_in('- devname: \"xxx\"', output)
782             assert_in('physical_network: \"nfv_sriov\"', output)
783         finally:
784             # put stdout back
785             sys.stdout = saved_stdout
786
787     @patch('apex.overcloud.deploy.os.path.isfile')
788     @patch('builtins.open', mock_open())
789     def test_prep_sriov_env_raises(self, mock_isfile):
790         ds_opts = {'sriov': True}
791         ds = {'deploy_options': MagicMock()}
792         ds['deploy_options'].__getitem__.side_effect = \
793             lambda i: ds_opts.get(i, MagicMock())
794         mock_isfile.return_value = False
795         ds = {'deploy_options': MagicMock()}
796         assert_raises(ApexDeployException, prep_sriov_env, ds, '/tmp')
797
798     def test_external_network_cmds(self):
799         ds = {'deploy_options':
800               {'sdn_controller': 'opendaylight',
801                'dataplane': 'ovs'}}
802
803         cidr = MagicMock()
804         cidr.version = 6
805         ns_dict = {'networks':
806                    {'external': [{'floating_ip_range': (0, 1),
807                                   'nic_mapping':
808                                   {'compute': {'vlan': 'native'}},
809                                   'gateway': 'gw',
810                                   'cidr': cidr}]}}
811         ns = MagicMock()
812         ns.enabled_network_list = ['external']
813         ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
814         cmds = ' '.join(external_network_cmds(ns, ds))
815         assert_in('--external', cmds)
816         assert_in('--allocation-pool start=0,end=1', cmds)
817         assert_in('--gateway gw', cmds)
818         assert_in('--network external', cmds)
819         assert_in('--provider-physical-network datacentre', cmds)
820
821     def test_external_network_cmds_nosdn_fdio(self):
822         ds = {'deploy_options':
823               {'sdn_controller': False,
824                'dataplane': 'fdio'}}
825
826         cidr = MagicMock()
827         cidr.version = 6
828         ns_dict = {'networks':
829                    {'external': [{'floating_ip_range': (0, 1),
830                                   'nic_mapping':
831                                   {'compute': {'vlan': 'native'}},
832                                   'gateway': 'gw',
833                                   'cidr': cidr}]}}
834         ns = MagicMock()
835         ns.enabled_network_list = ['external']
836         ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
837         cmds = ' '.join(external_network_cmds(ns, ds))
838         assert_in('--external', cmds)
839         assert_in('--allocation-pool start=0,end=1', cmds)
840         assert_in('--gateway gw', cmds)
841         assert_in('--network external', cmds)
842         assert_in('--provider-physical-network external', cmds)
843
844     def test_external_network_cmds_no_ext(self):
845         ds = {'deploy_options':
846               {'sdn_controller': 'opendaylight',
847                'dataplane': 'ovs'}}
848
849         cidr = MagicMock()
850         cidr.version = 6
851         ns_dict = {'apex':
852                    {'networks':
853                     {'admin':
854                      {'introspection_range': (0, 1),
855                       'nic_mapping':
856                       {'compute': {'vlan': '123'}},
857                       'gateway': 'gw',
858                       'cidr': cidr}}}}
859         ns = MagicMock()
860         ns.enabled_network_list = ['admin']
861         ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
862         cmds = ' '.join(external_network_cmds(ns, ds))
863         assert_in('--external', cmds)
864         assert_in('--allocation-pool start=0,end=1', cmds)
865         assert_in('--network external', cmds)
866         assert_in('--provider-network-type vlan', cmds)
867
868     @patch('apex.overcloud.deploy.parsers')
869     def test_create_congress_cmds(self, mock_parsers):
870         assert_greater(len(create_congress_cmds('overcloud_file')), 0)
871
872     @patch('apex.overcloud.deploy.parsers.parse_overcloudrc')
873     def test_create_congress_cmds_raises(self, mock_parsers):
874         mock_parsers.return_value.__getitem__.side_effect = KeyError()
875         assert_raises(KeyError, create_congress_cmds, 'overcloud_file')
876
877     def test_get_docker_sdn_files(self):
878         ds_opts = {'ha_enabled': True,
879                    'congress': True,
880                    'tacker': True,
881                    'containers': False,
882                    'barometer': True,
883                    'ceph': False,
884                    'vpn': True,
885                    'sdn_controller': 'opendaylight',
886                    'os_version': 'queens'
887                    }
888         output = get_docker_sdn_files(ds_opts)
889         compare = ['/usr/share/openstack-tripleo-heat-templates/'
890                    'environments/services/neutron-opendaylight.yaml',
891                    '/usr/share/openstack-tripleo-heat-templates/environments'
892                    '/services/neutron-bgpvpn-opendaylight.yaml']
893         self.assertEqual(output, compare)