Add send socket commands function
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_node.py
1 ##############################################################################
2 # Copyright (c) 2015-2017 Huawei Technologies Co.,Ltd 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 import os
11 import unittest
12 import errno
13 import mock
14
15 from yardstick.common import constants as consts
16 from yardstick.benchmark.contexts import base
17 from yardstick.benchmark.contexts import node
18
19
20 class NodeContextTestCase(unittest.TestCase):
21
22     PREFIX = 'yardstick.benchmark.contexts.node'
23
24     NODES_SAMPLE = "nodes_sample.yaml"
25     NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
26
27     def setUp(self):
28         self.test_context = node.NodeContext()
29         self.addCleanup(self._remove_contexts)
30         self.os_path_join = os.path.join
31         self.attrs = {
32             'name': 'foo',
33             'task_id': '1234567890',
34             'file': self._get_file_abspath(self.NODES_SAMPLE)
35         }
36
37     @staticmethod
38     def _remove_contexts():
39         for context in base.Context.list:
40             context._delete_context()
41         base.Context.list = []
42
43     def _get_file_abspath(self, filename):
44         curr_path = os.path.dirname(os.path.abspath(__file__))
45         file_path = self.os_path_join(curr_path, filename)
46         return file_path
47
48     def test___init__(self):
49         self.assertIsNone(self.test_context._name)
50         self.assertIsNone(self.test_context.file_path)
51         self.assertEqual(self.test_context.nodes, [])
52         self.assertEqual(self.test_context.controllers, [])
53         self.assertEqual(self.test_context.computes, [])
54         self.assertEqual(self.test_context.baremetals, [])
55         self.assertEqual(self.test_context.env, {})
56         self.assertEqual(self.test_context.attrs, {})
57
58     @mock.patch('{}.os.path.join'.format(PREFIX))
59     def test_init_negative(self, mock_path_join):
60         special_path = '/foo/bar/error_file'
61         error_path = self._get_file_abspath("error_file")
62
63         def path_join(*args):
64             if args == (consts.YARDSTICK_ROOT_PATH, error_path):
65                 return special_path
66             return self.os_path_join(*args)
67
68         # we can't count mock_path_join calls because
69         # it can catch join calls for .pyc files.
70         mock_path_join.side_effect = path_join
71         self.test_context.read_config_file = read_mock = mock.Mock()
72         read_calls = 0
73
74         with self.assertRaises(KeyError):
75             self.test_context.init({})
76
77         self.assertEqual(read_mock.call_count, read_calls)
78
79         attrs = {
80             'name': 'foo',
81             'task_id': '1234567890',
82             'file': error_path,
83         }
84         read_mock.side_effect = IOError(errno.EBUSY, 'busy')
85         with self.assertRaises(IOError) as raised:
86             self.test_context.init(attrs)
87
88         read_calls += 1
89         self.assertEqual(read_mock.called, read_calls)
90         self.assertIn(attrs['file'], self.test_context.file_path)
91         self.assertEqual(raised.exception.errno, errno.EBUSY)
92         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
93
94         read_mock.side_effect = IOError(errno.ENOENT, 'not found')
95         with self.assertRaises(IOError) as raised:
96             self.test_context.init(attrs)
97
98         read_calls += 2
99         self.assertEqual(read_mock.call_count, read_calls)
100         self.assertEqual(self.test_context.file_path, special_path)
101         self.assertEqual(raised.exception.errno, errno.ENOENT)
102         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
103
104     def test_read_config_file(self):
105         self.test_context.init(self.attrs)
106
107         self.assertIsNotNone(self.test_context.read_config_file())
108
109     def test__dispatch_script(self):
110         self.test_context.init(self.attrs)
111
112         self.test_context.env = {'bash': [{'script': 'dummy'}]}
113         self.test_context._execute_script = mock.Mock()
114         self.assertEqual(self.test_context._dispatch_script('bash'), None)
115
116     def test__dispatch_ansible(self):
117         self.test_context.init(self.attrs)
118
119         self.test_context.env = {'ansible': [{'script': 'dummy'}]}
120         self.test_context._do_ansible_job = mock.Mock()
121         self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
122         self.test_context.env = {}
123         self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
124
125     @mock.patch("{}.AnsibleCommon".format(PREFIX))
126     def test__do_ansible_job(self, *args):
127         self.assertIsNone(self.test_context._do_ansible_job('dummy'))
128
129     def test_init(self):
130         self.test_context.init(self.attrs)
131
132         self.assertEqual(self.test_context.name, "foo-12345678")
133         self.assertEqual(len(self.test_context.nodes), 4)
134         self.assertEqual(len(self.test_context.controllers), 2)
135         self.assertEqual(len(self.test_context.computes), 1)
136         self.assertEqual(self.test_context.computes[0]["name"], "node3")
137         self.assertEqual(len(self.test_context.baremetals), 1)
138         self.assertEqual(self.test_context.baremetals[0]["name"], "node4")
139
140     def test__get_server_with_dict_attr_name(self):
141         self.test_context.init(self.attrs)
142         result = self.test_context._get_server({'name': 'node1.foo-12345678'})
143
144         self.assertIsNone(result, None)
145
146     def test__get_server_not_found(self):
147         self.test_context.init(self.attrs)
148
149         self.assertIsNone(self.test_context._get_server('bar.foo-12345678'))
150
151     def test__get_server_mismatch(self):
152         self.test_context.init(self.attrs)
153
154         self.assertIsNone(self.test_context._get_server('bar.foo1'))
155
156     def test__get_server_duplicate(self):
157         self.attrs['file'] = self._get_file_abspath(
158             self.NODES_DUPLICATE_SAMPLE)
159         self.test_context.init(self.attrs)
160
161         with self.assertRaises(ValueError):
162             self.test_context._get_server('node1.foo-12345678')
163
164     def test__get_server_found(self):
165         self.test_context.init(self.attrs)
166
167         result = self.test_context._get_server('node1.foo-12345678')
168
169         self.assertEqual(result['ip'], '10.229.47.137')
170         self.assertEqual(result['name'], 'node1.foo-12345678')
171         self.assertEqual(result['user'], 'root')
172         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
173
174     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
175     def test_deploy(self, dispatch_script_mock):
176         obj = node.NodeContext()
177         self.addCleanup(obj._delete_context)
178         obj.env = {
179             'type': 'script'
180         }
181         obj.deploy()
182         dispatch_script_mock.assert_called_once()
183
184     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
185     def test_deploy_anisible(self, dispatch_ansible_mock):
186         obj = node.NodeContext()
187         self.addCleanup(obj._delete_context)
188         obj.env = {
189             'type': 'ansible'
190         }
191         obj.deploy()
192         dispatch_ansible_mock.assert_called_once()
193
194     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
195     def test_undeploy(self, dispatch_script_mock):
196         obj = node.NodeContext()
197         obj.env = {
198             'type': 'script'
199         }
200         obj.undeploy()
201         dispatch_script_mock.assert_called_once()
202
203     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
204     def test_undeploy_anisble(self, dispatch_ansible_mock):
205         obj = node.NodeContext()
206         obj.env = {
207             'type': 'ansible'
208         }
209         obj.undeploy()
210         dispatch_ansible_mock.assert_called_once()
211
212     @mock.patch('{}.ssh.SSH._put_file_shell'.format(PREFIX))
213     @mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
214     def test_execute_remote_script(self, execute_mock, put_file_mock):
215         obj = node.NodeContext()
216         self.addCleanup(obj._delete_context)
217         obj.env = {'prefix': 'yardstick.benchmark.scenarios.compute'}
218         node_name_args = 'node5'
219         obj.nodes = [{
220             'name': node_name_args,
221             'user': 'ubuntu',
222             'ip': '10.10.10.10',
223             'pwd': 'ubuntu',
224         }]
225
226         info = {'script': 'computecapacity.bash'}
227         execute_mock.return_value = (0, '', '')
228         obj._execute_remote_script('node5', info)
229
230         put_file_mock.assert_called_once()
231         execute_mock.assert_called()
232
233     @mock.patch('{}.NodeContext._execute_local_script'.format(PREFIX))
234     def test_execute_script_local(self, local_execute_mock):
235         node_name = 'local'
236         info = {}
237         obj = node.NodeContext()
238         self.addCleanup(obj._delete_context)
239         obj._execute_script(node_name, info)
240         local_execute_mock.assert_called_once()
241
242     @mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
243     def test_execute_script_remote(self, remote_execute_mock):
244         node_name = 'node5'
245         info = {}
246         obj = node.NodeContext()
247         self.addCleanup(obj._delete_context)
248         obj._execute_script(node_name, info)
249         remote_execute_mock.assert_called_once()
250
251     def test_get_script(self):
252         script_args = 'hello.bash'
253         info_args = {
254             'script': script_args
255         }
256         obj = node.NodeContext()
257         self.addCleanup(obj._delete_context)
258         script, options = obj._get_script(info_args)
259         self.assertEqual(script_args, script)
260         self.assertEqual('', options)
261
262     def test_node_info(self):
263         node_name_args = 'node5'
264         obj = node.NodeContext()
265         self.addCleanup(obj._delete_context)
266         obj.nodes = [{'name': node_name_args, 'check': node_name_args}]
267         node_info = obj._get_node_info(node_name_args)
268         self.assertEqual(node_info.get('check'), node_name_args)
269
270     @mock.patch('{}.ssh.SSH.wait'.format(PREFIX))
271     def test_get_client(self, wait_mock):
272         node_name_args = 'node5'
273         obj = node.NodeContext()
274         self.addCleanup(obj._delete_context)
275         obj.nodes = [{
276             'name': node_name_args,
277             'user': 'ubuntu',
278             'ip': '10.10.10.10',
279             'pwd': 'ubuntu',
280         }]
281         obj._get_client(node_name_args)
282         wait_mock.assert_called_once()
283
284     def test_get_server(self):
285         self.test_context.init(self.attrs)
286         self.test_context._name = 'foo'
287         self.test_context._task_id = '1234567890'
288         self.test_context._name_task_id = '{}-{}'.format(
289             self.test_context._name, self.test_context._task_id[:8])
290         self.assertEqual('foo-12345678', self.test_context.name)
291         self.assertIsNotNone(self.test_context._task_id)
292
293         result = self.test_context.get_server('node1.foo-12345678')
294
295         self.assertEqual(result['ip'], '10.229.47.137')
296         self.assertEqual(result['name'], 'node1.foo-12345678')
297         self.assertEqual(result['user'], 'root')
298         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
299
300     def test_get_server_server_not_in_context(self):
301         self.test_context.init(self.attrs)
302
303         with self.assertRaises(ValueError):
304             self.test_context.get_server('my2.foo-12345678')
305
306     def test_get_context_from_server(self):
307         self.test_context._name = 'vnf1'
308         self.test_context._task_id = '1234567890'
309         self.test_context._name_task_id = '{}-{}'.format(
310             self.test_context._name, self.test_context._task_id[:8])
311         self.test_context.nodes = [{'name': 'my', 'value': 100}]
312         self.test_context.attrs = {'attr1': 200}
313
314         self.assertIs(
315             self.test_context.get_context_from_server('my.vnf1-12345678'),
316             self.test_context)
317
318     # TODO: Split this into more granular tests
319     def test__get_network(self):
320         network1 = {
321             'name': 'net_1',
322             'vld_id': 'vld111',
323             'segmentation_id': 'seg54',
324             'network_type': 'type_a',
325             'physical_network': 'phys',
326         }
327         network2 = {
328             'name': 'net_2',
329             'vld_id': 'vld999',
330         }
331         self.test_context.networks = {
332             'a': network1,
333             'b': network2,
334         }
335
336         attr_name = {}
337         self.assertIsNone(self.test_context._get_network(attr_name))
338
339         attr_name = {'vld_id': 'vld777'}
340         self.assertIsNone(self.test_context._get_network(attr_name))
341
342         self.assertIsNone(self.test_context._get_network(None))
343
344         attr_name = 'vld777'
345         self.assertIsNone(self.test_context._get_network(attr_name))
346
347         attr_name = {'vld_id': 'vld999'}
348         expected = {
349             "name": 'net_2',
350             "vld_id": 'vld999',
351             "segmentation_id": None,
352             "network_type": None,
353             "physical_network": None,
354         }
355         result = self.test_context._get_network(attr_name)
356         self.assertDictEqual(result, expected)
357
358         attr_name = 'a'
359         expected = network1
360         result = self.test_context._get_network(attr_name)
361         self.assertDictEqual(result, expected)