Merge "Bump pip packages installed in "nsb_setup.sh" script"
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / standalone / test_model.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import copy
16 import os
17 import unittest
18 import mock
19
20 from xml.etree import ElementTree
21 from yardstick.benchmark.contexts.standalone import model
22 from yardstick.network_services import utils
23
24
25 XML_SAMPLE = """<?xml version="1.0"?>
26 <domain type="kvm">
27     <devices>
28     </devices>
29 </domain>
30 """
31
32 XML_SAMPLE_INTERFACE = """<?xml version="1.0"?>
33 <domain type="kvm">
34     <devices>
35         <interface>
36         </interface>
37     </devices>
38 </domain>
39 """
40
41 class ModelLibvirtTestCase(unittest.TestCase):
42
43     def setUp(self):
44         self.xml = ElementTree.ElementTree(
45             element=ElementTree.fromstring(XML_SAMPLE))
46         self.pci_address_str = '0001:04:03.2'
47         self.pci_address = utils.PciAddress(self.pci_address_str)
48         self.mac = '00:00:00:00:00:01'
49         self._mock_write_xml = mock.patch.object(ElementTree.ElementTree,
50                                                  'write')
51         self.mock_write_xml = self._mock_write_xml.start()
52
53         self.addCleanup(self._cleanup)
54
55     def _cleanup(self):
56         self._mock_write_xml.stop()
57
58     # TODO: Remove mocking of yardstick.ssh.SSH (here and elsewhere)
59     # In this case, we are mocking a param to be passed into other methods
60     # It can be a generic Mock() with return values set for the right methods
61     def test_check_if_vm_exists_and_delete(self):
62         with mock.patch("yardstick.ssh.SSH") as ssh:
63             ssh_mock = mock.Mock(autospec=ssh.SSH)
64             ssh_mock.execute = mock.Mock(return_value=(0, "a", ""))
65             ssh.return_value = ssh_mock
66         # NOTE(ralonsoh): this test doesn't cover function execution.
67         model.Libvirt.check_if_vm_exists_and_delete("vm_0", ssh_mock)
68
69     def test_virsh_create_vm(self):
70         with mock.patch("yardstick.ssh.SSH") as ssh:
71             ssh_mock = mock.Mock(autospec=ssh.SSH)
72             ssh_mock.execute = mock.Mock(return_value=(0, "a", ""))
73             ssh.return_value = ssh_mock
74         # NOTE(ralonsoh): this test doesn't cover function execution.
75         model.Libvirt.virsh_create_vm(ssh_mock, "vm_0")
76
77     def test_virsh_destroy_vm(self):
78         with mock.patch("yardstick.ssh.SSH") as ssh:
79             ssh_mock = mock.Mock(autospec=ssh.SSH)
80             ssh_mock.execute = mock.Mock(return_value=(0, "a", ""))
81             ssh.return_value = ssh_mock
82         # NOTE(ralonsoh): this test doesn't cover function execution.
83         model.Libvirt.virsh_destroy_vm("vm_0", ssh_mock)
84
85     def test_add_interface_address(self):
86         xml = ElementTree.ElementTree(
87             element=ElementTree.fromstring(XML_SAMPLE_INTERFACE))
88         interface = xml.find('devices').find('interface')
89         result = model.Libvirt._add_interface_address(interface, self.pci_address)
90         self.assertEqual('pci', result.get('type'))
91         self.assertEqual('0x{}'.format(self.pci_address.domain),
92                          result.get('domain'))
93         self.assertEqual('0x{}'.format(self.pci_address.bus),
94                          result.get('bus'))
95         self.assertEqual('0x{}'.format(self.pci_address.slot),
96                          result.get('slot'))
97         self.assertEqual('0x{}'.format(self.pci_address.function),
98                          result.get('function'))
99
100     def test_add_ovs_interfaces(self):
101         xml_input = mock.Mock()
102         with mock.patch.object(ElementTree, 'parse', return_value=self.xml) \
103                 as mock_parse:
104             xml = copy.deepcopy(self.xml)
105             mock_parse.return_value = xml
106             model.Libvirt.add_ovs_interface(
107                 '/usr/local', 0, self.pci_address_str, self.mac, xml_input)
108             mock_parse.assert_called_once_with(xml_input)
109             self.mock_write_xml.assert_called_once_with(xml_input)
110             interface = xml.find('devices').find('interface')
111             self.assertEqual('vhostuser', interface.get('type'))
112             mac = interface.find('mac')
113             self.assertEqual(self.mac, mac.get('address'))
114             source = interface.find('source')
115             self.assertEqual('unix', source.get('type'))
116             self.assertEqual('/usr/local/var/run/openvswitch/dpdkvhostuser0',
117                              source.get('path'))
118             self.assertEqual('client', source.get('mode'))
119             _model = interface.find('model')
120             self.assertEqual('virtio', _model.get('type'))
121             driver = interface.find('driver')
122             self.assertEqual('4', driver.get('queues'))
123             host = driver.find('host')
124             self.assertEqual('off', host.get('mrg_rxbuf'))
125             self.assertIsNotNone(interface.find('address'))
126
127     def test_add_sriov_interfaces(self):
128         xml_input = mock.Mock()
129         with mock.patch.object(ElementTree, 'parse', return_value=self.xml) \
130                 as mock_parse:
131             xml = copy.deepcopy(self.xml)
132             mock_parse.return_value = xml
133             vm_pci = '0001:05:04.2'
134             model.Libvirt.add_sriov_interfaces(
135                 vm_pci, self.pci_address_str, self.mac, xml_input)
136             mock_parse.assert_called_once_with(xml_input)
137             self.mock_write_xml.assert_called_once_with(xml_input)
138             interface = xml.find('devices').find('interface')
139             self.assertEqual('yes', interface.get('managed'))
140             self.assertEqual('hostdev', interface.get('type'))
141             mac = interface.find('mac')
142             self.assertEqual(self.mac, mac.get('address'))
143             source = interface.find('source')
144             source_address = source.find('address')
145             self.assertIsNotNone(source.find('address'))
146
147             self.assertEqual('pci', source_address.get('type'))
148             self.assertEqual('0x' + self.pci_address_str.split(':')[0],
149                              source_address.get('domain'))
150             self.assertEqual('0x' + self.pci_address_str.split(':')[1],
151                              source_address.get('bus'))
152             self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[0],
153                              source_address.get('slot'))
154             self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[1],
155                              source_address.get('function'))
156
157             interface_address = interface.find('address')
158             self.assertEqual('pci', interface_address.get('type'))
159             self.assertEqual('0x' + vm_pci.split(':')[0],
160                              interface_address.get('domain'))
161             self.assertEqual('0x' + vm_pci.split(':')[1],
162                              interface_address.get('bus'))
163             self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[0],
164                              interface_address.get('slot'))
165             self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[1],
166                              interface_address.get('function'))
167
168     def test_create_snapshot_qemu(self):
169         result = "/var/lib/libvirt/images/0.qcow2"
170         with mock.patch("yardstick.ssh.SSH") as ssh:
171             ssh_mock = mock.Mock(autospec=ssh.SSH)
172             ssh_mock.execute = \
173                 mock.Mock(return_value=(0, "a", ""))
174             ssh.return_value = ssh_mock
175         image = model.Libvirt.create_snapshot_qemu(ssh_mock, "0", "ubuntu.img")
176         self.assertEqual(image, result)
177
178     @mock.patch.object(model.Libvirt, 'pin_vcpu_for_perf')
179     @mock.patch.object(model.Libvirt, 'create_snapshot_qemu')
180     def test_build_vm_xml(self, mock_create_snapshot_qemu,
181                           *args):
182         # NOTE(ralonsoh): this test doesn't cover function execution. This test
183         # should also check mocked function calls.
184         cfg_file = 'test_config_file.cfg'
185         self.addCleanup(os.remove, cfg_file)
186         result = [4]
187         with mock.patch("yardstick.ssh.SSH") as ssh:
188             ssh_mock = mock.Mock(autospec=ssh.SSH)
189             ssh_mock.execute = \
190                 mock.Mock(return_value=(0, "a", ""))
191             ssh.return_value = ssh_mock
192         mock_create_snapshot_qemu.return_value = "0.img"
193
194         status = model.Libvirt.build_vm_xml(ssh_mock, {}, cfg_file, 'vm_0', 0)
195         self.assertEqual(status[0], result[0])
196
197     # TODO: Edit this test to test state instead of output
198     # update_interrupts_hugepages_perf does not return anything
199     def test_update_interrupts_hugepages_perf(self):
200         with mock.patch("yardstick.ssh.SSH") as ssh:
201             ssh_mock = mock.Mock(autospec=ssh.SSH)
202             ssh_mock.execute = \
203                 mock.Mock(return_value=(0, "a", ""))
204             ssh.return_value = ssh_mock
205         # NOTE(ralonsoh): 'update_interrupts_hugepages_perf' always return
206         # None, this check is trivial.
207         #status = Libvirt.update_interrupts_hugepages_perf(ssh_mock)
208         #self.assertIsNone(status)
209         model.Libvirt.update_interrupts_hugepages_perf(ssh_mock)
210
211     @mock.patch.object(model, 'CpuSysCores')
212     @mock.patch.object(model.Libvirt, 'update_interrupts_hugepages_perf')
213     def test_pin_vcpu_for_perf(self, *args):
214         # NOTE(ralonsoh): test mocked methods/variables.
215         with mock.patch("yardstick.ssh.SSH") as ssh:
216             ssh_mock = mock.Mock(autospec=ssh.SSH)
217             ssh_mock.execute = \
218                 mock.Mock(return_value=(0, "a", ""))
219             ssh.return_value = ssh_mock
220         status = model.Libvirt.pin_vcpu_for_perf(ssh_mock, 4)
221         self.assertIsNotNone(status)
222
223 class StandaloneContextHelperTestCase(unittest.TestCase):
224
225     NODE_SAMPLE = "nodes_sample.yaml"
226     NODE_SRIOV_SAMPLE = "nodes_sriov_sample.yaml"
227
228     NETWORKS = {
229         'mgmt': {'cidr': '152.16.100.10/24'},
230         'private_0': {
231             'phy_port': "0000:05:00.0",
232             'vpci': "0000:00:07.0",
233             'cidr': '152.16.100.10/24',
234             'gateway_ip': '152.16.100.20'},
235         'public_0': {
236             'phy_port': "0000:05:00.1",
237             'vpci': "0000:00:08.0",
238             'cidr': '152.16.40.10/24',
239             'gateway_ip': '152.16.100.20'}
240     }
241
242     def setUp(self):
243         self.helper = model.StandaloneContextHelper()
244
245     def test___init__(self):
246         self.assertIsNone(self.helper.file_path)
247
248     def test_install_req_libs(self):
249         with mock.patch("yardstick.ssh.SSH") as ssh:
250             ssh_mock = mock.Mock(autospec=ssh.SSH)
251             ssh_mock.execute = \
252                 mock.Mock(return_value=(1, "a", ""))
253             ssh.return_value = ssh_mock
254         # NOTE(ralonsoh): this test doesn't cover function execution. This test
255         # should also check mocked function calls.
256         model.StandaloneContextHelper.install_req_libs(ssh_mock)
257
258     def test_get_kernel_module(self):
259         with mock.patch("yardstick.ssh.SSH") as ssh:
260             ssh_mock = mock.Mock(autospec=ssh.SSH)
261             ssh_mock.execute = \
262                 mock.Mock(return_value=(1, "i40e", ""))
263             ssh.return_value = ssh_mock
264         # NOTE(ralonsoh): this test doesn't cover function execution. This test
265         # should also check mocked function calls.
266         model.StandaloneContextHelper.get_kernel_module(
267             ssh_mock, "05:00.0", None)
268
269     @mock.patch.object(model.StandaloneContextHelper, 'get_kernel_module')
270     def test_get_nic_details(self, mock_get_kernel_module):
271         with mock.patch("yardstick.ssh.SSH") as ssh:
272             ssh_mock = mock.Mock(autospec=ssh.SSH)
273             ssh_mock.execute = mock.Mock(return_value=(1, "i40e ixgbe", ""))
274             ssh.return_value = ssh_mock
275         mock_get_kernel_module.return_value = "i40e"
276         # NOTE(ralonsoh): this test doesn't cover function execution. This test
277         # should also check mocked function calls.
278         model.StandaloneContextHelper.get_nic_details(
279             ssh_mock, self.NETWORKS, 'dpdk-devbind.py')
280
281     def test_get_virtual_devices(self):
282         pattern = "PCI_SLOT_NAME=0000:05:00.0"
283         with mock.patch("yardstick.ssh.SSH") as ssh:
284             ssh_mock = mock.Mock(autospec=ssh.SSH)
285             ssh_mock.execute = \
286                 mock.Mock(return_value=(1, pattern, ""))
287             ssh.return_value = ssh_mock
288         # NOTE(ralonsoh): this test doesn't cover function execution. This test
289         # should also check mocked function calls.
290         model.StandaloneContextHelper.get_virtual_devices(
291             ssh_mock, '0000:00:05.0')
292
293     def _get_file_abspath(self, filename):
294         curr_path = os.path.dirname(os.path.abspath(__file__))
295         file_path = os.path.join(curr_path, filename)
296         return file_path
297
298     def test_read_config_file(self):
299         self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE)
300         status = self.helper.read_config_file()
301         self.assertIsNotNone(status)
302
303     def test_parse_pod_file(self):
304         self.helper.file_path = self._get_file_abspath("dummy")
305         self.assertRaises(IOError, self.helper.parse_pod_file,
306                           self.helper.file_path)
307
308         self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE)
309         self.assertRaises(TypeError, self.helper.parse_pod_file,
310                           self.helper.file_path)
311
312         self.helper.file_path = self._get_file_abspath(self.NODE_SRIOV_SAMPLE)
313         self.assertIsNotNone(self.helper.parse_pod_file(self.helper.file_path))
314
315     def test_get_mac_address(self):
316         status = model.StandaloneContextHelper.get_mac_address()
317         self.assertIsNotNone(status)
318
319     @mock.patch('yardstick.ssh.SSH')
320     def test_get_mgmt_ip(self, *args):
321         # NOTE(ralonsoh): test mocked methods/variables.
322         with mock.patch("yardstick.ssh.SSH") as ssh:
323             ssh_mock = mock.Mock(autospec=ssh.SSH)
324             ssh_mock.execute = mock.Mock(
325                 return_value=(1, "1.2.3.4 00:00:00:00:00:01", ""))
326             ssh.return_value = ssh_mock
327         # NOTE(ralonsoh): this test doesn't cover function execution. This test
328         # should also check mocked function calls.
329         status = model.StandaloneContextHelper.get_mgmt_ip(
330             ssh_mock, "00:00:00:00:00:01", "1.1.1.1/24", {})
331         self.assertIsNotNone(status)
332
333     @mock.patch('yardstick.ssh.SSH')
334     def test_get_mgmt_ip_no(self, *args):
335         # NOTE(ralonsoh): test mocked methods/variables.
336         with mock.patch("yardstick.ssh.SSH") as ssh:
337             ssh_mock = mock.Mock(autospec=ssh.SSH)
338             ssh_mock.execute = \
339                 mock.Mock(return_value=(1, "", ""))
340             ssh.return_value = ssh_mock
341         # NOTE(ralonsoh): this test doesn't cover function execution. This test
342         # should also check mocked function calls.
343         model.WAIT_FOR_BOOT = 0
344         status = model.StandaloneContextHelper.get_mgmt_ip(
345             ssh_mock, "99", "1.1.1.1/24", {})
346         self.assertIsNone(status)
347
348
349 class ServerTestCase(unittest.TestCase):
350
351     NETWORKS = {
352         'mgmt': {'cidr': '152.16.100.10/24'},
353         'private_0': {
354             'phy_port': "0000:05:00.0",
355             'vpci': "0000:00:07.0",
356             'driver': 'i40e',
357             'mac': '',
358             'cidr': '152.16.100.10/24',
359             'gateway_ip': '152.16.100.20'},
360         'public_0': {
361             'phy_port': "0000:05:00.1",
362             'vpci': "0000:00:08.0",
363             'driver': 'i40e',
364             'mac': '',
365             'cidr': '152.16.40.10/24',
366             'gateway_ip': '152.16.100.20'}
367     }
368
369     def setUp(self):
370         self.server = model.Server()
371
372     def test___init__(self):
373         self.assertIsNotNone(self.server)
374
375     def test_build_vnf_interfaces(self):
376         vnf = {
377             "network_ports": {
378                 'mgmt': {'cidr': '152.16.100.10/24'},
379                 'xe0': ['private_0'],
380                 'xe1': ['public_0'],
381             }
382         }
383         status = model.Server.build_vnf_interfaces(vnf, self.NETWORKS)
384         self.assertIsNotNone(status)
385
386     def test_generate_vnf_instance(self):
387         vnf = {
388             "network_ports": {
389                 'mgmt': {'cidr': '152.16.100.10/24'},
390                 'xe0': ['private_0'],
391                 'xe1': ['public_0'],
392             }
393         }
394         status = self.server.generate_vnf_instance(
395             {}, self.NETWORKS, '1.1.1.1/24', 'vm_0', vnf, '00:00:00:00:00:01')
396         self.assertIsNotNone(status)
397
398
399 class OvsDeployTestCase(unittest.TestCase):
400
401     NETWORKS = {
402         'mgmt': {'cidr': '152.16.100.10/24'},
403         'private_0': {
404             'phy_port': "0000:05:00.0",
405             'vpci': "0000:00:07.0",
406             'driver': 'i40e',
407             'mac': '',
408             'cidr': '152.16.100.10/24',
409             'gateway_ip': '152.16.100.20'},
410         'public_0': {
411             'phy_port': "0000:05:00.1",
412             'vpci': "0000:00:08.0",
413             'driver': 'i40e',
414             'mac': '',
415             'cidr': '152.16.40.10/24',
416             'gateway_ip': '152.16.100.20'}
417     }
418
419     @mock.patch('yardstick.ssh.SSH')
420     def setUp(self, mock_ssh):
421         self.ovs_deploy = model.OvsDeploy(mock_ssh, '/tmp/dpdk-devbind.py', {})
422
423     def test___init__(self):
424         self.assertIsNotNone(self.ovs_deploy.connection)
425
426     @mock.patch('yardstick.benchmark.contexts.standalone.model.os')
427     def test_prerequisite(self, *args):
428         # NOTE(ralonsoh): this test should check mocked function calls.
429         self.ovs_deploy.helper = mock.Mock()
430         self.assertIsNone(self.ovs_deploy.prerequisite())
431
432     @mock.patch('yardstick.benchmark.contexts.standalone.model.os')
433     def test_prerequisite_2(self, *args):
434         # NOTE(ralonsoh): this test should check mocked function calls. Rename
435         # this test properly.
436         self.ovs_deploy.helper = mock.Mock()
437         self.ovs_deploy.connection.execute = mock.Mock(
438             return_value=(1, '1.2.3.4 00:00:00:00:00:01', ''))
439         self.ovs_deploy.prerequisite = mock.Mock()
440         self.assertIsNone(self.ovs_deploy.ovs_deploy())