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