SEBA-941 updated apis to poweron/shutdown all ONUs in PON/OLT
Change-Id: I6923cbcc51a4391f70ff08d266c274e1f34ca3ca
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index 0f898e8..330621a 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -74,6 +74,7 @@
return &res, nil
}
+// ShutdownONU sends DyingGasp indication for specified ONUs and mark ONUs as disabled.
func (s BBSimServer) ShutdownONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
// NOTE this method is now sending a Dying Gasp and then disabling the device (operState: down, adminState: up),
// is this the only way to do? Should we address other cases?
@@ -81,82 +82,70 @@
// - a fiber is pulled
// - ONU malfunction
// - ONU shutdown
- res := &bbsim.Response{}
-
logger.WithFields(log.Fields{
"OnuSn": req.SerialNumber,
}).Infof("Received request to shutdown ONU")
+ res := &bbsim.Response{}
olt := devices.GetOLT()
onu, err := olt.FindOnuBySn(req.SerialNumber)
-
if err != nil {
res.StatusCode = int32(codes.NotFound)
res.Message = err.Error()
return res, err
}
- dyingGasp := bbsim.ONUAlarmRequest{
- AlarmType: "DyingGasp",
- SerialNumber: onu.Sn(),
- Status: "on",
- }
+ return handleShutdownONU(onu)
+}
- if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot send Dying Gasp: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
+// ShutdownONUsOnPON sends DyingGasp indication for all ONUs under specified PON port
+func (s BBSimServer) ShutdownONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
+ logger.WithFields(log.Fields{
+ "IntfId": req.PonPortId,
+ }).Infof("Received request to shutdown all ONUs on PON")
- losReq := bbsim.ONUAlarmRequest{
- AlarmType: "LossOfSignal",
- SerialNumber: onu.Sn(),
- Status: "on",
- }
+ res := &bbsim.Response{}
+ olt := devices.GetOLT()
+ pon, _ := olt.GetPonById(req.PonPortId)
- if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot send LOS: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
-
- // TODO if it's the last ONU on the PON, then send a PON LOS
-
- if err := onu.InternalState.Event("disable"); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot shutdown ONU: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
-
+ go func() {
+ for _, onu := range pon.Onus {
+ res, _ = handleShutdownONU(onu)
+ }
+ }()
res.StatusCode = int32(codes.OK)
- res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
+ res.Message = fmt.Sprintf("Request accepted for shutdown all ONUs on PON port %d", pon.ID)
return res, nil
}
-func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
+// ShutdownAllONUs sends DyingGasp indication for all ONUs and mark ONUs as disabled.
+func (s BBSimServer) ShutdownAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
+ logger.Infof("Received request to shutdown all ONUs")
res := &bbsim.Response{}
+ olt := devices.GetOLT()
+ go func() {
+ for _, pon := range olt.Pons {
+ for _, onu := range pon.Onus {
+ res, _ = handleShutdownONU(onu)
+ }
+ }
+ }()
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("Request Accepted for shutdown all ONUs in OLT %d", olt.ID)
+
+ return res, nil
+}
+
+// PoweronONU simulates ONU power on and start sending discovery indications to VOLTHA
+func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
logger.WithFields(log.Fields{
"OnuSn": req.SerialNumber,
}).Infof("Received request to poweron ONU")
+ res := &bbsim.Response{}
olt := devices.GetOLT()
onu, err := olt.FindOnuBySn(req.SerialNumber)
@@ -180,60 +169,59 @@
return res, err
}
- if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
- if err := onu.InternalState.Event("initialize"); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot poweron ONU: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
+ return handlePoweronONU(onu)
+}
+
+// PoweronONUsOnPON simulates ONU power on for all ONUs under specified PON port
+func (s BBSimServer) PoweronONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
+ logger.WithFields(log.Fields{
+ "IntfId": req.PonPortId,
+ }).Infof("Received request to poweron all ONUs on PON")
+
+ res := &bbsim.Response{}
+ olt := devices.GetOLT()
+
+ pon, _ := olt.GetPonById(req.PonPortId)
+ if pon.InternalState.Current() != "enabled" {
+ err := fmt.Errorf("PON port %d not enabled", pon.ID)
+ logger.WithFields(log.Fields{
+ "IntfId": pon.ID,
+ }).Errorf("Cannot poweron ONUs on PON: %s", err.Error())
+
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ go func() {
+ for _, onu := range pon.Onus {
+ res, _ = handlePoweronONU(onu)
}
- }
-
- losReq := bbsim.ONUAlarmRequest{
- AlarmType: "LossOfSignal",
- SerialNumber: onu.Sn(),
- Status: "off",
- }
-
- if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot send LOS: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
-
- if err := onu.InternalState.Event("discover"); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot poweron ONU: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
-
- if err := onu.InternalState.Event("enable"); err != nil {
- logger.WithFields(log.Fields{
- "OnuId": onu.ID,
- "IntfId": onu.PonPortID,
- "OnuSn": onu.Sn(),
- }).Errorf("Cannot enable ONU: %s", err.Error())
- res.StatusCode = int32(codes.FailedPrecondition)
- res.Message = err.Error()
- return res, err
- }
-
+ }()
res.StatusCode = int32(codes.OK)
- res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
+ res.Message = fmt.Sprintf("Request Accepted for power on all ONUs on PON port %d", pon.ID)
+
+ return res, nil
+}
+
+// PoweronAllONUs simulates ONU power on for all ONUs on all PON ports
+func (s BBSimServer) PoweronAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
+ logger.Infof("Received request to poweron all ONUs")
+
+ res := &bbsim.Response{}
+ olt := devices.GetOLT()
+
+ go func() {
+ for _, pon := range olt.Pons {
+ if pon.InternalState.Current() == "enabled" {
+ for _, onu := range pon.Onus {
+ res, _ = handlePoweronONU(onu)
+ }
+ }
+ }
+ }()
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("Request Accepted for power on all ONUs in OLT %d", olt.ID)
return res, nil
}
@@ -397,3 +385,126 @@
return &ts, nil
}
}
+
+func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
+ res := &bbsim.Response{}
+ olt := devices.GetOLT()
+ intitalState := onu.InternalState.Current()
+ if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
+ if err := onu.InternalState.Event("initialize"); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot poweron ONU: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+ }
+
+ losReq := bbsim.ONUAlarmRequest{
+ AlarmType: "LossOfSignal",
+ SerialNumber: onu.Sn(),
+ Status: "off",
+ }
+
+ if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot send LOS: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ if err := onu.InternalState.Event("discover"); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot poweron ONU: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+ // move onu directly to enable state only when its a powercycle case
+ // in case of first time onu poweron onu will be moved to enable on
+ // receiving ActivateOnu request from openolt adapter
+ if intitalState == "disabled" {
+ if err := onu.InternalState.Event("enable"); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot enable ONU: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+ }
+
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
+
+ return res, nil
+}
+
+func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
+ res := &bbsim.Response{}
+ olt := devices.GetOLT()
+
+ dyingGasp := bbsim.ONUAlarmRequest{
+ AlarmType: "DyingGasp",
+ SerialNumber: onu.Sn(),
+ Status: "on",
+ }
+
+ if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot send Dying Gasp: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ losReq := bbsim.ONUAlarmRequest{
+ AlarmType: "LossOfSignal",
+ SerialNumber: onu.Sn(),
+ Status: "on",
+ }
+
+ if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot send LOS: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ // TODO if it's the last ONU on the PON, then send a PON LOS
+
+ if err := onu.InternalState.Event("disable"); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot shutdown ONU: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
+
+ return res, nil
+}
diff --git a/internal/bbsimctl/commands/olt.go b/internal/bbsimctl/commands/olt.go
index 3ea004c..a16edef 100644
--- a/internal/bbsimctl/commands/olt.go
+++ b/internal/bbsimctl/commands/olt.go
@@ -51,15 +51,21 @@
type OltFlows struct{}
+type OltPoweronAllOnus struct{}
+
+type OltShutdownAllOnus struct{}
+
type oltOptions struct {
- Get OltGet `command:"get"`
- NNI OltNNIs `command:"nnis"`
- PON OltPONs `command:"pons"`
- Shutdown OltShutdown `command:"shutdown"`
- Poweron OltPoweron `command:"poweron"`
- Reboot OltReboot `command:"reboot"`
- Alarms OltAlarmOptions `command:"alarms"`
- Flows OltFlows `command:"flows"`
+ Get OltGet `command:"get"`
+ NNI OltNNIs `command:"nnis"`
+ PON OltPONs `command:"pons"`
+ Shutdown OltShutdown `command:"shutdown"`
+ Poweron OltPoweron `command:"poweron"`
+ Reboot OltReboot `command:"reboot"`
+ Alarms OltAlarmOptions `command:"alarms"`
+ Flows OltFlows `command:"flows"`
+ PoweronAllOnus OltPoweronAllOnus `command:"poweronAllONUs"`
+ ShutdownAllOnus OltShutdownAllOnus `command:"shutdownAllONUs"`
}
func RegisterOltCommands(parser *flags.Parser) {
@@ -243,3 +249,39 @@
tableFlow.SetNewLine("")
return nil
}
+
+func (o *OltPoweronAllOnus) Execute(args []string) error {
+ client, conn := connect()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ res, err := client.PoweronAllONUs(ctx, &pb.Empty{})
+
+ if err != nil {
+ log.Errorf("Cannot poweron all ONUs: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
+
+func (o *OltShutdownAllOnus) Execute(args []string) error {
+ client, conn := connect()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ res, err := client.ShutdownAllONUs(ctx, &pb.Empty{})
+
+ if err != nil {
+ log.Errorf("Cannot shutdown all ONUs: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
diff --git a/internal/bbsimctl/commands/pon.go b/internal/bbsimctl/commands/pon.go
new file mode 100644
index 0000000..885fb75
--- /dev/null
+++ b/internal/bbsimctl/commands/pon.go
@@ -0,0 +1,91 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/jessevdk/go-flags"
+ pb "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsimctl/config"
+ log "github.com/sirupsen/logrus"
+)
+
+type PonPoweronAllOnus struct {
+ Args struct {
+ IntfID OltInterfaceID
+ } `positional-args:"yes" required:"yes"`
+}
+
+type PonShutdownAllOnus struct {
+ Args struct {
+ IntfID OltInterfaceID
+ } `positional-args:"yes" required:"yes"`
+}
+
+type PONOptions struct {
+ PoweronAllOnus PonPoweronAllOnus `command:"poweronAllONUs"`
+ ShutdownAllOnus PonShutdownAllOnus `command:"shutdownAllONUs"`
+}
+
+func RegisterPonCommands(parser *flags.Parser) {
+ parser.AddCommand("pon", "PON Commands", "Commands to query and manipulate the PON port", &PONOptions{})
+}
+
+func (pon *PonPoweronAllOnus) Execute(args []string) error {
+ client, conn := connect()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := pb.PONRequest{
+ PonPortId: uint32(pon.Args.IntfID),
+ }
+
+ res, err := client.PoweronONUsOnPON(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot poweron all ONUs on PON port: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
+
+func (pon *PonShutdownAllOnus) Execute(args []string) error {
+ client, conn := connect()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := pb.PONRequest{
+ PonPortId: uint32(pon.Args.IntfID),
+ }
+
+ res, err := client.ShutdownONUsOnPON(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot shutdown all ONUs on PON port: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}