Create a SampleVNF MQ consumer class
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_base.py
1 # Copyright (c) 2016-2017 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 import multiprocessing
16 import os
17 import uuid
18
19 import mock
20 from oslo_config import cfg
21 import oslo_messaging
22 import unittest
23
24 from yardstick.common import messaging
25 from yardstick.common.messaging import payloads
26 from yardstick.network_services.vnf_generic.vnf import base
27 from yardstick.ssh import SSH
28 from yardstick.tests.unit import base as ut_base
29
30
31 IP_PIPELINE_CFG_FILE_TPL = ("arp_route_tbl = ({port0_local_ip_hex},"
32                             "{port0_netmask_hex},1,{port1_local_ip_hex}) "
33                             "({port1_local_ip_hex},{port1_netmask_hex},0,"
34                             "{port0_local_ip_hex})")
35
36 IP_PIPELINE_ND_CFG_FILE_TPL = """
37 nd_route_tbl = ({port1_dst_ip_hex6},"""
38 """{port1_dst_netmask_hex6},1,{port1_dst_ip_hex6})"""
39
40 _LOCAL_OBJECT = object()
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                         'local_ip': '152.16.100.19',
83                         'type': 'PCI-PASSTHROUGH',
84                         'netmask': '255.255.255.0',
85                         'dpdk_port_num': 0,
86                         'bandwidth': '10 Gbps',
87                         'dst_ip': '152.16.100.20',
88                         'local_mac': '00:00:00:00:00:01'
89                     },
90                     'vnfd-connection-point-ref': 'xe0',
91                     'name': 'xe0'
92                 },
93                 {
94                     'virtual-interface': {
95                         'dst_mac': '00:00:00:00:00:04',
96                         'vpci': '0000:05:00.1',
97                         'local_ip': '152.16.40.19',
98                         'type': 'PCI-PASSTHROUGH',
99                         'netmask': '255.255.255.0',
100                         'dpdk_port_num': 1,
101                         'bandwidth': '10 Gbps',
102                         'dst_ip': '152.16.40.20',
103                         'local_mac': '00:00:00:00:00:02'
104                     },
105                     'vnfd-connection-point-ref': 'xe1',
106                     'name': 'xe1'
107                 },
108             ],
109         },
110     ],
111     'description': 'Vpe approximation using DPDK',
112     'mgmt-interface': {
113         'vdu-id': 'vpevnf-baremetal',
114         'host': '1.1.1.1',
115         'password': 'r00t',
116         'user': 'root',
117         'ip': '1.1.1.1'
118     },
119     'benchmark': {
120         'kpi': [
121             'packets_in',
122             'packets_fwd',
123             'packets_dropped',
124         ],
125     },
126     'connection-point': [
127         {
128             'type': 'VPORT',
129             'name': 'xe0',
130         },
131         {
132             'type': 'VPORT',
133             'name': 'xe1',
134         },
135     ],
136     'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
137 }
138
139 VNFD = {
140     'vnfd:vnfd-catalog': {
141         'vnfd': [
142             VNFD_0,
143         ]
144     }
145 }
146
147
148 class _DummyGenericTrafficGen(base.GenericTrafficGen):  # pragma: no cover
149
150     def run_traffic(self, *args):
151         pass
152
153     def terminate(self):
154         pass
155
156     def collect_kpi(self):
157         pass
158
159     def instantiate(self, *args):
160         pass
161
162     def scale(self, flavor=''):
163         pass
164
165
166 class FileAbsPath(object):
167     def __init__(self, module_file):
168         super(FileAbsPath, self).__init__()
169         self.module_path = os.path.dirname(os.path.abspath(module_file))
170
171     def get_path(self, filename):
172         file_path = os.path.join(self.module_path, filename)
173         return file_path
174
175
176 def mock_ssh(mock_ssh_type, spec=None, exec_result=_LOCAL_OBJECT, run_result=_LOCAL_OBJECT):
177     if spec is None:
178         spec = SSH
179
180     if exec_result is _LOCAL_OBJECT:
181         exec_result = 0, "", ""
182
183     if run_result is _LOCAL_OBJECT:
184         run_result = 0, "", ""
185
186     mock_ssh_instance = mock.Mock(autospec=spec)
187     mock_ssh_instance._get_client.return_value = mock.Mock()
188     mock_ssh_instance.execute.return_value = exec_result
189     mock_ssh_instance.run.return_value = run_result
190     mock_ssh_type.from_node.return_value = mock_ssh_instance
191     return mock_ssh_instance
192
193
194 class TestQueueFileWrapper(unittest.TestCase):
195     def setUp(self):
196         self.prompt = "pipeline>"
197         self.q_in = multiprocessing.Queue()
198         self.q_out = multiprocessing.Queue()
199
200     def test___init__(self):
201         queue_file_wrapper = \
202             base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
203         self.assertEqual(queue_file_wrapper.prompt, self.prompt)
204
205     def test_clear(self):
206         queue_file_wrapper = \
207             base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
208         queue_file_wrapper.bufsize = 5
209         queue_file_wrapper.write("pipeline>")
210         queue_file_wrapper.close()
211         self.assertIsNone(queue_file_wrapper.clear())
212         self.assertIsNotNone(queue_file_wrapper.q_out.empty())
213
214     def test_close(self):
215         queue_file_wrapper = \
216             base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
217         self.assertIsNone(queue_file_wrapper.close())
218
219     def test_read(self):
220         queue_file_wrapper = \
221             base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
222         queue_file_wrapper.q_in.put("pipeline>")
223         self.assertEqual("pipeline>", queue_file_wrapper.read(20))
224
225     def test_write(self):
226         queue_file_wrapper = \
227             base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
228         queue_file_wrapper.write("pipeline>")
229         self.assertIsNotNone(queue_file_wrapper.q_out.empty())
230
231
232 class TestGenericVNF(ut_base.BaseUnitTestCase):
233
234     def test_definition(self):
235         """Make sure that the abstract class cannot be instantiated"""
236         with self.assertRaises(TypeError) as exc:
237             # pylint: disable=abstract-class-instantiated
238             base.GenericVNF('vnf1', VNFD['vnfd:vnfd-catalog']['vnfd'][0],
239                             'task_id')
240
241         msg = ("Can't instantiate abstract class GenericVNF with abstract "
242                "methods collect_kpi, instantiate, scale, start_collect, "
243                "stop_collect, terminate, wait_for_instantiate")
244
245         self.assertEqual(msg, str(exc.exception))
246
247
248 class GenericTrafficGenTestCase(ut_base.BaseUnitTestCase):
249
250     def test_definition(self):
251         """Make sure that the abstract class cannot be instantiated"""
252         vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
253         name = 'vnf1'
254         with self.assertRaises(TypeError) as exc:
255             # pylint: disable=abstract-class-instantiated
256             base.GenericTrafficGen(name, vnfd, 'task_id')
257         msg = ("Can't instantiate abstract class GenericTrafficGen with "
258                "abstract methods collect_kpi, instantiate, run_traffic, "
259                "scale, terminate")
260         self.assertEqual(msg, str(exc.exception))
261
262     def test_get_mq_producer_id(self):
263         vnfd = {'benchmark': {'kpi': mock.ANY},
264                 'vdu': [{'external-interface': 'ext_int'}]
265                 }
266         tg = _DummyGenericTrafficGen('name', vnfd, 'task_id')
267         tg._mq_producer = mock.Mock()
268         tg._mq_producer.id = 'fake_id'
269         self.assertEqual('fake_id', tg.get_mq_producer_id())
270
271
272 class TrafficGeneratorProducerTestCase(ut_base.BaseUnitTestCase):
273
274     @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
275     @mock.patch.object(oslo_messaging, 'RPCClient')
276     @mock.patch.object(oslo_messaging, 'get_rpc_transport',
277                        return_value='rpc_transport')
278     @mock.patch.object(cfg, 'CONF')
279     def test__init(self, mock_config, mock_transport, mock_rpcclient,
280                    mock_target):
281         _id = uuid.uuid1().int
282         tg_producer = base.TrafficGeneratorProducer(_id)
283         mock_transport.assert_called_once_with(
284             mock_config, url='rabbit://yardstick:yardstick@localhost:5672/')
285         mock_target.assert_called_once_with(topic=messaging.TOPIC_TG,
286                                             fanout=True,
287                                             server=messaging.SERVER)
288         mock_rpcclient.assert_called_once_with('rpc_transport', 'rpc_target')
289         self.assertEqual(_id, tg_producer._id)
290         self.assertEqual(messaging.TOPIC_TG, tg_producer._topic)
291
292     @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
293     @mock.patch.object(oslo_messaging, 'RPCClient')
294     @mock.patch.object(oslo_messaging, 'get_rpc_transport',
295                        return_value='rpc_transport')
296     @mock.patch.object(payloads, 'TrafficGeneratorPayload',
297                        return_value='tg_pload')
298     def test_tg_method_started(self, mock_tg_payload, *args):
299         tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
300         with mock.patch.object(tg_producer, 'send_message') as mock_message:
301             tg_producer.tg_method_started(version=10)
302
303         mock_message.assert_called_once_with(messaging.TG_METHOD_STARTED,
304                                              'tg_pload')
305         mock_tg_payload.assert_called_once_with(version=10, iteration=0,
306                                                 kpi={})
307
308     @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
309     @mock.patch.object(oslo_messaging, 'RPCClient')
310     @mock.patch.object(oslo_messaging, 'get_rpc_transport',
311                        return_value='rpc_transport')
312     @mock.patch.object(payloads, 'TrafficGeneratorPayload',
313                        return_value='tg_pload')
314     def test_tg_method_finished(self, mock_tg_payload, *args):
315         tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
316         with mock.patch.object(tg_producer, 'send_message') as mock_message:
317             tg_producer.tg_method_finished(version=20)
318
319         mock_message.assert_called_once_with(messaging.TG_METHOD_FINISHED,
320                                              'tg_pload')
321         mock_tg_payload.assert_called_once_with(version=20, iteration=0,
322                                                 kpi={})
323
324     @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
325     @mock.patch.object(oslo_messaging, 'RPCClient')
326     @mock.patch.object(oslo_messaging, 'get_rpc_transport',
327                        return_value='rpc_transport')
328     @mock.patch.object(payloads, 'TrafficGeneratorPayload',
329                        return_value='tg_pload')
330     def test_tg_method_iteration(self, mock_tg_payload, *args):
331         tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
332         with mock.patch.object(tg_producer, 'send_message') as mock_message:
333             tg_producer.tg_method_iteration(100, version=30, kpi={'k': 'v'})
334
335         mock_message.assert_called_once_with(messaging.TG_METHOD_ITERATION,
336                                              'tg_pload')
337         mock_tg_payload.assert_called_once_with(version=30, iteration=100,
338                                                 kpi={'k': 'v'})
339
340
341 class GenericVNFConsumerTestCase(ut_base.BaseUnitTestCase):
342
343     def test__init(self):
344         endpoints = 'endpoint_1'
345         _ids = [uuid.uuid1().int]
346         gvnf_consumer = base.GenericVNFConsumer(_ids, endpoints)
347         self.assertEqual(_ids, gvnf_consumer._ids)
348         self.assertEqual([endpoints], gvnf_consumer._endpoints)