Add RFC2544 iteration status field
[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.common import exceptions as y_exceptions
22 from yardstick.common import utils
23 from yardstick.network_services.nfvi.resource import ResourceProfile
24 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
25 from yardstick.network_services.vnf_generic.vnf import sample_vnf
26 from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
27 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
28 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
29 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
30 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
31 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
32 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
33 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
34 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
35 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
36 from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
37 from yardstick.benchmark.contexts import base as ctx_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     @mock.patch.object(ClientResourceHelper, '_build_ports')
1094     @mock.patch.object(ClientResourceHelper, '_run_traffic_once',
1095                        return_value=(True, mock.ANY))
1096     def test_run_traffic(self, mock_run_traffic_once, mock_build_ports):
1097         client_resource_helper = ClientResourceHelper(mock.Mock())
1098         client = mock.Mock()
1099         traffic_profile = mock.Mock()
1100         mq_producer = mock.Mock()
1101         with mock.patch.object(client_resource_helper, '_connect') \
1102                 as mock_connect, \
1103                 mock.patch.object(client_resource_helper, '_terminated') \
1104                 as mock_terminated:
1105             mock_connect.return_value = client
1106             type(mock_terminated).value = mock.PropertyMock(
1107                 side_effect=[0, 1, 1, lambda x: x])
1108             client_resource_helper.run_traffic(traffic_profile, mq_producer)
1109
1110         mock_build_ports.assert_called_once()
1111         traffic_profile.register_generator.assert_called_once()
1112         mq_producer.tg_method_started.assert_called_once()
1113         mq_producer.tg_method_finished.assert_called_once()
1114         mq_producer.tg_method_iteration.assert_called_once_with(1)
1115         mock_run_traffic_once.assert_called_once_with(traffic_profile)
1116
1117     @mock.patch.object(ClientResourceHelper, '_build_ports')
1118     @mock.patch.object(ClientResourceHelper, '_run_traffic_once',
1119                        side_effect=Exception)
1120     def test_run_traffic_exception(self, mock_run_traffic_once,
1121                                    mock_build_ports):
1122         client_resource_helper = ClientResourceHelper(mock.Mock())
1123         client = mock.Mock()
1124         traffic_profile = mock.Mock()
1125         mq_producer = mock.Mock()
1126         with mock.patch.object(client_resource_helper, '_connect') \
1127                 as mock_connect, \
1128                 mock.patch.object(client_resource_helper, '_terminated') \
1129                 as mock_terminated:
1130             mock_connect.return_value = client
1131             type(mock_terminated).value = mock.PropertyMock(return_value=0)
1132             mq_producer.reset_mock()
1133             # NOTE(ralonsoh): "trex_stl_exceptions.STLError" is mocked
1134             with self.assertRaises(Exception):
1135                 client_resource_helper.run_traffic(traffic_profile,
1136                                                    mq_producer)
1137
1138         mock_build_ports.assert_called_once()
1139         traffic_profile.register_generator.assert_called_once()
1140         mock_run_traffic_once.assert_called_once_with(traffic_profile)
1141         mq_producer.tg_method_started.assert_called_once()
1142         mq_producer.tg_method_finished.assert_not_called()
1143         mq_producer.tg_method_iteration.assert_not_called()
1144
1145
1146 class TestRfc2544ResourceHelper(unittest.TestCase):
1147
1148     RFC2544_CFG_1 = {
1149         'latency': True,
1150         'correlated_traffic': True,
1151         'allowed_drop_rate': '0.1 - 0.15',
1152     }
1153
1154     RFC2544_CFG_2 = {
1155         'allowed_drop_rate': '  0.25    -   0.05  ',
1156     }
1157
1158     RFC2544_CFG_3 = {
1159         'allowed_drop_rate': '0.2',
1160     }
1161
1162     RFC2544_CFG_4 = {
1163         'latency': True,
1164     }
1165
1166     SCENARIO_CFG_1 = {
1167         'options': {
1168             'rfc2544': RFC2544_CFG_1,
1169         }
1170     }
1171
1172     SCENARIO_CFG_2 = {
1173         'options': {
1174             'rfc2544': RFC2544_CFG_2,
1175         }
1176     }
1177
1178     SCENARIO_CFG_3 = {
1179         'options': {
1180             'rfc2544': RFC2544_CFG_3,
1181         }
1182     }
1183
1184     SCENARIO_CFG_4 = {
1185         'options': {
1186             'rfc2544': RFC2544_CFG_4,
1187         }
1188     }
1189
1190     def test_property_rfc2544(self):
1191         scenario_helper = ScenarioHelper('name1')
1192         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1193         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1194
1195         self.assertIsNone(rfc2544_resource_helper._rfc2544)
1196         self.assertDictEqual(rfc2544_resource_helper.rfc2544, self.RFC2544_CFG_1)
1197         self.assertDictEqual(rfc2544_resource_helper._rfc2544, self.RFC2544_CFG_1)
1198         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1199         self.assertDictEqual(rfc2544_resource_helper.rfc2544, self.RFC2544_CFG_1)
1200
1201     def test_property_tolerance_high(self):
1202         scenario_helper = ScenarioHelper('name1')
1203         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1204         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1205
1206         self.assertIsNone(rfc2544_resource_helper._tolerance_high)
1207         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.15)
1208         self.assertEqual(rfc2544_resource_helper._tolerance_high, 0.15)
1209         self.assertEqual(rfc2544_resource_helper._tolerance_precision, 2)
1210         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1211         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.15)
1212
1213     def test_property_tolerance_low(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._tolerance_low)
1219         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.1)
1220         self.assertEqual(rfc2544_resource_helper._tolerance_low, 0.1)
1221         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1222         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.1)
1223
1224     def test_property_tolerance_high_range_swap(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.assertEqual(rfc2544_resource_helper.tolerance_high, 0.25)
1230
1231     def test_property_tolerance_low_range_swap(self):
1232         scenario_helper = ScenarioHelper('name1')
1233         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1234         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1235
1236         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.05)
1237
1238     def test_property_tolerance_high_not_range(self):
1239         scenario_helper = ScenarioHelper('name1')
1240         scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
1241         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1242
1243         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.2)
1244         self.assertEqual(rfc2544_resource_helper._tolerance_precision, 1)
1245
1246     def test_property_tolerance_low_not_range(self):
1247         scenario_helper = ScenarioHelper('name1')
1248         scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
1249         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1250
1251         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.2)
1252
1253     def test_property_tolerance_high_default(self):
1254         scenario_helper = ScenarioHelper('name1')
1255         scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
1256         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1257
1258         self.assertEqual(rfc2544_resource_helper.tolerance_high, 0.0001)
1259
1260     def test_property_tolerance_low_default(self):
1261         scenario_helper = ScenarioHelper('name1')
1262         scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
1263         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1264
1265         self.assertEqual(rfc2544_resource_helper.tolerance_low, 0.0001)
1266
1267     def test_property_latency(self):
1268         scenario_helper = ScenarioHelper('name1')
1269         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1270         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1271
1272         self.assertIsNone(rfc2544_resource_helper._latency)
1273         self.assertTrue(rfc2544_resource_helper.latency)
1274         self.assertTrue(rfc2544_resource_helper._latency)
1275         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1276         self.assertTrue(rfc2544_resource_helper.latency)
1277
1278     def test_property_latency_default(self):
1279         scenario_helper = ScenarioHelper('name1')
1280         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1281         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1282
1283         self.assertFalse(rfc2544_resource_helper.latency)
1284
1285     def test_property_correlated_traffic(self):
1286         scenario_helper = ScenarioHelper('name1')
1287         scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
1288         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1289
1290         self.assertIsNone(rfc2544_resource_helper._correlated_traffic)
1291         self.assertTrue(rfc2544_resource_helper.correlated_traffic)
1292         self.assertTrue(rfc2544_resource_helper._correlated_traffic)
1293         scenario_helper.scenario_cfg = {}  # ensure that resource_helper caches
1294         self.assertTrue(rfc2544_resource_helper.correlated_traffic)
1295
1296     def test_property_correlated_traffic_default(self):
1297         scenario_helper = ScenarioHelper('name1')
1298         scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
1299         rfc2544_resource_helper = Rfc2544ResourceHelper(scenario_helper)
1300
1301         self.assertFalse(rfc2544_resource_helper.correlated_traffic)
1302
1303
1304 class TestSampleVNFDeployHelper(unittest.TestCase):
1305
1306     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
1307     @mock.patch('subprocess.check_output')
1308     def test_deploy_vnfs_disabled(self, *_):
1309         vnfd_helper = mock.Mock()
1310         ssh_helper = mock.Mock()
1311         ssh_helper.join_bin_path.return_value = 'joined_path'
1312         ssh_helper.execute.return_value = 1, 'bad output', 'error output'
1313         ssh_helper.put.return_value = None
1314         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1315
1316         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1317         sample_vnf_deploy_helper.DISABLE_DEPLOY = True
1318         self.assertEqual(ssh_helper.execute.call_count, 5)
1319         ssh_helper.put.assert_called_once()
1320
1321     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
1322     @mock.patch('subprocess.check_output')
1323     def test_deploy_vnfs(self, *args):
1324         vnfd_helper = mock.Mock()
1325         ssh_helper = mock.Mock()
1326         ssh_helper.join_bin_path.return_value = 'joined_path'
1327         ssh_helper.execute.return_value = 1, 'bad output', 'error output'
1328         ssh_helper.put.return_value = None
1329         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1330         sample_vnf_deploy_helper.DISABLE_DEPLOY = False
1331
1332         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1333         self.assertEqual(ssh_helper.execute.call_count, 5)
1334         ssh_helper.put.assert_called_once()
1335
1336     @mock.patch('subprocess.check_output')
1337     def test_deploy_vnfs_early_success(self, *args):
1338         vnfd_helper = mock.Mock()
1339         ssh_helper = mock.Mock()
1340         ssh_helper.join_bin_path.return_value = 'joined_path'
1341         ssh_helper.execute.return_value = 0, 'output', ''
1342         ssh_helper.put.return_value = None
1343         sample_vnf_deploy_helper = SampleVNFDeployHelper(vnfd_helper, ssh_helper)
1344         sample_vnf_deploy_helper.DISABLE_DEPLOY = False
1345
1346         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
1347         ssh_helper.execute.assert_called_once()
1348         ssh_helper.put.assert_not_called()
1349
1350
1351 class TestScenarioHelper(unittest.TestCase):
1352
1353     def test_property_task_path(self):
1354         scenario_helper = ScenarioHelper('name1')
1355         scenario_helper.scenario_cfg = {
1356             'task_path': 'my_path',
1357         }
1358
1359         self.assertEqual(scenario_helper.task_path, 'my_path')
1360
1361     def test_property_nodes(self):
1362         nodes = ['node1', 'node2']
1363         scenario_helper = ScenarioHelper('name1')
1364         scenario_helper.scenario_cfg = {
1365             'nodes': nodes,
1366         }
1367
1368         self.assertEqual(scenario_helper.nodes, nodes)
1369
1370     def test_property_all_options(self):
1371         data = {
1372             'name1': {
1373                 'key3': 'value3',
1374             },
1375             'name2': {}
1376         }
1377         scenario_helper = ScenarioHelper('name1')
1378         scenario_helper.scenario_cfg = {
1379             'options': data,
1380         }
1381
1382         self.assertDictEqual(scenario_helper.all_options, data)
1383
1384     def test_property_options(self):
1385         data = {
1386             'key1': 'value1',
1387             'key2': 'value2',
1388         }
1389         scenario_helper = ScenarioHelper('name1')
1390         scenario_helper.scenario_cfg = {
1391             'options': {
1392                 'name1': data,
1393             },
1394         }
1395
1396         self.assertDictEqual(scenario_helper.options, data)
1397
1398     def test_property_vnf_cfg(self):
1399         scenario_helper = ScenarioHelper('name1')
1400         scenario_helper.scenario_cfg = {
1401             'options': {
1402                 'name1': {
1403                     'vnf_config': 'my_config',
1404                 },
1405             },
1406         }
1407
1408         self.assertEqual(scenario_helper.vnf_cfg, 'my_config')
1409
1410     def test_property_vnf_cfg_default(self):
1411         scenario_helper = ScenarioHelper('name1')
1412         scenario_helper.scenario_cfg = {
1413             'options': {
1414                 'name1': {},
1415             },
1416         }
1417
1418         self.assertDictEqual(scenario_helper.vnf_cfg, ScenarioHelper.DEFAULT_VNF_CFG)
1419
1420     def test_property_topology(self):
1421         scenario_helper = ScenarioHelper('name1')
1422         scenario_helper.scenario_cfg = {
1423             'topology': 'my_topology',
1424         }
1425
1426         self.assertEqual(scenario_helper.topology, 'my_topology')
1427
1428
1429 class TestSampleVnf(unittest.TestCase):
1430
1431     VNFD_0 = {
1432         'short-name': 'VpeVnf',
1433         'vdu': [
1434             {
1435                 'routing_table': [
1436                     {
1437                         'network': '152.16.100.20',
1438                         'netmask': '255.255.255.0',
1439                         'gateway': '152.16.100.20',
1440                         'if': 'xe0'
1441                     },
1442                     {
1443                         'network': '152.16.40.20',
1444                         'netmask': '255.255.255.0',
1445                         'gateway': '152.16.40.20',
1446                         'if': 'xe1'
1447                     },
1448                 ],
1449                 'description': 'VPE approximation using DPDK',
1450                 'name': 'vpevnf-baremetal',
1451                 'nd_route_tbl': [
1452                     {
1453                         'network': '0064:ff9b:0:0:0:0:9810:6414',
1454                         'netmask': '112',
1455                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
1456                         'if': 'xe0'
1457                     },
1458                     {
1459                         'network': '0064:ff9b:0:0:0:0:9810:2814',
1460                         'netmask': '112',
1461                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
1462                         'if': 'xe1'
1463                     },
1464                 ],
1465                 'id': 'vpevnf-baremetal',
1466                 'external-interface': [
1467                     {
1468                         'virtual-interface': {
1469                             'dst_mac': '00:00:00:00:00:03',
1470                             'vpci': '0000:05:00.0',
1471                             'local_ip': '152.16.100.19',
1472                             'type': 'PCI-PASSTHROUGH',
1473                             'netmask': '255.255.255.0',
1474                             'dpdk_port_num': 0,
1475                             'bandwidth': '10 Gbps',
1476                             'dst_ip': '152.16.100.20',
1477                             'local_mac': '00:00:00:00:00:01'
1478                         },
1479                         'vnfd-connection-point-ref': 'xe0',
1480                         'name': 'xe0'
1481                     },
1482                     {
1483                         'virtual-interface': {
1484                             'dst_mac': '00:00:00:00:00:04',
1485                             'vpci': '0000:05:00.1',
1486                             'local_ip': '152.16.40.19',
1487                             'type': 'PCI-PASSTHROUGH',
1488                             'netmask': '255.255.255.0',
1489                             'dpdk_port_num': 1,
1490                             'bandwidth': '10 Gbps',
1491                             'dst_ip': '152.16.40.20',
1492                             'local_mac': '00:00:00:00:00:02'
1493                         },
1494                         'vnfd-connection-point-ref': 'xe1',
1495                         'name': 'xe1'
1496                     },
1497                 ],
1498             },
1499         ],
1500         'description': 'Vpe approximation using DPDK',
1501         'mgmt-interface': {
1502             'vdu-id': 'vpevnf-baremetal',
1503             'host': '1.1.1.1',
1504             'password': 'r00t',
1505             'user': 'root',
1506             'ip': '1.1.1.1'
1507         },
1508         'benchmark': {
1509             'kpi': [
1510                 'packets_in',
1511                 'packets_fwd',
1512                 'packets_dropped',
1513             ],
1514         },
1515         'connection-point': [
1516             {
1517                 'type': 'VPORT',
1518                 'name': 'xe0',
1519             },
1520             {
1521                 'type': 'VPORT',
1522                 'name': 'xe1',
1523             },
1524         ],
1525         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
1526     }
1527
1528     VNFD = {
1529         'vnfd:vnfd-catalog': {
1530             'vnfd': [
1531                 VNFD_0,
1532             ]
1533         }
1534     }
1535
1536     TRAFFIC_PROFILE = {
1537         "schema": "isb:traffic_profile:0.1",
1538         "name": "fixed",
1539         "description": "Fixed traffic profile to run UDP traffic",
1540         "traffic_profile": {
1541             "traffic_type": "FixedTraffic",
1542             "frame_rate": 100,  # pps
1543             "flow_number": 10,
1544             "frame_size": 64,
1545         },
1546     }
1547
1548     def test___init__(self):
1549         sample_vnf = SampleVNF('vnf1', self.VNFD_0, 'task_id')
1550
1551         self.assertEqual(sample_vnf.name, 'vnf1')
1552         self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0)
1553
1554         # test the default setup helper is SetupEnvHelper, not subclass
1555         self.assertEqual(type(sample_vnf.setup_helper), SetupEnvHelper)
1556
1557         # test the default resource helper is ResourceHelper, not subclass
1558         self.assertEqual(type(sample_vnf.resource_helper), ResourceHelper)
1559
1560     def test___init___alt_types(self):
1561         class MySetupEnvHelper(SetupEnvHelper):
1562             pass
1563
1564         class MyResourceHelper(ResourceHelper):
1565             pass
1566
1567         sample_vnf = SampleVNF('vnf1', self.VNFD_0, 'task_id',
1568                                MySetupEnvHelper, MyResourceHelper)
1569
1570         self.assertEqual(sample_vnf.name, 'vnf1')
1571         self.assertDictEqual(sample_vnf.vnfd_helper, self.VNFD_0)
1572
1573         # test the default setup helper is MySetupEnvHelper, not subclass
1574         self.assertEqual(type(sample_vnf.setup_helper), MySetupEnvHelper)
1575
1576         # test the default resource helper is MyResourceHelper, not subclass
1577         self.assertEqual(type(sample_vnf.resource_helper), MyResourceHelper)
1578
1579     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.Process')
1580     def test__start_vnf(self, *args):
1581         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1582         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1583         sample_vnf._run = mock.Mock()
1584
1585         self.assertIsNone(sample_vnf.queue_wrapper)
1586         self.assertIsNone(sample_vnf._vnf_process)
1587         self.assertIsNone(sample_vnf._start_vnf())
1588         self.assertIsNotNone(sample_vnf.queue_wrapper)
1589         self.assertIsNotNone(sample_vnf._vnf_process)
1590
1591     @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
1592     @mock.patch("yardstick.ssh.SSH")
1593     def test_instantiate(self, ssh, *args):
1594         test_base.mock_ssh(ssh)
1595         nodes = {
1596             'vnf1': 'name1',
1597             'vnf2': 'name2',
1598         }
1599
1600         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1601         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1602         sample_vnf.scenario_helper.scenario_cfg = {
1603             'nodes': {sample_vnf.name: 'mock'}
1604         }
1605         sample_vnf.APP_NAME = 'sample1'
1606         sample_vnf._start_server = mock.Mock(return_value=0)
1607         sample_vnf._vnf_process = mock.MagicMock()
1608         sample_vnf._vnf_process._is_alive.return_value = 1
1609         sample_vnf.ssh_helper = mock.MagicMock()
1610         sample_vnf.deploy_helper = mock.MagicMock()
1611         sample_vnf.resource_helper.ssh_helper = mock.MagicMock()
1612         scenario_cfg = {
1613             'nodes': nodes,
1614         }
1615
1616         self.assertIsNone(sample_vnf.instantiate(scenario_cfg, {}))
1617
1618     def test__update_collectd_options(self):
1619         scenario_cfg = {'options':
1620                             {'collectd':
1621                                  {'interval': 3,
1622                                   'plugins':
1623                                       {'plugin3': {'param': 3}}},
1624                              'vnf__0':
1625                                  {'collectd':
1626                                       {'interval': 2,
1627                                        'plugins':
1628                                            {'plugin3': {'param': 2},
1629                                             'plugin2': {'param': 2}}}}}}
1630         context_cfg = {'nodes':
1631                            {'vnf__0':
1632                                 {'collectd':
1633                                      {'interval': 1,
1634                                       'plugins':
1635                                           {'plugin3': {'param': 1},
1636                                            'plugin2': {'param': 1},
1637                                            'plugin1': {'param': 1}}}}}}
1638         expected = {'interval': 1,
1639                     'plugins':
1640                         {'plugin3': {'param': 1},
1641                          'plugin2': {'param': 1},
1642                          'plugin1': {'param': 1}}}
1643
1644         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1645         sample_vnf = SampleVNF('vnf__0', vnfd, 'task_id')
1646         sample_vnf._update_collectd_options(scenario_cfg, context_cfg)
1647         self.assertEqual(sample_vnf.setup_helper.collectd_options, expected)
1648
1649     def test__update_options(self):
1650         options1 = {'interval': 1,
1651                     'param1': 'value1',
1652                     'plugins':
1653                         {'plugin3': {'param': 3},
1654                          'plugin2': {'param': 1},
1655                          'plugin1': {'param': 1}}}
1656         options2 = {'interval': 2,
1657                     'param2': 'value2',
1658                     'plugins':
1659                         {'plugin4': {'param': 4},
1660                          'plugin2': {'param': 2},
1661                          'plugin1': {'param': 2}}}
1662         expected = {'interval': 1,
1663                     'param1': 'value1',
1664                     'param2': 'value2',
1665                     'plugins':
1666                         {'plugin4': {'param': 4},
1667                          'plugin3': {'param': 3},
1668                          'plugin2': {'param': 1},
1669                          'plugin1': {'param': 1}}}
1670
1671         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1672         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1673         sample_vnf._update_options(options2, options1)
1674         self.assertEqual(options2, expected)
1675
1676     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
1677     @mock.patch("yardstick.ssh.SSH")
1678     def test_wait_for_instantiate_empty_queue(self, ssh, *args):
1679         test_base.mock_ssh(ssh, exec_result=(1, "", ""))
1680
1681         queue_size_list = [
1682             0,
1683             1,
1684             0,
1685             1,
1686         ]
1687
1688         queue_get_list = [
1689             'some output',
1690             'pipeline> ',
1691         ]
1692
1693         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1694         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1695         sample_vnf.APP_NAME = 'sample1'
1696         sample_vnf.WAIT_TIME_FOR_SCRIPT = 0
1697         sample_vnf._start_server = mock.Mock(return_value=0)
1698         sample_vnf._vnf_process = mock.MagicMock()
1699         sample_vnf._vnf_process.exitcode = 0
1700         sample_vnf._vnf_process._is_alive.return_value = 1
1701         sample_vnf.queue_wrapper = mock.Mock()
1702         sample_vnf.q_out = mock.Mock()
1703         sample_vnf.q_out.qsize.side_effect = iter(queue_size_list)
1704         sample_vnf.q_out.get.side_effect = iter(queue_get_list)
1705         sample_vnf.ssh_helper = mock.MagicMock()
1706         sample_vnf.resource_helper.ssh_helper = mock.MagicMock()
1707         sample_vnf.resource_helper.start_collect = mock.MagicMock()
1708
1709         self.assertEqual(sample_vnf.wait_for_instantiate(), 0)
1710
1711     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
1712     def test_vnf_execute_with_queue_data(self, *args):
1713         queue_size_list = [
1714             1,
1715             1,
1716             0,
1717         ]
1718
1719         queue_get_list = [
1720             'hello ',
1721             'world'
1722         ]
1723
1724         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1725         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1726         sample_vnf.APP_NAME = 'sample1'
1727         sample_vnf.q_out = mock.Mock()
1728         sample_vnf.q_out.qsize.side_effect = iter(queue_size_list)
1729         sample_vnf.q_out.get.side_effect = iter(queue_get_list)
1730
1731         self.assertEqual(sample_vnf.vnf_execute('my command'), 'hello world')
1732
1733     def test_terminate_without_vnf_process(self):
1734         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1735         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1736         sample_vnf.APP_NAME = 'sample1'
1737         sample_vnf.vnf_execute = mock.Mock()
1738         sample_vnf.ssh_helper = mock.Mock()
1739         sample_vnf._tear_down = mock.Mock()
1740         sample_vnf.resource_helper = mock.Mock()
1741
1742         self.assertIsNone(sample_vnf.terminate())
1743
1744     def test_get_stats(self):
1745         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1746         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1747         sample_vnf.APP_NAME = 'sample1'
1748         sample_vnf.APP_WORD = 'sample1'
1749         sample_vnf.vnf_execute = mock.Mock(return_value='the stats')
1750
1751         self.assertEqual(sample_vnf.get_stats(), 'the stats')
1752
1753     @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
1754     def test_collect_kpi(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.COLLECT_MAP = {
1763             'k1': 3,
1764             'k2': 1,
1765             'k3': 2,
1766         }
1767         sample_vnf.get_stats = mock.Mock(return_value='index0: 34 -- 91, 27')
1768         sample_vnf.resource_helper = mock.Mock()
1769         sample_vnf.resource_helper.collect_kpi.return_value = {}
1770
1771         expected = {
1772             'k1': 27,
1773             'k2': 34,
1774             'k3': 91,
1775             'collect_stats': {},
1776             'physical_node': 'mock_node'
1777         }
1778         result = sample_vnf.collect_kpi()
1779         self.assertDictEqual(result, expected)
1780
1781     @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
1782     def test_collect_kpi_default(self, *args):
1783         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1784         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1785         sample_vnf.scenario_helper.scenario_cfg = {
1786             'nodes': {sample_vnf.name: "mock"}
1787         }
1788         sample_vnf.APP_NAME = 'sample1'
1789         sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
1790         sample_vnf.get_stats = mock.Mock(return_value='')
1791
1792         expected = {
1793             'physical_node': 'mock_node',
1794             'packets_in': 0,
1795             'packets_fwd': 0,
1796             'packets_dropped': 0,
1797         }
1798         result = sample_vnf.collect_kpi()
1799         self.assertDictEqual(result, expected)
1800
1801     def test_scale(self):
1802         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1803         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1804         self.assertRaises(y_exceptions.FunctionNotImplemented,
1805                           sample_vnf.scale)
1806
1807     def test__run(self):
1808         test_cmd = 'test cmd'
1809         run_kwargs = {'arg1': 'val1', 'arg2': 'val2'}
1810         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
1811         sample_vnf = SampleVNF('vnf1', vnfd, 'task_id')
1812         sample_vnf.ssh_helper = mock.Mock()
1813         sample_vnf.setup_helper = mock.Mock()
1814         with mock.patch.object(sample_vnf, '_build_config',
1815                                return_value=test_cmd), \
1816                 mock.patch.object(sample_vnf, '_build_run_kwargs'):
1817             sample_vnf.run_kwargs = run_kwargs
1818             sample_vnf._run()
1819         sample_vnf.ssh_helper.drop_connection.assert_called_once()
1820         sample_vnf.ssh_helper.run.assert_called_once_with(test_cmd,
1821                                                           **run_kwargs)
1822         sample_vnf.setup_helper.kill_vnf.assert_called_once()
1823
1824
1825 class TestSampleVNFTrafficGen(unittest.TestCase):
1826
1827     VNFD_0 = {
1828         'short-name': 'VpeVnf',
1829         'vdu': [
1830             {
1831                 'routing_table': [
1832                     {
1833                         'network': '152.16.100.20',
1834                         'netmask': '255.255.255.0',
1835                         'gateway': '152.16.100.20',
1836                         'if': 'xe0'
1837                     },
1838                     {
1839                         'network': '152.16.40.20',
1840                         'netmask': '255.255.255.0',
1841                         'gateway': '152.16.40.20',
1842                         'if': 'xe1'
1843                     },
1844                 ],
1845                 'description': 'VPE approximation using DPDK',
1846                 'name': 'vpevnf-baremetal',
1847                 'nd_route_tbl': [
1848                     {
1849                         'network': '0064:ff9b:0:0:0:0:9810:6414',
1850                         'netmask': '112',
1851                         'gateway': '0064:ff9b:0:0:0:0:9810:6414',
1852                         'if': 'xe0'
1853                     },
1854                     {
1855                         'network': '0064:ff9b:0:0:0:0:9810:2814',
1856                         'netmask': '112',
1857                         'gateway': '0064:ff9b:0:0:0:0:9810:2814',
1858                         'if': 'xe1'
1859                     },
1860                 ],
1861                 'id': 'vpevnf-baremetal',
1862                 'external-interface': [
1863                     {
1864                         'virtual-interface': {
1865                             'dst_mac': '00:00:00:00:00:03',
1866                             'vpci': '0000:05:00.0',
1867                             'driver': 'i40e',
1868                             'local_ip': '152.16.100.19',
1869                             'type': 'PCI-PASSTHROUGH',
1870                             'netmask': '255.255.255.0',
1871                             'dpdk_port_num': 0,
1872                             'bandwidth': '10 Gbps',
1873                             'dst_ip': '152.16.100.20',
1874                             'local_mac': '00:00:00:00:00:01'
1875                         },
1876                         'vnfd-connection-point-ref': 'xe0',
1877                         'name': 'xe0'
1878                     },
1879                     {
1880                         'virtual-interface': {
1881                             'dst_mac': '00:00:00:00:00:04',
1882                             'vpci': '0000:05:00.1',
1883                             'driver': 'ixgbe',
1884                             'local_ip': '152.16.40.19',
1885                             'type': 'PCI-PASSTHROUGH',
1886                             'netmask': '255.255.255.0',
1887                             'dpdk_port_num': 1,
1888                             'bandwidth': '10 Gbps',
1889                             'dst_ip': '152.16.40.20',
1890                             'local_mac': '00:00:00:00:00:02'
1891                         },
1892                         'vnfd-connection-point-ref': 'xe1',
1893                         'name': 'xe1'
1894                     },
1895                 ],
1896             },
1897         ],
1898         'description': 'Vpe approximation using DPDK',
1899         'mgmt-interface': {
1900             'vdu-id': 'vpevnf-baremetal',
1901             'host': '1.1.1.1',
1902             'password': 'r00t',
1903             'user': 'root',
1904             'ip': '1.1.1.1'
1905         },
1906         'benchmark': {
1907             'kpi': [
1908                 'packets_in',
1909                 'packets_fwd',
1910                 'packets_dropped',
1911             ],
1912         },
1913         'connection-point': [
1914             {
1915                 'type': 'VPORT',
1916                 'name': 'xe0',
1917             },
1918             {
1919                 'type': 'VPORT',
1920                 'name': 'xe1',
1921             },
1922         ],
1923         'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
1924     }
1925
1926     VNFD = {
1927         'vnfd:vnfd-catalog': {
1928             'vnfd': [
1929                 VNFD_0,
1930             ],
1931         },
1932     }
1933
1934     TRAFFIC_PROFILE = {
1935         "schema": "isb:traffic_profile:0.1",
1936         "name": "fixed",
1937         "description": "Fixed traffic profile to run UDP traffic",
1938         "traffic_profile": {
1939             "traffic_type": "FixedTraffic",
1940             "frame_rate": 100,  # pps
1941             "flow_number": 10,
1942             "frame_size": 64,
1943         },
1944     }
1945
1946     def test__check_status(self):
1947         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1948
1949         with self.assertRaises(NotImplementedError):
1950             sample_vnf_tg._check_status()
1951
1952     def test_listen_traffic(self):
1953         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1954
1955         sample_vnf_tg.listen_traffic(mock.Mock())
1956
1957     def test_verify_traffic(self):
1958         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1959
1960         sample_vnf_tg.verify_traffic(mock.Mock())
1961
1962     def test_terminate(self):
1963         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1964         sample_vnf_tg._traffic_process = mock.Mock()
1965         sample_vnf_tg._tg_process = mock.Mock()
1966
1967         sample_vnf_tg.terminate()
1968
1969     def test__wait_for_process(self):
1970         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1971         with mock.patch.object(sample_vnf_tg, '_check_status',
1972                                return_value=0) as mock_status, \
1973                 mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
1974             mock_proc.is_alive.return_value = True
1975             mock_proc.exitcode = 234
1976             self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
1977             mock_proc.is_alive.assert_called_once()
1978             mock_status.assert_called_once()
1979
1980     def test__wait_for_process_not_alive(self):
1981         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1982         with mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
1983             mock_proc.is_alive.return_value = False
1984             self.assertRaises(RuntimeError, sample_vnf_tg._wait_for_process)
1985             mock_proc.is_alive.assert_called_once()
1986
1987     def test__wait_for_process_delayed(self):
1988         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
1989         with mock.patch.object(sample_vnf_tg, '_check_status',
1990                                side_effect=[1, 0]) as mock_status, \
1991                 mock.patch.object(sample_vnf_tg,
1992                                   '_tg_process') as mock_proc:
1993             mock_proc.is_alive.return_value = True
1994             mock_proc.exitcode = 234
1995             self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
1996             mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()])
1997             mock_status.assert_has_calls([mock.call(), mock.call()])
1998
1999     def test_scale(self):
2000         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0, 'task_id')
2001         self.assertRaises(y_exceptions.FunctionNotImplemented,
2002                           sample_vnf_tg.scale)