3 ##############################################################################
4 # Copyright (c) 2015 Ericsson AB and others.
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
12 from collections import OrderedDict
13 from itertools import count
19 from yardstick.benchmark.contexts import base
20 from yardstick.benchmark.contexts import heat
21 from yardstick.benchmark.contexts import model
22 from yardstick.common import exceptions as y_exc
23 from yardstick.orchestrator import heat as orch_heat
24 from yardstick import ssh
27 LOG = logging.getLogger(__name__)
30 class HeatContextTestCase(unittest.TestCase):
32 def __init__(self, *args, **kwargs):
33 super(HeatContextTestCase, self).__init__(*args, **kwargs)
34 self.name_iter = ('vnf{:03}'.format(x) for x in count(0, step=3))
37 self.test_context = heat.HeatContext()
38 self.addCleanup(self._remove_contexts)
39 self.mock_context = mock.Mock(spec=heat.HeatContext())
41 def _remove_contexts(self):
42 if self.test_context in self.test_context.list:
43 self.test_context._delete_context()
45 def test___init__(self):
46 self.assertIsNone(self.test_context._name)
47 self.assertIsNone(self.test_context._task_id)
48 self.assertFalse(self.test_context._flags.no_setup)
49 self.assertFalse(self.test_context._flags.no_teardown)
50 self.assertIsNone(self.test_context.stack)
51 self.assertEqual(self.test_context.networks, OrderedDict())
52 self.assertEqual(self.test_context.servers, [])
53 self.assertEqual(self.test_context.placement_groups, [])
54 self.assertEqual(self.test_context.server_groups, [])
55 self.assertIsNone(self.test_context.keypair_name)
56 self.assertIsNone(self.test_context.secgroup_name)
57 self.assertEqual(self.test_context._server_map, {})
58 self.assertIsNone(self.test_context._image)
59 self.assertIsNone(self.test_context._flavor)
60 self.assertIsNone(self.test_context._user)
61 self.assertIsNone(self.test_context.template_file)
62 self.assertIsNone(self.test_context.heat_parameters)
63 self.assertIsNone(self.test_context.key_filename)
65 @mock.patch.object(ssh.SSH, 'gen_keys')
66 @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
67 @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
68 @mock.patch('yardstick.benchmark.contexts.heat.Network')
69 @mock.patch('yardstick.benchmark.contexts.heat.Server')
70 def test_init(self, mock_server, mock_network, mock_sg, mock_pg, mock_ssh_gen_keys):
72 pgs = {'pgrp1': {'policy': 'availability'}}
73 sgs = {'servergroup1': {'policy': 'affinity'}}
74 networks = {'bar': {'cidr': '10.0.1.0/24'}}
75 servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
76 attrs = {'name': 'foo',
77 'task_id': '1234567890',
78 'placement_groups': pgs,
83 self.test_context.init(attrs)
85 self.assertFalse(self.test_context._flags.no_setup)
86 self.assertFalse(self.test_context._flags.no_teardown)
87 self.assertEqual(self.test_context._name, "foo")
88 self.assertEqual(self.test_context._task_id, '1234567890')
89 self.assertEqual(self.test_context.name, "foo-12345678")
90 self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
91 self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
93 mock_pg.assert_called_with('pgrp1', self.test_context,
94 pgs['pgrp1']['policy'])
95 mock_sg.assert_called_with('servergroup1', self.test_context,
96 sgs['servergroup1']['policy'])
97 self.assertEqual(len(self.test_context.placement_groups), 1)
98 self.assertEqual(len(self.test_context.server_groups), 1)
100 mock_network.assert_called_with(
101 'bar', self.test_context, networks['bar'])
102 self.assertEqual(len(self.test_context.networks), 1)
104 mock_server.assert_called_with('baz', self.test_context,
106 self.assertEqual(len(self.test_context.servers), 1)
108 mock_ssh_gen_keys.assert_called()
110 def test_init_no_name_or_task_id(self):
112 self.assertRaises(KeyError, self.test_context.init, attrs)
115 self.test_context._name = 'foo'
116 self.test_context._task_id = '1234567890'
117 self.test_context._name_task_id = '{}-{}'.format(
118 self.test_context._name, self.test_context._task_id[:8])
119 self.assertEqual(self.test_context.name, 'foo-12345678')
120 self.assertEqual(self.test_context.assigned_name, 'foo')
122 def test_name_flags(self):
123 self.test_context._flags = base.Flags(**{"no_setup": True, "no_teardown": True})
124 self.test_context._name = 'foo'
125 self.test_context._task_id = '1234567890'
127 self.assertEqual(self.test_context.name, 'foo')
128 self.assertEqual(self.test_context.assigned_name, 'foo')
130 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
131 def test__add_resources_to_template_no_servers(self, mock_template):
132 self.test_context._name = 'ctx'
133 self.test_context._task_id = '1234567890'
134 self.test_context._name_task_id = '{}-{}'.format(
135 self.test_context._name, self.test_context._task_id[:8])
136 self.test_context.keypair_name = "ctx-key"
137 self.test_context.secgroup_name = "ctx-secgroup"
138 self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
139 netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
140 'external_network': 'ext_net'}
142 self.test_context.networks = OrderedDict(
143 {"mynet": model.Network("mynet", self.test_context,
146 self.test_context._add_resources_to_template(mock_template)
147 mock_template.add_keypair.assert_called_with(
150 mock_template.add_security_group.assert_called_with("ctx-secgroup")
151 mock_template.add_network.assert_called_with(
152 "ctx-12345678-mynet", 'physnet1', None, None, None, None)
153 mock_template.add_router.assert_called_with(
154 "ctx-12345678-mynet-router",
155 netattrs["external_network"],
156 "ctx-12345678-mynet-subnet")
157 mock_template.add_router_interface.assert_called_with(
158 "ctx-12345678-mynet-router-if0",
159 "ctx-12345678-mynet-router",
160 "ctx-12345678-mynet-subnet")
162 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
163 def test_attrs_get(self, *args):
164 image, flavor, user = expected_tuple = 'foo1', 'foo2', 'foo3'
165 self.assertNotEqual(self.test_context.image, image)
166 self.assertNotEqual(self.test_context.flavor, flavor)
167 self.assertNotEqual(self.test_context.user, user)
168 self.test_context._image = image
169 self.test_context._flavor = flavor
170 self.test_context._user = user
171 attr_tuple = self.test_context.image, self.test_context.flavor, self.test_context.user
172 self.assertEqual(attr_tuple, expected_tuple)
174 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
175 def test_attrs_set_negative(self, *args):
176 with self.assertRaises(AttributeError):
177 self.test_context.image = 'foo'
179 with self.assertRaises(AttributeError):
180 self.test_context.flavor = 'foo'
182 with self.assertRaises(AttributeError):
183 self.test_context.user = 'foo'
185 def test__create_new_stack(self):
186 template = mock.Mock()
187 self.test_context._create_new_stack(template)
188 template.create.assert_called_once()
190 def test__create_new_stack_stack_create_failed(self):
191 template = mock.Mock()
192 template.create.side_effect = y_exc.HeatTemplateError
194 self.assertRaises(y_exc.HeatTemplateError,
195 self.test_context._create_new_stack,
198 def test__create_new_stack_keyboard_interrupt(self):
199 template = mock.Mock()
200 template.create.side_effect = KeyboardInterrupt
201 self.assertRaises(y_exc.StackCreationInterrupt,
202 self.test_context._create_new_stack,
205 @mock.patch.object(orch_heat.HeatTemplate, 'add_keypair')
206 @mock.patch.object(heat.HeatContext, '_create_new_stack')
207 def test_deploy_stack_creation_failed(self, mock_create, *args):
208 self.test_context._name = 'foo'
209 self.test_context._task_id = '1234567890'
210 self.test_context._name_task_id = 'foo-12345678'
211 mock_create.side_effect = y_exc.HeatTemplateError
212 self.assertRaises(y_exc.HeatTemplateError,
213 self.test_context.deploy)
215 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
216 def test_deploy(self, mock_template):
217 self.test_context._name = 'foo'
218 self.test_context._task_id = '1234567890'
219 self.test_context._name_task_id = '{}-{}'.format(
220 self.test_context._name, self.test_context._task_id[:8])
221 self.test_context.template_file = '/bar/baz/some-heat-file'
222 self.test_context.heat_parameters = {'image': 'cirros'}
223 self.test_context.get_neutron_info = mock.MagicMock()
224 self.test_context.deploy()
226 mock_template.assert_called_with('foo-12345678',
227 '/bar/baz/some-heat-file',
229 self.assertIsNotNone(self.test_context.stack)
231 def test_add_server_port(self):
232 network1 = mock.MagicMock()
233 network2 = mock.MagicMock()
234 self.test_context._name = 'foo'
235 self.test_context._task_id = '1234567890'
236 self.test_context._name_task_id = '{}-{}'.format(
237 self.test_context._name, self.test_context._task_id[:8])
238 self.test_context.stack = mock.MagicMock()
239 self.test_context.networks = {
243 self.test_context.stack.outputs = {
244 u'b': u'10.20.30.45',
246 u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
247 u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
248 u'b-mac_address': u'00:01',
249 u'b-device_id': u'dev21',
250 u'b-network_id': u'net789',
251 u'd': u'40.30.20.15',
253 u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
254 u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
255 u'd-mac_address': u'00:10',
256 u'd-device_id': u'dev43',
257 u'd-network_id': u'net987',
258 u'e': u'40.30.20.15',
260 u'e-mac_address': u'00:10',
261 u'e-device_id': u'dev43',
262 u'e-network_id': u'net987',
264 server = mock.MagicMock()
265 server.ports = OrderedDict([
266 ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
267 ('c', [{'stack_name': 'd', 'port': 'port_c'},
268 {'stack_name': 'e', 'port': 'port_f'}]),
272 "private_ip": '10.20.30.45',
274 "subnet_cidr": '10.20.0.0/15',
275 "network": '10.20.0.0',
276 "netmask": '255.254.0.0',
278 "gateway_ip": '10.20.30.1',
279 "mac_address": '00:01',
280 "device_id": 'dev21',
281 "network_id": 'net789',
283 "local_mac": '00:01',
284 "local_ip": '10.20.30.45',
286 self.test_context.add_server_port(server)
287 self.assertEqual(server.private_ip, '10.20.30.45')
288 self.assertEqual(len(server.interfaces), 3)
289 self.assertDictEqual(server.interfaces['port_a'], expected)
291 @mock.patch('yardstick.benchmark.contexts.heat.os')
292 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
293 def test_undeploy(self, mock_template, *args):
294 self.test_context.stack = mock_template
295 self.test_context._name = 'foo'
296 self.test_context._task_id = '1234567890'
297 self.test_context._name_task_id = '{}-{}'.format(
298 self.test_context._name, self.test_context._task_id[:8])
299 # mock_os.path.exists.return_value = True
300 self.test_context.key_filename = 'foo/bar/foobar'
301 self.test_context.undeploy()
302 self.assertTrue(mock_template.delete.called)
304 @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
305 @mock.patch('yardstick.benchmark.contexts.heat.os')
306 def test_undeploy_key_filename(self, mock_os, mock_template):
307 self.test_context.stack = mock_template
308 self.test_context._name = 'foo'
309 self.test_context._task_id = '1234567890'
310 self.test_context._name_task_id = '{}-{}'.format(
311 self.test_context._name, self.test_context._task_id)
312 mock_os.path.exists.return_value = True
313 self.test_context.key_filename = 'foo/bar/foobar'
314 self.assertIsNone(self.test_context.undeploy())
316 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
317 def test__get_server_found_dict(self, *args):
319 Use HeatContext._get_server to get a server that matches
320 based on a dictionary input.
322 foo2_server = mock.Mock()
323 foo2_server.key_filename = None
324 foo2_server.private_ip = '10.0.0.2'
325 foo2_server.public_ip = '127.0.0.2'
326 foo2_server.context.user = 'oof'
328 baz3_server = mock.Mock()
329 baz3_server.key_filename = None
330 baz3_server.private_ip = '10.0.0.3'
331 baz3_server.public_ip = '127.0.0.3'
332 baz3_server.context.user = 'zab'
334 self.test_context._name = 'bar'
335 self.test_context._task_id = '1234567890'
336 self.test_context._name_task_id = '{}-{}'.format(
337 self.test_context._name, self.test_context._task_id[:8])
338 self.test_context._user = 'bot'
339 self.test_context.stack = mock.Mock()
340 self.test_context.stack.outputs = {
341 'private_ip': '10.0.0.1',
342 'public_ip': '127.0.0.1',
344 self.test_context._server_map = {
350 'name': 'foo.bar-12345678',
351 'private_ip_attr': 'private_ip',
352 'public_ip_attr': 'public_ip',
354 self.test_context.key_uuid = 'foo-42'
355 result = self.test_context._get_server(attr_name)
356 self.assertEqual(result['user'], 'bot')
357 self.assertEqual(result['ip'], '127.0.0.1')
358 self.assertEqual(result['private_ip'], '10.0.0.1')
360 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
361 def test__get_server_found_dict_no_attrs(self, *args):
363 Use HeatContext._get_server to get a server that matches
364 based on a dictionary input.
366 foo2_server = mock.Mock()
367 foo2_server.private_ip = '10.0.0.2'
368 foo2_server.public_ip = '127.0.0.2'
369 foo2_server.context.user = 'oof'
371 baz3_server = mock.Mock()
372 baz3_server.private_ip = '10.0.0.3'
373 baz3_server.public_ip = '127.0.0.3'
374 baz3_server.context.user = 'zab'
376 self.test_context._name = 'bar'
377 self.test_context._task_id = '1234567890'
378 self.test_context._name_task_id = '{}-{}'.format(
379 self.test_context._name, self.test_context._task_id[:8])
380 self.test_context._user = 'bot'
381 self.test_context.stack = mock.Mock()
382 self.test_context.stack.outputs = {
383 'private_ip': '10.0.0.1',
384 'public_ip': '127.0.0.1',
386 self.test_context._server_map = {
392 'name': 'foo.bar-12345678',
395 self.test_context.key_uuid = 'foo-42'
396 result = self.test_context._get_server(attr_name)
397 self.assertEqual(result['user'], 'bot')
398 # no private ip attr mapping in the map results in None value in the result
399 self.assertIsNone(result['private_ip'])
400 # no public ip attr mapping in the map results in no value in the result
401 self.assertNotIn('ip', result)
403 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
404 def test__get_server_found_not_dict(self, *args):
406 Use HeatContext._get_server to get a server that matches
407 based on a non-dictionary input
409 foo2_server = mock.Mock()
410 foo2_server.private_ip = '10.0.0.2'
411 foo2_server.public_ip = '127.0.0.2'
412 foo2_server.context.user = 'oof'
414 baz3_server = mock.Mock()
415 baz3_server.private_ip = '10.0.0.3'
416 baz3_server.public_ip = None
417 baz3_server.context.user = 'zab'
419 self.test_context._name = 'bar1'
420 self.test_context._task_id = '1234567890'
421 self.test_context._name_task_id = 'bar1-12345678'
422 self.test_context.stack = mock.Mock()
423 self.test_context.stack.outputs = {
424 'private_ip': '10.0.0.1',
425 'public_ip': '127.0.0.1',
427 self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
429 self.test_context._server_map = {
435 result = self.test_context._get_server(attr_name)
436 self.assertEqual(result['user'], 'zab')
437 self.assertEqual(result['private_ip'], '10.0.0.3')
438 # no public_ip on the server results in no value in the result
439 self.assertNotIn('public_ip', result)
441 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
442 def test__get_server_none_found_not_dict(self, *args):
444 Use HeatContext._get_server to not get a server due to
445 None value associated with the match to a non-dictionary
448 foo2_server = mock.Mock()
449 foo2_server.private_ip = '10.0.0.2'
450 foo2_server.public_ip = '127.0.0.2'
451 foo2_server.context.user = 'oof'
453 baz3_server = mock.Mock()
454 baz3_server.private_ip = '10.0.0.3'
455 baz3_server.public_ip = None
456 baz3_server.context.user = 'zab'
458 self.test_context._name = 'bar1'
459 self.test_context.stack = mock.Mock()
460 self.test_context.stack.outputs = {
461 'private_ip': '10.0.0.1',
462 'public_ip': '127.0.0.1',
464 self.test_context._server_map = {
470 self.test_context.key_uuid = 'foo-42'
472 result = self.test_context._get_server(attr_name)
473 self.assertIsNone(result)
475 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
476 def test__get_server_not_found_dict(self, *args):
478 Use HeatContext._get_server to not get a server for lack
479 of a match to a dictionary input
481 foo2_server = mock.Mock()
482 foo2_server.private_ip = '10.0.0.2'
483 foo2_server.public_ip = '127.0.0.2'
484 foo2_server.context.user = 'oof'
486 baz3_server = mock.Mock()
487 baz3_server.private_ip = '10.0.0.3'
488 baz3_server.public_ip = None
489 baz3_server.context.user = 'zab'
491 self.test_context._name = 'bar1'
492 self.test_context._task_id = '1235467890'
493 self.test_context._name_task_id = '{}-{}'.format(
494 self.test_context._name, self.test_context._task_id[:8])
495 self.test_context.stack = mock.Mock()
496 self.test_context.stack.outputs = {
497 'private_ip': '10.0.0.1',
498 'public_ip': '127.0.0.1',
500 self.test_context._server_map = {
505 self.test_context.key_uuid = 'foo-42'
508 'private_ip_attr': 'private_ip',
509 'public_ip_attr': 'public_ip',
511 result = self.test_context._get_server(attr_name)
512 self.assertIsNone(result)
514 @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
515 def test__get_server_not_found_not_dict(self, *args):
517 Use HeatContext._get_server to not get a server for lack
518 of a match to a non-dictionary input
520 foo2_server = mock.Mock()
521 foo2_server.private_ip = '10.0.0.2'
522 foo2_server.public_ip = '127.0.0.2'
523 foo2_server.context.user = 'oof'
525 baz3_server = mock.Mock()
526 baz3_server.private_ip = '10.0.0.3'
527 baz3_server.public_ip = None
528 baz3_server.context.user = 'zab'
530 self.mock_context._name = 'bar1'
531 self.test_context.stack = mock.Mock()
532 self.mock_context.stack.outputs = {
533 'private_ip': '10.0.0.1',
534 'public_ip': '127.0.0.1',
536 self.mock_context._server_map = {
541 self.test_context.key_uuid = 'foo-42'
542 attr_name = 'foo.wow4'
543 result = self.test_context._get_server(attr_name)
544 self.assertIsNone(result)
546 # TODO: Split this into more granular tests
547 def test__get_network(self):
548 network1 = mock.MagicMock()
549 network1.name = 'net_1'
550 network1.vld_id = 'vld111'
551 network1.segmentation_id = 'seg54'
552 network1.network_type = 'type_a'
553 network1.physical_network = 'phys'
555 network2 = mock.MagicMock()
556 network2.name = 'net_2'
557 network2.segmentation_id = 'seg45'
558 network2.network_type = 'type_b'
559 network2.physical_network = 'virt'
561 self.test_context.networks = {
567 self.assertIsNone(self.test_context._get_network(attr_name))
570 self.assertIsNone(self.test_context._get_network(attr_name))
572 attr_name = {'network_type': 'nosuch'}
573 self.assertIsNone(self.test_context._get_network(attr_name))
576 self.assertIsNone(self.test_context._get_network(attr_name))
578 attr_name = {'segmentation_id': 'seg45'}
581 "segmentation_id": 'seg45',
582 "network_type": 'type_b',
583 "physical_network": 'virt',
585 result = self.test_context._get_network(attr_name)
586 self.assertDictEqual(result, expected)
591 "segmentation_id": 'seg54',
592 "network_type": 'type_a',
593 "physical_network": 'phys',
595 result = self.test_context._get_network(attr_name)
596 self.assertDictEqual(result, expected)