blob: 355e26aa1ac1893a3045ca57c810aad0df6de4e2 [file] [log] [blame]
William Kurkian6f436d02019-02-06 16:25:01 -05001#
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 task import Task
17from twisted.internet import reactor
18from twisted.internet.defer import inlineCallbacks, failure, TimeoutError
19from voltha.extensions.omci.omci_defs import ReasonCodes, EntityOperations
20from voltha.extensions.omci.omci_frame import OmciFrame
21from voltha.extensions.omci.omci_messages import OmciCreate
22
23RC = ReasonCodes
24OP = EntityOperations
25
26
27class CreatePMException(Exception):
28 pass
29
30
31class OmciCreatePMRequest(Task):
32 """
33 OpenOMCI routine to create the requested PM Interval MEs
34
35 TODO: Support of thresholding crossing alarms will be in a future VOLTHA release
36 """
37 task_priority = Task.DEFAULT_PRIORITY
38 name = "ONU OMCI Create PM ME Task"
39
40 def __init__(self, omci_agent, device_id, me_dict, exclusive=False):
41 """
42 Class initialization
43
44 :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
45 :param me_dict: (dict) (pm cid, pm eid) -> (me cid, me eid, upstream)
46 :param exclusive: (bool) True if this Create request Task exclusively own the
47 OMCI-CC while running. Default: False
48 """
49 super(OmciCreatePMRequest, self).__init__(OmciCreatePMRequest.name,
50 omci_agent,
51 device_id,
52 priority=OmciCreatePMRequest.task_priority,
53 exclusive=exclusive)
54 self._device = omci_agent.get_device(device_id)
55 self._me_dict = me_dict
56 self._local_deferred = None
57
58 def cancel_deferred(self):
59 super(OmciCreatePMRequest, self).cancel_deferred()
60
61 d, self._local_deferred = self._local_deferred, None
62 try:
63 if d is not None and not d.called:
64 d.cancel()
65 except:
66 pass
67
68 def start(self):
69 """ Start task """
70 super(OmciCreatePMRequest, self).start()
71 self._local_deferred = reactor.callLater(0, self.perform_create)
72
73 @inlineCallbacks
74 def perform_create(self):
75 """ Perform the create requests """
76
77 try:
78 for pm, me in self._me_dict.items():
79 pm_class_id = pm[0]
80 pm_entity_id = pm[1]
81 me_class_id = me[0]
82 me_entity_id = me[1]
83 upstream = me[2]
84 self.log.debug('create-pm-me', class_id=pm_class_id, entity_id=pm_entity_id)
85
86 if me_class_id == 0:
87 # Typical/common PM interval format
88 frame = OmciFrame(
89 transaction_id=None, # OMCI-CC will set
90 message_type=OmciCreate.message_id,
91 omci_message=OmciCreate(
92 entity_class=pm_class_id,
93 entity_id=pm_entity_id,
94 data=dict()
95 )
96 )
97 else:
98 # Extended PM interval format. See ITU-T G.988 Section 9.3.32.
99 # Bit 1 - continuous accumulation if set, 15-minute interval if unset
100 # Bit 2 - directionality (0=upstream, 1=downstream)
101 # Bit 3..14 - Reserved
102 # Bit 15 - Use P bits of TCI field to filter
103 # Bit 16 - Use VID bits of TCI field to filter
104 bitmap = 0 if upstream else 1 << 1
105
106 data = {'control_block': [
107 0, # Threshold data 1/2 ID
108 me_class_id, # Parent ME Class
109 me_entity_id, # Parent ME Instance
110 0, # Accumulation disable
111 0, # TCA Disable
112 bitmap, # Control fields bitmap
113 0, # TCI
114 0 # Reserved
115 ]}
116 frame = OmciFrame(
117 transaction_id=None, # OMCI-CC will set
118 message_type=OmciCreate.message_id,
119 omci_message=OmciCreate(
120 entity_class=pm_class_id,
121 entity_id=pm_entity_id,
122 data=data
123 )
124 )
125 self.strobe_watchdog()
126 try:
127 results = yield self._device.omci_cc.send(frame)
128 except TimeoutError:
129 self.log.warning('perform-create-timeout', me_class_id=me_class_id, me_entity_id=me_entity_id,
130 pm_class_id=pm_class_id, pm_entity_id=pm_entity_id)
131 raise
132
133 status = results.fields['omci_message'].fields['success_code']
134 self.log.debug('perform-create-status', status=status)
135
136 # Did it fail
137 if status != RC.Success.value and status != RC.InstanceExists.value:
138 msg = 'ME: {}, entity: {} failed with status {}'.format(pm_class_id,
139 pm_entity_id,
140 status)
141 raise CreatePMException(msg)
142
143 self.log.debug('create-pm-success', class_id=pm_class_id,
144 entity_id=pm_entity_id)
145
146 self.deferred.callback(self)
147
148 except Exception as e:
149 self.log.exception('perform-create', e=e)
150 self.deferred.errback(failure.Failure(e))