From d2bcd6ca868f1a6ac87d534430b0317bcb70344e Mon Sep 17 00:00:00 2001 From: Neha Das Date: Thu, 31 Oct 2024 11:45:31 -0700 Subject: [PATCH] gNOI System APIs (Reboot, RebootStatus, CancelReboot) changes --- gnmi_server/gnoi_system.go | 43 +++++---------------------------- gnmi_server/gnoi_system_test.go | 24 +++++++++--------- gnmi_server/swss_util.go | 36 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 gnmi_server/swss_util.go diff --git a/gnmi_server/gnoi_system.go b/gnmi_server/gnoi_system.go index 0bb3d2aa..f52dc771 100644 --- a/gnmi_server/gnoi_system.go +++ b/gnmi_server/gnoi_system.go @@ -28,8 +28,8 @@ const ( notificationTimeout = 10 * time.Second ) -// Vaild reboot method map. -var validRebootMap = map[syspb.RebootMethod]bool{ +// Supported reboot method map. +var supportedRebootMap = map[syspb.RebootMethod]bool{ syspb.RebootMethod_COLD: true, syspb.RebootMethod_WARM: true, syspb.RebootMethod_POWERDOWN: true, @@ -37,8 +37,8 @@ var validRebootMap = map[syspb.RebootMethod]bool{ } // Validates reboot request. -func validRebootReq(req *syspb.RebootRequest) error { - if _, ok := validRebootMap[req.GetMethod()]; !ok { +func ValidRebootReq(req *syspb.RebootRequest) error { + if _, ok := supportedRebootMap[req.GetMethod()]; !ok { log.Error("Invalid request: reboot method is not supported.") return fmt.Errorf("Invalid request: reboot method is not supported.") } @@ -125,37 +125,6 @@ func processMsgPayload(pload string) (string, string, map[string]string, error) return op, data, fvs, nil } -// Converts a SWSS error code string into a gRPC code. -func swssToErrorCode(statusStr string) codes.Code { - switch statusStr { - case "SWSS_RC_SUCCESS": - return codes.OK - case "SWSS_RC_UNKNOWN": - return codes.Unknown - case "SWSS_RC_IN_USE", "SWSS_RC_INVALID_PARAM": - return codes.InvalidArgument - case "SWSS_RC_DEADLINE_EXCEEDED": - return codes.DeadlineExceeded - case "SWSS_RC_NOT_FOUND": - return codes.NotFound - case "SWSS_RC_EXISTS": - return codes.AlreadyExists - case "SWSS_RC_PERMISSION_DENIED": - return codes.PermissionDenied - case "SWSS_RC_FULL", "SWSS_RC_NO_MEMORY": - return codes.ResourceExhausted - case "SWSS_RC_UNIMPLEMENTED": - return codes.Unimplemented - case "SWSS_RC_INTERNAL": - return codes.Internal - case "SWSS_RC_NOT_EXECUTED", "SWSS_RC_FAILED_PRECONDITION": - return codes.FailedPrecondition - case "SWSS_RC_UNAVAIL": - return codes.Unavailable - } - return codes.Internal -} - func sendRebootReqOnNotifCh(ctx context.Context, req proto.Message, sc *redis.Client, rebootNotifKey string) (resp proto.Message, err error, msgDataStr string) { np, err := common_utils.NewNotificationProducer(rebootReqCh) if err != nil { @@ -219,7 +188,7 @@ func sendRebootReqOnNotifCh(ctx context.Context, req proto.Message, sc *redis.Cl msgDataStr = fvs[dataMsgFld] } } - if swssCode := swssToErrorCode(data); swssCode != codes.OK { + if swssCode := SwssToErrorCode(data); swssCode != codes.OK { errStr := fmt.Sprintf("Response Notification returned SWSS Error code: %v, error = %v", swssCode, msgDataStr) log.V(1).Infof(errStr) return nil, status.Errorf(swssCode, errStr), msgDataStr @@ -244,7 +213,7 @@ func (srv *Server) Reboot(ctx context.Context, req *syspb.RebootRequest) (*syspb log.V(1).Info("Error while authenticating: ", err.Error()) } log.V(2).Info("gNOI: Reboot") - if err := validRebootReq(req); err != nil { + if err := ValidRebootReq(req); err != nil { return nil, status.Errorf(codes.InvalidArgument, err.Error()) } // Initialize State DB. diff --git a/gnmi_server/gnoi_system_test.go b/gnmi_server/gnoi_system_test.go index 53fd98c5..4be67111 100644 --- a/gnmi_server/gnoi_system_test.go +++ b/gnmi_server/gnoi_system_test.go @@ -63,10 +63,10 @@ func errorCodeToSwss(errCode codes.Code) string { return "" } -func rebootBackendResponse(t *testing.T, sc *redis.Client, expectedResponse codes.Code, fvs map[string]string, done chan bool, key string) { +func RebootBackendResponse(t *testing.T, sc *redis.Client, expectedResponse codes.Code, fvs map[string]string, done chan bool, key string) { sub := sc.Subscribe("Reboot_Request_Channel") if _, err := sub.Receive(); err != nil { - t.Errorf("rebootBackendResponse failed to subscribe to request channel: %v", err) + t.Errorf("RebootBackendResponse failed to subscribe to request channel: %v", err) return } defer sub.Close() @@ -74,7 +74,7 @@ func rebootBackendResponse(t *testing.T, sc *redis.Client, expectedResponse code np, err := common_utils.NewNotificationProducer("Reboot_Response_Channel") if err != nil { - t.Errorf("rebootBackendResponse failed to create notification producer: %v", err) + t.Errorf("RebootBackendResponse failed to create notification producer: %v", err) return } defer np.Close() @@ -82,16 +82,16 @@ func rebootBackendResponse(t *testing.T, sc *redis.Client, expectedResponse code tc := time.After(5 * time.Second) select { case msg := <-channel: - t.Logf("rebootBackendResponse received request: %v", msg) + t.Logf("RebootBackendResponse received request: %v", msg) // Respond to the request if err := np.Send(key, errorCodeToSwss(expectedResponse), fvs); err != nil { - t.Errorf("rebootBackendResponse failed to send response: %v", err) + t.Errorf("RebootBackendResponse failed to send response: %v", err) return } case <-done: return case <-tc: - t.Error("rebootBackendResponse timed out waiting for request") + t.Error("RebootBackendResponse timed out waiting for request") return } } @@ -200,7 +200,7 @@ func TestSystem(t *testing.T) { Delay: 0, Message: "Cold reboot starting ...", } - go rebootBackendResponse(t, rclient, codes.OK, fvs, done, "testKey") + go RebootBackendResponse(t, rclient, codes.OK, fvs, done, "testKey") defer func() { done <- true }() _, err := sc.Reboot(ctx, req) testErr(err, codes.Internal, "Op: testKey doesn't match for Reboot!", t) @@ -211,7 +211,7 @@ func TestSystem(t *testing.T) { fvs["MESSAGE"] = "{}" // Start goroutine for mock Reboot Backend to respond to Reboot requests done := make(chan bool, 1) - go rebootBackendResponse(t, rclient, code, fvs, done, rebootKey) + go RebootBackendResponse(t, rclient, code, fvs, done, rebootKey) defer func() { done <- true }() req := &syspb.RebootRequest{ Method: syspb.RebootMethod_COLD, @@ -227,7 +227,7 @@ func TestSystem(t *testing.T) { fvs["MESSAGE"] = "{}" // Start goroutine for mock Reboot Backend to respond to Reboot requests done := make(chan bool, 1) - go rebootBackendResponse(t, rclient, codes.Unauthenticated, fvs, done, rebootKey) + go RebootBackendResponse(t, rclient, codes.Unauthenticated, fvs, done, rebootKey) defer func() { done <- true }() req := &syspb.RebootRequest{ Method: syspb.RebootMethod_COLD, @@ -242,7 +242,7 @@ func TestSystem(t *testing.T) { done := make(chan bool, 1) fvs := make(map[string]string) fvs["MESSAGE"] = "{}" - go rebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootKey) + go RebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootKey) defer func() { done <- true }() req := &syspb.RebootRequest{ @@ -264,7 +264,7 @@ func TestSystem(t *testing.T) { done := make(chan bool, 1) fvs := make(map[string]string) fvs["MESSAGE"] = "{\"active\": true, \"method\":\"NSF\",\"status\":{\"status\":\"STATUS_SUCCESS\"}}" - go rebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootStatusKey) + go RebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootStatusKey) defer func() { done <- true }() _, err := sc.RebootStatus(ctx, &syspb.RebootStatusRequest{}) @@ -288,7 +288,7 @@ func TestSystem(t *testing.T) { done := make(chan bool, 1) fvs := make(map[string]string) fvs["MESSAGE"] = "{}" - go rebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootCancelKey) + go RebootBackendResponse(t, rclient, codes.OK, fvs, done, rebootCancelKey) defer func() { done <- true }() req := &syspb.CancelRebootRequest{ diff --git a/gnmi_server/swss_util.go b/gnmi_server/swss_util.go new file mode 100644 index 00000000..4a3d2cdf --- /dev/null +++ b/gnmi_server/swss_util.go @@ -0,0 +1,36 @@ +package gnmi + +import ( + "google.golang.org/grpc/codes" +) + +// Converts a SWSS error code string into a gRPC code. +func SwssToErrorCode(statusStr string) codes.Code { + switch statusStr { + case "SWSS_RC_SUCCESS": + return codes.OK + case "SWSS_RC_UNKNOWN": + return codes.Unknown + case "SWSS_RC_IN_USE", "SWSS_RC_INVALID_PARAM": + return codes.InvalidArgument + case "SWSS_RC_DEADLINE_EXCEEDED": + return codes.DeadlineExceeded + case "SWSS_RC_NOT_FOUND": + return codes.NotFound + case "SWSS_RC_EXISTS": + return codes.AlreadyExists + case "SWSS_RC_PERMISSION_DENIED": + return codes.PermissionDenied + case "SWSS_RC_FULL", "SWSS_RC_NO_MEMORY": + return codes.ResourceExhausted + case "SWSS_RC_UNIMPLEMENTED": + return codes.Unimplemented + case "SWSS_RC_INTERNAL": + return codes.Internal + case "SWSS_RC_NOT_EXECUTED", "SWSS_RC_FAILED_PRECONDITION": + return codes.FailedPrecondition + case "SWSS_RC_UNAVAIL": + return codes.Unavailable + } + return codes.Internal +} \ No newline at end of file