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