3 # Copyright (c) 2016-2017 Intel Corporation
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 # Unittest for yardstick.benchmark.scenarios.networking.test_vnf_generic
20 from __future__ import absolute_import
25 from yardstick.benchmark.scenarios.networking.vnf_generic import \
26 ssh_manager, NetworkServiceTestCase, IncorrectConfig, IncorrectSetup
27 from yardstick.network_services.collector.subscriber import Collector
28 from yardstick.network_services.vnf_generic.vnf.base import \
29 GenericTrafficGen, GenericVNF
31 COMPLETE_TREX_VNFD = \
40 'tx_throughput_pc_linerate',
41 'rx_throughput_pc_linerate',
45 'connection-point': [{'name': 'xe0',
49 'description': 'TRex stateless traffic generator for RFC2544',
50 'id': 'TrexTrafficGen',
51 'mgmt-interface': {'ip': '1.1.1.1',
54 'vdu-id': 'trexgen-baremetal'},
56 'short-name': 'trexgen',
57 'vdu': [{'description': 'TRex stateless traffic generator for RFC2544',
60 'virtual-interface': {'bandwidth': '10 Gbps',
62 'dst_mac': '00:01:02:03:04:05',
63 'local_ip': '1.1.1.2',
64 'local_mac': '00:01:02:03:05:05',
65 'type': 'PCI-PASSTHROUGH',
66 'netmask': "255.255.255.0",
68 'vpci': '0000:00:10.2'},
69 'vnfd-connection-point-ref': 'xe0'},
71 'virtual-interface': {'bandwidth': '10 Gbps',
73 'dst_mac': '00:01:02:03:04:06',
74 'local_ip': '2.1.1.2',
75 'local_mac': '00:01:02:03:05:06',
76 'type': 'PCI-PASSTHROUGH',
77 'netmask': "255.255.255.0",
79 'vpci': '0000:00:10.1'},
80 'vnfd-connection-point-ref': 'xe1'}],
81 'id': 'trexgen-baremetal',
82 'name': 'trexgen-baremetal'}]}]}}
85 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP """
86 """group default qlen 1000
87 link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
88 inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
89 inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
90 valid_lft forever preferred_lft forever
91 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP """
92 """group default qlen 1000
93 link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
94 inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
95 inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
96 valid_lft forever preferred_lft forever
100 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> """
101 """../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
102 lrwxrwxrwx 1 root root 0 sie 3 10:37 eth2 -> """
103 """../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
107 "schema": "isb:traffic_profile:0.1",
109 "description": "Fixed traffic profile to run UDP traffic",
111 "traffic_type": "FixedTraffic",
112 "frame_rate": 100, # pps
117 class TestNetworkServiceTestCase(unittest.TestCase):
121 {'trexgen__1': {'role': 'TrafficGen',
122 'name': 'trafficgen_1.yardstick',
126 {'netmask': '255.255.255.0',
127 'local_ip': '152.16.100.20',
128 'local_mac': '00:00:00:00:00:01',
130 'vpci': '0000:07:00.0',
133 {'netmask': '255.255.255.0',
134 'local_ip': '152.16.40.20',
135 'local_mac': '00:00:00:00:00:02',
137 'vpci': '0000:07:00.1',
138 'dpdk_port_num': 1}},
141 'trexvnf__1': {'name': 'vnf.yardstick',
145 {'netmask': '255.255.255.0',
146 'local_ip': '152.16.100.19',
147 'local_mac': '00:00:00:00:00:03',
149 'vpci': '0000:07:00.0',
151 'xe1': {'netmask': '255.255.255.0',
152 'local_ip': '152.16.40.19',
153 'local_mac': '00:00:00:00:00:04',
155 'vpci': '0000:07:00.1',
156 'dpdk_port_num': 1}},
157 'routing_table': [{'netmask': '255.255.255.0',
158 'gateway': '152.16.100.20',
159 'network': '152.16.100.20',
161 {'netmask': '255.255.255.0',
162 'gateway': '152.16.40.20',
163 'network': '152.16.40.20',
165 'host': '10.223.197.164',
170 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
171 'network': '0064:ff9b:0:0:0:0:9810:6414',
174 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
175 'network': '0064:ff9b:0:0:0:0:9810:2814',
177 'password': 'r00t'}}}
180 {'short-name': 'trex-tg-topology',
182 [{'member-vnf-index': '1',
183 'VNF model': 'tg_trex_tpl.yaml',
184 'vnfd-id-ref': 'trexgen__1'},
185 {'member-vnf-index': '2',
186 'VNF model': 'tg_trex_tpl.yaml',
187 'vnfd-id-ref': 'trexvnf__1'}],
188 'description': 'trex-tg-topology',
189 'name': 'trex-tg-topology',
190 'vld': [{'vnfd-connection-point-ref': [
191 {'vnfd-connection-point-ref': 'xe0',
192 'member-vnf-index-ref': '1',
193 'vnfd-id-ref': 'trexgen'},
194 {'vnfd-connection-point-ref': 'xe0',
195 'member-vnf-index-ref': '2',
196 'vnfd-id-ref': 'trexgen'}],
199 'name': 'trexgen__1 to trexvnf__1 link 1'},
200 {'vnfd-connection-point-ref': [
201 {'vnfd-connection-point-ref': 'xe1',
202 'member-vnf-index-ref': '1',
203 'vnfd-id-ref': 'trexgen'},
204 {'vnfd-connection-point-ref': 'xe1',
205 'member-vnf-index-ref': '2',
206 'vnfd-id-ref': 'trexgen'}],
209 'name': 'trexvnf__1 to trexgen__1 link 2'}],
210 'id': 'trex-tg-topology'}
212 self.scenario_cfg = {'tc_options':
213 {'rfc2544': {'allowed_drop_rate': '0.8 - 1'}},
214 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
215 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
216 'runner': {'object': 'NetworkServiceTestCase',
218 'output_filename': 'yardstick.out',
220 'duration': 400, 'type': 'Duration'},
221 'traffic_profile': 'ipv4_throughput_vpe.yaml',
223 {'flow': 'ipv4_1flow_Packets_vpe.yaml',
224 'imix': 'imix_voice.yaml'},
226 'nodes': {'tg__2': 'trafficgen_2.yardstick',
227 'tg__1': 'trafficgen_1.yardstick',
228 'vnf__1': 'vnf.yardstick'},
229 'topology': 'vpe_vnf_topology.yaml'}
231 self.scenario_cfg["topology"] = \
232 self._get_file_abspath("vpe_vnf_topology.yaml")
233 self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
235 def _get_file_abspath(self, filename):
236 curr_path = os.path.dirname(os.path.abspath(__file__))
237 file_path = os.path.join(curr_path, filename)
240 def test_ssh_manager(self):
241 with mock.patch("yardstick.ssh.SSH") as ssh:
242 ssh_mock = mock.Mock(autospec=ssh.SSH)
244 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
245 ssh.return_value = ssh_mock
246 for node, node_dict in self.context_cfg["nodes"].items():
247 with ssh_manager(node_dict) as conn:
248 self.assertIsNotNone(conn)
250 def test___init__(self):
253 def test___get_traffic_flow(self):
254 self.scenario_cfg["traffic_options"]["flow"] = \
255 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
256 result = {'flow': {'dstip4_range': '152.40.0.20',
257 'srcip4_range': '152.16.0.20', 'count': 1}}
258 self.assertEqual(result, self.s._get_traffic_flow(self.scenario_cfg))
260 def test___get_traffic_flow_error(self):
261 self.scenario_cfg["traffic_options"]["flow"] = \
262 "ipv4_1flow_Packets_vpe.yaml1"
263 self.assertEqual({}, self.s._get_traffic_flow(self.scenario_cfg))
265 def test_get_vnf_impl_invalid(self):
266 self.assertRaises(IncorrectConfig, self.s.get_vnf_impl,
267 COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0])
269 def test_load_vnf_models_invalid(self):
270 self.context_cfg["nodes"]['trexgen__1']['VNF model'] = \
271 self._get_file_abspath("tg_trex_tpl.yaml")
272 self.context_cfg["nodes"]['trexvnf__1']['VNF model'] = \
273 self._get_file_abspath("tg_trex_tpl.yaml")
275 vnf = mock.Mock(autospec=GenericVNF)
276 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
278 self.assertIsNotNone(self.s.load_vnf_models(self.context_cfg))
280 def test_map_topology_to_infrastructure(self):
281 with mock.patch("yardstick.ssh.SSH") as ssh:
282 ssh_mock = mock.Mock(autospec=ssh.SSH)
284 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
285 ssh.return_value = ssh_mock
286 self.s.map_topology_to_infrastructure(self.context_cfg,
288 self.assertEqual("tg_trex_tpl.yaml",
289 self.context_cfg["nodes"]['trexgen__1']['VNF model'])
290 self.assertEqual("tg_trex_tpl.yaml",
291 self.context_cfg["nodes"]['trexvnf__1']['VNF model'])
293 def test_map_topology_to_infrastructure_insufficient_nodes(self):
294 del self.context_cfg['nodes']['trexvnf__1']
295 with mock.patch("yardstick.ssh.SSH") as ssh:
296 ssh_mock = mock.Mock(autospec=ssh.SSH)
298 mock.Mock(return_value=(1, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
299 ssh.return_value = ssh_mock
301 self.assertRaises(IncorrectSetup,
302 self.s.map_topology_to_infrastructure,
303 self.context_cfg, self.topology)
305 def test_map_topology_to_infrastructure_config_invalid(self):
306 del self.context_cfg\
307 ['nodes']['trexvnf__1']['interfaces']['xe0']['local_mac']
308 with mock.patch("yardstick.ssh.SSH") as ssh:
309 ssh_mock = mock.Mock(autospec=ssh.SSH)
311 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
312 ssh.return_value = ssh_mock
314 self.assertRaises(IncorrectConfig,
315 self.s.map_topology_to_infrastructure,
316 self.context_cfg, self.topology)
318 def test__resolve_topology_invalid_config(self):
319 with mock.patch("yardstick.ssh.SSH") as ssh:
320 ssh_mock = mock.Mock(autospec=ssh.SSH)
322 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
323 ssh.return_value = ssh_mock
325 del self.context_cfg['nodes']
326 self.assertRaises(IncorrectConfig, self.s._resolve_topology,
327 self.context_cfg, self.topology)
329 self.topology['vld'][0]['vnfd-connection-point-ref'].append(
330 self.topology['vld'][0]['vnfd-connection-point-ref'])
331 self.assertRaises(IncorrectConfig, self.s._resolve_topology,
332 self.context_cfg, self.topology)
335 tgen = mock.Mock(autospec=GenericTrafficGen)
336 tgen.traffic_finished = True
337 verified_dict = {"verified": True}
338 tgen.verify_traffic = lambda x: verified_dict
339 tgen.name = "tgen__1"
340 vnf = mock.Mock(autospec=GenericVNF)
341 vnf.runs_traffic = False
342 self.s.vnfs = [tgen, vnf]
343 self.s.traffic_profile = mock.Mock()
344 self.s.collector = mock.Mock(autospec=Collector)
345 self.s.collector.get_kpi = \
346 mock.Mock(return_value={tgen.name: verified_dict})
349 self.assertDictEqual(result, {tgen.name: verified_dict})
351 def test_setup(self):
352 with mock.patch("yardstick.ssh.SSH") as ssh:
353 ssh_mock = mock.Mock(autospec=ssh.SSH)
355 mock.Mock(return_value=(0, SYS_CLASS_NET+IP_ADDR_SHOW, ""))
356 ssh.return_value = ssh_mock
358 tgen = mock.Mock(autospec=GenericTrafficGen)
359 tgen.traffic_finished = True
360 verified_dict = {"verified": True}
361 tgen.verify_traffic = lambda x: verified_dict
362 tgen.terminate = mock.Mock(return_value=True)
363 tgen.name = "tgen__1"
364 vnf = mock.Mock(autospec=GenericVNF)
365 vnf.runs_traffic = False
366 vnf.terminate = mock.Mock(return_value=True)
367 self.s.vnfs = [tgen, vnf]
368 self.s.traffic_profile = mock.Mock()
369 self.s.collector = mock.Mock(autospec=Collector)
370 self.s.collector.get_kpi = \
371 mock.Mock(return_value={tgen.name: verified_dict})
372 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
373 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
374 self.s._fill_traffic_profile = \
375 mock.Mock(return_value=TRAFFIC_PROFILE)
376 self.assertEqual(None, self.s.setup())
378 def test__get_traffic_profile(self):
379 self.scenario_cfg["traffic_profile"] = \
380 self._get_file_abspath("ipv4_throughput_vpe.yaml")
381 self.assertIsNotNone(self.s._get_traffic_profile(self.scenario_cfg,
384 def test__get_traffic_profile_exception(self):
385 self.assertRaises(IOError, self.s._get_traffic_profile,
386 self.scenario_cfg, self.context_cfg)
388 def test___get_traffic_imix_exception(self):
389 self.assertEqual({}, self.s._get_traffic_imix(self.scenario_cfg))
391 def test__fill_traffic_profile(self):
392 self.scenario_cfg["traffic_profile"] = \
393 self._get_file_abspath("ipv4_throughput_vpe.yaml")
394 self.scenario_cfg["traffic_options"]["flow"] = \
395 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
396 self.scenario_cfg["traffic_options"]["imix"] = \
397 self._get_file_abspath("imix_voice.yaml")
398 self.assertRaises(RuntimeError, self.s._fill_traffic_profile,
399 self.scenario_cfg, self.context_cfg)
401 def test_teardown(self):
402 vnf = mock.Mock(autospec=GenericVNF)
404 mock.Mock(return_value=True)
406 self.s.traffic_profile = mock.Mock()
407 self.s.collector = mock.Mock(autospec=Collector)
408 self.s.collector.stop = \
409 mock.Mock(return_value=True)
410 self.assertIsNone(self.s.teardown())