Merge "Bump pip packages installed in "nsb_setup.sh" script"
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_model.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.model
13
14 from __future__ import absolute_import
15 import unittest
16 import mock
17
18 from yardstick.benchmark.contexts import model
19
20
21 class ObjectTestCase(unittest.TestCase):
22
23     def setUp(self):
24         self.mock_context = mock.Mock()
25
26     def test_construct(self):
27
28         test_object = model.Object('foo', self.mock_context)
29
30         self.assertEqual(test_object.name, 'foo')
31         self.assertEqual(test_object._context, self.mock_context)
32         self.assertIsNone(test_object.stack_name)
33         self.assertIsNone(test_object.stack_id)
34
35     def test_dn(self):
36
37         self.mock_context.name = 'bar'
38         test_object = model.Object('foo', self.mock_context)
39
40         self.assertEqual('foo.bar', test_object.dn)
41
42
43 class PlacementGroupTestCase(unittest.TestCase):
44
45     def setUp(self):
46         self.mock_context = mock.Mock()
47         self.mock_context.name = 'bar'
48
49     def tearDown(self):
50         model.PlacementGroup.map = {}
51
52     def test_sucessful_construct(self):
53
54         test_pg = model.PlacementGroup('foo', self.mock_context, 'affinity')
55
56         self.assertEqual(test_pg.name, 'foo')
57         self.assertEqual(test_pg.members, set())
58         self.assertEqual(test_pg.stack_name, 'bar-foo')
59         self.assertEqual(test_pg.policy, 'affinity')
60
61         test_map = {'foo': test_pg}
62         self.assertEqual(model.PlacementGroup.map, test_map)
63
64     def test_wrong_policy_in_construct(self):
65
66         self.assertRaises(ValueError, model.PlacementGroup, 'foo',
67                           self.mock_context, 'baz')
68
69     def test_add_member(self):
70
71         test_pg = model.PlacementGroup('foo', self.mock_context, 'affinity')
72         test_pg.add_member('foo')
73
74         self.assertEqual(test_pg.members, set(['foo']))
75
76     def test_get_name_successful(self):
77
78         model.PlacementGroup.map = {'foo': True}
79         self.assertTrue(model.PlacementGroup.get('foo'))
80
81     def test_get_name_unsuccessful(self):
82
83         self.assertIsNone(model.PlacementGroup.get('foo'))
84
85
86 class RouterTestCase(unittest.TestCase):
87
88     def test_construct(self):
89
90         mock_context = mock.Mock()
91         mock_context.name = 'baz'
92         test_router = model.Router('foo', 'bar', mock_context, 'qux')
93
94         self.assertEqual(test_router.stack_name, 'baz-bar-foo')
95         self.assertEqual(test_router.stack_if_name, 'baz-bar-foo-if0')
96         self.assertEqual(test_router.external_gateway_info, 'qux')
97
98
99 class NetworkTestCase(unittest.TestCase):
100
101     def setUp(self):
102         self.mock_context = mock.Mock()
103         self.mock_context.name = 'bar'
104
105     def tearDown(self):
106         model.Network.list = []
107
108     def test_construct_no_external_network(self):
109
110         attrs = {'cidr': '10.0.0.0/24'}
111         test_network = model.Network('foo', self.mock_context, attrs)
112
113         self.assertEqual(test_network.stack_name, 'bar-foo')
114         self.assertEqual(test_network.subnet_stack_name, 'bar-foo-subnet')
115         self.assertEqual(test_network.subnet_cidr, attrs['cidr'])
116         self.assertIsNone(test_network.router)
117         self.assertIn(test_network, model.Network.list)
118
119     def test_construct_has_external_network(self):
120
121         attrs = {'external_network': 'ext_net'}
122         test_network = model.Network('foo', self.mock_context, attrs)
123         exp_router = model.Router('router', 'foo', self.mock_context,
124                                   'ext_net')
125
126         self.assertEqual(test_network.router.stack_name, exp_router.stack_name)
127         self.assertEqual(test_network.router.stack_if_name,
128                          exp_router.stack_if_name)
129         self.assertEqual(test_network.router.external_gateway_info,
130                          exp_router.external_gateway_info)
131
132     def test_has_route_to(self):
133
134         attrs = {'external_network': 'ext_net'}
135         test_network = model.Network('foo', self.mock_context, attrs)
136
137         self.assertTrue(test_network.has_route_to('ext_net'))
138
139     def test_has_no_route_to(self):
140
141         attrs = {}
142         test_network = model.Network('foo', self.mock_context, attrs)
143
144         self.assertFalse(test_network.has_route_to('ext_net'))
145
146     @mock.patch('yardstick.benchmark.contexts.model.Network.has_route_to')
147     def test_find_by_route_to(self, mock_has_route_to):
148
149         mock_network = mock.Mock()
150         model.Network.list = [mock_network]
151         mock_has_route_to.return_value = True
152
153         self.assertIs(mock_network, model.Network.find_by_route_to('foo'))
154
155     def test_find_external_network(self):
156
157         mock_network = mock.Mock()
158         mock_network.router = mock.Mock() #pylint ignore assignment-from-none
159         mock_network.router.external_gateway_info = 'ext_net'
160         model.Network.list = [mock_network]
161
162         self.assertEqual(model.Network.find_external_network(), 'ext_net')
163
164     def test_construct_gateway_ip_is_null(self):
165
166         attrs = {'gateway_ip': 'null'}
167         test_network = model.Network('foo', self.mock_context, attrs)
168         self.assertEqual(test_network.gateway_ip, 'null')
169
170     def test_construct_gateway_ip_is_none(self):
171
172         attrs = {'gateway_ip': None}
173         test_network = model.Network('foo', self.mock_context, attrs)
174         self.assertEqual(test_network.gateway_ip, 'null')
175
176     def test_construct_gateway_ip_is_absent(self):
177
178         attrs = {}
179         test_network = model.Network('foo', self.mock_context, attrs)
180         self.assertIsNone(test_network.gateway_ip)
181
182
183 class ServerTestCase(unittest.TestCase):
184
185     def setUp(self):
186         self.mock_context = mock.Mock()
187         self.mock_context.name = 'bar'
188         self.mock_context.keypair_name = 'some-keys'
189         self.mock_context.secgroup_name = 'some-secgroup'
190         self.mock_context.user = "some-user"
191         netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
192         self.mock_context.networks = [model.Network("some-network", self.mock_context, netattrs)]
193
194     def test_construct_defaults(self):
195
196         attrs = None
197         test_server = model.Server('foo', self.mock_context, attrs)
198
199         self.assertEqual(test_server.stack_name, 'foo.bar')
200         self.assertEqual(test_server.keypair_name, 'some-keys')
201         self.assertEqual(test_server.secgroup_name, 'some-secgroup')
202         self.assertEqual(test_server.placement_groups, [])
203         self.assertIsNone(test_server.server_group)
204         self.assertEqual(test_server.instances, 1)
205         self.assertIsNone(test_server.floating_ip)
206         self.assertIsNone(test_server._image)
207         self.assertIsNone(test_server._flavor)
208         self.assertIn(test_server, model.Server.list)
209
210     @mock.patch('yardstick.benchmark.contexts.model.PlacementGroup')
211     def test_construct_get_wrong_placement_group(self, mock_pg):
212
213         attrs = {'placement': 'baz'}
214         mock_pg.get.return_value = None
215
216         self.assertRaises(ValueError, model.Server, 'foo',
217                           self.mock_context, attrs)
218
219     @mock.patch('yardstick.benchmark.contexts.model.PlacementGroup')
220     def test_construct_get_wrong_server_group(self, mock_sg):
221
222         attrs = {'server_group': 'baz'}
223         mock_sg.get.return_value = None
224
225         self.assertRaises(ValueError, model.Server, 'foo',
226                           self.mock_context, attrs)
227
228     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
229     def test__add_instance(self, mock_template):
230         attrs = {'image': 'some-image', 'flavor': 'some-flavor', 'floating_ip': '192.168.1.10',
231                  'floating_ip_assoc': 'some-vm',
232                  'availability_zone': 'zone'}
233         test_server = model.Server('foo', self.mock_context, attrs)
234
235         self.mock_context.flavors = ['flavor1', 'flavor2', 'some-flavor']
236
237         mock_network = mock.Mock()
238         mock_network.name = 'some-network'
239         mock_network.stack_name = 'some-network-stack'
240         mock_network.allowed_address_pairs = ["1", "2"]
241         mock_network.vnic_type = 'normal'
242         mock_network.subnet_stack_name = 'some-network-stack-subnet'
243         mock_network.provider = 'sriov'
244         mock_network.external_network = 'ext_net'
245         mock_network.router = model.Router('some-router', 'some-network', self.mock_context,
246                                            'ext_net')
247
248         test_server._add_instance(mock_template, 'some-server',
249                                   [mock_network], 'hints')
250
251         mock_template.add_port.assert_called_with(
252             'some-server-some-network-port',
253             mock_network.stack_name,
254             mock_network.subnet_stack_name,
255             mock_network.vnic_type,
256             sec_group_id=self.mock_context.secgroup_name,
257             provider=mock_network.provider,
258             allowed_address_pairs=mock_network.allowed_address_pairs)
259
260         mock_template.add_floating_ip.assert_called_with(
261             'some-server-fip',
262             mock_network.external_network,
263             'some-server-some-network-port',
264             'bar-some-network-some-router-if0',
265             'some-secgroup'
266         )
267
268         mock_template.add_floating_ip_association.assert_called_with(
269             'some-server-fip-assoc',
270             'some-server-fip',
271             'some-server-some-network-port'
272         )
273
274         mock_template.add_server.assert_called_with(
275             'some-server', 'some-image',
276             flavor='some-flavor',
277             flavors=['flavor1', 'flavor2', 'some-flavor'],
278             ports=['some-server-some-network-port'],
279             user=self.mock_context.user,
280             key_name=self.mock_context.keypair_name,
281             user_data='',
282             scheduler_hints='hints',
283             availability_zone='zone')
284
285     def test_override_ip(self):
286         network_ports = {
287             'mgmt': ['mgmt'],
288             'uplink_0': [
289                 {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
290             ],
291             'downlink_0': [
292                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
293             ],
294         }
295         attrs = {
296             'image': 'some-image', 'flavor': 'some-flavor',
297         }
298         test_server = model.Server('foo', self.mock_context, attrs)
299         test_server.interfaces = {
300             "xe0": {
301                 "local_ip": "1.2.3.4",
302                 "netmask": "255.255.255.0",
303             },
304             "xe1": {
305                 "local_ip": "1.2.3.5",
306                 "netmask": "255.255.255.0"
307             }
308         }
309         test_server.network_ports = network_ports
310
311         test_server.override_ip("uplink_0", {"port": "xe0"})
312         self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][0]["xe0"])
313
314     def test_override_ip_multiple(self):
315         network_ports = {
316             'mgmt': ['mgmt'],
317             'uplink_0': [
318                 {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
319                 {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
320             ],
321             'downlink_0': [
322                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
323             ],
324         }
325         attrs = {
326             'image': 'some-image', 'flavor': 'some-flavor',
327         }
328         test_server = model.Server('foo', self.mock_context, attrs)
329         test_server.interfaces = {
330             "xe0": {
331                 "local_ip": "1.2.3.4",
332                 "netmask": "255.255.255.0",
333             },
334             "xe1": {
335                 "local_ip": "1.2.3.5",
336                 "netmask": "255.255.255.0"
337             }
338         }
339         test_server.network_ports = network_ports
340         test_server.override_ip("uplink_0", {"port": "xe0"})
341         self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][0]["xe0"])
342
343     def test_override_ip_mixed(self):
344         network_ports = {
345             'mgmt': ['mgmt'],
346             'uplink_0': [
347                 'xe0',
348                 {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
349             ],
350             'downlink_0': [
351                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
352             ],
353         }
354         attrs = {
355             'image': 'some-image', 'flavor': 'some-flavor',
356         }
357         test_server = model.Server('foo', self.mock_context, attrs)
358         test_server.interfaces = {
359             "xe0": {
360                 "local_ip": "1.2.3.4",
361                 "netmask": "255.255.255.0",
362             },
363             "xe1": {
364                 "local_ip": "1.2.3.5",
365                 "netmask": "255.255.255.0"
366             }
367         }
368         test_server.network_ports = network_ports
369         test_server.override_ip("uplink_0", {"port": "xe0"})
370         self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][1]["xe0"])
371
372     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
373     def test__add_instance_with_ip_override_invalid_syntax(self, mock_template):
374         network_ports = {
375             'mgmt': ['mgmt'],
376             'uplink_0': 'xe0',
377             'downlink_0': [
378                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
379             ],
380         }
381         attrs = {
382             'image': 'some-image', 'flavor': 'some-flavor',
383         }
384         test_server = model.Server('foo', self.mock_context, attrs)
385         test_server.network_ports = network_ports
386         context = type("Context", (object,), {})
387         # can't use Mock because Mock.name is reserved
388         context.name = "context"
389         networks = [model.Network(n, context, {}) for n in network_ports]
390
391         with self.assertRaises(SyntaxError):
392             test_server._add_instance(mock_template, 'some-server',
393                                       networks, 'hints')
394
395     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
396     def test__add_instance_with_ip_override(self, mock_template):
397         network_ports = {
398             'mgmt': ['mgmt'],
399             'uplink_0': [
400                 {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
401             ],
402             'downlink_0': [
403                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
404             ],
405         }
406         attrs = {
407             'image': 'some-image', 'flavor': 'some-flavor',
408         }
409         test_server = model.Server('foo', self.mock_context, attrs)
410         test_server.network_ports = network_ports
411         context = type("Context", (object,), {})
412         # can't use Mock because Mock.name is reserved
413         context.name = "context"
414         networks = [model.Network(n, context, {}) for n in network_ports]
415
416         test_server._add_instance(mock_template, 'some-server',
417                                   networks, 'hints')
418         self.assertEqual(test_server.ports, {
419             'downlink_0': [{'port': 'xe1', 'stack_name': 'some-server-xe1-port'}],
420             'mgmt': [{'port': 'mgmt', 'stack_name': 'some-server-mgmt-port'}],
421             'uplink_0': [{'port': 'xe0', 'stack_name': 'some-server-xe0-port'}]
422         })
423
424     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
425     def test__add_instance_with_multiple_ip_override(self, mock_template):
426         network_ports = {
427             'mgmt': ['mgmt'],
428             'uplink_0': [
429                 {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
430                 {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
431             ],
432             'downlink_0': [
433                 {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
434             ],
435         }
436         attrs = {
437             'image': 'some-image', 'flavor': 'some-flavor',
438         }
439         test_server = model.Server('foo', self.mock_context, attrs)
440         test_server.network_ports = network_ports
441         context = type("Context", (object,), {})
442         # can't use Mock because Mock.name is reserved
443         context.name = "context"
444         networks = [model.Network(n, context, {}) for n in network_ports]
445
446         test_server._add_instance(mock_template, 'some-server',
447                                   networks, 'hints')
448         self.assertEqual(test_server.ports, {
449             'downlink_0': [{'port': 'xe1', 'stack_name': 'some-server-xe1-port'}],
450             'mgmt': [{'port': 'mgmt', 'stack_name': 'some-server-mgmt-port'}],
451             'uplink_0': [{'port': 'xe0', 'stack_name': 'some-server-xe0-port'},
452                          # this is not an error, we can produce this, it is left to Heat
453                          # to detect duplicate ports and error
454                          {'port': 'xe0', 'stack_name': 'some-server-xe0-port'}]
455         })
456
457     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
458     def test__add_instance_with_user_data(self, mock_template):
459         user_data = "USER_DATA"
460         attrs = {
461             'image': 'some-image', 'flavor': 'some-flavor',
462             'user_data': user_data,
463         }
464         test_server = model.Server('foo', self.mock_context, attrs)
465
466         test_server._add_instance(mock_template, 'some-server',
467                                   [], 'hints')
468
469         mock_template.add_server.assert_called_with(
470             'some-server', 'some-image',
471             flavor='some-flavor',
472             flavors=self.mock_context.flavors,
473             ports=[],
474             user=self.mock_context.user,
475             key_name=self.mock_context.keypair_name,
476             user_data=user_data,
477             scheduler_hints='hints',
478             availability_zone=None)
479
480     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
481     def test__add_instance_with_availablity_zone(self, mock_template):
482         attrs = {
483             'image': 'some-image', 'flavor': 'some-flavor',
484             'availability_zone': 'zone',
485         }
486         test_server = model.Server('foo', self.mock_context, attrs)
487
488         test_server._add_instance(mock_template, 'some-server',
489                                   [], 'hints')
490
491         mock_template.add_server.assert_called_with(
492             'some-server', 'some-image',
493             flavor='some-flavor',
494             flavors=self.mock_context.flavors,
495             ports=[],
496             user=self.mock_context.user,
497             key_name=self.mock_context.keypair_name,
498             user_data='',
499             scheduler_hints='hints',
500             availability_zone='zone')
501
502     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
503     def test__add_instance_plus_flavor(self, mock_template):
504
505         user_data = ''
506         attrs = {
507             'image': 'some-image', 'flavor': 'flavor1',
508             'flavors': ['flavor2'], 'user_data': user_data
509         }
510         test_server = model.Server('ServerFlavor-2', self.mock_context, attrs)
511
512         self.mock_context.flavors = ['flavor2']
513         mock_network = mock.Mock()
514         mock_network.allowed_address_pairs = ["1", "2"]
515         mock_network.vnic_type = 'normal'
516         mock_network.configure_mock(name='some-network', stack_name='some-network-stack',
517                                     subnet_stack_name='some-network-stack-subnet',
518                                     provider='some-provider')
519
520         test_server._add_instance(mock_template, 'ServerFlavor-2',
521                                   [mock_network], 'hints')
522
523         mock_template.add_port.assert_called_with(
524             'ServerFlavor-2-some-network-port',
525             mock_network.stack_name,
526             mock_network.subnet_stack_name,
527             mock_network.vnic_type,
528             provider=mock_network.provider,
529             sec_group_id=self.mock_context.secgroup_name,
530             allowed_address_pairs=mock_network.allowed_address_pairs)
531
532         mock_template.add_server.assert_called_with(
533             'ServerFlavor-2', 'some-image',
534             flavor='flavor1',
535             flavors=['flavor2'],
536             ports=['ServerFlavor-2-some-network-port'],
537             user=self.mock_context.user,
538             key_name=self.mock_context.keypair_name,
539             user_data=user_data,
540             scheduler_hints='hints',
541             availability_zone=None)
542
543     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
544     def test__add_instance_misc(self, mock_template):
545
546         user_data = ''
547         attrs = {
548             'image': 'some-image', 'flavor': 'flavor1',
549             'flavors': ['flavor2'], 'user_data': user_data
550         }
551         test_server = model.Server('ServerFlavor-3', self.mock_context, attrs)
552
553         self.mock_context.flavors = ['flavor2']
554         self.mock_context.flavor = {'vcpus': 4}
555         mock_network = mock.Mock()
556         mock_network.name = 'some-network'
557         mock_network.stack_name = 'some-network-stack'
558         mock_network.subnet_stack_name = 'some-network-stack-subnet'
559
560         test_server._add_instance(mock_template, 'ServerFlavor-3',
561                                   [mock_network], 'hints')
562
563         mock_template.add_port(
564             'ServerFlavor-3-some-network-port',
565             mock_network.stack_name,
566             mock_network.subnet_stack_name,
567             sec_group_id=self.mock_context.secgroup_name)
568
569         mock_template.add_flavor(
570             vcpus=4,
571             ram=2048,
572             disk=1)
573
574         mock_template.add_flavor(
575             vcpus=4,
576             ram=2048,
577             disk=1,
578             extra_specs={'cat': 1, 'dog': 2, 'dragon': 1000})
579
580         mock_template.add_server.assert_called_with(
581             'ServerFlavor-3', 'some-image',
582             flavor='flavor1',
583             flavors=['flavor2'],
584             ports=['ServerFlavor-3-some-network-port'],
585             user=self.mock_context.user,
586             key_name=self.mock_context.keypair_name,
587             user_data=user_data,
588             scheduler_hints='hints',
589             availability_zone=None)