Enable heat context to support existing network
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_heat.py
1 #!/usr/bin/env python
2
3 ##############################################################################
4 # Copyright (c) 2015 Ericsson AB and others.
5 #
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 ##############################################################################
11
12 from collections import OrderedDict
13 from itertools import count
14 import logging
15 import os
16 import uuid
17
18 import mock
19 import unittest
20
21 from yardstick.benchmark.contexts import heat
22 from yardstick.benchmark.contexts import model
23
24
25 LOG = logging.getLogger(__name__)
26
27
28 class HeatContextTestCase(unittest.TestCase):
29
30     def __init__(self, *args, **kwargs):
31         super(HeatContextTestCase, self).__init__(*args, **kwargs)
32         self.name_iter = ('vnf{:03}'.format(x) for x in count(0, step=3))
33
34     def setUp(self):
35         self.test_context = heat.HeatContext()
36         self.mock_context = mock.Mock(spec=heat.HeatContext())
37
38     def test___init__(self):
39         self.assertIsNone(self.test_context.name)
40         self.assertIsNone(self.test_context.stack)
41         self.assertEqual(self.test_context.networks, OrderedDict())
42         self.assertEqual(self.test_context.servers, [])
43         self.assertEqual(self.test_context.placement_groups, [])
44         self.assertEqual(self.test_context.server_groups, [])
45         self.assertIsNone(self.test_context.keypair_name)
46         self.assertIsNone(self.test_context.secgroup_name)
47         self.assertEqual(self.test_context._server_map, {})
48         self.assertIsNone(self.test_context._image)
49         self.assertIsNone(self.test_context._flavor)
50         self.assertIsNone(self.test_context._user)
51         self.assertIsNone(self.test_context.template_file)
52         self.assertIsNone(self.test_context.heat_parameters)
53         self.assertIsNotNone(self.test_context.key_uuid)
54         self.assertIsNotNone(self.test_context.key_filename)
55
56     @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
57     @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
58     @mock.patch('yardstick.benchmark.contexts.heat.Network')
59     @mock.patch('yardstick.benchmark.contexts.heat.Server')
60     def test_init(self, mock_server, mock_network, mock_sg, mock_pg):
61
62         pgs = {'pgrp1': {'policy': 'availability'}}
63         sgs = {'servergroup1': {'policy': 'affinity'}}
64         networks = {'bar': {'cidr': '10.0.1.0/24'}}
65         servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
66         attrs = {'name': 'foo',
67                  'placement_groups': pgs,
68                  'server_groups': sgs,
69                  'networks': networks,
70                  'servers': servers}
71
72         self.test_context.init(attrs)
73
74         self.assertEqual(self.test_context.name, "foo")
75         self.assertEqual(self.test_context.keypair_name, "foo-key")
76         self.assertEqual(self.test_context.secgroup_name, "foo-secgroup")
77
78         mock_pg.assert_called_with('pgrp1', self.test_context,
79                                    pgs['pgrp1']['policy'])
80         mock_sg.assert_called_with('servergroup1', self.test_context,
81                                    sgs['servergroup1']['policy'])
82         self.assertEqual(len(self.test_context.placement_groups), 1)
83         self.assertEqual(len(self.test_context.server_groups), 1)
84
85         mock_network.assert_called_with(
86             'bar', self.test_context, networks['bar'])
87         self.assertEqual(len(self.test_context.networks), 1)
88
89         mock_server.assert_called_with('baz', self.test_context,
90                                        servers['baz'])
91         self.assertEqual(len(self.test_context.servers), 1)
92
93         if os.path.exists(self.test_context.key_filename):
94             try:
95                 os.remove(self.test_context.key_filename)
96                 os.remove(self.test_context.key_filename + ".pub")
97             except OSError:
98                 LOG.exception("key_filename: %s",
99                               self.test_context.key_filename)
100
101     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
102     def test__add_resources_to_template_no_servers(self, mock_template):
103
104         self.test_context.keypair_name = "foo-key"
105         self.test_context.secgroup_name = "foo-secgroup"
106         self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
107         netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
108         self.mock_context.name = 'bar'
109         self.test_context.networks = OrderedDict(
110             {"fool-network": model.Network("fool-network", self.mock_context,
111                                            netattrs)})
112
113         self.test_context._add_resources_to_template(mock_template)
114         mock_template.add_keypair.assert_called_with(
115             "foo-key",
116             "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b")
117         mock_template.add_security_group.assert_called_with("foo-secgroup")
118 #        mock_template.add_network.assert_called_with("bar-fool-network", 'physnet1', None)
119         mock_template.add_router.assert_called_with(
120             "bar-fool-network-router",
121             netattrs["external_network"],
122             "bar-fool-network-subnet")
123         mock_template.add_router_interface.assert_called_with(
124             "bar-fool-network-router-if0",
125             "bar-fool-network-router",
126             "bar-fool-network-subnet")
127
128     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
129     def test_attrs_get(self, *args):
130         image, flavor, user = expected_tuple = 'foo1', 'foo2', 'foo3'
131         self.assertNotEqual(self.test_context.image, image)
132         self.assertNotEqual(self.test_context.flavor, flavor)
133         self.assertNotEqual(self.test_context.user, user)
134         self.test_context._image = image
135         self.test_context._flavor = flavor
136         self.test_context._user = user
137         attr_tuple = self.test_context.image, self.test_context.flavor, self.test_context.user
138         self.assertEqual(attr_tuple, expected_tuple)
139
140     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
141     def test_attrs_set_negative(self, *args):
142         with self.assertRaises(AttributeError):
143             self.test_context.image = 'foo'
144
145         with self.assertRaises(AttributeError):
146             self.test_context.flavor = 'foo'
147
148         with self.assertRaises(AttributeError):
149             self.test_context.user = 'foo'
150
151     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
152     def test_deploy(self, mock_template):
153         self.test_context.name = 'foo'
154         self.test_context.template_file = '/bar/baz/some-heat-file'
155         self.test_context.heat_parameters = {'image': 'cirros'}
156         self.test_context.get_neutron_info = mock.MagicMock()
157         self.test_context.deploy()
158
159         mock_template.assert_called_with('foo',
160                                          '/bar/baz/some-heat-file',
161                                          {'image': 'cirros'})
162         self.assertIsNotNone(self.test_context.stack)
163
164     def test_add_server_port(self):
165         network1 = mock.MagicMock()
166         network2 = mock.MagicMock()
167         self.test_context.name = 'foo'
168         self.test_context.stack = mock.MagicMock()
169         self.test_context.networks = {
170             'a': network1,
171             'c': network2,
172         }
173         self.test_context.stack.outputs = {
174             u'b': u'10.20.30.45',
175             u'b-subnet_id': 1,
176             u'foo-a-subnet-cidr': u'10.20.0.0/15',
177             u'foo-a-subnet-gateway_ip': u'10.20.30.1',
178             u'b-mac_address': u'00:01',
179             u'b-device_id': u'dev21',
180             u'b-network_id': u'net789',
181             u'd': u'40.30.20.15',
182             u'd-subnet_id': 2,
183             u'foo-c-subnet-cidr': u'40.30.0.0/18',
184             u'foo-c-subnet-gateway_ip': u'40.30.20.254',
185             u'd-mac_address': u'00:10',
186             u'd-device_id': u'dev43',
187             u'd-network_id': u'net987',
188             u'e': u'40.30.20.15',
189             u'e-subnet_id': 2,
190             u'e-mac_address': u'00:10',
191             u'e-device_id': u'dev43',
192             u'e-network_id': u'net987',
193         }
194         server = mock.MagicMock()
195         server.private_ip = None
196         server.ports = OrderedDict([
197             ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
198             ('c', [{'stack_name': 'd', 'port': 'port_c'},
199                    {'stack_name': 'e', 'port': 'port_f'}]),
200         ])
201
202         expected = {
203             "private_ip": '10.20.30.45',
204             "subnet_id": 1,
205             "subnet_cidr": '10.20.0.0/15',
206             "network": '10.20.0.0',
207             "netmask": '255.254.0.0',
208             "name": "port_a",
209             "gateway_ip": '10.20.30.1',
210             "mac_address": '00:01',
211             "device_id": 'dev21',
212             "network_id": 'net789',
213             "network_name": 'a',
214             "local_mac": '00:01',
215             "local_ip": '10.20.30.45',
216         }
217         self.test_context.add_server_port(server)
218         self.assertEqual(server.private_ip, '10.20.30.45')
219         self.assertEqual(len(server.interfaces), 3)
220         self.assertDictEqual(server.interfaces['port_a'], expected)
221
222     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
223     def test_undeploy(self, mock_template):
224         self.test_context.stack = mock_template
225         self.test_context.undeploy()
226         self.assertTrue(mock_template.delete.called)
227
228     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
229     @mock.patch('yardstick.benchmark.contexts.heat.os')
230     def test_undeploy_key_filename(self, mock_os, mock_template):
231         self.test_context.stack = mock_template
232         mock_os.path.exists.return_value = True
233         self.assertIsNone(self.test_context.undeploy())
234
235     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
236     def test__get_server_found_dict(self, *args):
237         """
238         Use HeatContext._get_server to get a server that matches
239         based on a dictionary input.
240         """
241         foo2_server = mock.Mock()
242         foo2_server.key_filename = None
243         foo2_server.private_ip = '10.0.0.2'
244         foo2_server.public_ip = '127.0.0.2'
245         foo2_server.context.user = 'oof'
246
247         baz3_server = mock.Mock()
248         baz3_server.key_filename = None
249         baz3_server.private_ip = '10.0.0.3'
250         baz3_server.public_ip = '127.0.0.3'
251         baz3_server.context.user = 'zab'
252
253         self.test_context.name = 'bar'
254         self.test_context._user = 'bot'
255         self.test_context.stack = mock.Mock()
256         self.test_context.stack.outputs = {
257             'private_ip': '10.0.0.1',
258             'public_ip': '127.0.0.1',
259         }
260         self.test_context.key_uuid = uuid.uuid4()
261         self.test_context._server_map = {
262             'baz3': baz3_server,
263             'foo2': foo2_server,
264         }
265
266         attr_name = {
267             'name': 'foo.bar',
268             'private_ip_attr': 'private_ip',
269             'public_ip_attr': 'public_ip',
270         }
271         result = self.test_context._get_server(attr_name)
272         self.assertEqual(result['user'], 'bot')
273         self.assertEqual(result['ip'], '127.0.0.1')
274         self.assertEqual(result['private_ip'], '10.0.0.1')
275
276     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
277     def test__get_server_found_dict_no_attrs(self, *args):
278         """
279         Use HeatContext._get_server to get a server that matches
280         based on a dictionary input.
281         """
282         foo2_server = mock.Mock()
283         foo2_server.private_ip = '10.0.0.2'
284         foo2_server.public_ip = '127.0.0.2'
285         foo2_server.context.user = 'oof'
286
287         baz3_server = mock.Mock()
288         baz3_server.private_ip = '10.0.0.3'
289         baz3_server.public_ip = '127.0.0.3'
290         baz3_server.context.user = 'zab'
291
292         self.test_context.name = 'bar'
293         self.test_context._user = 'bot'
294         self.test_context.stack = mock.Mock()
295         self.test_context.stack.outputs = {
296             'private_ip': '10.0.0.1',
297             'public_ip': '127.0.0.1',
298         }
299         self.test_context.key_uuid = uuid.uuid4()
300         self.test_context._server_map = {
301             'baz3': baz3_server,
302             'foo2': foo2_server,
303         }
304
305         attr_name = {
306             'name': 'foo.bar',
307         }
308         result = self.test_context._get_server(attr_name)
309         self.assertEqual(result['user'], 'bot')
310         # no private ip attr mapping in the map results in None value in the result
311         self.assertIsNone(result['private_ip'])
312         # no public ip attr mapping in the map results in no value in the result
313         self.assertNotIn('ip', result)
314
315     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
316     def test__get_server_found_not_dict(self, *args):
317         """
318         Use HeatContext._get_server to get a server that matches
319         based on a non-dictionary input
320         """
321         foo2_server = mock.Mock()
322         foo2_server.private_ip = '10.0.0.2'
323         foo2_server.public_ip = '127.0.0.2'
324         foo2_server.context.user = 'oof'
325
326         baz3_server = mock.Mock()
327         baz3_server.private_ip = '10.0.0.3'
328         baz3_server.public_ip = None
329         baz3_server.context.user = 'zab'
330
331         self.test_context.name = 'bar1'
332         self.test_context.stack = mock.Mock()
333         self.test_context.stack.outputs = {
334             'private_ip': '10.0.0.1',
335             'public_ip': '127.0.0.1',
336         }
337         self.test_context.key_uuid = uuid.uuid4()
338         self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
339
340         self.test_context._server_map = {
341             'baz3': baz3_server,
342             'foo2': foo2_server,
343         }
344
345         attr_name = 'baz3'
346         result = self.test_context._get_server(attr_name)
347         self.assertEqual(result['user'], 'zab')
348         self.assertEqual(result['private_ip'], '10.0.0.3')
349         # no public_ip on the server results in no value in the result
350         self.assertNotIn('public_ip', result)
351
352     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
353     def test__get_server_none_found_not_dict(self, *args):
354         """
355         Use HeatContext._get_server to not get a server due to
356         None value associated with the match to a non-dictionary
357         input
358         """
359         foo2_server = mock.Mock()
360         foo2_server.private_ip = '10.0.0.2'
361         foo2_server.public_ip = '127.0.0.2'
362         foo2_server.context.user = 'oof'
363
364         baz3_server = mock.Mock()
365         baz3_server.private_ip = '10.0.0.3'
366         baz3_server.public_ip = None
367         baz3_server.context.user = 'zab'
368
369         self.test_context.name = 'bar1'
370         self.test_context.stack = mock.Mock()
371         self.test_context.stack.outputs = {
372             'private_ip': '10.0.0.1',
373             'public_ip': '127.0.0.1',
374         }
375         self.test_context.key_uuid = uuid.uuid4()
376         self.test_context._server_map = {
377             'baz3': baz3_server,
378             'foo2': foo2_server,
379             'wow4': None,
380         }
381
382         attr_name = 'wow4'
383         result = self.test_context._get_server(attr_name)
384         self.assertIsNone(result)
385
386     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
387     def test__get_server_not_found_dict(self, *args):
388         """
389         Use HeatContext._get_server to not get a server for lack
390         of a match to a dictionary input
391         """
392         foo2_server = mock.Mock()
393         foo2_server.private_ip = '10.0.0.2'
394         foo2_server.public_ip = '127.0.0.2'
395         foo2_server.context.user = 'oof'
396
397         baz3_server = mock.Mock()
398         baz3_server.private_ip = '10.0.0.3'
399         baz3_server.public_ip = None
400         baz3_server.context.user = 'zab'
401
402         self.test_context.name = 'bar1'
403         self.test_context.stack = mock.Mock()
404         self.test_context.stack.outputs = {
405             'private_ip': '10.0.0.1',
406             'public_ip': '127.0.0.1',
407         }
408         self.test_context.key_uuid = uuid.uuid4()
409         self.test_context._server_map = {
410             'baz3': baz3_server,
411             'foo2': foo2_server,
412         }
413
414         attr_name = {
415             'name': 'foo.wow4',
416             'private_ip_attr': 'private_ip',
417             'public_ip_attr': 'public_ip',
418         }
419         result = self.test_context._get_server(attr_name)
420         self.assertIsNone(result)
421
422     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
423     def test__get_server_not_found_not_dict(self, *args):
424         """
425         Use HeatContext._get_server to not get a server for lack
426         of a match to a non-dictionary input
427         """
428         foo2_server = mock.Mock()
429         foo2_server.private_ip = '10.0.0.2'
430         foo2_server.public_ip = '127.0.0.2'
431         foo2_server.context.user = 'oof'
432
433         baz3_server = mock.Mock()
434         baz3_server.private_ip = '10.0.0.3'
435         baz3_server.public_ip = None
436         baz3_server.context.user = 'zab'
437
438         self.mock_context.name = 'bar1'
439         self.test_context.stack = mock.Mock()
440         self.mock_context.stack.outputs = {
441             'private_ip': '10.0.0.1',
442             'public_ip': '127.0.0.1',
443         }
444         self.mock_context.key_uuid = uuid.uuid4()
445         self.mock_context._server_map = {
446             'baz3': baz3_server,
447             'foo2': foo2_server,
448         }
449
450         attr_name = 'foo.wow4'
451         result = self.test_context._get_server(attr_name)
452         self.assertIsNone(result)
453
454     # TODO: Split this into more granular tests
455     def test__get_network(self):
456         network1 = mock.MagicMock()
457         network1.name = 'net_1'
458         network1.vld_id = 'vld111'
459         network1.segmentation_id = 'seg54'
460         network1.network_type = 'type_a'
461         network1.physical_network = 'phys'
462
463         network2 = mock.MagicMock()
464         network2.name = 'net_2'
465         network2.segmentation_id = 'seg45'
466         network2.network_type = 'type_b'
467         network2.physical_network = 'virt'
468
469         self.test_context.networks = {
470             'a': network1,
471             'b': network2,
472         }
473
474         attr_name = None
475         self.assertIsNone(self.test_context._get_network(attr_name))
476
477         attr_name = {}
478         self.assertIsNone(self.test_context._get_network(attr_name))
479
480         attr_name = {'network_type': 'nosuch'}
481         self.assertIsNone(self.test_context._get_network(attr_name))
482
483         attr_name = 'vld777'
484         self.assertIsNone(self.test_context._get_network(attr_name))
485
486         attr_name = {'segmentation_id': 'seg45'}
487         expected = {
488             "name": 'net_2',
489             "segmentation_id": 'seg45',
490             "network_type": 'type_b',
491             "physical_network": 'virt',
492         }
493         result = self.test_context._get_network(attr_name)
494         self.assertDictEqual(result, expected)
495
496         attr_name = 'a'
497         expected = {
498             "name": 'net_1',
499             "segmentation_id": 'seg54',
500             "network_type": 'type_a',
501             "physical_network": 'phys',
502         }
503         result = self.test_context._get_network(attr_name)
504         self.assertDictEqual(result, expected)