blob: 2d0643b4602b2ceee8ece35e4276581642a7f71d [file] [log] [blame]
Elia Battistone8d1fa42022-04-01 10:47:37 +02001/*
Joey Armstrong14628cd2023-01-10 08:38:31 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Elia Battistone8d1fa42022-04-01 10:47:37 +02003
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
17package dmiserver
18
19import (
20 "context"
21 "fmt"
22
23 "github.com/opencord/bbsim/api/bbsim"
24 "github.com/opencord/bbsim/internal/bbsim/devices"
25 dmi "github.com/opencord/device-management-interface/go/dmi"
26 log "github.com/sirupsen/logrus"
27 "google.golang.org/grpc/codes"
28 "google.golang.org/protobuf/types/known/timestamppb"
29)
30
31const (
32 ponInterfaceType = "pon"
33 alarmStatusRaise = "on"
34 alarmStatusClear = "off"
35)
36
37type Transceiver struct {
38 ID uint32
39 Uuid string
40 Name string
41 Pons []*devices.PonPort
42 Technology dmi.TransceiverType
43 //Setting this bool will prevent the transceiver
44 //from being plugged out while already out, and
45 //plugged in while already in, but won't prevent
46 //the associated PONs from being enabled in other
47 //ways while the transceiver is plugged out
48 PluggedIn bool
49}
50
51func newTransceiver(id uint32, pons []*devices.PonPort) *Transceiver {
52 return &Transceiver{
53 ID: id,
54 Uuid: getTransceiverUUID(id).Uuid,
55 Name: getTransceiverName(id),
56 Pons: pons,
57 Technology: dmi.TransceiverType_TYPE_UNDEFINED,
58 PluggedIn: true,
59 }
60}
61
62func getTransceiverWithId(transId uint32, dms *DmiAPIServer) (*Transceiver, error) {
63 for _, t := range dms.Transceivers {
64 if t.ID == transId {
65 return t, nil
66 }
67 }
68
69 return nil, fmt.Errorf("Cannot find transceiver with ID %d", transId)
70}
71
72/////// Handler methods for grpc API
73
74func (s DmiAPIServer) GetTransceivers(ctx context.Context, req *bbsim.DmiEmpty) (*bbsim.Transceivers, error) {
75 res := &bbsim.Transceivers{
76 Items: []*bbsim.Transceiver{},
77 }
78
79 for _, t := range s.Transceivers {
80 item := bbsim.Transceiver{
81 ID: t.ID,
82 UUID: t.Uuid,
83 Name: t.Name,
84 Technology: t.Technology.String(),
85 PluggedIn: t.PluggedIn,
86 PonIds: []uint32{},
87 }
88
89 for _, pon := range t.Pons {
90 item.PonIds = append(item.PonIds, pon.ID)
91 }
92
93 res.Items = append(res.Items, &item)
94 }
95
96 return res, nil
97}
98
99// PlugOutTransceiver plugs out the transceiver by its ID
100func (s DmiAPIServer) PlugOutTransceiver(ctx context.Context, req *bbsim.TransceiverRequest) (*bbsim.DmiResponse, error) {
101 logger.WithFields(log.Fields{
102 "IntfId": req.TransceiverId,
103 }).Infof("Received request to plug out PON transceiver")
104
105 res := &bbsim.DmiResponse{}
106 olt := devices.GetOLT()
107
108 //Generate DMI event
109 dmiServ, err := getDmiAPIServer()
110 if err != nil {
111 res.StatusCode = int32(codes.Unavailable)
112 res.Message = fmt.Sprintf("Cannot get DMI server instance: %v", err)
113 return res, nil
114 }
115
116 trans, err := getTransceiverWithId(req.TransceiverId, dmiServ)
117 if err != nil {
118 res.StatusCode = int32(codes.NotFound)
119 res.Message = fmt.Sprintf("Cannot find transceiver with ID %d: %v", req.TransceiverId, err)
120 return res, nil
121 }
122
123 if !trans.PluggedIn {
124 res.StatusCode = int32(codes.Aborted)
125 res.Message = fmt.Sprintf("Cannot plug out transceiver with ID %d since it's not plugged in", req.TransceiverId)
126 return res, nil
127 }
128
129 err = PlugoutTransceiverComponent(req.TransceiverId, dmiServ)
130 if err != nil {
131 res.StatusCode = int32(codes.NotFound)
132 res.Message = fmt.Sprintf("Cannot remove transceiver with ID %d: %v", req.TransceiverId, err)
133 return res, nil
134 }
135 logger.Debug("Removed transceiver from DMI inventory")
136
137 if olt.InternalState.Is(devices.OltInternalStateEnabled) {
138 logger.Debug("Sending alarms for transceiver plug out")
139 for _, pon := range trans.Pons {
140 if pon.InternalState.Is("enabled") {
141
142 if err = olt.SetAlarm(pon.ID, ponInterfaceType, alarmStatusRaise); err != nil {
143 logger.WithFields(log.Fields{
144 "ponId": pon.ID,
145 "err": err,
146 }).Error("Cannot raise LOS alarm for PON")
147 }
148
149 if err = pon.InternalState.Event("disable"); err != nil {
150 logger.WithFields(log.Fields{
151 "ponId": pon.ID,
152 "err": err,
153 }).Error("Cannot disable PON")
154 continue
155 }
156
157 for _, onu := range pon.Onus {
158 if err := onu.SetAlarm(bbsim.AlarmType_ONU_ALARM_LOS.String(), alarmStatusRaise); err != nil {
159 logger.WithFields(log.Fields{
160 "ponId": pon.ID,
161 "onuId": onu.ID,
162 "err": err,
163 }).Error("Cannot raise LOS alarm for ONU")
164 }
165 }
166 }
167 }
168 } else {
169 logger.Debug("No operation on devices since the OLT is not enabled")
170 }
171
172 event := dmi.Event{
173 EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT,
174 EventMetadata: &dmi.EventMetaData{
175 DeviceUuid: dmiServ.uuid,
176 ComponentUuid: &dmi.Uuid{
177 Uuid: trans.Uuid,
178 },
179 ComponentName: trans.Name,
180 },
181 RaisedTs: timestamppb.Now(),
182 }
183
184 sendOutEventOnKafka(event, dmiServ)
185 logger.Debug("Transceiver plug out event sent")
186
187 res.StatusCode = int32(codes.OK)
188 res.Message = fmt.Sprintf("Plugged out transceiver %d", req.TransceiverId)
189
190 return res, nil
191}
192
193// PlugInTransceiver plugs in the transceiver by its ID
194func (s DmiAPIServer) PlugInTransceiver(ctx context.Context, req *bbsim.TransceiverRequest) (*bbsim.DmiResponse, error) {
195 logger.WithFields(log.Fields{
196 "IntfId": req.TransceiverId,
197 }).Infof("Received request to plug in PON transceiver")
198
199 res := &bbsim.DmiResponse{}
200 olt := devices.GetOLT()
201
202 //Generate DMI event
203 dmiServ, err := getDmiAPIServer()
204 if err != nil {
205 res.StatusCode = int32(codes.Unavailable)
206 res.Message = fmt.Sprintf("Cannot get DMI server instance: %v", err)
207 return res, nil
208 }
209
210 trans, err := getTransceiverWithId(req.TransceiverId, dmiServ)
211 if err != nil {
212 res.StatusCode = int32(codes.NotFound)
213 res.Message = fmt.Sprintf("Cannot find transceiver with ID %d: %v", req.TransceiverId, err)
214 return res, nil
215 }
216
217 if trans.PluggedIn {
218 res.StatusCode = int32(codes.Aborted)
219 res.Message = fmt.Sprintf("Cannot plug in transceiver with ID %d since it's already plugged in", req.TransceiverId)
220 return res, nil
221 }
222
223 err = PluginTransceiverComponent(req.TransceiverId, dmiServ)
224 if err != nil {
225 res.StatusCode = int32(codes.NotFound)
226 res.Message = fmt.Sprintf("Cannot add transceiver with ID %d: %v", req.TransceiverId, err)
227 return res, nil
228 }
229 logger.Debug("Added transceiver to DMI inventory")
230
231 if olt.InternalState.Is(devices.OltInternalStateEnabled) {
232 logger.Debug("Sending alarms for transceiver plug in")
233 for _, pon := range trans.Pons {
234
235 if err = olt.SetAlarm(pon.ID, ponInterfaceType, alarmStatusClear); err != nil {
236 logger.WithFields(log.Fields{
237 "ponId": pon.ID,
238 "err": err,
239 }).Error("Cannot clear LOS alarm for ONU")
240 }
241
242 if err = pon.InternalState.Event("enable"); err != nil {
243 logger.WithFields(log.Fields{
244 "ponId": pon.ID,
245 "err": err,
246 }).Error("Cannot enable PON")
247 continue
248 }
249
250 for _, onu := range pon.Onus {
251 if err := onu.SetAlarm(bbsim.AlarmType_ONU_ALARM_LOS.String(), alarmStatusClear); err != nil {
252 logger.WithFields(log.Fields{
253 "ponId": pon.ID,
254 "onuId": onu.ID,
255 "err": err,
256 }).Error("Cannot clear LOS alarm for ONU")
257 }
258 }
259 }
260 } else {
261 logger.Debug("No operation on devices since the OLT is not enabled")
262 }
263
264 event := dmi.Event{
265 EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN,
266 EventMetadata: &dmi.EventMetaData{
267 DeviceUuid: dmiServ.uuid,
268 ComponentUuid: &dmi.Uuid{
269 Uuid: trans.Uuid,
270 },
271 ComponentName: trans.Name,
272 },
273 RaisedTs: timestamppb.Now(),
274 }
275
276 sendOutEventOnKafka(event, dmiServ)
277 logger.Debug("Transceiver plug in event sent")
278
279 res.StatusCode = int32(codes.OK)
280 res.Message = fmt.Sprintf("Plugged in transceiver %d", req.TransceiverId)
281
282 return res, nil
283}