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