blob: 1800e9e412151507815114916c8200eb0bff9e46 [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"
23 "sync"
24
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020025 pb "gerrit.opencord.org/voltha-bbsim/api"
Keita NISHIMOTO9617c852019-06-17 21:46:44 +090026 "gerrit.opencord.org/voltha-bbsim/common/logger"
27 "gerrit.opencord.org/voltha-bbsim/device"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020028 "github.com/grpc-ecosystem/grpc-gateway/runtime"
29 "google.golang.org/grpc"
30 "google.golang.org/grpc/codes"
31 "google.golang.org/grpc/status"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020032)
33
34// Response Constants
35const (
36 RequestAccepted = "API request accepted"
37 OLTNotEnabled = "OLT not enabled"
38 RequestFailed = "API request failed"
39 SoftReboot = "soft-reboot"
40 HardReboot = "hard-reboot"
41 DeviceTypeOlt = "olt"
42 DeviceTypeOnu = "onu"
43)
44
45// OLTStatus method returns OLT status.
46func (s *Server) OLTStatus(ctx context.Context, in *pb.Empty) (*pb.OLTStatusResponse, error) {
47 logger.Debug("OLTStatus request received")
48 oltInfo := &pb.OLTStatusResponse{
49 Olt: &pb.OLTInfo{
50 OltId: int64(s.Olt.ID),
51 OltSerial: s.Olt.SerialNumber,
52 OltIp: getOltIP().String(),
53 OltState: s.Olt.OperState,
54 OltVendor: s.Olt.Manufacture,
55 },
56 }
57
58 for _, nniPort := range s.Olt.NniIntfs {
59 nniPortInfo, _ := s.fetchPortDetail(nniPort.IntfID, nniPort.Type)
60 oltInfo.Ports = append(oltInfo.Ports, nniPortInfo)
61 }
62 for _, ponPort := range s.Olt.PonIntfs {
63 ponPortInfo, _ := s.fetchPortDetail(ponPort.IntfID, ponPort.Type)
64 oltInfo.Ports = append(oltInfo.Ports, ponPortInfo)
65 }
66
67 logger.Info("OLT Info: %v\n", oltInfo)
68 return oltInfo, nil
69}
70
71// PortStatus method returns Port status.
72func (s *Server) PortStatus(ctx context.Context, in *pb.PortInfo) (*pb.Ports, error) {
73 portInfo := &pb.Ports{}
74 logger.Debug("PortStatus() invoked")
75 if in.PortType == device.IntfNni {
76 for _, nniPort := range s.Olt.NniIntfs {
77 nniPortInfo, _ := s.fetchPortDetail(nniPort.IntfID, nniPort.Type)
78 portInfo.Ports = append(portInfo.Ports, nniPortInfo)
79 }
80 } else if in.PortType == device.IntfPon {
81 for _, ponPort := range s.Olt.PonIntfs {
82 ponPortInfo, _ := s.fetchPortDetail(ponPort.IntfID, ponPort.Type)
83 portInfo.Ports = append(portInfo.Ports, ponPortInfo)
84 }
85 } else {
86 return &pb.Ports{}, status.Errorf(codes.InvalidArgument, "Invalid port type")
87
88 }
89 return portInfo, nil
90}
91
92// ONUStatus method returns ONU status.
93func (s *Server) ONUStatus(ctx context.Context, in *pb.ONURequest) (*pb.ONUs, error) {
94 logger.Debug("ONUStatus request received")
95 if in.GetOnu() != nil {
96 logger.Debug("Received single ONU: %+v, %d\n", in.GetOnu(), in.GetOnu().PonPortId)
97 return s.handleONUStatusRequest(in.GetOnu())
98 }
99 logger.Debug("Received bulk ONUs status request")
100 onuInfo := &pb.ONUs{}
101 for intfid := range s.Onumap {
102 for _, onu := range s.Onumap[intfid] {
103 if onu.InternalState != device.ONU_FREE {
104 onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(onu))
105 }
106 }
107 }
108 return onuInfo, nil
109}
110
111// ONUActivate method handles ONU activate requests from user.
112func (s *Server) ONUActivate(ctx context.Context, in *pb.ONURequest) (*pb.BBSimResponse, error) {
113 logger.Info("ONUActivate request received")
114 logger.Debug("Received values: %+v\n", in)
115
116 var onuInfo = []*pb.ONUInfo{}
117 // Activate single ONU
118 if in.GetOnu() != nil {
119 logger.Debug("Received single ONU: %+v\n", in.GetOnu())
120 onuInfo = append(onuInfo, in.GetOnu())
121 } else if len(in.GetOnusBatch().GetOnus()) != 0 { // Activate multiple ONUs
122 logger.Debug("Received multiple ONUs")
123 onuInfo = in.GetOnusBatch().GetOnus()
124 } else {
125 logger.Debug("Received empty request body")
126 return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, RequestFailed)
127 }
128 resp, err := s.handleONUActivate(onuInfo)
129 return resp, err
130}
131
132// ONUDeactivate method handles ONU deactivation request.
133func (s *Server) ONUDeactivate(ctx context.Context, in *pb.ONURequest) (*pb.BBSimResponse, error) {
134 logger.Info("ONUDeactivate request received")
135
136 // deactivate single ONU
137 if in.GetOnu() != nil {
138 logger.Debug("Received single ONU: %+v\n", in.GetOnu())
139 err := s.handleONUDeactivate(in.GetOnu())
140 if err != nil {
141 return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
142 }
143 } else if len(in.GetOnusBatch().GetOnus()) != 0 { // bulk deactivate
144 logger.Debug("Received multiple ONUs")
145 for _, onuinfo := range in.GetOnusBatch().GetOnus() {
146 logger.Debug("ONU values: %+v\n", onuinfo)
147 err := s.handleONUDeactivate(onuinfo)
148 if err != nil {
149 return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
150 }
151 }
152 } else {
153 // Empty request body is passed, delete all ONUs from all PON ports
154 for intfID := range s.Onumap {
155 if err := s.DeactivateAllOnuByIntfID(intfID); err != nil {
156 logger.Error("Failed in ONUDeactivate: %v", err)
157 return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
158 }
159 }
160 }
161
162 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
163}
164
165// GenerateONUAlarm RPC generates alarm for the onu
166func (s *Server) GenerateONUAlarm(ctx context.Context, in *pb.ONUAlarmRequest) (*pb.BBSimResponse, error) {
167 logger.Debug("GenerateONUAlarms() invoked")
168 if in.OnuSerial == "" {
169 return &pb.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "serial number can not be blank")
170 }
171 if len(in.OnuSerial) != SerialNumberLength {
172 return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid serial number given (length mismatch)")
173 }
174 if in.Status != "on" && in.Status != "off" {
175 return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
176 }
177 if s.alarmCh == nil {
178 return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "alarm-channel not created, can not send alarm")
179 }
180 // TODO put these checks inside handleOnuAlarm for modularity
181 resp, err := s.handleOnuAlarm(in)
182 return resp, err
183}
184
185// GenerateOLTAlarm RPC generates alarm for the OLT
186func (s *Server) GenerateOLTAlarm(ctx context.Context, in *pb.OLTAlarmRequest) (*pb.BBSimResponse, error) {
187 logger.Debug("GenerateOLTAlarm() invoked")
188 if in.Status != "on" && in.Status != "off" {
189 return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
190 }
191 if s.alarmCh == nil {
192 return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "alarm-channel not created, can not send alarm")
193 }
194 resp, err := s.handleOltAlarm(in)
195 if err != nil {
196 return resp, err
197 }
198 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
199}
200
201// PerformDeviceAction rpc take the device request and performs OLT and ONU hard and soft reboot
202func (s *Server) PerformDeviceAction(ctx context.Context, in *pb.DeviceAction) (*pb.BBSimResponse, error) {
203 logger.Debug("PerformDeviceAction() invoked")
204 if s.deviceActionCh == nil {
205 return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "device action channel not created, can not entertain request")
206 }
207 in, err := s.validateDeviceActionRequest(in)
208 if err != nil {
209 return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
210 }
211 s.deviceActionCh <- in
212 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
213}
214
215// NewMgmtAPIServer method starts BBSim gRPC server.
216func NewMgmtAPIServer(addrport string) (l net.Listener, g *grpc.Server, e error) {
217 logger.Info("BBSim gRPC server listening %s ...", addrport)
218 g = grpc.NewServer()
219 l, e = net.Listen("tcp", addrport)
220 return
221}
222
223// StartRestGatewayService method starts REST server for BBSim.
224func StartRestGatewayService(grpcAddress string, hostandport string, wg *sync.WaitGroup) {
225 ctx := context.Background()
226 ctx, cancel := context.WithCancel(ctx)
227 defer cancel()
228
229 mux := runtime.NewServeMux()
230 opts := []grpc.DialOption{grpc.WithInsecure()}
231 // Register REST endpoints
232 err := pb.RegisterBBSimServiceHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
233 if err != nil {
234 logger.Error("%v", err)
235 return
236 }
237
238 logger.Info("BBSim REST server listening %s ...", hostandport)
239 err = http.ListenAndServe(hostandport, mux)
240 if err != nil {
241 logger.Error("%v", err)
242 return
243 }
244 return
245}