Merge "Update to support using external heat template"
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_heat.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
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 from collections import OrderedDict
11 import logging
12 import os
13
14 import mock
15 import unittest
16 import collections
17
18 from yardstick.benchmark.contexts import base
19 from yardstick.benchmark.contexts import heat
20 from yardstick.benchmark.contexts import model
21 from yardstick.common import constants as consts
22 from yardstick.common import exceptions as y_exc
23 from yardstick.common import openstack_utils
24 from yardstick.common import yaml_loader
25 from yardstick import ssh
26
27
28 LOG = logging.getLogger(__name__)
29
30
31 class HeatContextTestCase(unittest.TestCase):
32
33     HEAT_POD_SAMPLE = {
34         "nodes": [
35             {
36                 "name": "node1",
37                 "role": "Controller",
38                 "ip": "10.229.47.137",
39                 "user": "root",
40                 "key_filename": "/root/.yardstick_key"
41             },
42             {
43                 "name": "node2",
44                 "role": "Compute",
45                 "ip": "10.229.47.139",
46                 "user": "root",
47                 "key_filename": "/root/.yardstick_key"
48             }
49         ]
50     }
51
52     def __init__(self, *args, **kwargs):
53
54         super(HeatContextTestCase, self).__init__(*args, **kwargs)
55
56     def setUp(self):
57         self.test_context = heat.HeatContext()
58         self.addCleanup(self._remove_contexts)
59         self.mock_context = mock.Mock(spec=heat.HeatContext())
60
61     def _remove_contexts(self):
62         if self.test_context in self.test_context.list:
63             self.test_context._delete_context()
64
65     def test___init__(self):
66         self.assertIsNone(self.test_context._name)
67         self.assertIsNone(self.test_context._task_id)
68         self.assertFalse(self.test_context._flags.no_setup)
69         self.assertFalse(self.test_context._flags.no_teardown)
70         self.assertIsNone(self.test_context.stack)
71         self.assertEqual(self.test_context.networks, OrderedDict())
72         self.assertEqual(self.test_context.servers, [])
73         self.assertEqual(self.test_context.placement_groups, [])
74         self.assertEqual(self.test_context.server_groups, [])
75         self.assertIsNone(self.test_context.keypair_name)
76         self.assertIsNone(self.test_context.secgroup_name)
77         self.assertIsNone(self.test_context.security_group)
78         self.assertEqual(self.test_context._server_map, {})
79         self.assertIsNone(self.test_context._image)
80         self.assertIsNone(self.test_context._flavor)
81         self.assertIsNone(self.test_context._user)
82         self.assertIsNone(self.test_context.template_file)
83         self.assertIsNone(self.test_context.heat_parameters)
84         self.assertIsNone(self.test_context.key_filename)
85         self.assertTrue(self.test_context.yardstick_gen_key_file)
86
87     @mock.patch.object(yaml_loader, 'read_yaml_file')
88     @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
89     @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
90     @mock.patch('yardstick.benchmark.contexts.heat.Network')
91     @mock.patch('yardstick.benchmark.contexts.heat.Server')
92     def test_init(self, mock_server, mock_network, mock_sg, mock_pg,
93                   mock_read_yaml):
94
95         mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
96         pgs = {'pgrp1': {'policy': 'availability'}}
97         sgs = {'servergroup1': {'policy': 'affinity'}}
98         networks = {'bar': {'cidr': '10.0.1.0/24'}}
99         servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
100         attrs = {'name': 'foo',
101                  'file': 'pod.yaml',
102                  'task_id': '1234567890',
103                  'placement_groups': pgs,
104                  'server_groups': sgs,
105                  'networks': networks,
106                  'servers': servers}
107
108         with mock.patch.object(openstack_utils, 'get_shade_client'), \
109              mock.patch.object(openstack_utils, 'get_shade_operator_client'):
110             self.test_context.init(attrs)
111
112         self.assertFalse(self.test_context._flags.no_setup)
113         self.assertFalse(self.test_context._flags.no_teardown)
114         self.assertEqual(self.test_context._name, "foo")
115         self.assertEqual(self.test_context._task_id, '1234567890')
116         self.assertEqual(self.test_context.name, "foo-12345678")
117         self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
118         self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
119
120         mock_pg.assert_called_with('pgrp1', self.test_context,
121                                    pgs['pgrp1']['policy'])
122         mock_sg.assert_called_with('servergroup1', self.test_context,
123                                    sgs['servergroup1']['policy'])
124         self.assertEqual(len(self.test_context.placement_groups), 1)
125         self.assertEqual(len(self.test_context.server_groups), 1)
126
127         mock_network.assert_called_with(
128             'bar', self.test_context, networks['bar'])
129         self.assertEqual(len(self.test_context.networks), 1)
130
131         mock_server.assert_called_with('baz', self.test_context,
132                                        servers['baz'])
133         self.assertEqual(len(self.test_context.servers), 1)
134
135     def test_init_no_name_or_task_id(self):
136         attrs = {}
137         self.assertRaises(KeyError, self.test_context.init, attrs)
138
139     def test_name(self):
140         self.test_context._name = 'foo'
141         self.test_context._task_id = '1234567890'
142         self.test_context._name_task_id = '{}-{}'.format(
143             self.test_context._name, self.test_context._task_id[:8])
144         self.assertEqual(self.test_context.name, 'foo-12345678')
145         self.assertEqual(self.test_context.assigned_name, 'foo')
146
147     def test_name_flags(self):
148         self.test_context._flags = base.Flags(
149             **{"no_setup": True, "no_teardown": True})
150         self.test_context._name = 'foo'
151         self.test_context._task_id = '1234567890'
152
153         self.assertEqual(self.test_context.name, 'foo')
154         self.assertEqual(self.test_context.assigned_name, 'foo')
155
156     def test_init_no_setup_no_teardown(self):
157
158         attrs = {'name': 'foo',
159                  'task_id': '1234567890',
160                  'placement_groups': {},
161                  'server_groups': {},
162                  'networks': {},
163                  'servers': {},
164                  'file': "pod.yaml",
165                  'flags': {
166                      'no_setup': True,
167                      'no_teardown': True,
168                      },
169                 }
170
171         with mock.patch.object(openstack_utils, 'get_shade_client'), \
172              mock.patch.object(openstack_utils, 'get_shade_operator_client'):
173             self.test_context.init(attrs)
174
175         self.assertTrue(self.test_context._flags.no_setup)
176         self.assertTrue(self.test_context._flags.no_teardown)
177
178     def test_init_key_filename(self):
179         attrs = {'name': 'foo',
180                  'file': 'pod.yaml',
181                  'task_id': '1234567890',
182                  'server_groups': {},
183                  'networks': {},
184                  'servers': {},
185                  'heat_template': "/root/clearwater.yaml",
186                  'key_filename': '/etc/yardstick/yardstick.pem'}
187
188         with mock.patch.object(openstack_utils, 'get_shade_client'), \
189              mock.patch.object(openstack_utils, 'get_shade_operator_client'):
190             self.test_context.init(attrs)
191
192         self.assertIsNotNone(self.test_context.key_filename)
193         self.assertFalse(self.test_context.yardstick_gen_key_file)
194
195     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
196     def test__add_resources_to_template_no_servers(self, mock_template):
197         self.test_context._name = 'ctx'
198         self.test_context._task_id = '1234567890'
199         self.test_context._name_task_id = '{}-{}'.format(
200             self.test_context._name, self.test_context._task_id[:8])
201         self.test_context.keypair_name = "ctx-key"
202         self.test_context.secgroup_name = "ctx-secgroup"
203         self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
204         netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
205                     'external_network': 'ext_net'}
206
207         self.test_context.networks = OrderedDict(
208             {"mynet": model.Network("mynet", self.test_context,
209                                            netattrs)})
210
211         self.test_context._add_resources_to_template(mock_template)
212         mock_template.add_keypair.assert_called_with(
213             "ctx-key",
214             "ctx-12345678")
215         mock_template.add_security_group.assert_called_with("ctx-secgroup", None)
216         mock_template.add_network.assert_called_with(
217             "ctx-12345678-mynet", 'physnet1', None, None, None, None)
218         mock_template.add_router.assert_called_with(
219             "ctx-12345678-mynet-router",
220             netattrs["external_network"],
221             "ctx-12345678-mynet-subnet")
222         mock_template.add_router_interface.assert_called_with(
223             "ctx-12345678-mynet-router-if0",
224             "ctx-12345678-mynet-router",
225             "ctx-12345678-mynet-subnet")
226
227     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
228     def test_attrs_get(self, *args):
229         image, flavor, user = expected_tuple = 'foo1', 'foo2', 'foo3'
230         self.assertNotEqual(self.test_context.image, image)
231         self.assertNotEqual(self.test_context.flavor, flavor)
232         self.assertNotEqual(self.test_context.user, user)
233         self.test_context._image = image
234         self.test_context._flavor = flavor
235         self.test_context._user = user
236         attr_tuple = self.test_context.image, self.test_context.flavor, self.test_context.user
237         self.assertEqual(attr_tuple, expected_tuple)
238
239     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
240     def test_attrs_set_negative(self, *args):
241         with self.assertRaises(AttributeError):
242             self.test_context.image = 'foo'
243
244         with self.assertRaises(AttributeError):
245             self.test_context.flavor = 'foo'
246
247         with self.assertRaises(AttributeError):
248             self.test_context.user = 'foo'
249
250     def test__create_new_stack(self):
251         template = mock.Mock()
252         self.test_context._create_new_stack(template)
253         template.create.assert_called_once()
254
255     def test__create_new_stack_stack_create_failed(self):
256         template = mock.Mock()
257         template.create.side_effect = y_exc.HeatTemplateError
258
259         self.assertRaises(y_exc.HeatTemplateError,
260                           self.test_context._create_new_stack,
261                           template)
262
263     def test__create_new_stack_keyboard_interrupt(self):
264         template = mock.Mock()
265         template.create.side_effect = KeyboardInterrupt
266         self.assertRaises(y_exc.StackCreationInterrupt,
267                           self.test_context._create_new_stack,
268                           template)
269
270     @mock.patch.object(os.path, 'exists', return_value=True)
271     @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
272     @mock.patch.object(heat.HeatContext, '_create_new_stack')
273     def test_deploy_stack_creation_failed(self, mock_create,
274             mock_resources_template, mock_path_exists):
275         self.test_context._name = 'foo'
276         self.test_context._task_id = '1234567890'
277         self.test_context._name_task_id = 'foo-12345678'
278         mock_create.side_effect = y_exc.HeatTemplateError
279         self.assertRaises(y_exc.HeatTemplateError,
280                           self.test_context.deploy)
281
282         mock_path_exists.assert_called()
283         mock_resources_template.assert_called_once()
284
285     @mock.patch.object(os.path, 'exists', return_value=False)
286     @mock.patch.object(ssh.SSH, 'gen_keys')
287     @mock.patch.object(heat, 'HeatTemplate')
288     def test_deploy(self, mock_template, mock_genkeys, mock_path_exists):
289         self.test_context._name = 'foo'
290         self.test_context._task_id = '1234567890'
291         self.test_context._name_task_id = '{}-{}'.format(
292             self.test_context._name, self.test_context._task_id[:8])
293         self.test_context.template_file = '/bar/baz/some-heat-file'
294         self.test_context.heat_parameters = {'image': 'cirros'}
295         self.test_context.get_neutron_info = mock.MagicMock()
296         self.test_context.deploy()
297
298         mock_template.assert_called_with(
299             'foo-12345678', template_file='/bar/baz/some-heat-file',
300             heat_parameters={'image': 'cirros'},
301             os_cloud_config=self.test_context._flags.os_cloud_config)
302         self.assertIsNotNone(self.test_context.stack)
303         key_filename = ''.join(
304             [consts.YARDSTICK_ROOT_PATH,
305              'yardstick/resources/files/yardstick_key-',
306              self.test_context._name_task_id])
307         mock_genkeys.assert_called_once_with(key_filename)
308         mock_path_exists.assert_any_call(key_filename)
309
310     @mock.patch.object(heat, 'HeatTemplate')
311     @mock.patch.object(os.path, 'exists', return_value=False)
312     @mock.patch.object(ssh.SSH, 'gen_keys')
313     @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack')
314     @mock.patch.object(heat.HeatContext, '_create_new_stack')
315     def test_deploy_no_setup(self, mock_create_new_stack,
316             mock_retrieve_existing_stack, mock_genkeys, mock_path_exists,
317             *args):
318         self.test_context._name = 'foo'
319         self.test_context._task_id = '1234567890'
320         self.test_context.template_file = '/bar/baz/some-heat-file'
321         self.test_context.heat_parameters = {'image': 'cirros'}
322         self.test_context.get_neutron_info = mock.MagicMock()
323         self.test_context._flags.no_setup = True
324         self.test_context.deploy()
325
326         mock_create_new_stack.assert_not_called()
327         mock_retrieve_existing_stack.assert_called_with(self.test_context.name)
328         self.assertIsNotNone(self.test_context.stack)
329         key_filename = ''.join(
330             [consts.YARDSTICK_ROOT_PATH,
331              'yardstick/resources/files/yardstick_key-',
332              self.test_context._name])
333         mock_genkeys.assert_called_once_with(key_filename)
334         mock_path_exists.assert_any_call(key_filename)
335
336     @mock.patch.object(heat, 'HeatTemplate')
337     @mock.patch.object(os.path, 'exists', return_value=False)
338     @mock.patch.object(ssh.SSH, 'gen_keys')
339     @mock.patch.object(heat.HeatContext, '_create_new_stack')
340     @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack',
341                        return_value=None)
342     def test_deploy_try_retrieve_context_does_not_exist(self,
343             mock_retrieve_stack, mock_create_new_stack, mock_genkeys,
344             mock_path_exists, *args):
345         self.test_context._name = 'demo'
346         self.test_context._task_id = '1234567890'
347         self.test_context._flags.no_setup = True
348         self.test_context.template_file = '/bar/baz/some-heat-file'
349         self.test_context.get_neutron_info = mock.MagicMock()
350         self.test_context.deploy()
351
352         mock_retrieve_stack.assert_called_once_with(self.test_context._name)
353         mock_create_new_stack.assert_called()
354         key_filename = ''.join(
355             [consts.YARDSTICK_ROOT_PATH,
356              'yardstick/resources/files/yardstick_key-',
357              self.test_context._name])
358         mock_genkeys.assert_called_once_with(key_filename)
359         mock_path_exists.assert_any_call(key_filename)
360
361     @mock.patch.object(heat, 'HeatTemplate', return_value='heat_template')
362     @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
363     @mock.patch.object(os.path, 'exists', return_value=False)
364     @mock.patch.object(ssh.SSH, 'gen_keys')
365     def test_deploy_ssh_key_before_adding_resources(self, mock_genkeys,
366             mock_path_exists, mock_add_resources, *args):
367         mock_manager = mock.Mock()
368         mock_manager.attach_mock(mock_add_resources,
369                                  '_add_resources_to_template')
370         mock_manager.attach_mock(mock_genkeys, 'gen_keys')
371         mock_manager.reset_mock()
372         self.test_context._name_task_id = 'demo-12345678'
373         self.test_context.get_neutron_info = mock.Mock()
374         with mock.patch.object(self.test_context, '_create_new_stack') as \
375                 mock_create_stack, \
376                 mock.patch.object(self.test_context, 'get_neutron_info') as \
377                 mock_neutron_info:
378             self.test_context.deploy()
379
380         mock_neutron_info.assert_called_once()
381         mock_create_stack.assert_called_once()
382         key_filename = ''.join(
383             [consts.YARDSTICK_ROOT_PATH,
384              'yardstick/resources/files/yardstick_key-',
385              self.test_context._name_task_id])
386         mock_genkeys.assert_called_once_with(key_filename)
387         mock_path_exists.assert_any_call(key_filename)
388
389         mock_call_gen_keys = mock.call.gen_keys(key_filename)
390         mock_call_add_resources = (
391             mock.call._add_resources_to_template('heat_template'))
392         self.assertTrue(mock_manager.mock_calls.index(mock_call_gen_keys) <
393                         mock_manager.mock_calls.index(mock_call_add_resources))
394
395     @mock.patch.object(heat, 'HeatTemplate')
396     @mock.patch.object(ssh.SSH, 'gen_keys')
397     @mock.patch.object(heat.HeatContext, '_create_new_stack')
398     def test_deploy_with_key_filename_provided(self, mock_create_new_stack,
399                                                mock_gen_keys, *args):
400         self.test_context._name = 'foo'
401         self.test_context._task_id = '1234567890'
402         self.test_context._name_task_id = '{}-{}'.format(
403             self.test_context._name, self.test_context._task_id[:8])
404         self.test_context.template_file = '/bar/baz/some-heat-file'
405         self.test_context.heat_parameters = {'image': 'cirros'}
406         self.test_context.yardstick_gen_key_file = False
407         self.test_context.key_filename = '/etc/yardstick/yardstick.pem'
408         self.test_context.get_neutron_info = mock.MagicMock()
409         self.test_context.deploy()
410
411         mock_create_new_stack.assert_called()
412         mock_gen_keys.assert_not_called()
413
414     def test_check_for_context(self):
415         pass
416         # check that the context exists
417
418     def test_add_server_port(self):
419         network1 = mock.MagicMock()
420         network2 = mock.MagicMock()
421         self.test_context._name = 'foo'
422         self.test_context._task_id = '1234567890'
423         self.test_context._name_task_id = '{}-{}'.format(
424             self.test_context._name, self.test_context._task_id[:8])
425         self.test_context.stack = mock.MagicMock()
426         self.test_context.networks = {
427             'a': network1,
428             'c': network2,
429         }
430         self.test_context.stack.outputs = {
431             u'b': u'10.20.30.45',
432             u'b-subnet_id': 1,
433             u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
434             u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
435             u'b-mac_address': u'00:01',
436             u'b-device_id': u'dev21',
437             u'b-network_id': u'net789',
438             u'd': u'40.30.20.15',
439             u'd-subnet_id': 2,
440             u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
441             u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
442             u'd-mac_address': u'00:10',
443             u'd-device_id': u'dev43',
444             u'd-network_id': u'net987',
445             u'e': u'40.30.20.15',
446             u'e-subnet_id': 2,
447             u'e-mac_address': u'00:10',
448             u'e-device_id': u'dev43',
449             u'e-network_id': u'net987',
450         }
451         server = mock.MagicMock()
452         server.private_ip = None
453         server.ports = OrderedDict([
454             ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
455             ('c', [{'stack_name': 'd', 'port': 'port_c'},
456                    {'stack_name': 'e', 'port': 'port_f'}]),
457         ])
458
459         expected = {
460             "private_ip": '10.20.30.45',
461             "subnet_id": 1,
462             "subnet_cidr": '10.20.0.0/15',
463             "network": '10.20.0.0',
464             "netmask": '255.254.0.0',
465             "name": "port_a",
466             "gateway_ip": '10.20.30.1',
467             "mac_address": '00:01',
468             "device_id": 'dev21',
469             "network_id": 'net789',
470             "network_name": 'a',
471             "local_mac": '00:01',
472             "local_ip": '10.20.30.45',
473         }
474         self.test_context.add_server_port(server)
475         self.assertEqual(server.private_ip, '10.20.30.45')
476         self.assertEqual(len(server.interfaces), 3)
477         self.assertDictEqual(server.interfaces['port_a'], expected)
478
479     @mock.patch('yardstick.benchmark.contexts.heat.os')
480     @mock.patch.object(heat.HeatContext, '_delete_key_file')
481     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
482     def test_undeploy(self, mock_template, mock_delete_key, *args):
483         self.test_context.stack = mock_template
484         self.test_context._name = 'foo'
485         self.test_context._task_id = '1234567890'
486         self.test_context._name_task_id = '{}-{}'.format(
487             self.test_context._name, self.test_context._task_id[:8])
488         # mock_os.path.exists.return_value = True
489         self.test_context.key_filename = 'foo/bar/foobar'
490         self.test_context.undeploy()
491         mock_delete_key.assert_called()
492         mock_template.delete.assert_called_once()
493
494     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
495     def test_undeploy_no_teardown(self, mock_template):
496         self.test_context.stack = mock_template
497         self.test_context._name = 'foo'
498         self.test_context._task_id = '1234567890'
499         self.test_context._flags.no_teardown = True
500         self.test_context.undeploy()
501
502         mock_template.delete.assert_not_called()
503
504     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
505     @mock.patch('yardstick.benchmark.contexts.heat.os')
506     def test_undeploy_key_filename(self, mock_os, mock_template):
507         self.test_context.stack = mock_template
508         self.test_context._name = 'foo'
509         self.test_context._task_id = '1234567890'
510         self.test_context._name_task_id = '{}-{}'.format(
511             self.test_context._name, self.test_context._task_id)
512         mock_os.path.exists.return_value = True
513         self.test_context.key_filename = 'foo/bar/foobar'
514         self.assertIsNone(self.test_context.undeploy())
515
516     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
517     def test__get_server_found_dict(self, *args):
518         """
519         Use HeatContext._get_server to get a server that matches
520         based on a dictionary input.
521         """
522         foo2_server = mock.Mock()
523         foo2_server.key_filename = None
524         foo2_server.private_ip = '10.0.0.2'
525         foo2_server.public_ip = '127.0.0.2'
526         foo2_server.context.user = 'oof'
527
528         baz3_server = mock.Mock()
529         baz3_server.key_filename = None
530         baz3_server.private_ip = '10.0.0.3'
531         baz3_server.public_ip = '127.0.0.3'
532         baz3_server.context.user = 'zab'
533
534         self.test_context._name = 'bar'
535         self.test_context._task_id = '1234567890'
536         self.test_context._name_task_id = '{}-{}'.format(
537             self.test_context._name, self.test_context._task_id[:8])
538         self.test_context._user = 'bot'
539         self.test_context.stack = mock.Mock()
540         self.test_context.stack.outputs = {
541             'private_ip': '10.0.0.1',
542             'public_ip': '127.0.0.1',
543         }
544         self.test_context._server_map = {
545             'baz3': baz3_server,
546             'foo2': foo2_server,
547         }
548
549         attr_name = {
550             'name': 'foo.bar-12345678',
551             'private_ip_attr': 'private_ip',
552             'public_ip_attr': 'public_ip',
553         }
554         self.test_context.key_uuid = 'foo-42'
555         result = self.test_context._get_server(attr_name)
556         self.assertEqual(result['user'], 'bot')
557         self.assertEqual(result['ip'], '127.0.0.1')
558         self.assertEqual(result['private_ip'], '10.0.0.1')
559
560     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
561     def test__get_server_found_dict_no_attrs(self, *args):
562         """
563         Use HeatContext._get_server to get a server that matches
564         based on a dictionary input.
565         """
566         foo2_server = mock.Mock()
567         foo2_server.private_ip = '10.0.0.2'
568         foo2_server.public_ip = '127.0.0.2'
569         foo2_server.context.user = 'oof'
570
571         baz3_server = mock.Mock()
572         baz3_server.private_ip = '10.0.0.3'
573         baz3_server.public_ip = '127.0.0.3'
574         baz3_server.context.user = 'zab'
575
576         self.test_context._name = 'bar'
577         self.test_context._task_id = '1234567890'
578         self.test_context._name_task_id = '{}-{}'.format(
579             self.test_context._name, self.test_context._task_id[:8])
580         self.test_context._user = 'bot'
581         self.test_context.stack = mock.Mock()
582         self.test_context.stack.outputs = {
583             'private_ip': '10.0.0.1',
584             'public_ip': '127.0.0.1',
585         }
586         self.test_context._server_map = {
587             'baz3': baz3_server,
588             'foo2': foo2_server,
589         }
590
591         attr_name = {
592             'name': 'foo.bar-12345678',
593         }
594
595         self.test_context.key_uuid = 'foo-42'
596         result = self.test_context._get_server(attr_name)
597         self.assertEqual(result['user'], 'bot')
598         # no private ip attr mapping in the map results in None value in the result
599         self.assertIsNone(result['private_ip'])
600         # no public ip attr mapping in the map results in no value in the result
601         self.assertNotIn('ip', result)
602
603     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
604     def test__get_server_found_not_dict(self, *args):
605         """
606         Use HeatContext._get_server to get a server that matches
607         based on a non-dictionary input
608         """
609         foo2_server = mock.Mock()
610         foo2_server.private_ip = '10.0.0.2'
611         foo2_server.public_ip = '127.0.0.2'
612         foo2_server.context.user = 'oof'
613
614         baz3_server = mock.Mock()
615         baz3_server.private_ip = '10.0.0.3'
616         baz3_server.public_ip = None
617         baz3_server.context.user = 'zab'
618
619         self.test_context._name = 'bar1'
620         self.test_context._task_id = '1234567890'
621         self.test_context._name_task_id = 'bar1-12345678'
622         self.test_context.stack = mock.Mock()
623         self.test_context.stack.outputs = {
624             'private_ip': '10.0.0.1',
625             'public_ip': '127.0.0.1',
626         }
627         self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
628
629         self.test_context._server_map = {
630             'baz3': baz3_server,
631             'foo2': foo2_server,
632         }
633
634         attr_name = 'baz3'
635         result = self.test_context._get_server(attr_name)
636         self.assertEqual(result['user'], 'zab')
637         self.assertEqual(result['private_ip'], '10.0.0.3')
638         # no public_ip on the server results in no value in the result
639         self.assertNotIn('public_ip', result)
640
641     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
642     def test__get_server_none_found_not_dict(self, *args):
643         """
644         Use HeatContext._get_server to not get a server due to
645         None value associated with the match to a non-dictionary
646         input
647         """
648         foo2_server = mock.Mock()
649         foo2_server.private_ip = '10.0.0.2'
650         foo2_server.public_ip = '127.0.0.2'
651         foo2_server.context.user = 'oof'
652
653         baz3_server = mock.Mock()
654         baz3_server.private_ip = '10.0.0.3'
655         baz3_server.public_ip = None
656         baz3_server.context.user = 'zab'
657
658         self.test_context._name = 'bar1'
659         self.test_context.stack = mock.Mock()
660         self.test_context.stack.outputs = {
661             'private_ip': '10.0.0.1',
662             'public_ip': '127.0.0.1',
663         }
664         self.test_context._server_map = {
665             'baz3': baz3_server,
666             'foo2': foo2_server,
667             'wow4': None,
668         }
669
670         self.test_context.key_uuid = 'foo-42'
671         attr_name = 'wow4'
672         result = self.test_context._get_server(attr_name)
673         self.assertIsNone(result)
674
675     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
676     def test__get_server_not_found_dict(self, *args):
677         """
678         Use HeatContext._get_server to not get a server for lack
679         of a match to a dictionary input
680         """
681         foo2_server = mock.Mock()
682         foo2_server.private_ip = '10.0.0.2'
683         foo2_server.public_ip = '127.0.0.2'
684         foo2_server.context.user = 'oof'
685
686         baz3_server = mock.Mock()
687         baz3_server.private_ip = '10.0.0.3'
688         baz3_server.public_ip = None
689         baz3_server.context.user = 'zab'
690
691         self.test_context._name = 'bar1'
692         self.test_context._task_id = '1235467890'
693         self.test_context._name_task_id = '{}-{}'.format(
694             self.test_context._name, self.test_context._task_id[:8])
695         self.test_context.stack = mock.Mock()
696         self.test_context.stack.outputs = {
697             'private_ip': '10.0.0.1',
698             'public_ip': '127.0.0.1',
699         }
700         self.test_context._server_map = {
701             'baz3': baz3_server,
702             'foo2': foo2_server,
703         }
704
705         self.test_context.key_uuid = 'foo-42'
706         attr_name = {
707             'name': 'foo.wow4',
708             'private_ip_attr': 'private_ip',
709             'public_ip_attr': 'public_ip',
710         }
711         result = self.test_context._get_server(attr_name)
712         self.assertIsNone(result)
713
714     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
715     def test__get_server_not_found_not_dict(self, *args):
716         """
717         Use HeatContext._get_server to not get a server for lack
718         of a match to a non-dictionary input
719         """
720         foo2_server = mock.Mock()
721         foo2_server.private_ip = '10.0.0.2'
722         foo2_server.public_ip = '127.0.0.2'
723         foo2_server.context.user = 'oof'
724
725         baz3_server = mock.Mock()
726         baz3_server.private_ip = '10.0.0.3'
727         baz3_server.public_ip = None
728         baz3_server.context.user = 'zab'
729
730         self.mock_context._name = 'bar1'
731         self.test_context.stack = mock.Mock()
732         self.mock_context.stack.outputs = {
733             'private_ip': '10.0.0.1',
734             'public_ip': '127.0.0.1',
735         }
736         self.mock_context._server_map = {
737             'baz3': baz3_server,
738             'foo2': foo2_server,
739         }
740
741         self.test_context.key_uuid = 'foo-42'
742         attr_name = 'foo.wow4'
743         result = self.test_context._get_server(attr_name)
744         self.assertIsNone(result)
745
746     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
747     def test__get_server_found_dict_found_interfaces_dict(self, *args):
748         """
749         Use HeatContext._get_server to get a server that matches
750         based on a dictionary input.
751         """
752         self.test_context._name = 'bar'
753         self.test_context._task_id = '1234567890'
754         self.test_context._name_task_id = '{}-{}'.format(
755             self.test_context._name, self.test_context._task_id[:8])
756         self.test_context._user = 'bot'
757         self.test_context.stack = mock.Mock()
758         self.test_context.stack.outputs = {
759             'private_ip': '10.0.0.1',
760             'public_ip': '127.0.0.1',
761             'local_mac_addr': '64:00:6a:18:0f:d6',
762             'private_netmask': '255.255.255.0',
763             'private_net_name': 'private_network',
764             'private_net_gateway': '127.0.0.254'
765         }
766
767         attr_name = {
768             'name': 'foo.bar-12345678',
769             'private_ip_attr': 'private_ip',
770             'public_ip_attr': 'public_ip',
771             'interfaces': {
772                 'data_net': {
773                     'local_ip': 'private_ip',
774                     'local_mac': 'local_mac_addr',
775                     'netmask': 'private_netmask',
776                     'network': 'private_net_name',
777                     'gateway_ip': 'private_net_gateway'
778                     }
779                 }
780         }
781         self.test_context.key_uuid = 'foo-42'
782         result = self.test_context._get_server(attr_name)
783         self.assertIsInstance(result['interfaces'], collections.Mapping)
784         for key in attr_name.get("interfaces").keys():
785             self.assertEqual(result['interfaces'][key]['local_ip'], '10.0.0.1')
786             self.assertEqual(result['interfaces'][key]['local_mac'], '64:00:6a:18:0f:d6')
787             self.assertEqual(result['interfaces'][key]['netmask'], '255.255.255.0')
788             self.assertEqual(result['interfaces'][key]['gateway_ip'], '127.0.0.254')
789
790     # TODO: Split this into more granular tests
791     def test__get_network(self):
792         network1 = mock.MagicMock()
793         network1.name = 'net_1'
794         network1.vld_id = 'vld111'
795         network1.segmentation_id = 'seg54'
796         network1.network_type = 'type_a'
797         network1.physical_network = 'phys'
798
799         network2 = mock.MagicMock()
800         network2.name = 'net_2'
801         network2.segmentation_id = 'seg45'
802         network2.network_type = 'type_b'
803         network2.physical_network = 'virt'
804
805         self.test_context.networks = {
806             'a': network1,
807             'b': network2,
808         }
809
810         attr_name = None
811         self.assertIsNone(self.test_context._get_network(attr_name))
812
813         attr_name = {}
814         self.assertIsNone(self.test_context._get_network(attr_name))
815
816         attr_name = {'network_type': 'nosuch'}
817         self.assertIsNone(self.test_context._get_network(attr_name))
818
819         attr_name = 'vld777'
820         self.assertIsNone(self.test_context._get_network(attr_name))
821
822         attr_name = {'segmentation_id': 'seg45'}
823         expected = {
824             "name": 'net_2',
825             "segmentation_id": 'seg45',
826             "network_type": 'type_b',
827             "physical_network": 'virt',
828         }
829         result = self.test_context._get_network(attr_name)
830         self.assertDictEqual(result, expected)
831
832         attr_name = 'a'
833         expected = {
834             "name": 'net_1',
835             "segmentation_id": 'seg54',
836             "network_type": 'type_a',
837             "physical_network": 'phys',
838         }
839         result = self.test_context._get_network(attr_name)
840         self.assertDictEqual(result, expected)
841
842     def _get_file_abspath(self, filename):
843         curr_path = os.path.dirname(os.path.abspath(__file__))
844         file_path = os.path.join(curr_path, filename)
845         return file_path
846
847     def test__get_physical_nodes(self):
848         self.test_context.nodes = {}
849         nodes = self.test_context._get_physical_nodes()
850         self.assertEquals(nodes, {})
851
852     @mock.patch.object(yaml_loader, 'read_yaml_file')
853     def test__get_physical_node_for_server(self, mock_read_yaml):
854         attrs = {'name': 'foo',
855                  'task_id': '12345678',
856                  'file': "pod.yaml",
857                  'servers': {'vnf': {}},
858                  'networks': {'mgmt': {'cidr': '10.0.1.0/24'}}
859                  }
860
861         with mock.patch.object(openstack_utils, 'get_shade_client'), \
862              mock.patch.object(openstack_utils, 'get_shade_operator_client'):
863             mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
864             self.test_context.init(attrs)
865
866         with mock.patch('yardstick.common.openstack_utils.get_server') as mock_get_server:
867             mock_get_server.return_value = {'vnf': {}}
868
869             # When server is not from this context
870             result = self.test_context._get_physical_node_for_server('node1.foo-context')
871             self.assertIsNone(result)
872
873             # When node_name is not from this context
874             result = self.test_context._get_physical_node_for_server('fake.foo-12345678')
875             self.assertIsNone(result)
876
877             mock_munch = mock.Mock()
878             mock_munch.toDict = mock.Mock(return_value={
879                 'OS-EXT-SRV-ATTR:hypervisor_hostname': 'hypervisor_hostname'
880             })
881             mock_get_server.return_value = mock_munch
882
883             hypervisor = mock.Mock()
884             hypervisor.hypervisor_hostname = 'hypervisor_hostname'
885             hypervisor.host_ip = '10.229.47.137'
886
887             self.test_context.operator_client.list_hypervisors = mock.Mock(
888                 return_value=[hypervisor])
889
890             mock_get_server.return_value = mock_munch
891
892             result = self.test_context._get_physical_node_for_server('vnf.foo-12345678')
893             self.assertEqual(result, 'node1.foo')