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