blob: f09b036a73fbf82592f0821d1309ac931f36a393 [file] [log] [blame]
Zdravko Bozakov7401ff22019-05-28 22:45:12 +02001/*
2 * Copyright 2018-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
17package core
18
19import (
20 "context"
21 "net"
22 "net/http"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020023
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020024 "github.com/grpc-ecosystem/grpc-gateway/runtime"
Zdravko Bozakov078a2712019-07-19 23:25:15 +020025 api "github.com/opencord/voltha-bbsim/api"
Zack Williams2abf3932019-08-05 14:07:05 -070026 "github.com/opencord/voltha-bbsim/common/logger"
27 "github.com/opencord/voltha-bbsim/device"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020028 "google.golang.org/grpc"
29 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020031)
32
33// Response Constants
34const (
35 RequestAccepted = "API request accepted"
36 OLTNotEnabled = "OLT not enabled"
37 RequestFailed = "API request failed"
38 SoftReboot = "soft-reboot"
39 HardReboot = "hard-reboot"
40 DeviceTypeOlt = "olt"
41 DeviceTypeOnu = "onu"
42)
43
44// OLTStatus method returns OLT status.
Zdravko Bozakov078a2712019-07-19 23:25:15 +020045func (s *Server) OLTStatus(ctx context.Context, in *api.Empty) (*api.OLTStatusResponse, error) {
46 logger.Trace("OLTStatus request received")
47 oltInfo := &api.OLTStatusResponse{
48 Olt: &api.OLTInfo{
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020049 OltId: int64(s.Olt.ID),
50 OltSerial: s.Olt.SerialNumber,
51 OltIp: getOltIP().String(),
52 OltState: s.Olt.OperState,
53 OltVendor: s.Olt.Manufacture,
54 },
55 }
56
57 for _, nniPort := range s.Olt.NniIntfs {
58 nniPortInfo, _ := s.fetchPortDetail(nniPort.IntfID, nniPort.Type)
59 oltInfo.Ports = append(oltInfo.Ports, nniPortInfo)
60 }
61 for _, ponPort := range s.Olt.PonIntfs {
62 ponPortInfo, _ := s.fetchPortDetail(ponPort.IntfID, ponPort.Type)
63 oltInfo.Ports = append(oltInfo.Ports, ponPortInfo)
64 }
65
66 logger.Info("OLT Info: %v\n", oltInfo)
67 return oltInfo, nil
68}
69
70// PortStatus method returns Port status.
Zdravko Bozakov078a2712019-07-19 23:25:15 +020071func (s *Server) PortStatus(ctx context.Context, in *api.PortInfo) (*api.Ports, error) {
72 logger.Trace("PortStatus() invoked")
73 ports := &api.Ports{}
74 portInfo, err := s.fetchPortDetail(in.PortId, in.PortType)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020075
Zdravko Bozakov078a2712019-07-19 23:25:15 +020076 if err != nil {
77 return &api.Ports{}, status.Errorf(codes.InvalidArgument, err.Error())
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020078 }
Zdravko Bozakov078a2712019-07-19 23:25:15 +020079
80 ports.Ports = append(ports.Ports, portInfo)
81 return ports, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020082}
83
84// ONUStatus method returns ONU status.
Zdravko Bozakov078a2712019-07-19 23:25:15 +020085func (s *Server) ONUStatus(ctx context.Context, in *api.ONURequest) (*api.ONUs, error) {
86 logger.Trace("ONUStatus request received")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020087 if in.GetOnu() != nil {
88 logger.Debug("Received single ONU: %+v, %d\n", in.GetOnu(), in.GetOnu().PonPortId)
89 return s.handleONUStatusRequest(in.GetOnu())
90 }
Zdravko Bozakov078a2712019-07-19 23:25:15 +020091
92 logger.Debug("Received all ONUS status request")
93 onuInfo := &api.ONUs{}
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020094 for intfid := range s.Onumap {
95 for _, onu := range s.Onumap[intfid] {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020096 if onu.InternalState != device.OnuFree {
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020097 onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(onu))
98 }
99 }
100 }
101 return onuInfo, nil
102}
103
104// ONUActivate method handles ONU activate requests from user.
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200105func (s *Server) ONUActivate(ctx context.Context, in *api.ONURequest) (*api.BBSimResponse, error) {
106 logger.Trace("ONUActivate request received")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200107 logger.Debug("Received values: %+v\n", in)
108
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200109 var onuInfo []*api.ONUInfo
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200110 // Activate single ONU
111 if in.GetOnu() != nil {
112 logger.Debug("Received single ONU: %+v\n", in.GetOnu())
113 onuInfo = append(onuInfo, in.GetOnu())
114 } else if len(in.GetOnusBatch().GetOnus()) != 0 { // Activate multiple ONUs
115 logger.Debug("Received multiple ONUs")
116 onuInfo = in.GetOnusBatch().GetOnus()
117 } else {
118 logger.Debug("Received empty request body")
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200119 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, RequestFailed)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200120 }
121 resp, err := s.handleONUActivate(onuInfo)
122 return resp, err
123}
124
125// ONUDeactivate method handles ONU deactivation request.
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200126func (s *Server) ONUDeactivate(ctx context.Context, in *api.ONURequest) (*api.BBSimResponse, error) {
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200127 logger.Info("ONUDeactivate request received")
128
129 // deactivate single ONU
130 if in.GetOnu() != nil {
131 logger.Debug("Received single ONU: %+v\n", in.GetOnu())
132 err := s.handleONUDeactivate(in.GetOnu())
133 if err != nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200134 return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200135 }
136 } else if len(in.GetOnusBatch().GetOnus()) != 0 { // bulk deactivate
137 logger.Debug("Received multiple ONUs")
138 for _, onuinfo := range in.GetOnusBatch().GetOnus() {
139 logger.Debug("ONU values: %+v\n", onuinfo)
140 err := s.handleONUDeactivate(onuinfo)
141 if err != nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200142 return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200143 }
144 }
145 } else {
146 // Empty request body is passed, delete all ONUs from all PON ports
147 for intfID := range s.Onumap {
148 if err := s.DeactivateAllOnuByIntfID(intfID); err != nil {
149 logger.Error("Failed in ONUDeactivate: %v", err)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200150 return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200151 }
152 }
153 }
154
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200155 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
156
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200157}
158
159// GenerateONUAlarm RPC generates alarm for the onu
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200160func (s *Server) GenerateONUAlarm(ctx context.Context, in *api.ONUAlarmRequest) (*api.BBSimResponse, error) {
161 logger.Trace("GenerateONUAlarms() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200162 if in.OnuSerial == "" {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200163 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "serial number can not be blank")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200164 }
165 if len(in.OnuSerial) != SerialNumberLength {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200166 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid serial number given (length mismatch)")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200167 }
168 if in.Status != "on" && in.Status != "off" {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200169 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200170 }
171 if s.alarmCh == nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200172 return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "alarm-channel not created, can not send alarm")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200173 }
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200174 resp, err := s.handleOnuAlarm(in)
175 return resp, err
176}
177
178// GenerateOLTAlarm RPC generates alarm for the OLT
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200179func (s *Server) GenerateOLTAlarm(ctx context.Context, in *api.OLTAlarmRequest) (*api.BBSimResponse, error) {
180 logger.Trace("GenerateOLTAlarm() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200181 if in.Status != "on" && in.Status != "off" {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200182 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200183 }
184 if s.alarmCh == nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200185 return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "alarm-channel not created, can not send alarm")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200186 }
187 resp, err := s.handleOltAlarm(in)
188 if err != nil {
189 return resp, err
190 }
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200191 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200192}
193
194// PerformDeviceAction rpc take the device request and performs OLT and ONU hard and soft reboot
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200195func (s *Server) PerformDeviceAction(ctx context.Context, in *api.DeviceAction) (*api.BBSimResponse, error) {
196 logger.Trace("PerformDeviceAction() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200197 if s.deviceActionCh == nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200198 return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "device action channel not created, can not entertain request")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200199 }
200 in, err := s.validateDeviceActionRequest(in)
201 if err != nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200202 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200203 }
204 s.deviceActionCh <- in
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200205 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
206}
207
208// GetFlows returns all flows or flows for specified ONU
209func (s *Server) GetFlows(ctx context.Context, in *api.ONUInfo) (*api.Flows, error) {
210 logger.Info("GetFlow request received")
211 flows := &api.Flows{}
212 if in.OnuSerial == "" {
213 for _, flow := range s.FlowMap {
214 flowInfo := flow
215 flows.Flows = append(flows.Flows, flowInfo)
216 }
217 } else {
218 serialNumber, err := getOpenoltSerialNumber(in.OnuSerial)
219 if err != nil {
220 return flows, status.Errorf(codes.InvalidArgument, err.Error())
221 }
222 onu, found := s.getOnuFromSNmap(serialNumber)
223 if !found {
224 return flows, status.Errorf(codes.InvalidArgument, "ONU with serial number %s not activated yet", in.OnuSerial)
225 }
226 for _, flowKey := range onu.Flows {
227 flow := s.FlowMap[flowKey]
228 flowInfo := flow
229 flows.Flows = append(flows.Flows, flowInfo)
230 }
231 }
232 return flows, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200233}
234
235// NewMgmtAPIServer method starts BBSim gRPC server.
236func NewMgmtAPIServer(addrport string) (l net.Listener, g *grpc.Server, e error) {
237 logger.Info("BBSim gRPC server listening %s ...", addrport)
238 g = grpc.NewServer()
239 l, e = net.Listen("tcp", addrport)
240 return
241}
242
243// StartRestGatewayService method starts REST server for BBSim.
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200244func StartRestGatewayService(grpcAddress string, hostandport string) {
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200245 ctx := context.Background()
246 ctx, cancel := context.WithCancel(ctx)
247 defer cancel()
248
249 mux := runtime.NewServeMux()
250 opts := []grpc.DialOption{grpc.WithInsecure()}
251 // Register REST endpoints
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200252 err := api.RegisterBBSimServiceHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200253 if err != nil {
254 logger.Error("%v", err)
255 return
256 }
257
258 logger.Info("BBSim REST server listening %s ...", hostandport)
259 err = http.ListenAndServe(hostandport, mux)
260 if err != nil {
261 logger.Error("%v", err)
262 return
263 }
264 return
265}