Merge "Fix exception handling ixload"
[yardstick.git] / yardstick / tests / unit / benchmark / scenarios / storage / test_storperf.py
1 ##############################################################################
2 # Copyright (c) 2016 Huawei Technologies Co.,Ltd.
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.scenarios.storage.storperf.StorPerf
11
12 from __future__ import absolute_import
13
14 import json
15 import unittest
16
17 import mock
18 from oslo_serialization import jsonutils
19 import requests
20
21 from yardstick.benchmark.scenarios.storage import storperf
22
23
24 # pylint: disable=unused-argument
25 # disable this for now because I keep forgetting mock patch arg ordering
26 def mocked_requests_config_post(*args, **kwargs):
27     class MockResponseConfigPost(object):
28
29         def __init__(self, json_data, status_code):
30             self.content = json_data
31             self.status_code = status_code
32
33     return MockResponseConfigPost(
34         '{"stack_id": "dac27db1-3502-4300-b301-91c64e6a1622",'
35         '"stack_created": false}',
36         200)
37
38
39 def mocked_requests_config_post_fail(*args, **kwargs):
40     class MockResponseConfigPost(object):
41
42         def __init__(self, json_data, status_code):
43             self.content = json_data
44             self.status_code = status_code
45
46     return MockResponseConfigPost(
47         '{"message": "ERROR: Parameter \'public_network\' is invalid: ' +
48         'Error validating value \'foo\': Unable to find network with ' +
49         'name or id \'foo\'"}',
50         400)
51
52
53 def mocked_requests_config_get(*args, **kwargs):
54     class MockResponseConfigGet(object):
55
56         def __init__(self, json_data, status_code):
57             self.content = json_data
58             self.status_code = status_code
59
60     return MockResponseConfigGet(
61         '{"stack_id": "dac27db1-3502-4300-b301-91c64e6a1622",'
62         '"stack_created": true}',
63         200)
64
65
66 def mocked_requests_config_get_not_created(*args, **kwargs):
67     class MockResponseConfigGet(object):
68
69         def __init__(self, json_data, status_code):
70             self.content = json_data
71             self.status_code = status_code
72
73     return MockResponseConfigGet(
74         '{"stack_id": "",'
75         '"stack_created": false}',
76         200)
77
78
79 def mocked_requests_config_get_no_payload(*args, **kwargs):
80     class MockResponseConfigGet(object):
81
82         def __init__(self, json_data, status_code):
83             self.content = json_data
84             self.status_code = status_code
85
86     return MockResponseConfigGet(
87         '{}',
88         200)
89
90
91 def mocked_requests_initialize_post_fail(*args, **kwargs):
92     class MockResponseJobPost(object):
93
94         def __init__(self, json_data, status_code):
95             self.content = json_data
96             self.status_code = status_code
97
98     return MockResponseJobPost(
99         '{"message": "ERROR: Stack StorPerfAgentGroup does not exist"}',
100         400)
101
102
103 def mocked_requests_job_get(*args, **kwargs):
104     class MockResponseJobGet(object):
105
106         def __init__(self, json_data, status_code):
107             self.content = json_data
108             self.status_code = status_code
109
110     return MockResponseJobGet(
111         '{"Status": "Completed",\
112          "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}',
113         200)
114
115
116 def mocked_requests_job_post(*args, **kwargs):
117     class MockResponseJobPost(object):
118
119         def __init__(self, json_data, status_code):
120             self.content = json_data
121             self.status_code = status_code
122
123     return MockResponseJobPost('{"job_id": \
124                                  "d46bfb8c-36f4-4a40-813b-c4b4a437f728"}', 200)
125
126
127 def mocked_requests_job_post_fail(*args, **kwargs):
128     class MockResponseJobPost(object):
129
130         def __init__(self, json_data, status_code):
131             self.content = json_data
132             self.status_code = status_code
133
134     return MockResponseJobPost(
135         '{"message": "ERROR: Stack StorPerfAgentGroup does not exist"}',
136         400)
137
138
139 def mocked_requests_job_delete(*args, **kwargs):
140     class MockResponseJobDelete(object):
141
142         def __init__(self, json_data, status_code):
143             self.content = json_data
144             self.status_code = status_code
145
146     return MockResponseJobDelete('{}', 200)
147
148
149 def mocked_requests_delete(*args, **kwargs):
150     class MockResponseDelete(object):
151
152         def __init__(self, json_data, status_code):
153             self.json_data = json_data
154             self.status_code = status_code
155
156     return MockResponseDelete('{}', 200)
157
158
159 def mocked_requests_delete_failed(*args, **kwargs):
160     class MockResponseDeleteFailed(object):
161
162         def __init__(self, json_data, status_code):
163             self.json_data = json_data
164             self.status_code = status_code
165
166     return MockResponseDeleteFailed('{"message": "Teardown failed"}', 400)
167
168
169 class StorPerfTestCase(unittest.TestCase):
170
171     def setUp(self):
172         self.ctx = {
173             'host': {
174                 'ip': '172.16.0.137',
175                 'user': 'cirros',
176                 'key_filename': "mykey.key"
177             }
178         }
179
180         self.result = {}
181
182     @mock.patch.object(requests, 'post')
183     @mock.patch.object(requests, 'get')
184     def test_setup(self, mock_get, mock_post):
185         mock_post.side_effect = [mocked_requests_config_post(),
186                                  mocked_requests_job_post()]
187         mock_get.side_effect = [mocked_requests_config_get(),
188                                 mocked_requests_job_get()]
189
190         options = {
191             "agent_count": 8,
192             "public_network": 'ext-net',
193             "volume_size": 10,
194             "block_sizes": 4096,
195             "queue_depths": 4,
196             "workload": "rs",
197             "StorPerf_ip": "192.168.23.2",
198             "query_interval": 0,
199             "timeout": 60
200         }
201
202         args = {
203             "options": options
204         }
205
206         s = storperf.StorPerf(args, self.ctx)
207
208         s.setup()
209
210         self.assertTrue(s.setup_done)
211
212     @mock.patch.object(requests, 'get')
213     def test_query_setup_state_unsuccessful(self, mock_get):
214         mock_get.side_effect = mocked_requests_config_get_not_created
215         args = {
216             "options": {}
217         }
218         s = storperf.StorPerf(args, self.ctx)
219         result = s._query_setup_state()
220         self.assertFalse(result)
221
222     @mock.patch.object(requests, 'get')
223     def test_query_setup_state_no_payload(self, mock_get):
224         mock_get.side_effect = mocked_requests_config_get_no_payload
225         args = {
226             "options": {}
227         }
228         s = storperf.StorPerf(args, self.ctx)
229         result = s._query_setup_state()
230         self.assertFalse(result)
231
232     @mock.patch.object(requests, 'post')
233     @mock.patch.object(requests, 'get')
234     def test_setup_config_post_failed(self, mock_get, mock_post):
235         mock_post.side_effect = mocked_requests_config_post_fail
236
237         args = {
238             "options": {
239                 "public_network": "foo"
240             }
241         }
242
243         s = storperf.StorPerf(args, self.ctx)
244
245         self.assertRaises(RuntimeError, s.setup)
246
247     @mock.patch.object(requests, 'get')
248     @mock.patch.object(requests, 'post')
249     def test_run_v1_successful(self, mock_post, mock_get):
250         mock_post.side_effect = mocked_requests_job_post
251         mock_get.side_effect = mocked_requests_job_get
252
253         options = {
254             "agent_count": 8,
255             "public_network": 'ext-net',
256             "volume_size": 10,
257             "block_sizes": 4096,
258             "queue_depths": 4,
259             "workload": "rs",
260             "StorPerf_ip": "192.168.23.2",
261             "query_interval": 0,
262             "timeout": 60
263         }
264         expected_post = {
265             'metadata': {
266                 'build_tag': 'latest',
267                 'test_case': 'opnfv_yardstick_tc074'
268             },
269             'deadline': 60,
270             'block_sizes': 4096,
271             'queue_depths': 4,
272             "workload": "rs",
273             'agent_count': 8
274         }
275
276         args = {
277             "options": options
278         }
279
280         s = storperf.StorPerf(args, self.ctx)
281         s.setup_done = True
282
283         sample_output = '{"Status": "Completed",\
284          "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}'
285
286         expected_result = jsonutils.loads(sample_output)
287
288         s.run(self.result)
289
290         mock_post.assert_called_once_with(
291             'http://192.168.23.2:5000/api/v1.0/jobs',
292             json=jsonutils.loads(json.dumps(expected_post)))
293
294         self.assertEqual(self.result, expected_result)
295
296     @mock.patch.object(requests, 'get')
297     @mock.patch.object(requests, 'post')
298     def test_run_v2_successful(self, mock_post, mock_get):
299         mock_post.side_effect = mocked_requests_job_post
300         mock_get.side_effect = mocked_requests_job_get
301
302         options = {
303             "agent_count": 8,
304             "public_network": 'ext-net',
305             "volume_size": 10,
306             "block_sizes": 4096,
307             "queue_depths": 4,
308             "workloads": {
309                 "read_sequential": {
310                     "rw": "rs"
311                 }
312             },
313             "StorPerf_ip": "192.168.23.2",
314             "query_interval": 0,
315             "timeout": 60
316         }
317         expected_post = {
318             'metadata': {
319                 'build_tag': 'latest',
320                 'test_case': 'opnfv_yardstick_tc074'
321             },
322             'deadline': 60,
323             'block_sizes': 4096,
324             'queue_depths': 4,
325             'workloads': {
326                 'read_sequential': {
327                     'rw': 'rs'
328                 }
329             },
330             'agent_count': 8
331         }
332
333         args = {
334             "options": options
335         }
336
337         s = storperf.StorPerf(args, self.ctx)
338         s.setup_done = True
339
340         sample_output = '{"Status": "Completed",\
341          "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}'
342
343         expected_result = jsonutils.loads(sample_output)
344
345         s.run(self.result)
346         mock_post.assert_called_once_with(
347             'http://192.168.23.2:5000/api/v2.0/jobs',
348             json=expected_post)
349
350         self.assertEqual(self.result, expected_result)
351
352     @mock.patch('time.sleep')
353     @mock.patch.object(requests, 'get')
354     @mock.patch.object(requests, 'post')
355     def test_run_failed(self, mock_post, mock_get, _):
356         mock_post.side_effect = mocked_requests_job_post_fail
357         mock_get.side_effect = mocked_requests_job_get
358
359         options = {
360             "agent_count": 8,
361             "public_network": 'ext-net',
362             "volume_size": 10,
363             "block_sizes": 4096,
364             "queue_depths": 4,
365             "workloads": {
366                 "read_sequential": {
367                     "rw": "rs"
368                 }
369             },
370             "StorPerf_ip": "192.168.23.2",
371             "query_interval": 0,
372             "timeout": 60
373         }
374         expected_post = {
375             'metadata': {
376                 'build_tag': 'latest',
377                 'test_case': 'opnfv_yardstick_tc074'
378             },
379             'deadline': 60,
380             'block_sizes': 4096,
381             'queue_depths': 4,
382             'workloads': {
383                 'read_sequential': {
384                     'rw': 'rs'
385                 }
386             },
387             'agent_count': 8
388         }
389
390         args = {
391             "options": options
392         }
393
394         s = storperf.StorPerf(args, self.ctx)
395         s.setup_done = True
396
397         self.assertRaises(RuntimeError, s.run, self.ctx)
398         mock_post.assert_called_once_with(
399             'http://192.168.23.2:5000/api/v2.0/jobs',
400             json=expected_post)
401
402     @mock.patch('time.sleep')
403     @mock.patch.object(requests, 'get')
404     @mock.patch.object(requests, 'post')
405     @mock.patch.object(storperf.StorPerf, 'setup')
406     def test_run_calls_setup(self, mock_setup, mock_post, mock_get, _):
407         mock_post.side_effect = mocked_requests_job_post
408         mock_get.side_effect = mocked_requests_job_get
409
410         args = {
411             "options": {
412                 'timeout': 60,
413             }
414         }
415
416         s = storperf.StorPerf(args, self.ctx)
417
418         s.run(self.result)
419
420         mock_setup.assert_called_once()
421
422     @mock.patch('time.sleep')
423     @mock.patch.object(requests, 'get')
424     @mock.patch.object(requests, 'post')
425     def test_initialize_disks(self, mock_post, mock_get, _):
426         mock_post.side_effect = mocked_requests_job_post
427         mock_get.side_effect = mocked_requests_job_get
428
429         args = {
430             "options": {
431                 "StorPerf_ip": "192.168.23.2"
432             }
433         }
434
435         s = storperf.StorPerf(args, self.ctx)
436
437         s.initialize_disks()
438
439         mock_post.assert_called_once_with(
440             'http://192.168.23.2:5000/api/v1.0/initializations',
441             json={})
442
443     @mock.patch('time.sleep')
444     @mock.patch.object(requests, 'get')
445     @mock.patch.object(requests, 'post')
446     def test_initialize_disks_post_failed(self, mock_post, mock_get, _):
447         mock_post.side_effect = mocked_requests_initialize_post_fail
448         mock_get.side_effect = mocked_requests_job_get
449
450         args = {
451             "options": {
452                 "StorPerf_ip": "192.168.23.2"
453             }
454         }
455
456         s = storperf.StorPerf(args, self.ctx)
457
458         self.assertRaises(RuntimeError, s.initialize_disks)
459         mock_post.assert_called_once_with(
460             'http://192.168.23.2:5000/api/v1.0/initializations',
461             json={})
462
463     @mock.patch.object(requests, 'delete')
464     def test_teardown(self, mock_delete):
465         mock_delete.side_effect = mocked_requests_job_delete
466         options = {
467             "agent_count": 8,
468             "public_network": 'ext-net',
469             "volume_size": 10,
470             "block_sizes": 4096,
471             "queue_depths": 4,
472             "workload": "rs",
473             "StorPerf_ip": "192.168.23.2",
474             "query_interval": 10,
475             "timeout": 60
476         }
477
478         args = {
479             "options": options
480         }
481
482         s = storperf.StorPerf(args, self.ctx)
483
484         s.teardown()
485
486         self.assertFalse(s.setup_done)
487         mock_delete.assert_called_once_with(
488             'http://192.168.23.2:5000/api/v1.0/configurations')
489
490     @mock.patch.object(requests, 'delete')
491     def test_teardown_request_delete_failed(self, mock_delete):
492         mock_delete.side_effect = mocked_requests_delete_failed
493         options = {
494             "agent_count": 8,
495             "public_network": 'ext-net',
496             "volume_size": 10,
497             "block_sizes": 4096,
498             "queue_depths": 4,
499             "workload": "rs",
500             "StorPerf_ip": "192.168.23.2",
501             "query_interval": 10,
502             "timeout": 60
503         }
504
505         args = {
506             "options": options
507         }
508
509         s = storperf.StorPerf(args, self.ctx)
510
511         self.assertRaises(RuntimeError, s.teardown)
512         mock_delete.assert_called_once_with(
513             'http://192.168.23.2:5000/api/v1.0/configurations')