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