Merge "Configure ACL via static file"
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_sample_vnf.py
1 # Copyright (c) 2017-2018 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 from copy import deepcopy
16
17 import unittest
18 import mock
19 import six
20
21 from yardstick.benchmark.contexts.base import Context
22 from yardstick.common import exceptions as y_exceptions
23 from yardstick.common import utils
24 from yardstick.network_services.nfvi.resource import ResourceProfile
25 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
26 from yardstick.network_services.vnf_generic.vnf import sample_vnf
27 from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
28 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
29 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
30 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
31 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
32 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
33 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
34 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
35 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
36 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
37 from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
38
39
40 class MockError(Exception):
41     pass
42
43
44 class TestVnfSshHelper(unittest.TestCase):
45
46     VNFD_0 = {
47         'short-name': 'VpeVnf',
48         'vdu': [
49             {
50                 'routing_table': [
51                     {
52                         'network': '152.16.100.20',
53                         'netmask': '255.255.255.0',
54                         'gateway': '152.16.100.20',
55                         'if': 'xe0'
56                     },
57                     {
58                         'network': '152.16.40.20',
59                         'netmask': '255.255.255.0',
60                         'gateway': '152.16.40.20',
61                         'if': 'xe1'
62                     },
63                 ],
64                 'description': 'VPE approximation using DPDK',
65                 'name': 'vpevnf-baremetal',
66                 'nd_route_tbl': [
67                     {
68                         'network': '0064:ff9b:0:0:0:0:9810:6414',
69                         'netmask': '112',
70                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
71                         'if': 'xe0'
72                     },
73                     {
74                         'network': '0064:ff9b:0:0:0:0:9810:2814',
75                         'netmask': '112',
76                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
77                         'if': 'xe1'
78                     },
79                 ],
80                 'id': 'vpevnf-baremetal',
81                 'external-interface': [
82                     {
83                         'virtual-interface': {
84                             'dst_mac': '00:00:00:00:00:03',
85                             'vpci': '0000:05:00.0',
86                             'local_ip': '152.16.100.19',
87                             'type': 'PCI-PASSTHROUGH',
88                             'netmask': '255.255.255.0',
89                             'dpdk_port_num': 0,
90                             'bandwidth': '10 Gbps',
91                             'dst_ip': '152.16.100.20',
92                             'local_mac': '00:00:00:00:00:01',
93                             'vld_id': 'uplink_0',
94                             'ifname': 'xe0',
95                         },
96                         'vnfd-connection-point-ref': 'xe0',
97                         'name': 'xe0'
98                     },
99                     {
100                         'virtual-interface': {
101                             'dst_mac': '00:00:00:00:00:04',
102                             'vpci': '0000:05:00.1',
103                             'local_ip': '152.16.40.19',
104                             'type': 'PCI-PASSTHROUGH',
105                             'netmask': '255.255.255.0',
106                             'dpdk_port_num': 1,
107                             'bandwidth': '10 Gbps',
108                             'dst_ip': '152.16.40.20',
109                             'local_mac': '00:00:00:00:00:02',
110                             'vld_id': 'downlink_0',
111                             'ifname': 'xe1',
112                         },
113                         'vnfd-connection-point-ref': 'xe1',
114                         'name': 'xe1'
115                     },
116                 ],
117             },
118         ],
119         'description': 'Vpe approximation using DPDK',
120         'mgmt-interface': {
121             'vdu-id': 'vpevnf-baremetal',
122             'host': '1.1.1.1',
123             'password': 'r00t',
124             'user': 'root',
125             'ip': '1.1.1.1'
126         },
127         'benchmark': {
128             'kpi': [
129                 'packets_in',
130                 'packets_fwd',
131                 'packets_dropped',
132             ],
133         },
134         'connection-point': [
135             {
136                 'type': 'VPORT',
137                 'name': 'xe0',
138             },
139             {
140                 'type': 'VPORT',
141                 'name': 'xe1',
142             },
143         ],
144         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
145     }
146
147     VNFD = {
148         'vnfd:vnfd-catalog': {
149             'vnfd': [
150                 VNFD_0,
151             ]
152         }
153     }
154
155     def assertAll(self, iterable, message=None):
156         self.assertTrue(all(iterable), message)
157
158     def test_get_class(self):
159         self.assertIs(VnfSshHelper.get_class(), VnfSshHelper)
160
161     @mock.patch('yardstick.ssh.paramiko')
162     def test_copy(self, _):
163         ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path')
164         ssh_helper._run = mock.Mock()
165
166         ssh_helper.execute('ls')
167         self.assertTrue(ssh_helper.is_connected)
168         result = ssh_helper.copy()
169         self.assertIsInstance(result, VnfSshHelper)
170         self.assertFalse(result.is_connected)
171         self.assertEqual(result.bin_path, ssh_helper.bin_path)
172         self.assertEqual(result.host, ssh_helper.host)
173         self.assertEqual(result.port, ssh_helper.port)
174         self.assertEqual(result.user, ssh_helper.user)
175         self.assertEqual(result.password, ssh_helper.password)
176         self.assertEqual(result.key_filename, ssh_helper.key_filename)
177
178     @mock.patch('yardstick.ssh.paramiko')
179     def test_upload_config_file(self, mock_paramiko):
180         ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path')
181         ssh_helper._run = mock.MagicMock()
182
183         self.assertFalse(ssh_helper.is_connected)
184         cfg_file = ssh_helper.upload_config_file('my/prefix', 'my content')
185         self.assertTrue(ssh_helper.is_connected)
186         mock_paramiko.SSHClient.assert_called_once()
187         self.assertTrue(cfg_file.startswith('/tmp'))
188
189         cfg_file = ssh_helper.upload_config_file('/my/prefix', 'my content')
190         self.assertTrue(ssh_helper.is_connected)
191         mock_paramiko.SSHClient.assert_called_once()
192         self.assertEqual(cfg_file, '/my/prefix')
193
194     def test_join_bin_path(self):
195         ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path')
196
197         expected_start = 'my'
198         expected_middle_list = ['bin']
199         expected_end = 'path'
200         result = ssh_helper.join_bin_path()
201         self.assertTrue(result.startswith(expected_start))
202         self.assertAll(middle in result for middle in expected_middle_list)
203         self.assertTrue(result.endswith(expected_end))
204
205         expected_middle_list.append(expected_end)
206         expected_end = 'some_file.sh'
207         result = ssh_helper.join_bin_path('some_file.sh')
208         self.assertTrue(result.startswith(expected_start))
209         self.assertAll(middle in result for middle in expected_middle_list)
210         self.assertTrue(result.endswith(expected_end))
211
212         expected_middle_list.append('some_dir')
213         expected_end = 'some_file.sh'
214         result = ssh_helper.join_bin_path('some_dir', 'some_file.sh')
215         self.assertTrue(result.startswith(expected_start))
216         self.assertAll(middle in result for middle in expected_middle_list)
217         self.assertTrue(result.endswith(expected_end))
218
219     @mock.patch('yardstick.ssh.paramiko')
220     @mock.patch('yardstick.ssh.provision_tool')
221     def test_provision_tool(self, mock_provision_tool, mock_paramiko):
222         ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path')
223         ssh_helper._run = mock.MagicMock()
224
225         self.assertFalse(ssh_helper.is_connected)
226         ssh_helper.provision_tool()
227         self.assertTrue(ssh_helper.is_connected)
228         mock_paramiko.SSHClient.assert_called_once()
229         mock_provision_tool.assert_called_once()
230
231         ssh_helper.provision_tool(tool_file='my_tool.sh')
232         self.assertTrue(ssh_helper.is_connected)
233         mock_paramiko.SSHClient.assert_called_once()
234         self.assertEqual(mock_provision_tool.call_count, 2)
235
236         ssh_helper.provision_tool('tool_path', 'my_tool.sh')
237         self.assertTrue(ssh_helper.is_connected)
238         mock_paramiko.SSHClient.assert_called_once()
239         self.assertEqual(mock_provision_tool.call_count, 3)
240
241
242 class TestSetupEnvHelper(unittest.TestCase):
243
244     VNFD_0 = {
245         'short-name': 'VpeVnf',
246         'vdu': [
247             {
248                 'routing_table': [
249                     {
250                         'network': '152.16.100.20',
251                         'netmask': '255.255.255.0',
252                         'gateway': '152.16.100.20',
253                         'if': 'xe0'
254                     },
255                     {
256                         'network': '152.16.40.20',
257                         'netmask': '255.255.255.0',
258                         'gateway': '152.16.40.20',
259                         'if': 'xe1'
260                     },
261                 ],
262                 'description': 'VPE approximation using DPDK',
263                 'name': 'vpevnf-baremetal',
264                 'nd_route_tbl': [
265                     {
266                         'network': '0064:ff9b:0:0:0:0:9810:6414',
267                         'netmask': '112',
268                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
269                         'if': 'xe0'
270                     },
271                     {
272                         'network': '0064:ff9b:0:0:0:0:9810:2814',
273                         'netmask': '112',
274                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
275                         'if': 'xe1'
276                     },
277                 ],
278                 'id': 'vpevnf-baremetal',
279                 'external-interface': [
280                     {
281                         'virtual-interface': {
282                             'dst_mac': '00:00:00:00:00:03',
283                             'vpci': '0000:05:00.0',
284                             'local_ip': '152.16.100.19',
285                             'type': 'PCI-PASSTHROUGH',
286                             'netmask': '255.255.255.0',
287                             'dpdk_port_num': 0,
288                             'bandwidth': '10 Gbps',
289                             'dst_ip': '152.16.100.20',
290                             'local_mac': '00:00:00:00:00:01',
291                             'vld_id': 'uplink_0',
292                             'ifname': 'xe0',
293                         },
294                         'vnfd-connection-point-ref': 'xe0',
295                         'name': 'xe0'
296                     },
297                     {
298                         'virtual-interface': {
299                             'dst_mac': '00:00:00:00:00:04',
300                             'vpci': '0000:05:00.1',
301                             'local_ip': '152.16.40.19',
302                             'type': 'PCI-PASSTHROUGH',
303                             'netmask': '255.255.255.0',
304                             'dpdk_port_num': 1,
305                             'bandwidth': '10 Gbps',
306                             'dst_ip': '152.16.40.20',
307                             'local_mac': '00:00:00:00:00:02',
308                             'vld_id': 'downlink_0',
309                             'ifname': 'xe1',
310                         },
311                         'vnfd-connection-point-ref': 'xe1',
312                         'name': 'xe1'
313                     },
314                 ],
315             },
316         ],
317         'description': 'Vpe approximation using DPDK',
318         'mgmt-interface': {
319             'vdu-id': 'vpevnf-baremetal',
320             'host': '1.1.1.1',
321             'password': 'r00t',
322             'user': 'root',
323             'ip': '1.1.1.1'
324         },
325         'benchmark': {
326             'kpi': [
327                 'packets_in',
328                 'packets_fwd',
329                 'packets_dropped',
330             ],
331         },
332         'connection-point': [
333             {
334                 'type': 'VPORT',
335                 'name': 'xe0',
336             },
337             {
338                 'type': 'VPORT',
339                 'name': 'xe1',
340             },
341         ],
342         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
343     }
344
345     def test_build_config(self):
346         setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
347
348         with self.assertRaises(NotImplementedError):
349             setup_env_helper.build_config()
350
351     def test_setup_vnf_environment(self):
352         setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
353         self.assertIsNone(setup_env_helper.setup_vnf_environment())
354
355     def test_tear_down(self):
356         setup_env_helper = SetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
357
358         with self.assertRaises(NotImplementedError):
359             setup_env_helper.tear_down()
360
361
362 class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
363
364     VNFD_0 = {
365         'short-name': 'VpeVnf',
366         'vdu': [
367             {
368                 'routing_table': [
369                     {
370                         'network': '152.16.100.20',
371                         'netmask': '255.255.255.0',
372                         'gateway': '152.16.100.20',
373                         'if': 'xe0'
374                     },
375                     {
376                         'network': '152.16.40.20',
377                         'netmask': '255.255.255.0',
378                         'gateway': '152.16.40.20',
379                         'if': 'xe1'
380                     },
381                 ],
382                 'description': 'VPE approximation using DPDK',
383                 'name': 'vpevnf-baremetal',
384                 'nd_route_tbl': [
385                     {
386                         'network': '0064:ff9b:0:0:0:0:9810:6414',
387                         'netmask': '112',
388                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
389                         'if': 'xe0'
390                     },
391                     {
392                         'network': '0064:ff9b:0:0:0:0:9810:2814',
393                         'netmask': '112',
394                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
395                         'if': 'xe1'
396                     },
397                 ],
398                 'id': 'vpevnf-baremetal',
399                 'external-interface': [
400                     {
401                         'virtual-interface': {
402                             'dst_mac': '00:00:00:00:00:03',
403                             'vpci': '0000:05:00.0',
404                             'dpdk_port_num': 0,
405                             'driver': 'i40e',
406                             'local_ip': '152.16.100.19',
407                             'type': 'PCI-PASSTHROUGH',
408                             'netmask': '255.255.255.0',
409                             'bandwidth': '10 Gbps',
410                             'dst_ip': '152.16.100.20',
411                             'local_mac': '00:00:00:00:00:01',
412                             'vld_id': 'uplink_0',
413                             'ifname': 'xe0',
414                         },
415                         'vnfd-connection-point-ref': 'xe0',
416                         'name': 'xe0'
417                     },
418                     {
419                         'virtual-interface': {
420                             'dst_mac': '00:00:00:00:00:04',
421                             'vpci': '0000:05:00.1',
422                             'dpdk_port_num': 1,
423                             'driver': 'ixgbe',
424                             'local_ip': '152.16.40.19',
425                             'type': 'PCI-PASSTHROUGH',
426                             'netmask': '255.255.255.0',
427                             'bandwidth': '10 Gbps',
428                             'dst_ip': '152.16.40.20',
429                             'local_mac': '00:00:00:00:00:02',
430                             'vld_id': 'downlink_0',
431                             'ifname': 'xe1',
432                         },
433                         'vnfd-connection-point-ref': 'xe1',
434                         'name': 'xe1'
435                     },
436                 ],
437             },
438         ],
439         'description': 'Vpe approximation using DPDK',
440         'mgmt-interface': {
441             'vdu-id': 'vpevnf-baremetal',
442             'host': '1.1.1.1',
443             'password': 'r00t',
444             'user': 'root',
445             'ip': '1.1.1.1'
446         },
447         'benchmark': {
448             'kpi': [
449                 'packets_in',
450                 'packets_fwd',
451                 'packets_dropped',
452             ],
453         },
454         'connection-point': [
455             {
456                 'type': 'VPORT',
457                 'name': 'xe0',
458             },
459             {
460                 'type': 'VPORT',
461                 'name': 'xe1',
462             },
463         ],
464         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
465     }
466
467     VNFD = {
468         'vnfd:vnfd-catalog': {
469             'vnfd': [
470                 VNFD_0,
471             ]
472         }
473     }
474
475     def test__update_packet_type(self):
476         ip_pipeline_cfg = 'pkt_type = ipv4'
477         pkt_type = {'pkt_type': '1'}
478
479         expected = "pkt_type = 1"
480         result = DpdkVnfSetupEnvHelper._update_packet_type(ip_pipeline_cfg, pkt_type)
481         self.assertEqual(result, expected)
482
483     def test__update_packet_type_no_op(self):
484         ip_pipeline_cfg = 'pkt_type = ipv6'
485         pkt_type = {'pkt_type': '1'}
486
487         expected = "pkt_type = ipv6"
488         result = DpdkVnfSetupEnvHelper._update_packet_type(ip_pipeline_cfg, pkt_type)
489         self.assertEqual(result, expected)
490
491     def test__update_packet_type_multi_op(self):
492         ip_pipeline_cfg = 'pkt_type = ipv4\npkt_type = 1\npkt_type = ipv4'
493         pkt_type = {'pkt_type': '1'}
494
495         expected = 'pkt_type = 1\npkt_type = 1\npkt_type = 1'
496         result = DpdkVnfSetupEnvHelper._update_packet_type(ip_pipeline_cfg, pkt_type)
497         self.assertEqual(result, expected)
498
499     def test__update_traffic_type(self):
500         ip_pipeline_cfg = 'pkt_type = ipv4'
501
502         traffic_options = {"vnf_type": DpdkVnfSetupEnvHelper.APP_NAME, 'traffic_type': 4}
503         expected = "pkt_type = ipv4"
504         result = DpdkVnfSetupEnvHelper._update_traffic_type(ip_pipeline_cfg, traffic_options)
505         self.assertEqual(result, expected)
506
507     def test__update_traffic_type_ipv6(self):
508         ip_pipeline_cfg = 'pkt_type = ipv4'
509
510         traffic_options = {"vnf_type": DpdkVnfSetupEnvHelper.APP_NAME, 'traffic_type': 6}
511         expected = "pkt_type = ipv6"
512         result = DpdkVnfSetupEnvHelper._update_traffic_type(ip_pipeline_cfg, traffic_options)
513         self.assertEqual(result, expected)
514
515     def test__update_traffic_type_not_app_name(self):
516         ip_pipeline_cfg = 'traffic_type = 4'
517
518         vnf_type = ''.join(["Not", DpdkVnfSetupEnvHelper.APP_NAME])
519         traffic_options = {"vnf_type": vnf_type, 'traffic_type': 8}
520         expected = "traffic_type = 8"
521         result = DpdkVnfSetupEnvHelper._update_traffic_type(ip_pipeline_cfg, traffic_options)
522         self.assertEqual(result, expected)
523
524     @mock.patch.object(six, 'BytesIO', return_value=six.BytesIO(b'100\n'))
525     @mock.patch.object(utils, 'read_meminfo',
526                        return_value={'Hugepagesize': '2048'})
527     def test__setup_hugepages_no_hugepages_defined(self, mock_meminfo, *args):
528         ssh_helper = mock.Mock()
529         scenario_helper = mock.Mock()
530         scenario_helper.all_options = {}
531         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
532             mock.ANY, ssh_helper, scenario_helper)
533         with mock.patch.object(sample_vnf.LOG, 'info') as mock_info:
534             dpdk_setup_helper._setup_hugepages()
535             mock_info.assert_called_once_with(
536                 'Hugepages size (kB): %s, number claimed: %s, number set: '
537                 '%s', 2048, 8192, 100)
538         mock_meminfo.assert_called_once_with(ssh_helper)
539
540     @mock.patch.object(six, 'BytesIO', return_value=six.BytesIO(b'100\n'))
541     @mock.patch.object(utils, 'read_meminfo',
542                        return_value={'Hugepagesize': '1048576'})
543     def test__setup_hugepages_8gb_hugepages_defined(self, mock_meminfo, *args):
544         ssh_helper = mock.Mock()
545         scenario_helper = mock.Mock()
546         scenario_helper.all_options = {'hugepages_gb': 8}
547         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
548             mock.ANY, ssh_helper, scenario_helper)
549         with mock.patch.object(sample_vnf.LOG, 'info') as mock_info:
550             dpdk_setup_helper._setup_hugepages()
551             mock_info.assert_called_once_with(
552                 'Hugepages size (kB): %s, number claimed: %s, number set: '
553                 '%s', 1048576, 8, 100)
554         mock_meminfo.assert_called_once_with(ssh_helper)
555
556     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
557     @mock.patch.object(utils, 'find_relative_file')
558     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
559     @mock.patch.object(utils, 'open_relative_file')
560     def test_build_config(self, mock_open_rf, mock_multi_port_config_class, mock_find, *args):
561         mock_multi_port_config = mock_multi_port_config_class()
562         vnfd_helper = VnfdHelper(self.VNFD_0)
563         ssh_helper = mock.Mock()
564         scenario_helper = mock.Mock()
565         scenario_helper.vnf_cfg = {}
566         scenario_helper.options = {}
567         scenario_helper.all_options = {}
568         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
569
570         dpdk_setup_helper.PIPELINE_COMMAND = expected = 'pipeline command'
571         result = dpdk_setup_helper.build_config()
572         self.assertEqual(result, expected)
573         self.assertGreaterEqual(ssh_helper.upload_config_file.call_count, 2)
574         mock_find.assert_called()
575         mock_multi_port_config.generate_config.assert_called()
576         mock_multi_port_config.generate_script.assert_called()
577
578         scenario_helper.options = {'rules': 'fake_file'}
579         scenario_helper.vnf_cfg = {'file': 'fake_file'}
580         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
581         mock_open_rf.side_effect = mock.mock_open(read_data='fake_data')
582         dpdk_setup_helper.PIPELINE_COMMAND = expected = 'pipeline command'
583
584         result = dpdk_setup_helper.build_config()
585
586         mock_open_rf.assert_called()
587         self.assertEqual(result, expected)
588         self.assertGreaterEqual(ssh_helper.upload_config_file.call_count, 2)
589         mock_find.assert_called()
590         mock_multi_port_config.generate_config.assert_called()
591         mock_multi_port_config.generate_script.assert_called()
592
593     def test__build_pipeline_kwargs(self):
594         vnfd_helper = VnfdHelper(self.VNFD_0)
595         ssh_helper = mock.Mock()
596         ssh_helper.provision_tool.return_value = 'tool_path'
597         scenario_helper = mock.Mock()
598         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
599         dpdk_setup_helper.CFG_CONFIG = 'config'
600         dpdk_setup_helper.CFG_SCRIPT = 'script'
601         dpdk_setup_helper.pipeline_kwargs = {}
602         dpdk_setup_helper.all_ports = [0, 1, 2]
603         dpdk_setup_helper.scenario_helper.vnf_cfg = {'lb_config': 'HW',
604                                                      'worker_threads': 1}
605
606         expected = {
607             'cfg_file': 'config',
608             'script': 'script',
609             'port_mask_hex': '0x3',
610             'tool_path': 'tool_path',
611             'hwlb': ' --hwlb 1',
612         }
613         dpdk_setup_helper._build_pipeline_kwargs()
614         self.assertDictEqual(dpdk_setup_helper.pipeline_kwargs, expected)
615
616     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
617     @mock.patch('yardstick.ssh.SSH')
618     def test_setup_vnf_environment(self, *args):
619         def execute(cmd):
620             if cmd.startswith('which '):
621                 return exec_failure
622             return exec_success
623
624         exec_success = (0, 'good output', '')
625         exec_failure = (1, 'bad output', 'error output')
626
627         vnfd_helper = VnfdHelper(self.VNFD_0)
628         ssh_helper = mock.Mock()
629         ssh_helper.execute = execute
630
631         scenario_helper = mock.Mock()
632         scenario_helper.nodes = [None, None]
633         dpdk_vnf_setup_env_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
634         dpdk_vnf_setup_env_helper._validate_cpu_cfg = mock.Mock(return_value=[])
635
636         with mock.patch.object(dpdk_vnf_setup_env_helper, '_setup_dpdk'):
637             self.assertIsInstance(
638                 dpdk_vnf_setup_env_helper.setup_vnf_environment(),
639                 ResourceProfile)
640
641     def test__setup_dpdk(self):
642         ssh_helper = mock.Mock()
643         ssh_helper.execute = mock.Mock()
644         ssh_helper.execute.return_value = (0, 0, 0)
645         dpdk_setup_helper = DpdkVnfSetupEnvHelper(mock.ANY, ssh_helper, mock.ANY)
646         with mock.patch.object(dpdk_setup_helper, '_setup_hugepages') as \
647                 mock_setup_hp:
648             dpdk_setup_helper._setup_dpdk()
649         mock_setup_hp.assert_called_once()
650         ssh_helper.execute.assert_has_calls([
651             mock.call('sudo modprobe uio && sudo modprobe igb_uio'),
652             mock.call('lsmod | grep -i igb_uio')
653         ])
654
655     @mock.patch('yardstick.ssh.SSH')
656     def test__setup_resources(self, _):
657         vnfd_helper = VnfdHelper(deepcopy(self.VNFD_0))
658         ssh_helper = mock.Mock()
659         scenario_helper = mock.Mock()
660         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
661         dpdk_setup_helper._validate_cpu_cfg = mock.Mock()
662
663         dpdk_setup_helper.bound_pci = [v['virtual-interface']["vpci"] for v in
664                                        vnfd_helper.interfaces]
665         result = dpdk_setup_helper._setup_resources()
666         self.assertIsInstance(result, ResourceProfile)
667         self.assertEqual(dpdk_setup_helper.socket, 0)
668
669     @mock.patch('yardstick.ssh.SSH')
670     def test__setup_resources_socket_1(self, _):
671         vnfd_helper = VnfdHelper(deepcopy(self.VNFD_0))
672         vnfd_helper.interfaces[0]['virtual-interface']['vpci'] = '0000:55:00.0'
673         vnfd_helper.interfaces[1]['virtual-interface']['vpci'] = '0000:35:00.0'
674         ssh_helper = mock.Mock()
675         scenario_helper = mock.Mock()
676         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
677         dpdk_setup_helper._validate_cpu_cfg = mock.Mock()
678
679         dpdk_setup_helper.bound_pci = [v['virtual-interface']["vpci"] for v in
680                                        vnfd_helper.interfaces]
681         result = dpdk_setup_helper._setup_resources()
682         self.assertIsInstance(result, ResourceProfile)
683         self.assertEqual(dpdk_setup_helper.socket, 1)
684
685     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
686     def test__detect_and_bind_drivers(self, *args):
687         vnfd_helper = VnfdHelper(deepcopy(self.VNFD_0))
688         ssh_helper = mock.Mock()
689         # ssh_helper.execute = mock.Mock(return_value = (0, 'text', ''))
690         # ssh_helper.execute.return_value = 0, 'output', ''
691         scenario_helper = mock.Mock()
692         scenario_helper.nodes = [None, None]
693         rv = ['0000:05:00.1', '0000:05:00.0']
694
695         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
696         dpdk_setup_helper.dpdk_bind_helper._get_bound_pci_addresses = mock.Mock(return_value=rv)
697         dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
698         dpdk_setup_helper.dpdk_bind_helper.read_status = mock.Mock()
699
700         self.assertIsNone(dpdk_setup_helper._detect_and_bind_drivers())
701
702         intf_0 = vnfd_helper.vdu[0]['external-interface'][0]['virtual-interface']
703         intf_1 = vnfd_helper.vdu[0]['external-interface'][1]['virtual-interface']
704         self.assertEqual(0, intf_0['dpdk_port_num'])
705         self.assertEqual(1, intf_1['dpdk_port_num'])
706
707     def test_tear_down(self):
708         vnfd_helper = VnfdHelper(self.VNFD_0)
709         ssh_helper = mock.Mock()
710         scenario_helper = mock.Mock()
711         scenario_helper.nodes = [None, None]
712         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
713         dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
714         dpdk_setup_helper.dpdk_bind_helper.used_drivers = {
715             'd1': ['0000:05:00.0'],
716             'd3': ['0000:05:01.0'],
717         }
718
719         self.assertIsNone(dpdk_setup_helper.tear_down())
720         dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call(['0000:05:00.0'], 'd1', True)
721         dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call(['0000:05:01.0'], 'd3', True)
722
723
724 class TestResourceHelper(unittest.TestCase):
725
726     VNFD_0 = {
727         'short-name': 'VpeVnf',
728         'vdu': [
729             {
730                 'routing_table': [
731                     {
732                         'network': '152.16.100.20',
733                         'netmask': '255.255.255.0',
734                         'gateway': '152.16.100.20',
735                         'if': 'xe0'
736                     },
737                     {
738                         'network': '152.16.40.20',
739                         'netmask': '255.255.255.0',
740                         'gateway': '152.16.40.20',
741                         'if': 'xe1'
742                     },
743                 ],
744                 'description': 'VPE approximation using DPDK',
745                 'name': 'vpevnf-baremetal',
746                 'nd_route_tbl': [
747                     {
748                         'network': '0064:ff9b:0:0:0:0:9810:6414',
749                         'netmask': '112',
750                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
751                         'if': 'xe0'
752                     },
753                     {
754                         'network': '0064:ff9b:0:0:0:0:9810:2814',
755                         'netmask': '112',
756                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
757                         'if': 'xe1'
758                     },
759                 ],
760                 'id': 'vpevnf-baremetal',
761                 'external-interface': [
762                     {
763                         'virtual-interface': {
764                             'dst_mac': '00:00:00:00:00:03',
765                             'vpci': '0000:05:00.0',
766                             'driver': 'i40e',
767                             'local_ip': '152.16.100.19',
768                             'type': 'PCI-PASSTHROUGH',
769                             'netmask': '255.255.255.0',
770                             'dpdk_port_num': 0,
771                             'bandwidth': '10 Gbps',
772                             'dst_ip': '152.16.100.20',
773                             'local_mac': '00:00:00:00:00:01'
774                         },
775                         'vnfd-connection-point-ref': 'xe0',
776                         'name': 'xe0'
777                     },
778                     {
779                         'virtual-interface': {
780                             'dst_mac': '00:00:00:00:00:04',
781                             'vpci': '0000:05:00.1',
782                             'driver': 'ixgbe',
783                             'local_ip': '152.16.40.19',
784                             'type': 'PCI-PASSTHROUGH',
785                             'netmask': '255.255.255.0',
786                             'dpdk_port_num': 1,
787                             'bandwidth': '10 Gbps',
788                             'dst_ip': '152.16.40.20',
789                             'local_mac': '00:00:00:00:00:02'
790                         },
791                         'vnfd-connection-point-ref': 'xe1',
792                         'name': 'xe1'
793                     },
794                 ],
795             },
796         ],
797         'description': 'Vpe approximation using DPDK',
798         'mgmt-interface': {
799             'vdu-id': 'vpevnf-baremetal',
800             'host': '1.1.1.1',
801             'password': 'r00t',
802             'user': 'root',
803             'ip': '1.1.1.1'
804         },
805         'benchmark': {
806             'kpi': [
807                 'packets_in',
808                 'packets_fwd',
809                 'packets_dropped',
810             ],
811         },
812         'connection-point': [
813             {
814                 'type': 'VPORT',
815                 'name': 'xe0',
816             },
817             {
818                 'type': 'VPORT',
819                 'name': 'xe1',
820             },
821         ],
822         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
823     }
824
825     def test_setup(self):
826         resource = object()
827         vnfd_helper = VnfdHelper(self.VNFD_0)
828         ssh_helper = mock.Mock()
829         scenario_helper = mock.Mock()
830         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
831         dpdk_setup_helper.setup_vnf_environment = mock.Mock(return_value=resource)
832         resource_helper = ResourceHelper(dpdk_setup_helper)
833
834         self.assertIsNone(resource_helper.setup())
835         self.assertIs(resource_helper.resource, resource)
836
837     def test_generate_cfg(self):
838         vnfd_helper = VnfdHelper(self.VNFD_0)
839         ssh_helper = mock.Mock()
840         scenario_helper = mock.Mock()
841         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
842         resource_helper = ResourceHelper(dpdk_setup_helper)
843
844         self.assertIsNone(resource_helper.generate_cfg())
845
846     def test_stop_collect(self):
847         vnfd_helper = VnfdHelper(self.VNFD_0)
848         ssh_helper = mock.Mock()
849         scenario_helper = mock.Mock()
850         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
851         resource_helper = ResourceHelper(dpdk_setup_helper)
852         resource_helper.resource = mock.Mock()
853
854         self.assertIsNone(resource_helper.stop_collect())
855
856     def test_stop_collect_none(self):
857         vnfd_helper = VnfdHelper(self.VNFD_0)
858         ssh_helper = mock.Mock()
859         scenario_helper = mock.Mock()
860         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
861         resource_helper = ResourceHelper(dpdk_setup_helper)
862         resource_helper.resource = None
863
864         self.assertIsNone(resource_helper.stop_collect())
865
866
867 class TestClientResourceHelper(unittest.TestCase):
868
869     VNFD_0 = {
870         'short-name': 'VpeVnf',
871         'vdu': [
872             {
873                 'routing_table': [
874                     {
875                         'network': '152.16.100.20',
876                         'netmask': '255.255.255.0',
877                         'gateway': '152.16.100.20',
878                         'if': 'xe0'
879                     },
880                     {
881                         'network': '152.16.40.20',
882                         'netmask': '255.255.255.0',
883                         'gateway': '152.16.40.20',
884                         'if': 'xe1'
885                     },
886                 ],
887                 'description': 'VPE approximation using DPDK',
888                 'name': 'vpevnf-baremetal',
889                 'nd_route_tbl': [
890                     {
891                         'network': '0064:ff9b:0:0:0:0:9810:6414',
892                         'netmask': '112',
893                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
894                         'if': 'xe0'
895                     },
896                     {
897                         'network': '0064:ff9b:0:0:0:0:9810:2814',
898                         'netmask': '112',
899                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
900                         'if': 'xe1'
901                     },
902                 ],
903                 'id': 'vpevnf-baremetal',
904                 'external-interface': [
905                     {
906                         'virtual-interface': {
907                             'dst_mac': '00:00:00:00:00:03',
908                             'vpci': '0000:05:00.0',
909                             'driver': 'i40e',
910                             'local_ip': '152.16.100.19',
911                             'type': 'PCI-PASSTHROUGH',
912                             'netmask': '255.255.255.0',
913                             'dpdk_port_num': 0,
914                             'bandwidth': '10 Gbps',
915                             'dst_ip': '152.16.100.20',
916                             'local_mac': '00:00:00:00:00:01',
917                             'vld_id': 'uplink_0',
918                             'ifname': 'xe0',
919                         },
920                         'vnfd-connection-point-ref': 'xe0',
921                         'name': 'xe0'
922                     },
923                     {
924                         'virtual-interface': {
925                             'dst_mac': '00:00:00:00:00:04',
926                             'vpci': '0000:05:00.1',
927                             'driver': 'ixgbe',
928                             'local_ip': '152.16.40.19',
929                             'type': 'PCI-PASSTHROUGH',
930                             'netmask': '255.255.255.0',
931                             'dpdk_port_num': 1,
932                             'bandwidth': '10 Gbps',
933                             'dst_ip': '152.16.40.20',
934                             'local_mac': '00:00:00:00:00:02',
935                             'vld_id': 'downlink_0',
936                             'ifname': 'xe1',
937                         },
938                         'vnfd-connection-point-ref': 'xe1',
939                         'name': 'xe1'
940                     },
941                     {
942                         'virtual-interface': {
943                             'dst_mac': '00:00:00:00:00:13',
944                             'vpci': '0000:05:00.2',
945                             'driver': 'ixgbe',
946                             'local_ip': '152.16.40.19',
947                             'type': 'PCI-PASSTHROUGH',
948                             'netmask': '255.255.255.0',
949                             'dpdk_port_num': 2,
950                             'bandwidth': '10 Gbps',
951                             'dst_ip': '152.16.40.30',
952                             'local_mac': '00:00:00:00:00:11'
953                         },
954                         'vnfd-connection-point-ref': 'xe2',
955                         'name': 'xe2'
956                     },
957                 ],
958             },
959         ],
960         'description': 'Vpe approximation using DPDK',
961         'mgmt-interface': {
962             'vdu-id': 'vpevnf-baremetal',
963             'host': '1.1.1.1',
964             'password': 'r00t',
965             'user': 'root',
966             'ip': '1.1.1.1'
967         },
968         'benchmark': {
969             'kpi': [
970                 'packets_in',
971                 'packets_fwd',
972                 'packets_dropped',
973             ],
974         },
975         'connection-point': [
976             {
977                 'type': 'VPORT',
978                 'name': 'xe0',
979             },
980             {
981                 'type': 'VPORT',
982                 'name': 'xe1',
983             },
984         ],
985         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
986     }
987
988     VNFD = {
989         'vnfd:vnfd-catalog': {
990             'vnfd': [
991                 VNFD_0,
992             ],
993         },
994     }
995
996     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
997     @mock.patch.object(sample_vnf, 'STLError', new_callable=lambda: MockError)
998     def test_get_stats_not_connected(self, mock_stl_error, *args):
999         vnfd_helper = VnfdHelper(self.VNFD_0)
1000         ssh_helper = mock.Mock()
1001         scenario_helper = mock.Mock()
1002         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
1003             vnfd_helper, ssh_helper, scenario_helper)
1004         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1005         client_resource_helper.client = mock.Mock()
1006         client_resource_helper.client.get_stats.side_effect = mock_stl_error
1007
1008         self.assertEqual(client_resource_helper.get_stats(), {})
1009         client_resource_helper.client.get_stats.assert_called_once()
1010
1011     def test_clear_stats(self):
1012         vnfd_helper = VnfdHelper(self.VNFD_0)
1013         ssh_helper = mock.Mock()
1014         scenario_helper = mock.Mock()
1015         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
1016             vnfd_helper, ssh_helper, scenario_helper)
1017         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1018         client_resource_helper.client = mock.Mock()
1019
1020         self.assertIsNone(client_resource_helper.clear_stats())
1021         self.assertEqual(
1022             client_resource_helper.client.clear_stats.call_count, 1)
1023
1024     def test_clear_stats_of_ports(self):
1025         vnfd_helper = VnfdHelper(self.VNFD_0)
1026         ssh_helper = mock.Mock()
1027         scenario_helper = mock.Mock()
1028         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
1029             vnfd_helper, ssh_helper, scenario_helper)
1030         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1031         client_resource_helper.client = mock.Mock()
1032
1033         self.assertIsNone(client_resource_helper.clear_stats([3, 4]))
1034         self.assertEqual(
1035             client_resource_helper.client.clear_stats.call_count, 1)
1036
1037     def test_start(self):
1038         vnfd_helper = VnfdHelper(self.VNFD_0)
1039         ssh_helper = mock.Mock()
1040         scenario_helper = mock.Mock()
1041         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
1042             vnfd_helper, ssh_helper, scenario_helper)
1043         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1044         client_resource_helper.client = mock.Mock()
1045
1046         self.assertIsNone(client_resource_helper.start())
1047         client_resource_helper.client.start.assert_called_once()
1048
1049     def test_start_ports(self):
1050         vnfd_helper = VnfdHelper(self.VNFD_0)
1051         ssh_helper = mock.Mock()
1052         scenario_helper = mock.Mock()
1053         dpdk_setup_helper = DpdkVnfSetupEnvHelper(
1054             vnfd_helper, ssh_helper, scenario_helper)
1055         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1056         client_resource_helper.client = mock.Mock()
1057
1058         self.assertIsNone(client_resource_helper.start([3, 4]))
1059         client_resource_helper.client.start.assert_called_once()
1060
1061     def test_collect_kpi_with_queue(self):
1062         vnfd_helper = VnfdHelper(self.VNFD_0)
1063         ssh_helper = mock.Mock()
1064         scenario_helper = mock.Mock()
1065         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
1066         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1067         client_resource_helper._result = {'existing': 43, 'replaceable': 12}
1068         client_resource_helper._queue = mock.Mock()
1069         client_resource_helper._queue.empty.return_value = False
1070         client_resource_helper._queue.get.return_value = {'incoming': 34, 'replaceable': 99}
1071
1072         expected = {
1073             'existing': 43,
1074             'incoming': 34,
1075             'replaceable': 99,
1076         }
1077         result = client_resource_helper.collect_kpi()
1078         self.assertDictEqual(result, expected)
1079
1080     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
1081     @mock.patch.object(sample_vnf, 'STLError')
1082     def test__connect_with_failures(self, mock_stl_error, *args):
1083         vnfd_helper = VnfdHelper(self.VNFD_0)
1084         ssh_helper = mock.Mock()
1085         scenario_helper = mock.Mock()
1086         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
1087         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
1088         client = mock.MagicMock()
1089         client.connect.side_effect = mock_stl_error(msg='msg')
1090
1091         self.assertIs(client_resource_helper._connect(client), client)
1092
1093
1094 class TestRfc2544ResourceHelper(unittest.TestCase):
1095
1096     RFC2544_CFG_1 = {
1097         'latency': True,
1098         'correlated_traffic': True,
1099         'allowed_drop_rate': '0.1 - 0.15',
1100     }
1101
1102     RFC2544_CFG_2 = {
1103         'allowed_drop_rate': '  0.25    -   0.05  ',
1104     }
1105
1106     RFC2544_CFG_3 = {
1107         'allowed_drop_rate': '0.2',
1108     }
1109
1110     RFC2544_CFG_4 = {
1111         'latency': True,
1112     }
1113
1114     SCENARIO_CFG_1 = {
1115         'options': {
1116             'rfc2544': RFC2544_CFG_1,
1117         }
1118     }
1119
1120     SCENARIO_CFG_2 = {
1121         'options': {
1122             'rfc2544': RFC2544_CFG_2,
1123         }
1124     }
1125
1126     SCENARIO_CFG_3 = {
1127         'options': {
1128             'rfc2544': RFC2544_CFG_3,
1129         }
1130     }
1131
1132     SCENARIO_CFG_4 = {
1133         'options': {
1134             'rfc2544': RFC2544_CFG_4,
1135         }
1136     }
1137
1138     def test_property_rfc2544(self):
1139         scenario_helper = ScenarioHelper('name1')
1140         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1141         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1142
1143         self.assertIsNone(rfc2544_resource_helper._rfc2544)
1144         self.assertDictEqual(rfc2544_resource_helper.rfc2544, self.RFC2544_CFG_1)
1145         self.assertDictEqual(rfc2544_resource_helper._rfc2544, self.RFC2544_CFG_1)
1146         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1147         self.assertDictEqual(rfc2544_resource_helper.rfc2544, self.RFC2544_CFG_1)
1148
1149     def test_property_tolerance_high(self):
1150         scenario_helper = ScenarioHelper('name1')
1151         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1152         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1153
1154         self.assertIsNone(rfc2544_resource_helper._tolerance_high)
1155         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.15)
1156         self.assertEqual(rfc2544_resource_helper._tolerance_high, 0.15)
1157         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1158         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.15)
1159
1160     def test_property_tolerance_low(self):
1161         scenario_helper = ScenarioHelper('name1')
1162         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1163         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1164
1165         self.assertIsNone(rfc2544_resource_helper._tolerance_low)
1166         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.1)
1167         self.assertEqual(rfc2544_resource_helper._tolerance_low, 0.1)
1168         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1169         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.1)
1170
1171     def test_property_tolerance_high_range_swap(self):
1172         scenario_helper = ScenarioHelper('name1')
1173         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1174         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1175
1176         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.25)
1177
1178     def test_property_tolerance_low_range_swap(self):
1179         scenario_helper = ScenarioHelper('name1')
1180         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1181         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1182
1183         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.05)
1184
1185     def test_property_tolerance_high_not_range(self):
1186         scenario_helper = ScenarioHelper('name1')
1187         scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
1188         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1189
1190         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.2)
1191
1192     def test_property_tolerance_low_not_range(self):
1193         scenario_helper = ScenarioHelper('name1')
1194         scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
1195         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1196
1197         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.2)
1198
1199     def test_property_tolerance_high_default(self):
1200         scenario_helper = ScenarioHelper('name1')
1201         scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
1202         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1203
1204         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.0001)
1205
1206     def test_property_tolerance_low_default(self):
1207         scenario_helper = ScenarioHelper('name1')
1208         scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
1209         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1210
1211         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.0001)
1212
1213     def test_property_latency(self):
1214         scenario_helper = ScenarioHelper('name1')
1215         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1216         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1217
1218         self.assertIsNone(rfc2544_resource_helper._latency)
1219         self.assertTrue(rfc2544_resource_helper.latency)
1220         self.assertTrue(rfc2544_resource_helper._latency)
1221         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1222         self.assertTrue(rfc2544_resource_helper.latency)
1223
1224     def test_property_latency_default(self):
1225         scenario_helper = ScenarioHelper('name1')
1226         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1227         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1228
1229         self.assertFalse(rfc2544_resource_helper.latency)
1230
1231     def test_property_correlated_traffic(self):
1232         scenario_helper = ScenarioHelper('name1')
1233         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1234         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1235
1236         self.assertIsNone(rfc2544_resource_helper._correlated_traffic)
1237         self.assertTrue(rfc2544_resource_helper.correlated_traffic)
1238         self.assertTrue(rfc2544_resource_helper._correlated_traffic)
1239         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1240         self.assertTrue(rfc2544_resource_helper.correlated_traffic)
1241
1242     def test_property_correlated_traffic_default(self):
1243         scenario_helper = ScenarioHelper('name1')
1244         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1245         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1246
1247         self.assertFalse(rfc2544_resource_helper.correlated_traffic)
1248
1249
1250 class TestSampleVNFDeployHelper(unittest.TestCase):
1251
1252     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
1253     @mock.patch('subprocess.check_output')
1254     def test_deploy_vnfs_disabled(self, *_):
1255         vnfd_helper = mock.Mock()
1256         ssh_helper = mock.Mock()
1257         ssh_helper.join_bin_path.return_value = 'joined_path'
1258         ssh_helper.execute.return_value = 1, 'bad output', 'error output'
1259         ssh_helper.put.return_value = None
1260         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1261
1262         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1263         sample_vnf_deploy_helper.DISABLE_DEPLOY = True
1264         self.assertEqual(ssh_helper.execute.call_count, 5)
1265         ssh_helper.put.assert_called_once()
1266
1267     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
1268     @mock.patch('subprocess.check_output')
1269     def test_deploy_vnfs(self, *args):
1270         vnfd_helper = mock.Mock()
1271         ssh_helper = mock.Mock()
1272         ssh_helper.join_bin_path.return_value = 'joined_path'
1273         ssh_helper.execute.return_value = 1, 'bad output', 'error output'
1274         ssh_helper.put.return_value = None
1275         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1276         sample_vnf_deploy_helper.DISABLE_DEPLOY = False
1277
1278         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1279         self.assertEqual(ssh_helper.execute.call_count, 5)
1280         ssh_helper.put.assert_called_once()
1281
1282     @mock.patch('subprocess.check_output')
1283     def test_deploy_vnfs_early_success(self, *args):
1284         vnfd_helper = mock.Mock()
1285         ssh_helper = mock.Mock()
1286         ssh_helper.join_bin_path.return_value = 'joined_path'
1287         ssh_helper.execute.return_value = 0, 'output', ''
1288         ssh_helper.put.return_value = None
1289         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1290         sample_vnf_deploy_helper.DISABLE_DEPLOY = False
1291
1292         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1293         ssh_helper.execute.assert_called_once()
1294         ssh_helper.put.assert_not_called()
1295
1296
1297 class TestScenarioHelper(unittest.TestCase):
1298
1299     def test_property_task_path(self):
1300         scenario_helper = ScenarioHelper('name1')
1301         scenario_helper.scenario_cfg = {
1302             'task_path': 'my_path',
1303         }
1304
1305         self.assertEqual(scenario_helper.task_path, 'my_path')
1306
1307     def test_property_nodes(self):
1308         nodes = ['node1', 'node2']
1309         scenario_helper = ScenarioHelper('name1')
1310         scenario_helper.scenario_cfg = {
1311             'nodes': nodes,
1312         }
1313
1314         self.assertEqual(scenario_helper.nodes, nodes)
1315
1316     def test_property_all_options(self):
1317         data = {
1318             'name1': {
1319                 'key3': 'value3',
1320             },
1321             'name2': {}
1322         }
1323         scenario_helper = ScenarioHelper('name1')
1324         scenario_helper.scenario_cfg = {
1325             'options': data,
1326         }
1327
1328         self.assertDictEqual(scenario_helper.all_options, data)
1329
1330     def test_property_options(self):
1331         data = {
1332             'key1': 'value1',
1333             'key2': 'value2',
1334         }
1335         scenario_helper = ScenarioHelper('name1')
1336         scenario_helper.scenario_cfg = {
1337             'options': {
1338                 'name1': data,
1339             },
1340         }
1341
1342         self.assertDictEqual(scenario_helper.options, data)
1343
1344     def test_property_vnf_cfg(self):
1345         scenario_helper = ScenarioHelper('name1')
1346         scenario_helper.scenario_cfg = {
1347             'options': {
1348                 'name1': {
1349                     'vnf_config': 'my_config',
1350                 },
1351             },
1352         }
1353
1354         self.assertEqual(scenario_helper.vnf_cfg, 'my_config')
1355
1356     def test_property_vnf_cfg_default(self):
1357         scenario_helper = ScenarioHelper('name1')
1358         scenario_helper.scenario_cfg = {
1359             'options': {
1360                 'name1': {},
1361             },
1362         }
1363
1364         self.assertDictEqual(scenario_helper.vnf_cfg, ScenarioHelper.DEFAULT_VNF_CFG)
1365
1366     def test_property_topology(self):
1367         scenario_helper = ScenarioHelper('name1')
1368         scenario_helper.scenario_cfg = {
1369             'topology': 'my_topology',
1370         }
1371
1372         self.assertEqual(scenario_helper.topology, 'my_topology')
1373
1374
1375 class TestSampleVnf(unittest.TestCase):
1376
1377     VNFD_0 = {
1378         'short-name': 'VpeVnf',
1379         'vdu': [
1380             {
1381                 'routing_table': [
1382                     {
1383                         'network': '152.16.100.20',
1384                         'netmask': '255.255.255.0',
1385                         'gateway': '152.16.100.20',
1386                         'if': 'xe0'
1387                     },
1388                     {
1389                         'network': '152.16.40.20',
1390                         'netmask': '255.255.255.0',
1391                         'gateway': '152.16.40.20',
1392                         'if': 'xe1'
1393                     },
1394                 ],
1395                 'description': 'VPE approximation using DPDK',
1396                 'name': 'vpevnf-baremetal',
1397                 'nd_route_tbl': [
1398                     {
1399                         'network': '0064:ff9b:0:0:0:0:9810:6414',
1400                         'netmask': '112',
1401                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
1402                         'if': 'xe0'
1403                     },
1404                     {
1405                         'network': '0064:ff9b:0:0:0:0:9810:2814',
1406                         'netmask': '112',
1407                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
1408                         'if': 'xe1'
1409                     },
1410                 ],
1411                 'id': 'vpevnf-baremetal',
1412                 'external-interface': [
1413                     {
1414                         'virtual-interface': {
1415                             'dst_mac': '00:00:00:00:00:03',
1416                             'vpci': '0000:05:00.0',
1417                             'local_ip': '152.16.100.19',
1418                             'type': 'PCI-PASSTHROUGH',
1419                             'netmask': '255.255.255.0',
1420                             'dpdk_port_num': 0,
1421                             'bandwidth': '10 Gbps',
1422                             'dst_ip': '152.16.100.20',
1423                             'local_mac': '00:00:00:00:00:01'
1424                         },
1425                         'vnfd-connection-point-ref': 'xe0',
1426                         'name': 'xe0'
1427                     },
1428                     {
1429                         'virtual-interface': {
1430                             'dst_mac': '00:00:00:00:00:04',
1431                             'vpci': '0000:05:00.1',
1432                             'local_ip': '152.16.40.19',
1433                             'type': 'PCI-PASSTHROUGH',
1434                             'netmask': '255.255.255.0',
1435                             'dpdk_port_num': 1,
1436                             'bandwidth': '10 Gbps',
1437                             'dst_ip': '152.16.40.20',
1438                             'local_mac': '00:00:00:00:00:02'
1439                         },
1440                         'vnfd-connection-point-ref': 'xe1',
1441                         'name': 'xe1'
1442                     },
1443                 ],
1444             },
1445         ],
1446         'description': 'Vpe approximation using DPDK',
1447         'mgmt-interface': {
1448             'vdu-id': 'vpevnf-baremetal',
1449             'host': '1.1.1.1',
1450             'password': 'r00t',
1451             'user': 'root',
1452             'ip': '1.1.1.1'
1453         },
1454         'benchmark': {
1455             'kpi': [
1456                 'packets_in',
1457                 'packets_fwd',
1458                 'packets_dropped',
1459             ],
1460         },
1461         'connection-point': [
1462             {
1463                 'type': 'VPORT',
1464                 'name': 'xe0',
1465             },
1466             {
1467                 'type': 'VPORT',
1468                 'name': 'xe1',
1469             },
1470         ],
1471         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
1472     }
1473
1474     VNFD = {
1475         'vnfd:vnfd-catalog': {
1476             'vnfd': [
1477                 VNFD_0,
1478             ]
1479         }
1480     }
1481
1482     TRAFFIC_PROFILE = {
1483         "schema": "isb:traffic_profile:0.1",
1484         "name": "fixed",
1485         "description": "Fixed traffic profile to run UDP traffic",
1486         "traffic_profile": {
1487             "traffic_type": "FixedTraffic",
1488             "frame_rate": 100,  # pps
1489             "flow_number": 10,
1490             "frame_size": 64,
1491         },
1492     }
1493
1494     def test___init__(self):
1495         sample_vnf = SampleVNF('vnf1', self.VNFD_0)
1496
1497         self.assertEqual(sample_vnf.name, 'vnf1')
1498         self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0)
1499
1500         # test the default setup helper is SetupEnvHelper, not subclass
1501         self.assertEqual(type(sample_vnf.setup_helper), SetupEnvHelper)
1502
1503         # test the default resource helper is ResourceHelper, not subclass
1504         self.assertEqual(type(sample_vnf.resource_helper), ResourceHelper)
1505
1506     def test___init___alt_types(self):
1507         class MySetupEnvHelper(SetupEnvHelper):
1508             pass
1509
1510         class MyResourceHelper(ResourceHelper):
1511             pass
1512
1513         sample_vnf = SampleVNF('vnf1', self.VNFD_0, MySetupEnvHelper, MyResourceHelper)
1514
1515         self.assertEqual(sample_vnf.name, 'vnf1')
1516         self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0)
1517
1518         # test the default setup helper is MySetupEnvHelper, not subclass
1519         self.assertEqual(type(sample_vnf.setup_helper), MySetupEnvHelper)
1520
1521         # test the default resource helper is MyResourceHelper, not subclass
1522         self.assertEqual(type(sample_vnf.resource_helper), MyResourceHelper)
1523
1524     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.Process')
1525     def test__start_vnf(self, *args):
1526         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1527         sample_vnf = SampleVNF('vnf1', vnfd)
1528         sample_vnf._run = mock.Mock()
1529
1530         self.assertIsNone(sample_vnf.queue_wrapper)
1531         self.assertIsNone(sample_vnf._vnf_process)
1532         self.assertIsNone(sample_vnf._start_vnf())
1533         self.assertIsNotNone(sample_vnf.queue_wrapper)
1534         self.assertIsNotNone(sample_vnf._vnf_process)
1535
1536     @mock.patch("yardstick.ssh.SSH")
1537     def test_instantiate(self, ssh):
1538         test_base.mock_ssh(ssh)
1539
1540         nodes = {
1541             'vnf1': 'name1',
1542             'vnf2': 'name2',
1543         }
1544
1545         context1 = mock.Mock()
1546         context1._get_server.return_value = None
1547         context2 = mock.Mock()
1548         context2._get_server.return_value = context2
1549
1550         try:
1551             Context.list.clear()
1552         except AttributeError:
1553             # clear() but works in Py2.7
1554             Context.list[:] = []
1555
1556         Context.list.extend([
1557             context1,
1558             context2,
1559         ])
1560
1561         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1562         sample_vnf = SampleVNF('vnf1', vnfd)
1563         sample_vnf.APP_NAME = 'sample1'
1564         sample_vnf._start_server = mock.Mock(return_value=0)
1565         sample_vnf._vnf_process = mock.MagicMock()
1566         sample_vnf._vnf_process._is_alive.return_value = 1
1567         sample_vnf.ssh_helper = mock.MagicMock()
1568         sample_vnf.deploy_helper = mock.MagicMock()
1569         sample_vnf.resource_helper.ssh_helper = mock.MagicMock()
1570         scenario_cfg = {
1571             'nodes': nodes,
1572         }
1573
1574         self.assertIsNone(sample_vnf.instantiate(scenario_cfg, {}))
1575         self.assertEqual(sample_vnf.nfvi_context, context2)
1576
1577     def test__update_collectd_options(self):
1578         scenario_cfg = {'options':
1579                             {'collectd':
1580                                  {'interval': 3,
1581                                   'plugins':
1582                                       {'plugin3': {'param': 3}}},
1583                              'vnf__0':
1584                                  {'collectd':
1585                                       {'interval': 2,
1586                                        'plugins':
1587                                            {'plugin3': {'param': 2},
1588                                             'plugin2': {'param': 2}}}}}}
1589         context_cfg = {'nodes':
1590                            {'vnf__0':
1591                                 {'collectd':
1592                                      {'interval': 1,
1593                                       'plugins':
1594                                           {'plugin3': {'param': 1},
1595                                            'plugin2': {'param': 1},
1596                                            'plugin1': {'param': 1}}}}}}
1597         expected = {'interval': 1,
1598                     'plugins':
1599                         {'plugin3': {'param': 1},
1600                          'plugin2': {'param': 1},
1601                          'plugin1': {'param': 1}}}
1602
1603         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1604         sample_vnf = SampleVNF('vnf__0', vnfd)
1605         sample_vnf._update_collectd_options(scenario_cfg, context_cfg)
1606         self.assertEqual(sample_vnf.setup_helper.collectd_options, expected)
1607
1608     def test__update_options(self):
1609         options1 = {'interval': 1,
1610                     'param1': 'value1',
1611                     'plugins':
1612                         {'plugin3': {'param': 3},
1613                          'plugin2': {'param': 1},
1614                          'plugin1': {'param': 1}}}
1615         options2 = {'interval': 2,
1616                     'param2': 'value2',
1617                     'plugins':
1618                         {'plugin4': {'param': 4},
1619                          'plugin2': {'param': 2},
1620                          'plugin1': {'param': 2}}}
1621         expected = {'interval': 1,
1622                     'param1': 'value1',
1623                     'param2': 'value2',
1624                     'plugins':
1625                         {'plugin4': {'param': 4},
1626                          'plugin3': {'param': 3},
1627                          'plugin2': {'param': 1},
1628                          'plugin1': {'param': 1}}}
1629
1630         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1631         sample_vnf = SampleVNF('vnf1', vnfd)
1632         sample_vnf._update_options(options2, options1)
1633         self.assertEqual(options2, expected)
1634
1635     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
1636     @mock.patch("yardstick.ssh.SSH")
1637     def test_wait_for_instantiate_empty_queue(self, ssh, *args):
1638         test_base.mock_ssh(ssh, exec_result=(1, "", ""))
1639
1640         queue_size_list = [
1641             0,
1642             1,
1643             0,
1644             1,
1645         ]
1646
1647         queue_get_list = [
1648             'some output',
1649             'pipeline> ',
1650         ]
1651
1652         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1653         sample_vnf = SampleVNF('vnf1', vnfd)
1654         sample_vnf.APP_NAME = 'sample1'
1655         sample_vnf.WAIT_TIME_FOR_SCRIPT = 0
1656         sample_vnf._start_server = mock.Mock(return_value=0)
1657         sample_vnf._vnf_process = mock.MagicMock()
1658         sample_vnf._vnf_process.exitcode = 0
1659         sample_vnf._vnf_process._is_alive.return_value = 1
1660         sample_vnf.queue_wrapper = mock.Mock()
1661         sample_vnf.q_out = mock.Mock()
1662         sample_vnf.q_out.qsize.side_effect = iter(queue_size_list)
1663         sample_vnf.q_out.get.side_effect = iter(queue_get_list)
1664         sample_vnf.ssh_helper = mock.MagicMock()
1665         sample_vnf.resource_helper.ssh_helper = mock.MagicMock()
1666         sample_vnf.resource_helper.start_collect = mock.MagicMock()
1667
1668         self.assertEqual(sample_vnf.wait_for_instantiate(), 0)
1669
1670     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
1671     def test_vnf_execute_with_queue_data(self, *args):
1672         queue_size_list = [
1673             1,
1674             1,
1675             0,
1676         ]
1677
1678         queue_get_list = [
1679             'hello ',
1680             'world'
1681         ]
1682
1683         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1684         sample_vnf = SampleVNF('vnf1', vnfd)
1685         sample_vnf.APP_NAME = 'sample1'
1686         sample_vnf.q_out = mock.Mock()
1687         sample_vnf.q_out.qsize.side_effect = iter(queue_size_list)
1688         sample_vnf.q_out.get.side_effect = iter(queue_get_list)
1689
1690         self.assertEqual(sample_vnf.vnf_execute('my command'), 'hello world')
1691
1692     def test_terminate_without_vnf_process(self):
1693         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1694         sample_vnf = SampleVNF('vnf1', vnfd)
1695         sample_vnf.APP_NAME = 'sample1'
1696         sample_vnf.vnf_execute = mock.Mock()
1697         sample_vnf.ssh_helper = mock.Mock()
1698         sample_vnf._tear_down = mock.Mock()
1699         sample_vnf.resource_helper = mock.Mock()
1700
1701         self.assertIsNone(sample_vnf.terminate())
1702
1703     def test_get_stats(self):
1704         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1705         sample_vnf = SampleVNF('vnf1', vnfd)
1706         sample_vnf.APP_NAME = 'sample1'
1707         sample_vnf.APP_WORD = 'sample1'
1708         sample_vnf.vnf_execute = mock.Mock(return_value='the stats')
1709
1710         self.assertEqual(sample_vnf.get_stats(), 'the stats')
1711
1712     def test_collect_kpi(self):
1713         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1714         sample_vnf = SampleVNF('vnf1', vnfd)
1715         sample_vnf.APP_NAME = 'sample1'
1716         sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
1717         sample_vnf.COLLECT_MAP = {
1718             'k1': 3,
1719             'k2': 1,
1720             'k3': 2,
1721         }
1722         sample_vnf.get_stats = mock.Mock(return_value='index0: 34 -- 91, 27')
1723         sample_vnf.resource_helper = mock.Mock()
1724         sample_vnf.resource_helper.collect_kpi.return_value = {}
1725
1726         expected = {
1727             'k1': 27,
1728             'k2': 34,
1729             'k3': 91,
1730             'collect_stats': {},
1731         }
1732         result = sample_vnf.collect_kpi()
1733         self.assertDictEqual(result, expected)
1734
1735     def test_collect_kpi_default(self):
1736         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1737         sample_vnf = SampleVNF('vnf1', vnfd)
1738         sample_vnf.APP_NAME = 'sample1'
1739         sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
1740         sample_vnf.get_stats = mock.Mock(return_value='')
1741
1742         expected = {
1743             'packets_in': 0,
1744             'packets_fwd': 0,
1745             'packets_dropped': 0,
1746         }
1747         result = sample_vnf.collect_kpi()
1748         self.assertDictEqual(result, expected)
1749
1750     def test_scale(self):
1751         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1752         sample_vnf = SampleVNF('vnf1', vnfd)
1753         self.assertRaises(y_exceptions.FunctionNotImplemented,
1754                           sample_vnf.scale)
1755
1756     def test__run(self):
1757         test_cmd = 'test cmd'
1758         run_kwargs = {'arg1': 'val1', 'arg2': 'val2'}
1759         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1760         sample_vnf = SampleVNF('vnf1', vnfd)
1761         sample_vnf.ssh_helper = mock.Mock()
1762         sample_vnf.setup_helper = mock.Mock()
1763         with mock.patch.object(sample_vnf, '_build_config',
1764                                return_value=test_cmd), \
1765                 mock.patch.object(sample_vnf, '_build_run_kwargs'):
1766             sample_vnf.run_kwargs = run_kwargs
1767             sample_vnf._run()
1768         sample_vnf.ssh_helper.drop_connection.assert_called_once()
1769         sample_vnf.ssh_helper.run.assert_called_once_with(test_cmd,
1770                                                           **run_kwargs)
1771         sample_vnf.setup_helper.kill_vnf.assert_called_once()
1772
1773
1774 class TestSampleVNFTrafficGen(unittest.TestCase):
1775
1776     VNFD_0 = {
1777         'short-name': 'VpeVnf',
1778         'vdu': [
1779             {
1780                 'routing_table': [
1781                     {
1782                         'network': '152.16.100.20',
1783                         'netmask': '255.255.255.0',
1784                         'gateway': '152.16.100.20',
1785                         'if': 'xe0'
1786                     },
1787                     {
1788                         'network': '152.16.40.20',
1789                         'netmask': '255.255.255.0',
1790                         'gateway': '152.16.40.20',
1791                         'if': 'xe1'
1792                     },
1793                 ],
1794                 'description': 'VPE approximation using DPDK',
1795                 'name': 'vpevnf-baremetal',
1796                 'nd_route_tbl': [
1797                     {
1798                         'network': '0064:ff9b:0:0:0:0:9810:6414',
1799                         'netmask': '112',
1800                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
1801                         'if': 'xe0'
1802                     },
1803                     {
1804                         'network': '0064:ff9b:0:0:0:0:9810:2814',
1805                         'netmask': '112',
1806                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
1807                         'if': 'xe1'
1808                     },
1809                 ],
1810                 'id': 'vpevnf-baremetal',
1811                 'external-interface': [
1812                     {
1813                         'virtual-interface': {
1814                             'dst_mac': '00:00:00:00:00:03',
1815                             'vpci': '0000:05:00.0',
1816                             'driver': 'i40e',
1817                             'local_ip': '152.16.100.19',
1818                             'type': 'PCI-PASSTHROUGH',
1819                             'netmask': '255.255.255.0',
1820                             'dpdk_port_num': 0,
1821                             'bandwidth': '10 Gbps',
1822                             'dst_ip': '152.16.100.20',
1823                             'local_mac': '00:00:00:00:00:01'
1824                         },
1825                         'vnfd-connection-point-ref': 'xe0',
1826                         'name': 'xe0'
1827                     },
1828                     {
1829                         'virtual-interface': {
1830                             'dst_mac': '00:00:00:00:00:04',
1831                             'vpci': '0000:05:00.1',
1832                             'driver': 'ixgbe',
1833                             'local_ip': '152.16.40.19',
1834                             'type': 'PCI-PASSTHROUGH',
1835                             'netmask': '255.255.255.0',
1836                             'dpdk_port_num': 1,
1837                             'bandwidth': '10 Gbps',
1838                             'dst_ip': '152.16.40.20',
1839                             'local_mac': '00:00:00:00:00:02'
1840                         },
1841                         'vnfd-connection-point-ref': 'xe1',
1842                         'name': 'xe1'
1843                     },
1844                 ],
1845             },
1846         ],
1847         'description': 'Vpe approximation using DPDK',
1848         'mgmt-interface': {
1849             'vdu-id': 'vpevnf-baremetal',
1850             'host': '1.1.1.1',
1851             'password': 'r00t',
1852             'user': 'root',
1853             'ip': '1.1.1.1'
1854         },
1855         'benchmark': {
1856             'kpi': [
1857                 'packets_in',
1858                 'packets_fwd',
1859                 'packets_dropped',
1860             ],
1861         },
1862         'connection-point': [
1863             {
1864                 'type': 'VPORT',
1865                 'name': 'xe0',
1866             },
1867             {
1868                 'type': 'VPORT',
1869                 'name': 'xe1',
1870             },
1871         ],
1872         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
1873     }
1874
1875     VNFD = {
1876         'vnfd:vnfd-catalog': {
1877             'vnfd': [
1878                 VNFD_0,
1879             ],
1880         },
1881     }
1882
1883     TRAFFIC_PROFILE = {
1884         "schema": "isb:traffic_profile:0.1",
1885         "name": "fixed",
1886         "description": "Fixed traffic profile to run UDP traffic",
1887         "traffic_profile": {
1888             "traffic_type": "FixedTraffic",
1889             "frame_rate": 100,  # pps
1890             "flow_number": 10,
1891             "frame_size": 64,
1892         },
1893     }
1894
1895     def test__check_status(self):
1896         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1897
1898         with self.assertRaises(NotImplementedError):
1899             sample_vnf_tg._check_status()
1900
1901     def test_listen_traffic(self):
1902         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1903
1904         sample_vnf_tg.listen_traffic(mock.Mock())
1905
1906     def test_verify_traffic(self):
1907         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1908
1909         sample_vnf_tg.verify_traffic(mock.Mock())
1910
1911     def test_terminate(self):
1912         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1913         sample_vnf_tg._traffic_process = mock.Mock()
1914         sample_vnf_tg._tg_process = mock.Mock()
1915
1916         sample_vnf_tg.terminate()
1917
1918     def test__wait_for_process(self):
1919         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1920         with mock.patch.object(sample_vnf_tg, '_check_status',
1921                                return_value=0) as mock_status, \
1922                 mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
1923             mock_proc.is_alive.return_value = True
1924             mock_proc.exitcode = 234
1925             self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
1926             mock_proc.is_alive.assert_called_once()
1927             mock_status.assert_called_once()
1928
1929     def test__wait_for_process_not_alive(self):
1930         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1931         with mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
1932             mock_proc.is_alive.return_value = False
1933             self.assertRaises(RuntimeError, sample_vnf_tg._wait_for_process)
1934             mock_proc.is_alive.assert_called_once()
1935
1936     def test__wait_for_process_delayed(self):
1937         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1938         with mock.patch.object(sample_vnf_tg, '_check_status',
1939                                side_effect=[1, 0]) as mock_status, \
1940                 mock.patch.object(sample_vnf_tg,
1941                                   '_tg_process') as mock_proc:
1942             mock_proc.is_alive.return_value = True
1943             mock_proc.exitcode = 234
1944             self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
1945             mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()])
1946             mock_status.assert_has_calls([mock.call(), mock.call()])
1947
1948     def test_scale(self):
1949         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
1950         self.assertRaises(y_exceptions.FunctionNotImplemented,
1951                           sample_vnf_tg.scale)