blob: bbd7660d3f1d2120a05b6d6286532f1b8962b90b [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001/*
2 * Copyright 2020-present Open Networking Foundation
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 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/hex"
23 "errors"
24 "fmt"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000025 "strconv"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000026 "sync"
27 "time"
28
29 "github.com/gogo/protobuf/proto"
30 "github.com/golang/protobuf/ptypes"
31 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000032 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000033 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
mpagenkoaf801632020-07-03 10:00:42 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/db"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000035 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000036 vc "github.com/opencord/voltha-protos/v3/go/common"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000037 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 oop "github.com/opencord/voltha-protos/v3/go/openolt"
39 "github.com/opencord/voltha-protos/v3/go/voltha"
40)
41
42/*
43// Constants for number of retries and for timeout
44const (
45 MaxRetry = 10
46 MaxTimeOutInMs = 500
47)
48*/
49
Holger Hildebrandt24d51952020-05-04 14:03:42 +000050//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
51const (
52 pon = voltha.EventSubCategory_PON
53 olt = voltha.EventSubCategory_OLT
54 ont = voltha.EventSubCategory_ONT
55 onu = voltha.EventSubCategory_ONU
56 nni = voltha.EventSubCategory_NNI
57 service = voltha.EventCategory_SERVICE
58 security = voltha.EventCategory_SECURITY
59 equipment = voltha.EventCategory_EQUIPMENT
60 processing = voltha.EventCategory_PROCESSING
61 environment = voltha.EventCategory_ENVIRONMENT
62 communication = voltha.EventCategory_COMMUNICATION
63)
64
65const (
66 cEventObjectType = "ONU"
67)
68const (
69 cOnuActivatedEvent = "ONU_ACTIVATED"
70)
71
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000072//DeviceHandler will interact with the ONU ? device.
73type DeviceHandler struct {
74 deviceID string
75 DeviceType string
76 adminState string
77 device *voltha.Device
78 logicalDeviceID string
79 ProxyAddressID string
80 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +000081 parentId string
82 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000083
Holger Hildebrandtc54939a2020-06-17 08:14:27 +000084 coreProxy adapterif.CoreProxy
85 AdapterProxy adapterif.AdapterProxy
86 EventProxy adapterif.EventProxy
87
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000088 pOpenOnuAc *OpenONUAC
89 pDeviceStateFsm *fsm.FSM
90 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +000091 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000092 pOnuOmciDevice *OnuDeviceEntry
mpagenkoaf801632020-07-03 10:00:42 +000093 pOnuTP *OnuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000094 exitChannel chan int
95 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +000096 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +000097 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000098 pLockStateFsm *LockStateFsm
99 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000100
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000101 //flowMgr *OpenOltFlowMgr
102 //eventMgr *OpenOltEventMgr
103 //resourceMgr *rsrcMgr.OpenOltResourceMgr
104
105 //discOnus sync.Map
106 //onus sync.Map
107 //portStats *OpenOltStatisticsMgr
108 //metrics *pmmetrics.PmMetrics
109 stopCollector chan bool
110 stopHeartbeatCheck chan bool
111 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000112 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113}
114
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000115//NewDeviceHandler creates a new device handler
116func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
117 var dh DeviceHandler
118 dh.coreProxy = cp
119 dh.AdapterProxy = ap
120 dh.EventProxy = ep
121 cloned := (proto.Clone(device)).(*voltha.Device)
122 dh.deviceID = cloned.Id
123 dh.DeviceType = cloned.Type
124 dh.adminState = "up"
125 dh.device = cloned
126 dh.pOpenOnuAc = adapter
127 dh.exitChannel = make(chan int, 1)
128 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000129 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000130 dh.stopCollector = make(chan bool, 2)
131 dh.stopHeartbeatCheck = make(chan bool, 2)
132 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
133 dh.activePorts = sync.Map{}
134 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000135 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000136
137 // Device related state machine
138 dh.pDeviceStateFsm = fsm.NewFSM(
139 "null",
140 fsm.Events{
141 {Name: "DeviceInit", Src: []string{"null", "down"}, Dst: "init"},
142 {Name: "GrpcConnected", Src: []string{"init"}, Dst: "connected"},
143 {Name: "GrpcDisconnected", Src: []string{"connected", "down"}, Dst: "init"},
144 {Name: "DeviceUpInd", Src: []string{"connected", "down"}, Dst: "up"},
145 {Name: "DeviceDownInd", Src: []string{"up"}, Dst: "down"},
146 },
147 fsm.Callbacks{
148 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
149 "before_DeviceInit": func(e *fsm.Event) { dh.doStateInit(e) },
150 "after_DeviceInit": func(e *fsm.Event) { dh.postInit(e) },
151 "before_GrpcConnected": func(e *fsm.Event) { dh.doStateConnected(e) },
152 "before_GrpcDisconnected": func(e *fsm.Event) { dh.doStateInit(e) },
153 "after_GrpcDisconnected": func(e *fsm.Event) { dh.postInit(e) },
154 "before_DeviceUpInd": func(e *fsm.Event) { dh.doStateUp(e) },
155 "before_DeviceDownInd": func(e *fsm.Event) { dh.doStateDown(e) },
156 },
157 )
mpagenkoaf801632020-07-03 10:00:42 +0000158
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000159 return &dh
160}
161
162// start save the device to the data model
163func (dh *DeviceHandler) Start(ctx context.Context) {
164 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
165 // Add the initial device to the local model
166 logger.Debug("device-handler-started")
167}
168
169// stop stops the device dh. Not much to do for now
170func (dh *DeviceHandler) stop(ctx context.Context) {
171 logger.Debug("stopping-device-handler")
172 dh.exitChannel <- 1
173}
174
175// ##########################################################################################
176// DeviceHandler methods that implement the adapters interface requests ##### begin #########
177
178//AdoptDevice adopts the OLT device
179func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
180 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
181
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000182 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000183 if dh.pDeviceStateFsm.Is("null") {
184 if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
185 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
186 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000187 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000188 } else {
189 logger.Debug("AdoptDevice: Agent/device init already done")
190 }
191
192 /*
193 // Now, set the initial PM configuration for that device
194 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
195 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
196 }
197
198 go startCollector(dh)
199 go startHeartbeatCheck(dh)
200 */
201}
202
203//ProcessInterAdapterMessage sends the proxied messages to the target device
204// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
205// is meant, and then send the unmarshalled omci message to this onu
206func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
207 msgID := msg.Header.Id
208 msgType := msg.Header.Type
209 fromTopic := msg.Header.FromTopic
210 toTopic := msg.Header.ToTopic
211 toDeviceID := msg.Header.ToDeviceId
212 proxyDeviceID := msg.Header.ProxyDeviceId
213 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
214 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
215
216 switch msgType {
217 case ic.InterAdapterMessageType_OMCI_REQUEST:
218 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000220 omciMsg := &ic.InterAdapterOmciMessage{}
221 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000222 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
223 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000224 return err
225 }
226
227 //assuming omci message content is hex coded!
228 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000229 logger.Debugw("inter-adapter-recv-omci", log.Fields{
230 "deviceID": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000231 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000232 pDevEntry := dh.GetOnuDeviceEntry(true)
233 if pDevEntry != nil {
234 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
235 } else {
236 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
237 return errors.New("No valid OnuDevice")
238 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000239 }
240 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
241 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000242 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000243 onu_indication := &oop.OnuIndication{}
244 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000245 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
246 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000247 return err
248 }
249
250 onu_operstate := onu_indication.GetOperState()
251 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
252 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
253 "SNR": onu_indication.GetSerialNumber()})
254
mpagenko3af1f032020-06-10 08:53:41 +0000255 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 if onu_operstate == "up" {
257 dh.create_interface(onu_indication)
258 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000259 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000260 } else {
261 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
262 return errors.New("InvalidOperState")
263 }
264 }
mpagenkoaf801632020-07-03 10:00:42 +0000265 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
266 {
267 if dh.pOnuTP == nil {
268 //should normally not happen ...
269 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
270 log.Fields{"deviceID": dh.deviceID})
271 return errors.New("TechProfile DLMsg request while onuTechProf instance not setup")
272 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000273
mpagenkoaf801632020-07-03 10:00:42 +0000274 msgBody := msg.GetBody()
275 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
276 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
277 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
278 "deviceID": dh.deviceID, "error": err})
279 return err
280 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000281
mpagenkoaf801632020-07-03 10:00:42 +0000282 // we have to lock access to TechProfile processing based on different messageType calls or
283 // even to fast subsequent calls of the same messageType
284 dh.pOnuTP.lockTpProcMutex()
285 // lock hangs as long as below decoupled or other related TechProfile processing is active
286 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
287 // if there has been some change for some uni TechProfilePath
288 //in order to allow concurrent calls to other dh instances we do not wait for execution here
289 //but doing so we can not indicate problems to the caller (who does what with that then?)
290 //by now we just assume straightforward successful execution
291 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
292 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000293
mpagenkoaf801632020-07-03 10:00:42 +0000294 // some code to coordinate TP 'run to completion'
295 // attention: completion and wg.Add is assumed to be done in both routines,
296 // no timeout control so far (needed)
297 var wg sync.WaitGroup
298 wg.Add(2) // for the 2 go routines to finish
299 go dh.pOnuTP.configureUniTp(techProfMsg.UniId, techProfMsg.Path, &wg)
300 go dh.pOnuTP.updateOnuTpPathKvStore(&wg)
301 //the wait.. function is responsible for tpProcMutex.Unlock()
302 go dh.pOnuTP.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
303 } else {
304 dh.pOnuTP.unlockTpProcMutex()
305 }
306 }
307 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
308 {
309 if dh.pOnuTP == nil {
310 //should normally not happen ...
311 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
312 log.Fields{"deviceID": dh.deviceID})
313 return errors.New("TechProfile DelGem request while onuTechProf instance not setup")
314 }
315
316 msgBody := msg.GetBody()
317 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
318 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
319 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
320 "deviceID": dh.deviceID, "error": err})
321 return err
322 }
323
324 //compare TECH_PROFILE_DOWNLOAD_REQUEST
325 dh.pOnuTP.lockTpProcMutex()
326 var wg sync.WaitGroup
327 wg.Add(1) // for the 1 go routine to finish
328 go dh.pOnuTP.deleteTpRessource(delGemPortMsg.UniId, delGemPortMsg.TpPath,
329 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
330 //the wait.. function is responsible for tpProcMutex.Unlock()
331 go dh.pOnuTP.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
332 }
333 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
334 {
335 if dh.pOnuTP == nil {
336 //should normally not happen ...
337 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
338 log.Fields{"deviceID": dh.deviceID})
339 return errors.New("TechProfile DelTcont request while onuTechProf instance not setup")
340 }
341
342 msgBody := msg.GetBody()
343 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
344 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
345 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
346 "deviceID": dh.deviceID, "error": err})
347 return err
348 }
349
350 //compare TECH_PROFILE_DOWNLOAD_REQUEST
351 dh.pOnuTP.lockTpProcMutex()
352 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
353 var wg sync.WaitGroup
354 wg.Add(2) // for the 1 go routine to finish
355 go dh.pOnuTP.deleteTpRessource(delTcontMsg.UniId, delTcontMsg.TpPath,
356 cResourceTcont, delTcontMsg.AllocId, &wg)
357 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
358 go dh.pOnuTP.updateOnuTpPathKvStore(&wg)
359 //the wait.. function is responsible for tpProcMutex.Unlock()
360 go dh.pOnuTP.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
361 } else {
362 dh.pOnuTP.unlockTpProcMutex()
363 }
364 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000365 default:
366 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000367 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
368 "deviceID": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000369 return errors.New("unimplemented")
370 }
371 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000372 return nil
373}
374
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000375//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000376// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
377// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300378func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000379 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
380
mpagenko3af1f032020-06-10 08:53:41 +0000381 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
382 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
383 if dh.deviceReason != "omci-admin-lock" {
384 // disable UNI ports/ONU
385 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
386 // here the result of the processing is not checked (trusted in background) *****
387 if dh.pLockStateFsm == nil {
388 dh.createUniLockFsm(true, UniAdminStateDone)
389 } else { //LockStateFSM already init
390 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
391 dh.runUniLockFsm(true)
392 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300393
mpagenko3af1f032020-06-10 08:53:41 +0000394 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
395 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
396 }
397 dh.deviceReason = "omci-admin-lock"
398 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
399 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
400 voltha.OperStatus_UNKNOWN); err != nil {
401 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
402 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300403 }
404}
405
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000406//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000407// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
408// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300409func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000410 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000411
412 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300413 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
414 voltha.OperStatus_ACTIVE); err != nil {
415 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
416 }
417
mpagenko3af1f032020-06-10 08:53:41 +0000418 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000419 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300420 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
421 }
mpagenko3af1f032020-06-10 08:53:41 +0000422 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000423
424 // enable ONU/UNI ports
425 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
426 // here the result of the processing is not checked (trusted in background) *****
427 if dh.pUnlockStateFsm == nil {
428 dh.createUniLockFsm(false, UniAdminStateDone)
429 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000430 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000431 dh.runUniLockFsm(false)
432 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300433}
434
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000435// DeviceHandler methods that implement the adapters interface requests## end #########
436// #####################################################################################
437
438// ################ to be updated acc. needs of ONU Device ########################
439// DeviceHandler StateMachine related state transition methods ##### begin #########
440
441func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
442 logger.Debugw("Device FSM: ", log.Fields{"event name": string(e.Event), "src state": string(e.Src), "dst state": string(e.Dst), "device-id": dh.deviceID})
443}
444
445// doStateInit provides the device update to the core
446func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
447
448 logger.Debug("doStateInit-started")
449 var err error
450
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000451 // populate what we know. rest comes later after mib sync
452 dh.device.Root = false
453 dh.device.Vendor = "OpenONU"
454 dh.device.Model = "go"
455 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000456 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000457
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000458 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000459 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
460
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000461 dh.parentId = dh.device.ParentId
462 dh.ponPortNumber = dh.device.ParentPortNo
463
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000464 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
465 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
466 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
467 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
468 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000469 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000470
471 /*
472 self._pon = PonPort.create(self, self._pon_port_number)
473 self._pon.add_peer(self.parent_id, self._pon_port_number)
474 self.logger.debug('adding-pon-port-to-agent',
475 type=self._pon.get_port().type,
476 admin_state=self._pon.get_port().admin_state,
477 oper_status=self._pon.get_port().oper_status,
478 )
479 */
480 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000481 var ponPortNo uint32 = 1
482 if dh.ponPortNumber != 0 {
483 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000484 }
485
486 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000487 PortNo: ponPortNo,
488 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000489 Type: voltha.Port_PON_ONU,
490 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000491 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
492 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000493 }
494 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
495 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
496 e.Cancel(err)
497 return
498 }
499 logger.Debug("doStateInit-done")
500}
501
502// postInit setups the DeviceEntry for the conerned device
503func (dh *DeviceHandler) postInit(e *fsm.Event) {
504
505 logger.Debug("postInit-started")
506 var err error
507 /*
508 dh.Client = oop.NewOpenoltClient(dh.clientCon)
509 dh.pTransitionMap.Handle(ctx, GrpcConnected)
510 return nil
511 */
mpagenko3af1f032020-06-10 08:53:41 +0000512 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
513 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000514 e.Cancel(err)
515 return
516 }
517
518 /*
519 ############################################################################
520 # Setup Alarm handler
521 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
522 device.serial_number)
523 ############################################################################
524 # Setup PM configuration for this device
525 # Pass in ONU specific options
526 kwargs = {
527 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
528 'heartbeat': self.heartbeat,
529 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
530 }
531 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
532 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
533 self.logical_device_id, device.serial_number,
534 grouped=True, freq_override=False, **kwargs)
535 pm_config = self._pm_metrics.make_proto()
536 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
537 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
538 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
539
540 # Note, ONU ID and UNI intf set in add_uni_port method
541 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
542 ani_ports=[self._pon])
543
544 # Code to Run OMCI Test Action
545 kwargs_omci_test_action = {
546 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
547 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
548 }
549 serial_number = device.serial_number
550 self._test_request = OmciTestRequest(self.core_proxy,
551 self.omci_agent, self.device_id,
552 AniG, serial_number,
553 self.logical_device_id,
554 exclusive=False,
555 **kwargs_omci_test_action)
556
557 self.enabled = True
558 else:
559 self.logger.info('onu-already-activated')
560 */
561 logger.Debug("postInit-done")
562}
563
564// doStateConnected get the device info and update to voltha core
565// for comparison of the original method (not that easy to uncomment): compare here:
566// voltha-openolt-adapter/adaptercore/device_handler.go
567// -> this one obviously initiates all communication interfaces of the device ...?
568func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
569
570 logger.Debug("doStateConnected-started")
571 var err error
572 err = errors.New("Device FSM: function not implemented yet!")
573 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000574 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700575 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000576}
577
578// doStateUp handle the onu up indication and update to voltha core
579func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
580
581 logger.Debug("doStateUp-started")
582 var err error
583 err = errors.New("Device FSM: function not implemented yet!")
584 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000585 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700586 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000587
588 /*
589 // Synchronous call to update device state - this method is run in its own go routine
590 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
591 voltha.OperStatus_ACTIVE); err != nil {
592 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
593 return err
594 }
595 return nil
596 */
597}
598
599// doStateDown handle the onu down indication
600func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
601
602 logger.Debug("doStateDown-started")
603 var err error
604
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000605 device := dh.device
606 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000607 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000608 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000609 e.Cancel(err)
610 return
611 }
612
613 cloned := proto.Clone(device).(*voltha.Device)
614 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
615 /*
616 // Update the all ports state on that device to disable
617 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
618 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
619 return er
620 }
621
622 //Update the device oper state and connection status
623 cloned.OperStatus = voltha.OperStatus_UNKNOWN
624 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
625 dh.device = cloned
626
627 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
628 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
629 return er
630 }
631
632 //get the child device for the parent device
633 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
634 if err != nil {
635 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
636 return err
637 }
638 for _, onuDevice := range onuDevices.Items {
639
640 // Update onu state as down in onu adapter
641 onuInd := oop.OnuIndication{}
642 onuInd.OperState = "down"
643 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
644 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
645 if er != nil {
646 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
647 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
648 //Do not return here and continue to process other ONUs
649 }
650 }
651 // * Discovered ONUs entries need to be cleared , since after OLT
652 // is up, it starts sending discovery indications again* /
653 dh.discOnus = sync.Map{}
654 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
655 return nil
656 */
657 err = errors.New("Device FSM: function not implemented yet!")
658 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000659 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700660 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000661}
662
663// DeviceHandler StateMachine related state transition methods ##### end #########
664// #################################################################################
665
666// ###################################################
667// DeviceHandler utility methods ##### begin #########
668
mpagenko3af1f032020-06-10 08:53:41 +0000669//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
670func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
671 dh.lockDevice.RLock()
672 pOnuDeviceEntry := dh.pOnuOmciDevice
673 if aWait && pOnuDeviceEntry == nil {
674 //keep the read sema short to allow for subsequent write
675 dh.lockDevice.RUnlock()
676 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
677 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
678 // so it might be needed to wait here for that event with some timeout
679 select {
680 case <-time.After(60 * time.Second): //timer may be discussed ...
681 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
682 return nil
683 case <-dh.deviceEntrySet:
684 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
685 // if written now, we can return the written value without sema
686 return dh.pOnuOmciDevice
687 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000688 }
mpagenko3af1f032020-06-10 08:53:41 +0000689 dh.lockDevice.RUnlock()
690 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000691}
692
mpagenko3af1f032020-06-10 08:53:41 +0000693//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000694func (dh *DeviceHandler) SetOnuDeviceEntry(
695 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000696 dh.lockDevice.Lock()
697 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000698 dh.pOnuOmciDevice = apDeviceEntry
699 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000700 return nil
701}
702
mpagenko3af1f032020-06-10 08:53:41 +0000703//AddOnuDeviceEntry creates a new ONU device or returns the existing
704func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000705 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
706
mpagenko3af1f032020-06-10 08:53:41 +0000707 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000708 if deviceEntry == nil {
709 /* costum_me_map in python code seems always to be None,
710 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
711 /* also no 'clock' argument - usage open ...*/
712 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000713 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
714 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000715 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000716 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000717 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000718 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000719 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000720 // fire deviceEntry ready event to spread to possibly waiting processing
721 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000722 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
723 } else {
724 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
725 }
726 // might be updated with some error handling !!!
727 return nil
728}
729
730// doStateInit provides the device update to the core
731func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000732 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
733 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
734
735 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000736
mpagenko3af1f032020-06-10 08:53:41 +0000737 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
738 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000739 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
740 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000741 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
742 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
743 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
mpagenkoaf801632020-07-03 10:00:42 +0000744 // but I would not know why, and the go code anyway does not work with the device directly anymore in the OnuDeviceEntry
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000745 // so let's just try to keep it simple ...
746 /*
747 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
748 if err != nil || device == nil {
749 //TODO: needs to handle error scenarios
750 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
751 return errors.New("Voltha Device not found")
752 }
753 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000754
mpagenko3af1f032020-06-10 08:53:41 +0000755 pDevEntry := dh.GetOnuDeviceEntry(true)
756 if pDevEntry != nil {
757 pDevEntry.Start(context.TODO())
758 } else {
759 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
760 return errors.New("No valid OnuDevice")
761 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000762 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
763 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
764 }
mpagenko3af1f032020-06-10 08:53:41 +0000765 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000766
767 /* this might be a good time for Omci Verify message? */
768 verifyExec := make(chan bool)
769 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000770 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000771 true, true) //eclusive and allowFailure (anyway not yet checked)
772 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
773
774 /* give the handler some time here to wait for the OMCi verification result
775 after Timeout start and try MibUpload FSM anyway
776 (to prevent stopping on just not supported OMCI verification from ONU) */
777 select {
778 case <-time.After(2 * time.Second):
779 logger.Warn("omci start-verification timed out (continue normal)")
780 case testresult := <-verifyExec:
781 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
782 }
783
784 /* In py code it looks earlier (on activate ..)
785 # Code to Run OMCI Test Action
786 kwargs_omci_test_action = {
787 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
788 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
789 }
790 serial_number = device.serial_number
791 self._test_request = OmciTestRequest(self.core_proxy,
792 self.omci_agent, self.device_id,
793 AniG, serial_number,
794 self.logical_device_id,
795 exclusive=False,
796 **kwargs_omci_test_action)
797 ...
798 # Start test requests after a brief pause
799 if not self._test_request_started:
800 self._test_request_started = True
801 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
802 reactor.callLater(tststart, self._test_request.start_collector)
803
804 */
805 /* which is then: in omci_test_request.py : */
806 /*
807 def start_collector(self, callback=None):
808 """
809 Start the collection loop for an adapter if the frequency > 0
810
811 :param callback: (callable) Function to call to collect PM data
812 """
813 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
814 if callback is None:
815 callback = self.perform_test_omci
816
817 if self.lc is None:
818 self.lc = LoopingCall(callback)
819
820 if self.default_freq > 0:
821 self.lc.start(interval=self.default_freq / 10)
822
823 def perform_test_omci(self):
824 """
825 Perform the initial test request
826 """
827 ani_g_entities = self._device.configuration.ani_g_entities
828 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
829 is not None else None
830 self._entity_id = ani_g_entities_ids[0]
831 self.logger.info('perform-test', entity_class=self._entity_class,
832 entity_id=self._entity_id)
833 try:
834 frame = MEFrame(self._entity_class, self._entity_id, []).test()
835 result = yield self._device.omci_cc.send(frame)
836 if not result.fields['omci_message'].fields['success_code']:
837 self.logger.info('Self-Test Submitted Successfully',
838 code=result.fields[
839 'omci_message'].fields['success_code'])
840 else:
841 raise TestFailure('Test Failure: {}'.format(
842 result.fields['omci_message'].fields['success_code']))
843 except TimeoutError as e:
844 self.deferred.errback(failure.Failure(e))
845
846 except Exception as e:
847 self.logger.exception('perform-test-Error', e=e,
848 class_id=self._entity_class,
849 entity_id=self._entity_id)
850 self.deferred.errback(failure.Failure(e))
851
852 */
853
854 // PM related heartbeat??? !!!TODO....
855 //self._heartbeat.enabled = True
856
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000857 //call MibUploadFSM - transition up to state "in_sync"
mpagenko3af1f032020-06-10 08:53:41 +0000858 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000859 if pMibUlFsm != nil {
860 if pMibUlFsm.Is("disabled") {
861 if err := pMibUlFsm.Event("start"); err != nil {
862 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
863 return errors.New("Can't go to state starting")
864 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000865 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000866 //Determine ONU status and start/re-start MIB Synchronization tasks
867 //Determine if this ONU has ever synchronized
868 if true { //TODO: insert valid check
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000869 if err := pMibUlFsm.Event("reset_mib"); err != nil {
870 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
871 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000872 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000873 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000874 pMibUlFsm.Event("examine_mds")
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000875 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000876 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000877 // callbacks to be handled:
878 // Event("success")
879 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000880 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000881 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000882 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000883 } else {
884 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
885 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000886 }
887 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000888 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000889 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000890 }
891 return nil
892}
893
mpagenko3af1f032020-06-10 08:53:41 +0000894func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
895 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
896 if dh.deviceReason != "stopping-openomci" {
897 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
898 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
899 pDevEntry := dh.GetOnuDeviceEntry(false)
900 if pDevEntry == nil {
901 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
902 return errors.New("No valid OnuDevice")
903 }
904
905 switch dh.deviceReason {
906 case "starting-openomci":
907 { //MIBSync FSM may run
908 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
909 if pMibUlFsm != nil {
910 pMibUlFsm.Event("stop") //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
911 }
912 }
913 case "discovery-mibsync-complete":
914 { //MibDownload may run
915 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
916 if pMibDlFsm != nil {
917 pMibDlFsm.Event("reset")
918 }
919 }
920 default:
921 { //port lock/unlock FSM's may be active
922 if dh.pUnlockStateFsm != nil {
923 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
924 }
925 if dh.pLockStateFsm != nil {
926 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
927 }
928 }
929 //TODO!!! care about PM/Alarm processing once started
930 }
931 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
932 // (mainly the still seperate 'Event states')
933 // so it is questionable, how this is resolved after some possible re-enable
934 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
935
936 //stop/remove(?) the device entry
937 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
938
939 //TODO!!! remove existing traffic profiles
940 /* from py code, if TP's exist, remove them - not yet implemented
941 self._tp = dict()
942 # Let TP download happen again
943 for uni_id in self._tp_service_specific_task:
944 self._tp_service_specific_task[uni_id].clear()
945 for uni_id in self._tech_profile_download_done:
946 self._tech_profile_download_done[uni_id].clear()
947 */
948
949 dh.disableUniPortStateUpdate()
950
951 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
952 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
953 log.Fields{"deviceID": dh.deviceID, "error": err})
954 // abort: system behavior is just unstable ...
955 return err
956 }
957 dh.deviceReason = "stopping-openomci"
958
959 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
960 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
961 logger.Errorw("error-updating-device-state unreachable-discovered",
962 log.Fields{"deviceID": dh.deviceID, "error": err})
963 // abort: system behavior is just unstable ...
964 return err
965 }
966 } else {
967 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
968 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000969 return nil
970}
971
mpagenko3af1f032020-06-10 08:53:41 +0000972//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000973func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
974 switch dev_Event {
975 case MibDatabaseSync:
976 {
977 logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
978 //initiate DevStateUpdate
979 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
980 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
981 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000982 }
mpagenko3af1f032020-06-10 08:53:41 +0000983 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000984
mpagenko3af1f032020-06-10 08:53:41 +0000985 pDevEntry := dh.GetOnuDeviceEntry(false)
986 unigMap, ok := pDevEntry.pOnuDB.meDb[me.UniGClassID]
987 unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(unigMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000988 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
989 if ok {
990 for _, mgmtEntityId := range unigInstKeys {
991 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
992 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
993 dh.addUniPort(mgmtEntityId, i, UniPPTP)
994 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000995 }
996 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000997 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000998 }
mpagenko3af1f032020-06-10 08:53:41 +0000999 veipMap, ok := pDevEntry.pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
1000 veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(veipMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001001 if ok {
1002 for _, mgmtEntityId := range veipInstKeys {
1003 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1004 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1005 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1006 i++
1007 }
1008 } else {
1009 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1010 }
1011 if i == 0 {
1012 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1013 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001014
mpagenko3af1f032020-06-10 08:53:41 +00001015 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1016 * left the code here as comment in case such processing should prove needed unexpectedly
1017 // Init Uni Ports to Admin locked state
1018 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1019 // *** should generate UniLockStateDone event *****
1020 if dh.pLockStateFsm == nil {
1021 dh.createUniLockFsm(true, UniLockStateDone)
1022 } else { //LockStateFSM already init
1023 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1024 dh.runUniLockFsm(true)
1025 }
1026 }
1027 case UniLockStateDone:
1028 {
1029 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1030 * lockState processing commented out
1031 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001032 /* Mib download procedure -
1033 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1034 */
mpagenko3af1f032020-06-10 08:53:41 +00001035 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001036 if pMibDlFsm != nil {
1037 if pMibDlFsm.Is("disabled") {
1038 if err := pMibDlFsm.Event("start"); err != nil {
1039 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1040 // maybe try a FSM reset and then again ... - TODO!!!
1041 } else {
1042 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1043 // maybe use more specific states here for the specific download steps ...
1044 if err := pMibDlFsm.Event("create_gal"); err != nil {
1045 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1046 } else {
1047 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1048 //Begin MIB data download (running autonomously)
1049 }
1050 }
1051 } else {
1052 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1053 // maybe try a FSM reset and then again ... - TODO!!!
1054 }
1055 /***** Mib download started */
1056 } else {
1057 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1058 }
1059 }
1060 case MibDownloadDone:
1061 {
1062 logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
1063 //initiate DevStateUpdate
1064 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1065 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1066 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
1067 }
mpagenko3af1f032020-06-10 08:53:41 +00001068
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001069 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
1070 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1071 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1072 log.Fields{"deviceID": dh.deviceID, "error": err})
1073 }
mpagenko3af1f032020-06-10 08:53:41 +00001074 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001075
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001076 // *** should generate UniUnlockStateDone event *****
1077 if dh.pUnlockStateFsm == nil {
1078 dh.createUniLockFsm(false, UniUnlockStateDone)
1079 } else { //UnlockStateFSM already init
1080 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1081 dh.runUniLockFsm(false)
1082 }
1083 }
1084 case UniUnlockStateDone:
1085 {
mpagenko3af1f032020-06-10 08:53:41 +00001086 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001087
1088 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1089 raisedTs := time.Now().UnixNano()
1090 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1091 }
1092 default:
1093 {
1094 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1095 }
1096 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001097}
1098
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001099func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001100 // parameters are IntfId, OnuId, uniId
1101 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1102 uint32(a_uniId))
1103 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001104 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1105 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001106 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001107 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001108 if pUniPort == nil {
1109 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1110 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001111 //store UniPort with the System-PortNumber key
1112 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001113 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001114 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1115 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1116 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001117 }
1118 }
1119}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001120
mpagenko3af1f032020-06-10 08:53:41 +00001121// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1122func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001123 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1124 // but towards core only the first port active state is signalled
1125 // with following remark:
1126 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1127 // # load on the core
1128
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001129 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001130
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001131 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001132 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001133 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1134 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1135 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1136 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001137 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1138 }
1139 }
1140}
1141
1142// Disable UniPortState and update core port state accordingly
1143func (dh *DeviceHandler) disableUniPortStateUpdate() {
1144 // compare enableUniPortStateUpdate() above
1145 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1146 for uniNo, uniPort := range dh.uniEntityMap {
1147 // only if this port is validated for operState transfer
1148 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1149 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1150 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1151 //maybe also use getter functions on uniPort - perhaps later ...
1152 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001153 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001154 }
1155}
1156
1157// ONU_Active/Inactive announcement on system KAFKA bus
1158// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1159func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1160 var de voltha.DeviceEvent
1161 eventContext := make(map[string]string)
1162 //Populating event context
1163 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1164 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1165 if err != nil || parentDevice == nil {
1166 logger.Errorw("Failed to fetch parent device for OnuEvent",
1167 log.Fields{"parentId": dh.parentId, "err": err})
1168 }
1169 oltSerialNumber := parentDevice.SerialNumber
1170
1171 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1172 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1173 eventContext["serial-number"] = dh.device.SerialNumber
1174 eventContext["olt_serial_number"] = oltSerialNumber
1175 eventContext["device_id"] = a_deviceID
1176 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1177 logger.Debugw("prepare ONU_ACTIVATED event",
1178 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1179
1180 /* Populating device event body */
1181 de.Context = eventContext
1182 de.ResourceId = a_deviceID
1183 if a_OperState == voltha.OperStatus_ACTIVE {
1184 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1185 de.Description = fmt.Sprintf("%s Event - %s - %s",
1186 cEventObjectType, cOnuActivatedEvent, "Raised")
1187 } else {
1188 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1189 de.Description = fmt.Sprintf("%s Event - %s - %s",
1190 cEventObjectType, cOnuActivatedEvent, "Cleared")
1191 }
1192 /* Send event to KAFKA */
1193 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1194 logger.Warnw("could not send ONU_ACTIVATED event",
1195 log.Fields{"DeviceId": a_deviceID, "error": err})
1196 }
1197 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1198 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1199}
1200
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001201// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1202func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1203 chLSFsm := make(chan Message, 2048)
1204 var sFsmName string
1205 if aAdminState == true {
1206 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1207 sFsmName = "LockStateFSM"
1208 } else {
1209 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1210 sFsmName = "UnLockStateFSM"
1211 }
mpagenko3af1f032020-06-10 08:53:41 +00001212
1213 pDevEntry := dh.GetOnuDeviceEntry(true)
1214 if pDevEntry == nil {
1215 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1216 return
1217 }
1218 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001219 sFsmName, dh.deviceID, chLSFsm)
1220 if pLSFsm != nil {
1221 if aAdminState == true {
1222 dh.pLockStateFsm = pLSFsm
1223 } else {
1224 dh.pUnlockStateFsm = pLSFsm
1225 }
1226 dh.runUniLockFsm(aAdminState)
1227 } else {
1228 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1229 }
1230}
1231
1232// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1233func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1234 /* Uni Port lock/unlock procedure -
1235 ***** should run via 'adminDone' state and generate the argument requested event *****
1236 */
1237 var pLSStatemachine *fsm.FSM
1238 if aAdminState == true {
1239 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1240 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1241 if (dh.pUnlockStateFsm != nil) &&
1242 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1243 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1244 }
1245 } else {
1246 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1247 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1248 if (dh.pLockStateFsm != nil) &&
1249 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1250 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1251 }
1252 }
1253 if pLSStatemachine != nil {
1254 if pLSStatemachine.Is("disabled") {
1255 if err := pLSStatemachine.Event("start"); err != nil {
1256 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1257 // maybe try a FSM reset and then again ... - TODO!!!
1258 } else {
1259 /***** LockStateFSM started */
1260 logger.Debugw("LockStateFSM started", log.Fields{
1261 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1262 }
1263 } else {
1264 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1265 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1266 // maybe try a FSM reset and then again ... - TODO!!!
1267 }
1268 } else {
1269 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1270 // maybe try a FSM reset and then again ... - TODO!!!
1271 }
1272}
1273
mpagenkoaf801632020-07-03 10:00:42 +00001274//SetBackend provides a DB backend for the specified path on the existing KV client
1275func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1276 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1277 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
1278 "BasePathKvStore": aBasePathKvStore, "deviceId": dh.deviceID})
1279 kvbackend := &db.Backend{
1280 Client: dh.pOpenOnuAc.kvClient,
1281 StoreType: dh.pOpenOnuAc.KVStoreType,
1282 /* address config update acc. to [VOL-2736] */
1283 Address: addr,
1284 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1285 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001286
mpagenkoaf801632020-07-03 10:00:42 +00001287 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001288}