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