Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions common_utils/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (
GNMI_SET
GNMI_SET_FAIL
GNOI_REBOOT
GNOI_OS_ACTIVATE
DBUS
DBUS_FAIL
DBUS_APPLY_PATCH_DB
Expand Down Expand Up @@ -77,6 +78,8 @@ func (c CounterType) String() string {
return "GNMI set fail"
case GNOI_REBOOT:
return "GNOI reboot"
case GNOI_OS_ACTIVATE:
return "GNOI OS Activate"
case DBUS:
return "DBUS"
case DBUS_FAIL:
Expand Down
9 changes: 4 additions & 5 deletions gnmi_server/gnoi.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
transutil "github.com/sonic-net/sonic-gnmi/transl_utils"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"os"
"os/user"
"strconv"
"strings"
Expand Down Expand Up @@ -138,9 +137,9 @@ func (srv *OSServer) Verify(ctx context.Context, req *gnoi_os_pb.VerifyRequest)
return resp, nil
}

func (srv *OSServer) Activate(ctx context.Context, req *gnoi_os_pb.ActivateRequest) (*gnoi_os_pb.ActivateResponse, error) {
_, err := authenticate(srv.config, ctx, "gnoi" /*writeAccess=*/, true)
if err != nil {
//func (srv *OSServer) Activate(ctx context.Context, req *gnoi_os_pb.ActivateRequest) (*gnoi_os_pb.ActivateResponse, error) {
// _, err := authenticate(srv.config, ctx, "gnoi" /*writeAccess=*/, true)
/* if err != nil {
log.Errorf("Failed to authenticate: %v", err)
return nil, err
}
Expand Down Expand Up @@ -186,7 +185,7 @@ func (srv *OSServer) Activate(ctx context.Context, req *gnoi_os_pb.ActivateReque
log.Infof("Successfully activated image %s", image)
resp.Response = &gnoi_os_pb.ActivateResponse_ActivateOk{}
return &resp, nil
}
}*/

func (srv *Server) Authenticate(ctx context.Context, req *spb_jwt.AuthenticateRequest) (*spb_jwt.AuthenticateResponse, error) {
// Can't enforce normal authentication here.. maybe only enforce client cert auth if enabled?
Expand Down
45 changes: 45 additions & 0 deletions gnmi_server/gnoi_os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package gnmi

import (
"fmt"
log "github.com/golang/glog"
ospb "github.com/openconfig/gnoi/os"
ssc "github.com/sonic-net/sonic-gnmi/sonic_service_client"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
json "google.golang.org/protobuf/encoding/protojson"
)

// Activate implements correspondig RPC
func (srv *OSServer) Activate(ctx context.Context, req *ospb.ActivateRequest) (*ospb.ActivateResponse, error) {
ctx, err := authenticate(srv.config, ctx, "gnoi", false)
if err != nil {
return nil, err
}
log.V(1).Info("gNOI: os.Activate")
// Front end marshals the request, and sends to the sonic-host-service.
// Back end is expected to return the response in JSON format.
reqStr, err := json.Marshal(req)
if err != nil {
// TODO(b/328077908) Alarms to be implemented later
// raiseAlarm(err)
return nil, status.Errorf(codes.Internal, fmt.Sprintf("Cannot marshal the Activate request: [%s].", req.String()))
}
sc, err := ssc.NewDbusClient()
if err != nil {
return nil, err
}
respStr, err := sc.ActivateOS(string(reqStr))
if err != nil {
// TODO(b/328077908) Alarms to be implemented later
// raiseAlarm(err)
return nil, status.Errorf(codes.Internal, err.Error())
}
resp := &ospb.ActivateResponse{}
if err := json.Unmarshal([]byte(respStr), resp); err != nil {
// TODO(b/328077908) Alarms to be implemented later
// raiseAlarm(err)
return nil, status.Errorf(codes.Internal, fmt.Sprintf("Cannot unmarshal the Activate response: [%s].", respStr))
}
return resp, nil
}
71 changes: 71 additions & 0 deletions gnoi_client/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/sonic-net/sonic-gnmi/gnoi_client/config"
"github.com/sonic-net/sonic-gnmi/gnoi_client/utils"
"google.golang.org/grpc"
"google.golang.org/protobuf/encoding/protojson"
)

func Verify(conn *grpc.ClientConn, ctx context.Context) {
Expand Down Expand Up @@ -44,3 +45,73 @@ func Activate(conn *grpc.ClientConn, ctx context.Context) {
}
fmt.Println(string(respstr))
}

func Install(conn *grpc.ClientConn, ctx context.Context) {
fmt.Println("OS Install")
fmt.Println("From client")
ctx = utils.SetUserCreds(ctx)
osc := pb.NewOSClient(conn)

// Directly unmarshal JSON input into InstallRequest (no intermediate TransferRequest)
var req pb.InstallRequest
err := protojson.Unmarshal([]byte(*config.Args), &req)
if err != nil {
panic("Failed to unmarshal InstallRequest: " + err.Error())
}

// Optional: Print the marshaled request for verification
jsonBytes, err := protojson.MarshalOptions{
Indent: " ",
Multiline: true,
}.Marshal(&req)
if err != nil {
fmt.Println("Failed to marshal InstallRequest:", err)
} else {
fmt.Println("InstallRequest (JSON):\n", string(jsonBytes))
}

// Start the Install stream
stream, err := osc.Install(ctx)
if err != nil {
panic("Failed to start Install stream: " + err.Error())
}

// Send the request
if err := stream.Send(&req); err != nil {
panic("Failed to send InstallRequest: " + err.Error())
}

// Handle responses
for {
resp, err := stream.Recv()
if err != nil {
panic("Failed to receive InstallResponse: " + err.Error())
}

jsonBytes, err := protojson.MarshalOptions{
Multiline: true,
Indent: " ",
}.Marshal(resp)
if err != nil {
fmt.Println("Failed to marshal InstallResponse to JSON:", err)
} else {
fmt.Println("InstallResponse (JSON):\n", string(jsonBytes))
}

// Handle specific response types
switch r := resp.Response.(type) {
case *pb.InstallResponse_TransferReady:
fmt.Println("Transfer Ready:", r.TransferReady)
case *pb.InstallResponse_TransferProgress:
fmt.Println("Transfer Progress:", r.TransferProgress)
case *pb.InstallResponse_SyncProgress:
fmt.Println("Sync Progress:", r.SyncProgress)
case *pb.InstallResponse_Validated:
fmt.Println("Validated:", r.Validated)
case *pb.InstallResponse_InstallError:
fmt.Println("Install Error:", r.InstallError)
default:
fmt.Println("Unknown InstallResponse type")
}
}
}
20 changes: 20 additions & 0 deletions sonic_service_client/dbus_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Service interface {
ActivateImage(image string) error
// Docker services APIs
LoadDockerImage(image string) error
ActivateOS(req string) (string, error)
}

type DbusClient struct {
Expand Down Expand Up @@ -305,3 +306,22 @@ func (c *DbusClient) LoadDockerImage(image string) error {
_, err := DbusApi(busName, busPath, intName /*timeout=*/, 180, image)
return err
}
func (c *DbusClient) ActivateOS(req string) (string, error) {
modName := "gnoi_os_mgmt"
busName := c.busNamePrefix + modName
busPath := c.busPathPrefix + modName
intName := c.intNamePrefix + modName + ".activate"

common_utils.IncCounter(common_utils.GNOI_OS_ACTIVATE)
//return DbusApi(busName, busPath, intName, 10, req)
result, err := DbusApi(busName, busPath, intName /*timeout=*/, 10, req)
if err != nil {
return "", err
}
strResult, ok := result.(string)
if !ok {
return "", fmt.Errorf("Invalid result type %v %v", result, reflect.TypeOf(result))
}
log.V(2).Infof("ActivateOS: %v", result)
return strResult, nil
}
Loading