blob: b0892ad59b3e4688bfbfe5f5ac7cccad31a93452 [file] [log] [blame]
Chip Boling8e042f62019-02-12 16:14:34 -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#
16from twisted.internet.defer import returnValue
17from pyvoltha.adapters.extensions.omci.omci_defs import *
18from voltha.extensions.omci.omci_entities import Ieee8021pMapperServiceProfile
19from voltha.extensions.omci.tasks.mib_reconcile_task import MibReconcileTask
20from voltha.extensions.omci.database.mib_db_api import ATTRIBUTES_KEY
21from twisted.internet.defer import inlineCallbacks
22from voltha.extensions.omci.omci_defs import ReasonCodes, EntityOperations
23from voltha.extensions.omci.omci_me import MEFrame
24
25OP = EntityOperations
26RC = ReasonCodes
27AA = AttributeAccess
28
29
30class AdtnMibReconcileTask(MibReconcileTask):
31 """
32 Adtran ONU OpenOMCI MIB Reconcile Task
33
34 For some crazy reason, the ADTRAN ONU does not report the IEEE802.1p Mapper ME
35 in the ONU upload even though it does exists. This results in an 'instance
36 exists' error when trying to create it on the ONU
37 """
38 name = "Adtran MIB Reconcile Task"
39
40 def __init__(self, omci_agent, device_id, diffs):
41 super(AdtnMibReconcileTask, self).__init__(omci_agent, device_id, diffs)
42
43 self.name = AdtnMibReconcileTask.name
44 self._me_130_okay = False # Set true once bug is fixed (auto detect)
45 self._omci_managed = False # Set once ONU Data tracking of MIB-Data-Sync supported
46
47 @inlineCallbacks
48 def fix_olt_only(self, olt, onu_db, olt_db):
49 """
50 Fix ME's that were only found on the OLT. For OLT only MEs there are
51 the following things that will be checked.
52
53 o ME's that do not have an OpenOMCI class decoder. These are stored
54 as binary blobs in the MIB database. Since the OLT will never
55 create these (all are learned from ONU), it is assumed the ONU
56 has removed them for some purpose. So delete them from the OLT
57 database.
58
59 o For ME's that are created by the ONU (no create/delete access), the
60 MEs 'may' not be on the ONU because of a reboot or an OLT created
61 ME was deleted and the ONU gratuitously removes it. So delete them
62 from the OLT database.
63
64 o For ME's that are created by the OLT/OpenOMCI, delete them from the
65 ONU
66
67 :param olt: (list(int,int)) List of tuples where (class_id, inst_id)
68 :param onu_db: (dict) ONU Database snapshot at time of audit
69 :param olt_db: (dict) OLT Database snapshot at time of audit
70
71 :return: (int, int) successes, failures
72 """
73 # Has IEEE 802.1p reporting Bug fixed?
74
75 if self._me_130_okay or Ieee8021pMapperServiceProfile.class_id in onu_db:
76 self._me_130_okay = True
77 returnValue(super(AdtnMibReconcileTask, self).fix_olt_only(olt, onu_db, olt_db))
78
79 ############################
80 # Base class handles all but ME 130
81 local_mes = {Ieee8021pMapperServiceProfile.class_id}
82 not_manual = [(cid, eid) for cid, eid in olt if cid not in local_mes]
83
84 results = yield super(AdtnMibReconcileTask, self).fix_olt_only(not_manual,
85 onu_db,
86 olt_db)
87 successes = results[0]
88 failures = results[1]
89
90 # If IEEE 802.1p mapper needs to be checked, do it manually as the IBONT 602
91 # manipulates it during MEF EVC/EVC-Map creation
92 for cid in local_mes:
93 class_entry = olt_db.get(cid, None)
94
95 if class_entry is not None:
96 entries = {k: v for k, v in class_entry.items() if isinstance(k, int)}
97 for eid, instance in entries.items():
98 try:
99 self.strobe_watchdog()
100 results = yield self.manual_verification(cid, eid, instance[ATTRIBUTES_KEY])
101 successes += results[0]
102 failures += results[1]
103
104 except Exception as _e:
105 failures += 1
106
107 returnValue((successes, failures))
108
109 @inlineCallbacks
110 def update_mib_data_sync(self):
111 """ IBONT version does not support MDS"""
112 if self._omci_managed:
113 results = yield super(AdtnMibReconcileTask, self).update_mib_data_sync()
114 returnValue(results)
115
116 returnValue((1, 0))
117
118 @inlineCallbacks
119 def manual_verification(self, cid, eid, attributes):
120 # Trim off read-only attributes from ones passed in
121
122 me_map = self._device.me_map
123 ro_set = {AA.R}
124 ro_attrs = {attr.field.name for attr in me_map[cid].attributes
125 if attr.access == ro_set}
126 attributes = {k: v for k, v in attributes.items() if k not in ro_attrs}
127 attributes_to_fix = dict()
128
129 try:
130 while len(attributes):
131 frame = MEFrame(me_map[cid], eid, attributes).get()
132 self.strobe_watchdog()
133 results = yield self._device.omci_cc.send(frame)
134 omci_message = results.fields['omci_message'].fields
135 status = omci_message['success_code']
136
137 if status == RC.UnknownEntity.value:
138 self.strobe_watchdog()
139 results = yield self.create_instance(me_map[cid], eid, attributes)
140 returnValue((results[0], results[1]))
141
142 if status != RC.Success.value:
143 self.log.error('manual-check-get-failed', cid=cid, eid=eid,
144 attributes=attributes, status=status)
145 returnValue((1, 0))
146
147 onu_attr = {k: v for k, v in omci_message['data'].items()}
148 attributes_to_fix.update({k: v for k, v in onu_attr.items()
149 if k in attributes and v != attributes[k]})
150 attributes = {k: v for k, v in attributes if k not in onu_attr.keys()}
151
152 if len(attributes_to_fix) > 0:
153 try:
154 frame = MEFrame(me_map[cid], eid, attributes_to_fix).set()
155 self.strobe_watchdog()
156 yield self._device.omci_cc.send(frame)
157 returnValue((1, 0))
158
159 except Exception as _e:
160 returnValue((0, 1))
161
162 except Exception as e:
163 self.log.exception('manual-check-failed', e=e, cid=cid, eid=eid)
164 raise
165
166 @inlineCallbacks
167 def create_instance(self, cid, eid, attributes):
168 try:
169 me_map = self._device.me_map
170 frame = MEFrame(me_map[cid], eid, attributes).create()
171
172 self.strobe_watchdog()
173 results = yield self._device.omci_cc.send(frame)
174 status = results.fields['omci_message'].fields['success_code']
175 if status == RC.Success.value or status == RC.InstanceExists.value:
176 returnValue((1, 0))
177
178 self.log.error('manual-check-create-failed', cid=cid, eid=eid,
179 attributes=attributes, status=status)
180 returnValue((0, 1))
181
182 except Exception as e:
183 self.log.exception('manual-check-failed', e=e, cid=cid, eid=eid)
184 raise