1 ##############################################################################
2 # Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat)
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
13 from mock import patch
14 from mock import MagicMock
15 from mock import mock_open
16 from io import StringIO
18 from apex.common import constants as con
19 from apex.common.exceptions import ApexDeployException
20 from apex.overcloud.deploy import build_sdn_env_list
21 from apex.overcloud.deploy import create_deploy_cmd
22 from apex.overcloud.deploy import prep_image
23 from apex.overcloud.deploy import make_ssh_key
24 from apex.overcloud.deploy import prep_env
25 from apex.overcloud.deploy import generate_ceph_key
26 from apex.overcloud.deploy import prep_storage_env
27 from apex.overcloud.deploy import external_network_cmds
28 from apex.overcloud.deploy import create_congress_cmds
30 from nose.tools import (
31 assert_regexp_matches,
39 class TestOvercloudDeploy(unittest.TestCase):
42 """This method is run once for each class before any tests are run"""
45 def teardown_class(cls):
46 """This method is run once for each class _after_ all tests are run"""
49 """This method is run once before _each_ test method is executed"""
52 """This method is run once after _each_ test method is executed"""
54 def test_build_sdn_env_list(self):
55 ds = {'sdn_controller': 'opendaylight'}
56 sdn_map = {'opendaylight': 'test'}
57 res = '/usr/share/openstack-tripleo-heat-templates/environments/test'
58 assert_equal(build_sdn_env_list(ds, sdn_map), [res])
60 def test_build_sdn_env_list_dict(self):
61 ds = {'opendaylight': True,
62 'sdn_controller': None}
63 sdn_map = {'opendaylight': {}}
64 assert_equal(build_sdn_env_list(ds, sdn_map), [])
66 def test_build_sdn_env_list_tuple(self):
67 ds = {'opendaylight': 'test',
68 'sdn_controller': None}
69 sdn_map = {'opendaylight': ('test', 'test')}
70 res = '/usr/share/openstack-tripleo-heat-templates/environments/test'
71 assert_equal(build_sdn_env_list(ds, sdn_map), [res])
73 @patch('apex.overcloud.deploy.prep_storage_env')
74 @patch('apex.overcloud.deploy.build_sdn_env_list')
75 @patch('builtins.open', mock_open())
76 def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage):
77 mock_sdn_list.return_value = []
78 ds = {'deploy_options': MagicMock(),
79 'global_params': MagicMock()}
80 ds['global_params'].__getitem__.side_effect = \
81 lambda i: True if i == 'ha_enabled' else MagicMock()
82 ds['deploy_options'].__getitem__.side_effect = \
83 lambda i: True if i == 'congress' else MagicMock()
84 ds['deploy_options'].__contains__.side_effect = \
85 lambda i: True if i == 'congress' else MagicMock()
88 inv.get_node_counts.return_value = (3, 2)
90 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
91 assert_in('--ntp-server ntp', result_cmd)
92 assert_in('enable_tacker.yaml', result_cmd)
93 assert_in('enable_congress.yaml', result_cmd)
94 assert_in('enable_barometer.yaml', result_cmd)
95 assert_in('virtual-environment.yaml', result_cmd)
96 assert_in('--control-scale 3', result_cmd)
97 assert_in('--compute-scale 2', result_cmd)
99 @patch('apex.overcloud.deploy.prep_storage_env')
100 @patch('apex.overcloud.deploy.build_sdn_env_list')
101 @patch('builtins.open', mock_open())
102 def test_create_deploy_cmd_no_ha_bm(self, mock_sdn_list,
104 mock_sdn_list.return_value = []
105 ds = {'deploy_options': MagicMock(),
106 'global_params': MagicMock()}
107 ds['global_params'].__getitem__.side_effect = \
108 lambda i: False if i == 'ha_enabled' else MagicMock()
109 ns = {'ntp': ['ntp']}
111 inv.get_node_counts.return_value = (3, 2)
113 result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
114 assert_in('--ntp-server ntp', result_cmd)
115 assert_in('--control-scale 1', result_cmd)
116 assert_in('--compute-scale 2', result_cmd)
117 assert_in('baremetal-environment.yaml', result_cmd)
118 assert_not_in('enable_tacker.yaml', result_cmd)
119 assert_not_in('enable_congress.yaml', result_cmd)
120 assert_not_in('enable_barometer.yaml', result_cmd)
122 @patch('apex.overcloud.deploy.prep_storage_env')
123 @patch('apex.overcloud.deploy.build_sdn_env_list')
124 def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage):
125 mock_sdn_list.return_value = []
126 ds = {'deploy_options': MagicMock(),
127 'global_params': MagicMock()}
130 inv.get_node_counts.return_value = (0, 0)
132 assert_raises(ApexDeployException, create_deploy_cmd,
133 ds, ns, inv, '/tmp', virt)
135 @patch('apex.overcloud.deploy.virt_utils')
136 @patch('apex.overcloud.deploy.shutil')
137 @patch('apex.overcloud.deploy.os.path')
138 @patch('builtins.open', mock_open())
139 def test_prep_image(self, mock_os_path, mock_shutil, mock_virt_utils):
140 ds_opts = {'dataplane': 'fdio',
141 'sdn_controller': 'opendaylight',
142 'odl_version': 'master'}
143 ds = {'deploy_options': MagicMock(),
144 'global_params': MagicMock()}
145 ds['deploy_options'].__getitem__.side_effect = \
146 lambda i: ds_opts.get(i, MagicMock())
147 prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
148 mock_virt_utils.virt_customize.assert_called()
150 @patch('apex.overcloud.deploy.virt_utils')
151 @patch('apex.overcloud.deploy.shutil')
152 @patch('apex.overcloud.deploy.os.path')
153 @patch('builtins.open', mock_open())
154 def test_prep_image_sdn_false(self, mock_os_path, mock_shutil,
156 ds_opts = {'dataplane': 'fdio',
157 'sdn_controller': False}
158 ds = {'deploy_options': MagicMock(),
159 'global_params': MagicMock()}
160 ds['deploy_options'].__getitem__.side_effect = \
161 lambda i: ds_opts.get(i, MagicMock())
162 prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
163 mock_virt_utils.virt_customize.assert_called()
165 @patch('apex.overcloud.deploy.virt_utils')
166 @patch('apex.overcloud.deploy.shutil')
167 @patch('apex.overcloud.deploy.os.path')
168 @patch('builtins.open', mock_open())
169 def test_prep_image_sdn_odl(self, mock_os_path, mock_shutil,
171 ds_opts = {'dataplane': 'ovs',
172 'sdn_controller': 'opendaylight',
173 'odl_version': con.DEFAULT_ODL_VERSION,
174 'odl_vpp_netvirt': True}
175 ds = {'deploy_options': MagicMock(),
176 'global_params': MagicMock()}
177 ds['deploy_options'].__getitem__.side_effect = \
178 lambda i: ds_opts.get(i, MagicMock())
179 ds['deploy_options'].__contains__.side_effect = \
180 lambda i: True if i in ds_opts else MagicMock()
181 prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
182 mock_virt_utils.virt_customize.assert_called()
184 @patch('apex.overcloud.deploy.virt_utils')
185 @patch('apex.overcloud.deploy.shutil')
186 @patch('apex.overcloud.deploy.os.path')
187 @patch('builtins.open', mock_open())
188 def test_prep_image_sdn_odl_not_def(self, mock_os_path,
189 mock_shutil, mock_virt_utils):
190 ds_opts = {'dataplane': 'ovs',
191 'sdn_controller': 'opendaylight',
192 'odl_version': 'uncommon'}
193 ds = {'deploy_options': MagicMock(),
194 'global_params': MagicMock()}
195 ds['deploy_options'].__getitem__.side_effect = \
196 lambda i: ds_opts.get(i, MagicMock())
197 prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
198 mock_virt_utils.virt_customize.assert_called()
200 @patch('apex.overcloud.deploy.virt_utils')
201 @patch('apex.overcloud.deploy.shutil')
202 @patch('apex.overcloud.deploy.os.path')
203 @patch('builtins.open', mock_open())
204 def test_prep_image_sdn_ovn(self, mock_os_path, mock_shutil,
206 ds_opts = {'dataplane': 'ovs',
207 'sdn_controller': 'ovn'}
208 ds = {'deploy_options': MagicMock(),
209 'global_params': MagicMock()}
210 ds['deploy_options'].__getitem__.side_effect = \
211 lambda i: ds_opts.get(i, MagicMock())
212 prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
213 mock_virt_utils.virt_customize.assert_called()
215 @patch('apex.overcloud.deploy.os.path.isfile')
216 def test_prep_image_no_image(self, mock_isfile):
217 mock_isfile.return_value = False
218 assert_raises(ApexDeployException, prep_image,
219 {}, 'undercloud.qcow2', '/tmp')
221 def test_make_ssh_key(self):
222 priv, pub = make_ssh_key()
223 assert_in('-----BEGIN PRIVATE KEY-----', priv)
224 assert_in('ssh-rsa', pub)
226 @patch('apex.overcloud.deploy.fileinput')
227 @patch('apex.overcloud.deploy.shutil')
228 def test_prep_env(self, mock_shutil, mock_fileinput):
229 mock_fileinput.input.return_value = \
230 ['CloudDomain', 'replace_private_key', 'replace_public_key',
231 'opendaylight::vpp_routing_node', 'ControllerExtraConfig',
232 'NovaComputeExtraConfig', 'ComputeKernelArgs', 'HostCpusList',
233 'ComputeExtraConfigPre', 'resource_registry',
234 'NovaSchedulerDefaultFilters']
235 ds = {'deploy_options':
236 {'sdn_controller': 'opendaylight',
237 'odl_vpp_routing_node': 'test',
238 'dataplane': 'ovs_dpdk',
239 'performance': {'Compute': {'vpp': {'main-core': 'test',
240 'corelist-workers': 'test'},
241 'ovs': {'dpdk_cores': 'test'},
242 'kernel': {'test': 'test'}},
243 'Controller': {'vpp': 'test'}}}}
244 ns = {'domain_name': 'test.domain',
247 {'nic_mapping': {'controller':
248 {'members': ['test']},
250 {'members': ['test']}}}}}
254 saved_stdout = sys.stdout
258 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
259 output = out.getvalue().strip()
260 assert_in('CloudDomain: test.domain', output)
261 assert_in('ssh-rsa', output)
262 assert_in('ComputeKernelArgs: \'test=test \'', output)
263 assert_in('fdio::vpp_cpu_main_core: \'test\'', output)
266 sys.stdout = saved_stdout
268 @patch('apex.overcloud.deploy.fileinput')
269 @patch('apex.overcloud.deploy.shutil')
270 def test_prep_env_round_two(self, mock_shutil, mock_fileinput):
271 mock_fileinput.input.return_value = \
272 ['NeutronVPPAgentPhysnets']
273 ds = {'deploy_options':
274 {'sdn_controller': False,
276 'performance': {'Compute': {},
278 ns = {'domain_name': 'test.domain',
281 {'nic_mapping': {'controller':
282 {'members': ['test']},
284 {'members': ['test']}}}}}
288 saved_stdout = sys.stdout
292 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
293 output = out.getvalue().strip()
294 assert_in('NeutronVPPAgentPhysnets: \'datacentre:test\'', output)
295 assert_in('NeutronVPPAgentPhysnets', output)
298 sys.stdout = saved_stdout
300 @patch('apex.overcloud.deploy.fileinput')
301 @patch('apex.overcloud.deploy.shutil')
302 def test_prep_env_round_three(self, mock_shutil, mock_fileinput):
303 mock_fileinput.input.return_value = \
304 ['OS::TripleO::Services::NeutronDhcpAgent',
305 'NeutronDhcpAgentsPerNetwork', 'ComputeServices']
306 ds = {'deploy_options':
307 {'sdn_controller': 'opendaylight',
310 ns = {'domain_name': 'test.domain',
313 {'nic_mapping': {'controller':
314 {'members': ['test']},
316 {'members': ['test']}}}}}
318 inv.get_node_counts.return_value = (3, 2)
321 saved_stdout = sys.stdout
325 prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
326 output = out.getvalue().strip()
327 assert_in('NeutronDhcpAgentsPerNetwork: 2', output)
330 sys.stdout = saved_stdout
332 def test_generate_ceph_key(self):
333 assert_equal(len(generate_ceph_key()), 40)
335 @patch('apex.overcloud.deploy.generate_ceph_key')
336 @patch('apex.overcloud.deploy.fileinput')
337 @patch('apex.overcloud.deploy.os.path.isfile')
338 @patch('builtins.open', mock_open())
339 def test_prep_storage_env(self, mock_isfile, mock_fileinput,
341 mock_fileinput.input.return_value = \
342 ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
343 ds = {'deploy_options': MagicMock()}
344 ds['deploy_options'].__getitem__.side_effect = \
345 lambda i: '/dev/sdx' if i == 'ceph_device' else MagicMock()
346 ds['deploy_options'].__contains__.side_effect = \
347 lambda i: True if i == 'ceph_device' else MagicMock()
348 prep_storage_env(ds, '/tmp')
350 @patch('apex.overcloud.deploy.os.path.isfile')
351 @patch('builtins.open', mock_open())
352 def test_prep_storage_env_raises(self, mock_isfile):
353 mock_isfile.return_value = False
354 ds = {'deploy_options': MagicMock()}
355 assert_raises(ApexDeployException, prep_storage_env, ds, '/tmp')
357 def test_external_network_cmds(self):
360 ns_dict = {'networks':
361 {'external': [{'floating_ip_range': (0, 1),
363 {'compute': {'vlan': 'native'}},
367 ns.enabled_network_list = ['external']
368 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
369 cmds = ' '.join(external_network_cmds(ns))
370 assert_in('--external', cmds)
371 assert_in('--allocation-pool start=0,end=1', cmds)
372 assert_in('--gateway gw', cmds)
373 assert_in('--network external', cmds)
375 def test_external_network_cmds_no_ext(self):
381 {'introspection_range': (0, 1),
383 {'compute': {'vlan': '123'}},
387 ns.enabled_network_list = ['admin']
388 ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
389 external_network_cmds(ns)
390 cmds = ' '.join(external_network_cmds(ns))
391 assert_in('--external', cmds)
392 assert_in('--allocation-pool start=0,end=1', cmds)
393 assert_in('--network external', cmds)
394 assert_in('--provider-network-type vlan', cmds)
396 @patch('apex.overcloud.deploy.parsers')
397 def test_create_congress_cmds(self, mock_parsers):
398 assert_greater(len(create_congress_cmds('overcloud_file')), 0)
400 @patch('apex.overcloud.deploy.parsers.parse_overcloudrc')
401 def test_create_congress_cmds_raises(self, mock_parsers):
402 mock_parsers.return_value.__getitem__.side_effect = KeyError()
403 assert_raises(KeyError, create_congress_cmds, 'overcloud_file')