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