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