blob: 1a38b1cdc51da7d4f517c932d90623d3f365ab7d [file] [log] [blame]
Chip Boling67b674a2019-02-08 11:42:18 -06001#
2# Copyright 2018 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
Zack Williams84a71e92019-11-15 09:00:19 -070016from __future__ import absolute_import
Chip Boling67b674a2019-02-08 11:42:18 -060017from hashlib import md5
18from unittest import TestCase, main
19from nose.tools import raises
20from nose.twistedtools import deferred
21from copy import deepcopy
Zack Williams84a71e92019-11-15 09:00:19 -070022from .mock.mock_adapter_agent import MockAdapterAgent, MockCore
23from .mock.mock_onu_handler import MockOnuHandler
24from .mock.mock_olt_handler import MockOltHandler
25from .mock.mock_onu import MockOnu
Chip Boling67b674a2019-02-08 11:42:18 -060026from pyvoltha.adapters.extensions.omci.openomci_agent import OpenOMCIAgent, OpenOmciAgentDefaults
27from pyvoltha.adapters.extensions.omci.onu_configuration import OMCCVersion
28from pyvoltha.adapters.extensions.omci.omci_defs import *
29from pyvoltha.adapters.extensions.omci.omci_entities import OntG, Ont2G, Cardholder, \
30 CircuitPack, SoftwareImage, AniG, UniG
31from pyvoltha.common.utils.asleep import asleep
32from pyvoltha.adapters.extensions.omci.database.mib_db_dict import MibDbVolatileDict
33from datetime import datetime
34
35DEFAULT_OLT_DEVICE_ID = 'default_olt_mock'
36DEFAULT_ONU_DEVICE_ID = 'default_onu_mock'
37DEFAULT_PON_ID = 0
38DEFAULT_ONU_ID = 0
39DEFAULT_ONU_SN = 'TEST00000001'
40
41OP = EntityOperations
42RC = ReasonCodes
43
44
45class TestOmciConfiguration(TestCase):
46 """
47 Test the OMCI read-only Configuration library methods
48 """
49 def setUp(self):
50 self.adapter_agent = MockAdapterAgent()
51
52 custom = deepcopy(OpenOmciAgentDefaults)
53 custom['mib-synchronizer']['database'] = MibDbVolatileDict
54
55 self.omci_agent = OpenOMCIAgent(MockCore, support_classes=custom)
56 self.omci_agent.start()
57
58 def tearDown(self):
59 if self.omci_agent is not None:
60 self.omci_agent.stop()
61
62 if self.adapter_agent is not None:
63 self.adapter_agent.tearDown()
64
65 def setup_mock_olt(self, device_id=DEFAULT_OLT_DEVICE_ID):
66 handler = MockOltHandler(self.adapter_agent, device_id)
67 self.adapter_agent.add_device(handler.device)
68 return handler
69
70 def setup_mock_onu(self, parent_id=DEFAULT_OLT_DEVICE_ID,
71 device_id=DEFAULT_ONU_DEVICE_ID,
72 pon_id=DEFAULT_PON_ID,
73 onu_id=DEFAULT_ONU_ID,
74 serial_no=DEFAULT_ONU_SN):
75 handler = MockOnuHandler(self.adapter_agent, parent_id, device_id, pon_id, onu_id)
76 handler.serial_number = serial_no
77 onu = MockOnu(serial_no, self.adapter_agent, handler.device_id) \
78 if serial_no is not None else None
79 handler.onu_mock = onu
80 return handler
81
82 def setup_one_of_each(self):
83 # Most tests will use at lease one or more OLT and ONU
84 self.olt_handler = self.setup_mock_olt()
85 self.onu_handler = self.setup_mock_onu(parent_id=self.olt_handler.device_id)
86 self.onu_device = self.onu_handler.onu_mock
87
88 self.adapter_agent.add_child_device(self.olt_handler.device,
89 self.onu_handler.device)
90 # Add device to OpenOMCI
91 self.onu_device = self.omci_agent.add_device(DEFAULT_ONU_DEVICE_ID,
92 self.adapter_agent)
93
94 # Allow timeout trigger support while in disabled state for mib sync
95 # to make tests run cleanly while profiling.
96 self.onu_device.mib_synchronizer.machine.add_transition('timeout', 'disabled', 'disabled')
97
98 def not_called(self, _reason):
99 assert False, 'Should never be called'
100
101 def _stuff_database(self, entries):
102 """
103 Stuff the MIB database with some entries that we will use during tests
104 """
105 database = self.onu_device.mib_synchronizer._database
106
107 # Stuff a value into last in sync. This makes it look like
108 # the ONU has been in in-sync at least once.
109 self.onu_device.mib_synchronizer.last_mib_db_sync = datetime.utcnow()
110
111 # Entry is a tuple of (class_id, instance_id, {attributes})
112 for entry in entries:
113 database.set(DEFAULT_ONU_DEVICE_ID, entry[0], entry[1], entry[2])
114
115 def test_OMCCVersion(self):
116 for key, value in OMCCVersion.__members__.items():
117 self.assertEqual(OMCCVersion.to_enum(OMCCVersion[key].value), value)
118
119 self.assertEqual(OMCCVersion.to_enum(-1), OMCCVersion.Unknown)
120
121 @deferred(timeout=50000)
122 def test_defaults(self):
123 self.setup_one_of_each()
124 self.assertEqual(len(self.omci_agent.device_ids()), 1)
125
126 @raises(AssertionError)
127 def do_my_tests(_results):
128 config = self.onu_device.configuration
129 # Should raise assertion if never been synchronized
130 config.version
131
132 # No capabilities available until started
133 self.assertIsNone(self.onu_device.configuration)
134
135 # Yield context so that MIB Database callLater runs. This is a waiting
136 # Async task from when the OpenOMCIAgent was started. But also start the
137 # device so that it's queued async state machines can run as well
138 self.onu_device.start()
139 d = asleep(0.2)
140 d.addCallbacks(do_my_tests, self.not_called)
141 return d
142
143 @deferred(timeout=5)
144 def test_in_sync_but_empty(self):
145 self.setup_one_of_each()
146 self.assertEqual(len(self.omci_agent.device_ids()), 1)
147
148 def stuff_db(_results):
149 self._stuff_database([])
150
151 def do_my_tests(_results):
152 config = self.onu_device.configuration
153
154 # On no Class ID for requested property, None should be
155 # returned
156 self.assertIsNone(config.version)
157 self.assertIsNone(config.traffic_management_option)
158 self.assertIsNone(config.onu_survival_time)
159 self.assertIsNone(config.equipment_id)
160 self.assertIsNone(config.omcc_version)
161 self.assertIsNone(config.vendor_product_code)
162 self.assertIsNone(config.total_priority_queues)
163 self.assertIsNone(config.total_traffic_schedulers)
164 self.assertIsNone(config.total_gem_ports)
165 self.assertIsNone(config.uptime)
166 self.assertIsNone(config.connectivity_capability)
167 self.assertIsNone(config.qos_configuration_flexibility)
168 self.assertIsNone(config.priority_queue_scale_factor)
169 self.assertIsNone(config.cardholder_entities)
170 self.assertIsNone(config.circuitpack_entities)
171 self.assertIsNone(config.software_images)
172 self.assertIsNone(config.ani_g_entities)
173 self.assertIsNone(config.uni_g_entities)
174
175 # No capabilities available until started
176 self.assertIsNone(self.onu_device.configuration)
177
178 # Yield context so that MIB Database callLater runs.
179 self.onu_device.start()
180 d = asleep(0.2)
181 d.addCallbacks(stuff_db, self.not_called)
182 d.addCallbacks(do_my_tests, self.not_called)
183 return d
184
185 @deferred(timeout=5)
186 def test_in_sync_with_ont_g_values(self):
187 self.setup_one_of_each()
188 self.assertEqual(len(self.omci_agent.device_ids()), 1)
189
190 version = 'abcDEF'
191 tm_opt = 2
192 onu_survival = 123
193
194 def stuff_db(_results):
195 self._stuff_database([
196 (OntG.class_id, 0, {'version': version,
197 'traffic_management_options': tm_opt,
198 'ont_survival_time': onu_survival
199 })])
200
201 def do_my_tests(_results):
202 config = self.onu_device.configuration
203
204 # On no Class ID for requested property, None should be
205 # returned
206 self.assertEqual(config.version, version)
207 self.assertEqual(config.traffic_management_option, tm_opt)
208 self.assertEqual(config.onu_survival_time, onu_survival)
209
210 # No capabilities available until started
211 self.assertIsNone(self.onu_device.configuration)
212
213 # Yield context so that MIB Database callLater runs.
214 self.onu_device.start()
215 d = asleep(0.2)
216 d.addCallbacks(stuff_db, self.not_called)
217 d.addCallbacks(do_my_tests, self.not_called)
218 return d
219
220 @deferred(timeout=5)
221 def test_in_sync_with_ont_2g_values(self):
222 self.setup_one_of_each()
223 self.assertEqual(len(self.omci_agent.device_ids()), 1)
224
225 equip_id = 'br-549'
226 omcc_ver = OMCCVersion.G_988_2012
227 vend_code = 0x1234
228 queues = 64
229 scheds = 8
230 gem_ports = 24
231 uptime = 12345
232 conn_capp = 0x00aa
233 qos_flex = 0x001b
234 queue_scale = 1
235
236 def stuff_db(_results):
237 self._stuff_database([
238 (Ont2G.class_id, 0, {'equipment_id': equip_id,
239 'omcc_version': omcc_ver.value,
240 'vendor_product_code': vend_code,
241 'total_priority_queue_number': queues,
242 'total_traffic_scheduler_number': scheds,
243 'total_gem_port_id_number': gem_ports,
244 'sys_uptime': uptime,
245 'connectivity_capability': conn_capp,
246 'qos_configuration_flexibility': qos_flex,
247 'priority_queue_scale_factor': queue_scale
248 })])
249
250 def do_my_tests(_results):
251 config = self.onu_device.configuration
252
253 self.assertEqual(config.equipment_id, equip_id)
254 self.assertEqual(config.omcc_version, omcc_ver)
255 self.assertEqual(config.vendor_product_code, vend_code)
256 self.assertEqual(config.total_priority_queues, queues)
257 self.assertEqual(config.total_traffic_schedulers, scheds)
258 self.assertEqual(config.total_gem_ports, gem_ports)
259 self.assertEqual(config.uptime, uptime)
260 self.assertEqual(config.connectivity_capability, conn_capp)
261 self.assertEqual(config.qos_configuration_flexibility, qos_flex)
262 self.assertEqual(config.priority_queue_scale_factor, queue_scale)
263
264 # No capabilities available until started
265 self.assertIsNone(self.onu_device.configuration)
266
267 # Yield context so that MIB Database callLater runs.
268 self.onu_device.start()
269 d = asleep(0.2)
270 d.addCallbacks(stuff_db, self.not_called)
271 d.addCallbacks(do_my_tests, self.not_called)
272 return d
273
274 @deferred(timeout=5)
275 def test_in_sync_with_cardholder_values(self):
276 self.setup_one_of_each()
277 self.assertEqual(len(self.omci_agent.device_ids()), 1)
278
279 ch_entity = 0x102
280 unit_type = 255
281 clie_code = 'abc123'
282 prot_ptr = 0
283
284 def stuff_db(_results):
285 self._stuff_database([
286 (Cardholder.class_id, ch_entity, {'actual_plugin_unit_type': unit_type,
287 'actual_equipment_id': clie_code,
288 'protection_profile_pointer': prot_ptr,
289 })])
290
291 def do_my_tests(_results):
292 config = self.onu_device.configuration
293
294 cardholder = config.cardholder_entities
295 self.assertTrue(isinstance(cardholder, dict))
296 self.assertEqual(len(cardholder), 1)
297 self.assertEqual(cardholder[ch_entity]['entity-id'], ch_entity)
298 self.assertEqual(cardholder[ch_entity]['is-single-piece'], ch_entity >= 256)
299 self.assertEqual(cardholder[ch_entity]['slot-number'], ch_entity & 0xFF)
300 self.assertEqual(cardholder[ch_entity]['actual-plug-in-type'], unit_type)
301 self.assertEqual(cardholder[ch_entity]['actual-equipment-id'], clie_code)
302 self.assertEqual(cardholder[ch_entity]['protection-profile-ptr'], prot_ptr)
303
304 # No capabilities available until started
305 self.assertIsNone(self.onu_device.configuration)
306
307 # Yield context so that MIB Database callLater runs.
308 self.onu_device.start()
309 d = asleep(0.2)
310 d.addCallbacks(stuff_db, self.not_called)
311 d.addCallbacks(do_my_tests, self.not_called)
312 return d
313
314 @deferred(timeout=5)
315 def test_in_sync_with_circuitpack_values(self):
316 self.setup_one_of_each()
317 self.assertEqual(len(self.omci_agent.device_ids()), 1)
318
319 cp_entity = 0x100
320 num_ports = 1
321 serial_num = 'ABCD01234'
322 cp_version = '1234ABCD'
323 vendor_id = 'AB-9876'
324 tconts = 2
325 pqueues = 64
326 sched_count = 8
327
328 def stuff_db(_results):
329 self._stuff_database([
330 (CircuitPack.class_id, cp_entity, {'number_of_ports': num_ports,
331 'serial_number': serial_num,
332 'version': cp_version,
333 'vendor_id': vendor_id,
334 'total_tcont_buffer_number': tconts,
335 'total_priority_queue_number': pqueues,
336 'total_traffic_scheduler_number': sched_count,
337 })])
338
339 def do_my_tests(_results):
340 config = self.onu_device.configuration
341
342 circuitpack = config.circuitpack_entities
343 self.assertTrue(isinstance(circuitpack, dict))
344 self.assertEqual(len(circuitpack), 1)
345 self.assertEqual(circuitpack[cp_entity]['entity-id'], cp_entity)
346 self.assertEqual(circuitpack[cp_entity]['number-of-ports'], num_ports)
347 self.assertEqual(circuitpack[cp_entity]['serial-number'], serial_num)
348 self.assertEqual(circuitpack[cp_entity]['version'], cp_version)
349 self.assertEqual(circuitpack[cp_entity]['vendor-id'], vendor_id)
350 self.assertEqual(circuitpack[cp_entity]['total-tcont-count'], tconts)
351 self.assertEqual(circuitpack[cp_entity]['total-priority-queue-count'], pqueues)
352 self.assertEqual(circuitpack[cp_entity]['total-traffic-sched-count'], sched_count)
353
354 # No capabilities available until started
355 self.assertIsNone(self.onu_device.configuration)
356
357 # Yield context so that MIB Database callLater runs.
358 self.onu_device.start()
359 d = asleep(0.2)
360 d.addCallbacks(stuff_db, self.not_called)
361 d.addCallbacks(do_my_tests, self.not_called)
362 return d
363
364 @deferred(timeout=5)
365 def test_in_sync_with_software_values(self):
366 self.setup_one_of_each()
367 self.assertEqual(len(self.omci_agent.device_ids()), 1)
368
369 sw_entity = 0x200
370 sw_version = 'Beta-0.0.2'
371 sw_hash = md5("just_a_test").hexdigest()
372 prod_code = 'MySoftware'
373 sw_active = True
374 sw_committed = True
375 sw_valid = True
376
377 def stuff_db(_results):
378 self._stuff_database([
379 (SoftwareImage.class_id, sw_entity, {'version': sw_version,
380 'is_committed': sw_committed,
381 'is_active': sw_active,
382 'is_valid': sw_valid,
383 'product_code': prod_code,
384 'image_hash': sw_hash,
385 })])
386
387 def do_my_tests(_results):
388 config = self.onu_device.configuration
389
390 images = config.software_images
391 self.assertTrue(isinstance(images, list))
392 self.assertEqual(len(images), 1)
393 self.assertEqual(images[0].name, 'running-revision' if sw_active else 'candidate-revision')
394 self.assertEqual(images[0].version, sw_version)
395 self.assertEqual(images[0].is_active, 1 if sw_active else 0)
396 self.assertEqual(images[0].is_committed, 1 if sw_committed else 0)
397 self.assertEqual(images[0].is_valid, 1 if sw_valid else 0)
398 self.assertEqual(images[0].hash, sw_hash)
399
400 # No capabilities available until started
401 self.assertIsNone(self.onu_device.configuration)
402
403 # Yield context so that MIB Database callLater runs.
404 self.onu_device.start()
405 d = asleep(0.2)
406 d.addCallbacks(stuff_db, self.not_called)
407 d.addCallbacks(do_my_tests, self.not_called)
408 return d
409
410 @deferred(timeout=5)
411 def test_in_sync_with_ani_g_values(self):
412 self.setup_one_of_each()
413 self.assertEqual(len(self.omci_agent.device_ids()), 1)
414
415 entity_id = 0x0106
416 tconts = 4
417 dba_report = 4
418
419 def stuff_db(_results):
420 self._stuff_database([
421 (AniG.class_id, entity_id, {'total_tcont_number': tconts,
422 'piggyback_dba_reporting': dba_report
423 })
424 ])
425
426 def do_my_tests(_results):
427 config = self.onu_device.configuration
428
429 anig = config.ani_g_entities
430 self.assertTrue(isinstance(anig, dict))
431 self.assertEqual(len(anig), 1)
432
433 self.assertEqual(anig[entity_id]['entity-id'], entity_id)
434 self.assertEqual(anig[entity_id]['slot-number'], (entity_id >> 8) & 0xff)
435 self.assertEqual(anig[entity_id]['port-number'], entity_id & 0xff)
436 self.assertEqual(anig[entity_id]['total-tcont-count'], tconts)
437 self.assertEqual(anig[entity_id]['piggyback-dba-reporting'], dba_report)
438
439 # No capabilities available until started
440 self.assertIsNone(self.onu_device.configuration)
441
442 # Yield context so that MIB Database callLater runs.
443 self.onu_device.start()
444 d = asleep(0.2)
445 d.addCallbacks(stuff_db, self.not_called)
446 d.addCallbacks(do_my_tests, self.not_called)
447 return d
448
449 @deferred(timeout=5)
450 def test_in_sync_with_uni_g_values(self):
451 self.setup_one_of_each()
452 self.assertEqual(len(self.omci_agent.device_ids()), 1)
453
454 entity_id = 0x4321
455 mgmt_cap = 0
456
457 def stuff_db(_results):
458 self._stuff_database([
459 (UniG.class_id, entity_id, {'management_capability': mgmt_cap})
460 ])
461
462 def do_my_tests(_results):
463 config = self.onu_device.configuration
464
465 unig = config.uni_g_entities
466 self.assertTrue(isinstance(unig, dict))
467 self.assertEqual(len(unig), 1)
468
469 self.assertEqual(unig[entity_id]['entity-id'], entity_id)
470 self.assertEqual(unig[entity_id]['management-capability'], mgmt_cap)
471
472 # No capabilities available until started
473 self.assertIsNone(self.onu_device.configuration)
474
475 # Yield context so that MIB Database callLater runs.
476 self.onu_device.start()
477 d = asleep(0.2)
478 d.addCallbacks(stuff_db, self.not_called)
479 d.addCallbacks(do_my_tests, self.not_called)
480 return d
481
482
483if __name__ == '__main__':
484 main()
485