| /* |
| * Copyright 2018-present Open Networking Foundation |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package api |
| |
| import ( |
| "context" |
| "fmt" |
| "strings" |
| "time" |
| |
| "google.golang.org/grpc/status" |
| |
| "github.com/opencord/bbsim/api/bbsim" |
| "github.com/opencord/bbsim/internal/bbsim/devices" |
| "github.com/opencord/bbsim/internal/common" |
| log "github.com/sirupsen/logrus" |
| "google.golang.org/grpc/codes" |
| ) |
| |
| var logger = log.WithFields(log.Fields{ |
| "module": "GrpcApiServer", |
| }) |
| |
| var ( |
| version string |
| buildTime string |
| commitHash string |
| gitStatus string |
| ) |
| |
| type BBSimServer struct { |
| } |
| |
| func (s BBSimServer) Version(ctx context.Context, req *bbsim.Empty) (*bbsim.VersionNumber, error) { |
| // TODO add a flag to specify whether the tree was clean at this commit or not |
| return &bbsim.VersionNumber{ |
| Version: version, |
| BuildTime: buildTime, |
| CommitHash: commitHash, |
| GitStatus: gitStatus, |
| }, nil |
| } |
| |
| func (s BBSimServer) GetOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Olt, error) { |
| olt := devices.GetOLT() |
| nnis := []*bbsim.NNIPort{} |
| pons := []*bbsim.PONPort{} |
| |
| for _, nni := range olt.Nnis { |
| n := bbsim.NNIPort{ |
| ID: int32(nni.ID), |
| OperState: nni.OperState.Current(), |
| } |
| nnis = append(nnis, &n) |
| } |
| |
| for _, pon := range olt.Pons { |
| |
| allocatedOnuIds := []*bbsim.PonAllocatedResources{} |
| allocatedAllocIds := []*bbsim.PonAllocatedResources{} |
| allocatedGemPorts := []*bbsim.PonAllocatedResources{} |
| |
| for k, v := range pon.AllocatedOnuIds { |
| resource := &bbsim.PonAllocatedResources{ |
| SerialNumber: common.OnuSnToString(v), |
| Id: int32(k), |
| } |
| allocatedOnuIds = append(allocatedOnuIds, resource) |
| } |
| |
| for k, v := range pon.AllocatedGemPorts { |
| resource := &bbsim.PonAllocatedResources{ |
| SerialNumber: common.OnuSnToString(v), |
| Id: int32(k), |
| } |
| allocatedGemPorts = append(allocatedGemPorts, resource) |
| } |
| |
| for _, v := range pon.AllocatedAllocIds { |
| resource := &bbsim.PonAllocatedResources{ |
| SerialNumber: common.OnuSnToString(v.OnuSn), |
| Id: int32(v.AllocID), |
| } |
| allocatedAllocIds = append(allocatedAllocIds, resource) |
| } |
| |
| p := bbsim.PONPort{ |
| ID: int32(pon.ID), |
| Technology: pon.Technology.String(), |
| OperState: pon.OperState.Current(), |
| InternalState: pon.InternalState.Current(), |
| PacketCount: pon.PacketCount, |
| AllocatedOnuIds: allocatedOnuIds, |
| AllocatedAllocIds: allocatedAllocIds, |
| AllocatedGemPorts: allocatedGemPorts, |
| } |
| pons = append(pons, &p) |
| } |
| |
| oltAddress := strings.Split(common.Config.BBSim.OpenOltAddress, ":")[0] |
| if oltAddress == "" { |
| oltAddress = getOltIP().String() |
| } |
| |
| res := bbsim.Olt{ |
| ID: int32(olt.ID), |
| SerialNumber: olt.SerialNumber, |
| OperState: olt.OperState.Current(), |
| InternalState: olt.InternalState.Current(), |
| IP: oltAddress, |
| NNIPorts: nnis, |
| PONPorts: pons, |
| } |
| return &res, nil |
| } |
| |
| // takes a nested map and return a proto |
| func resourcesMapToresourcesProto(resourceType bbsim.OltAllocatedResourceType_Type, resources map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool) *bbsim.OltAllocatedResources { |
| proto := &bbsim.OltAllocatedResources{ |
| Resources: []*bbsim.OltAllocatedResource{}, |
| } |
| for ponId, ponValues := range resources { |
| for onuId, onuValues := range ponValues { |
| for uniId, uniValues := range onuValues { |
| for allocId, flows := range uniValues { |
| for flow := range flows { |
| resource := &bbsim.OltAllocatedResource{ |
| Type: resourceType.String(), |
| PonPortId: ponId, |
| OnuId: onuId, |
| PortNo: uniId, |
| ResourceId: allocId, |
| FlowId: flow, |
| } |
| proto.Resources = append(proto.Resources, resource) |
| } |
| } |
| } |
| } |
| } |
| return proto |
| } |
| |
| func (s BBSimServer) GetOltAllocatedResources(ctx context.Context, req *bbsim.OltAllocatedResourceType) (*bbsim.OltAllocatedResources, error) { |
| o := devices.GetOLT() |
| |
| switch req.Type { |
| case bbsim.OltAllocatedResourceType_UNKNOWN: |
| return nil, status.Errorf(codes.InvalidArgument, "resource-type-%s-is-invalid", req.Type) |
| case bbsim.OltAllocatedResourceType_ALLOC_ID: |
| return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_ALLOC_ID, o.AllocIDs), nil |
| case bbsim.OltAllocatedResourceType_GEM_PORT: |
| return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_GEM_PORT, o.GemPortIDs), nil |
| default: |
| return nil, status.Errorf(codes.InvalidArgument, "unkown-resource-type-%s", req.Type) |
| } |
| } |
| |
| func (s BBSimServer) PoweronOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) { |
| res := &bbsim.Response{} |
| o := devices.GetOLT() |
| |
| if err := o.InternalState.Event(devices.OltInternalTxInitialize); err != nil { |
| log.Errorf("Error initializing OLT: %v", err) |
| res.StatusCode = int32(codes.FailedPrecondition) |
| return res, err |
| } |
| |
| res.StatusCode = int32(codes.OK) |
| return res, nil |
| } |
| |
| func (s BBSimServer) ShutdownOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) { |
| res := &bbsim.Response{} |
| o := devices.GetOLT() |
| |
| if err := o.InternalState.Event(devices.OltInternalTxDisable); err != nil { |
| log.Errorf("Error disabling OLT: %v", err) |
| res.StatusCode = int32(codes.FailedPrecondition) |
| return res, err |
| } |
| |
| res.StatusCode = int32(codes.OK) |
| return res, nil |
| } |
| |
| func (s BBSimServer) RebootOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) { |
| res := &bbsim.Response{} |
| o := devices.GetOLT() |
| go func() { _ = o.RestartOLT() }() |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("OLT restart triggered.") |
| return res, nil |
| } |
| |
| func (s BBSimServer) StopgRPCServer(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) { |
| res := &bbsim.Response{} |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("Openolt gRPC server stopped") |
| o := devices.GetOLT() |
| |
| logger.Infof("Received request to stop Openolt gRPC Server") |
| |
| o.StopOltServer() |
| |
| return res, nil |
| } |
| |
| func (s BBSimServer) StartgRPCServer(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) { |
| res := &bbsim.Response{} |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("Openolt gRPC server started") |
| o := devices.GetOLT() |
| |
| logger.Infof("Received request to start Openolt gRPC Server") |
| |
| if o.OltServer != nil { |
| return nil, fmt.Errorf("Openolt gRPC server already running.") |
| } |
| |
| oltGrpcServer, err := o.StartOltServer() |
| if err != nil { |
| return nil, err |
| } |
| o.OltServer = oltGrpcServer |
| |
| return res, nil |
| } |
| |
| func (s BBSimServer) RestartgRPCServer(ctx context.Context, req *bbsim.Timeout) (*bbsim.Response, error) { |
| o := devices.GetOLT() |
| logger.Infof("Received request to restart Openolt gRPC Server in %v seconds", req.Delay) |
| o.StopOltServer() |
| |
| res := &bbsim.Response{} |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("Openolt gRPC server stopped, restarting in %v", req.Delay) |
| |
| go func() { |
| time.Sleep(time.Duration(req.Delay) * time.Second) |
| oltGrpcServer, err := o.StartOltServer() |
| if err != nil { |
| logger.WithFields(log.Fields{ |
| "err": err, |
| }).Error("Cannot restart Openolt gRPC server") |
| } |
| o.OltServer = oltGrpcServer |
| logger.Infof("Openolt gRPC Server restarted after %v seconds", req.Delay) |
| }() |
| |
| return res, nil |
| } |
| |
| func (s BBSimServer) SetLogLevel(ctx context.Context, req *bbsim.LogLevel) (*bbsim.LogLevel, error) { |
| |
| common.SetLogLevel(log.StandardLogger(), req.Level, req.Caller) |
| |
| return &bbsim.LogLevel{ |
| Level: log.StandardLogger().Level.String(), |
| Caller: log.StandardLogger().ReportCaller, |
| }, nil |
| } |
| |
| func (s BBSimServer) SetOnuAlarmIndication(ctx context.Context, req *bbsim.ONUAlarmRequest) (*bbsim.Response, error) { |
| o := devices.GetOLT() |
| |
| res := &bbsim.Response{} |
| |
| onu, err := o.FindOnuBySn(req.SerialNumber) |
| if err != nil { |
| res.StatusCode = int32(codes.NotFound) |
| res.Message = err.Error() |
| return nil, err |
| } |
| |
| if err := onu.SetAlarm(req.AlarmType, req.Status); err != nil { |
| res.StatusCode = int32(codes.Internal) |
| res.Message = err.Error() |
| return nil, err |
| } |
| |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("Onu Alarm Indication Sent.") |
| return res, nil |
| } |
| |
| // SetOltAlarmIndication generates OLT Alarms for LOS |
| func (s BBSimServer) SetOltAlarmIndication(ctx context.Context, req *bbsim.OLTAlarmRequest) (*bbsim.Response, error) { |
| o := devices.GetOLT() |
| res := &bbsim.Response{} |
| |
| if err := o.SetAlarm(req.InterfaceID, req.InterfaceType, req.Status); err != nil { |
| res.StatusCode = int32(codes.Internal) |
| res.Message = err.Error() |
| return nil, err |
| } |
| |
| res.StatusCode = int32(codes.OK) |
| res.Message = fmt.Sprintf("Olt Alarm Indication Sent.") |
| return res, nil |
| } |