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