Skip to content

Commit 0c809a9

Browse files
hdwhdwCopilot
andauthored
Server side implementation of System.SetPackage (#360)
* initial commit. * add unit test and fix an error. * rebase back. * more unit test coverage * fix test. * Update gnmi_server/server_test.go Co-authored-by: Copilot <[email protected]> * copilot comment. * fix errors. * seperate test for setpackage * improve error code and add mocks with better unit tests. * update Makefile to filter out mocks from coverage. * propagate grpc internal error and address comment. * explicitly reject request if activate = false. * format fix. * import fix. * import fix again. * fix error * address comment, add path check. * Revert "address comment, add path check." This reverts commit b1fe364. --------- Co-authored-by: Copilot <[email protected]>
1 parent 1d8e216 commit 0c809a9

6 files changed

+775
-18
lines changed

Makefile

+13-3
Original file line numberDiff line numberDiff line change
@@ -211,17 +211,27 @@ check_gotest: $(DBCONFG) $(ENVFILE)
211211
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(GO) test -race -coverprofile=coverage-config.txt -covermode=atomic -v github.com/sonic-net/sonic-gnmi/sonic_db_config
212212
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(TESTENV) $(GO) test -race -timeout 20m -coverprofile=coverage-gnmi.txt -covermode=atomic -mod=vendor $(BLD_FLAGS) -v github.com/sonic-net/sonic-gnmi/gnmi_server -coverpkg ../...
213213
ifneq ($(ENABLE_DIALOUT_VALUE),0)
214-
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(TESTENV) $(GO) test -coverprofile=coverage-dialcout.txt -covermode=atomic -mod=vendor $(BLD_FLAGS) -v github.com/sonic-net/sonic-gnmi/dialout/dialout_client
214+
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(TESTENV) $(GO) test -coverprofile=coverage-dialout.txt -covermode=atomic -mod=vendor $(BLD_FLAGS) -v github.com/sonic-net/sonic-gnmi/dialout/dialout_client
215215
endif
216216
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(GO) test -race -coverprofile=coverage-data.txt -covermode=atomic -mod=vendor -v github.com/sonic-net/sonic-gnmi/sonic_data_client
217217
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(GO) test -race -coverprofile=coverage-dbus.txt -covermode=atomic -mod=vendor -v github.com/sonic-net/sonic-gnmi/sonic_service_client
218218
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(TESTENV) $(GO) test -race -coverprofile=coverage-translutils.txt -covermode=atomic -mod=vendor -v github.com/sonic-net/sonic-gnmi/transl_utils
219219
sudo CGO_LDFLAGS="$(CGO_LDFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" $(TESTENV) $(GO) test -race -coverprofile=coverage-gnoi-client-system.txt -covermode=atomic -mod=vendor -v github.com/sonic-net/sonic-gnmi/gnoi_client/system
220+
221+
# Install required coverage tools
220222
$(GO) install github.com/axw/gocov/[email protected]
221223
$(GO) install github.com/AlekSi/gocov-xml@latest
222224
$(GO) mod vendor
223-
gocov convert coverage-*.txt | gocov-xml -source $(shell pwd) > coverage.xml
224-
rm -rf coverage-*.txt
225+
226+
# Filter out "mocks" from the coverage reports
227+
for file in coverage-*.txt; do grep -v "/mocks/" $$file > $$file.filtered; done
228+
229+
# Convert and generate the final coverage.xml file
230+
gocov convert coverage-*.txt.filtered | gocov-xml -source $(shell pwd) > coverage.xml
231+
232+
# Cleanup temporary files
233+
rm -rf coverage-*.txt coverage-*.txt.filtered
234+
225235

226236
check_memleak: $(DBCONFG) $(ENVFILE)
227237
sudo CGO_LDFLAGS="$(MEMCHECK_CGO_LDFLAGS)" CGO_CXXFLAGS="$(MEMCHECK_CGO_CXXFLAGS)" $(GO) test -coverprofile=coverage-telemetry.txt -covermode=atomic -mod=vendor $(MEMCHECK_FLAGS) -v github.com/sonic-net/sonic-gnmi/telemetry

gnmi_server/gnoi.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ package gnmi
33
import (
44
"context"
55
"encoding/json"
6-
"os"
7-
"os/user"
8-
"strconv"
9-
"strings"
10-
"time"
11-
126
jwt "github.com/dgrijalva/jwt-go"
137
log "github.com/golang/glog"
148
gnoi_file_pb "github.com/openconfig/gnoi/file"
@@ -19,6 +13,11 @@ import (
1913
transutil "github.com/sonic-net/sonic-gnmi/transl_utils"
2014
"google.golang.org/grpc/codes"
2115
"google.golang.org/grpc/status"
16+
"os"
17+
"os/user"
18+
"strconv"
19+
"strings"
20+
"time"
2221
)
2322

2423
const (

gnmi_server/gnoi_system.go

+83-5
Original file line numberDiff line numberDiff line change
@@ -298,15 +298,93 @@ func (srv *Server) Traceroute(req *syspb.TracerouteRequest, stream syspb.System_
298298
return status.Errorf(codes.Unimplemented, "Method system.Traceroute is unimplemented.")
299299
}
300300

301-
// SetPackage is unimplemented.
302-
func (srv *Server) SetPackage(stream syspb.System_SetPackageServer) error {
303-
ctx := stream.Context()
301+
func (srv *Server) SetPackage(rs syspb.System_SetPackageServer) error {
302+
ctx := rs.Context()
303+
304304
_, err := authenticate(srv.config, ctx, true)
305305
if err != nil {
306+
log.Errorf("Authentication failed: %v", err)
307+
return status.Errorf(codes.PermissionDenied, "authentication failed: %v", err)
308+
}
309+
log.V(1).Info("gNOI: SetPackage request received")
310+
311+
// Create D-Bus client
312+
dbus, err := ssc.NewDbusClient()
313+
if err != nil {
314+
log.Errorf("Failed to create D-Bus client: %v", err)
315+
return status.Errorf(codes.Internal, "failed to create D-Bus client: %v", err)
316+
}
317+
defer dbus.Close()
318+
319+
// Receive the package request
320+
req, err := rs.Recv()
321+
if err != nil {
322+
log.Errorf("Failed to receive package request: %v", err)
323+
return err
324+
}
325+
326+
// Validate request type
327+
pkg, ok := req.GetRequest().(*syspb.SetPackageRequest_Package)
328+
if !ok {
329+
errMsg := fmt.Sprintf("invalid request type: %T, expected SetPackageRequest_Package", req.GetRequest())
330+
log.Errorf(errMsg)
331+
return status.Errorf(codes.InvalidArgument, errMsg)
332+
}
333+
334+
// A filename and a version must be provided
335+
if pkg.Package.Filename == "" {
336+
log.Errorf("Filename is missing in package request")
337+
return status.Errorf(codes.InvalidArgument, "filename is missing in package request")
338+
}
339+
if pkg.Package.Version == "" {
340+
log.Errorf("Version is missing in package request")
341+
return status.Errorf(codes.InvalidArgument, "version is missing in package request")
342+
}
343+
// Log the package filename and version
344+
log.V(1).Infof("Package filename: %s, version: %s", pkg.Package.Filename, pkg.Package.Version)
345+
346+
// Download the package if RemoteDownload is provided
347+
if pkg.Package.RemoteDownload != nil {
348+
// Validate RemoteDownload
349+
log.V(1).Infof("RemoteDownload provided")
350+
// Check if the path is provided
351+
if pkg.Package.RemoteDownload.Path == "" {
352+
log.Errorf("RemoteDownload path is missing")
353+
return status.Errorf(codes.InvalidArgument, "remote download path is missing")
354+
}
355+
log.V(1).Infof("RemoteDownload path: %s", pkg.Package.RemoteDownload.Path)
356+
357+
// Download the package
358+
err = dbus.DownloadImage(pkg.Package.RemoteDownload.Path, pkg.Package.Filename)
359+
if err != nil {
360+
log.Errorf("Failed to download image: %v", err)
361+
return status.Errorf(codes.Internal, "failed to download image: %v", err)
362+
}
363+
log.V(1).Infof("Package %s downloaded successfully to %s", pkg.Package.Version, pkg.Package.Filename)
364+
}
365+
366+
// If activate is requested, install the package and set it to be the next boot image
367+
if pkg.Package.Activate {
368+
log.V(1).Infof("Activate is requested")
369+
// Install the package
370+
err = dbus.InstallImage(pkg.Package.Filename)
371+
if err != nil {
372+
log.Errorf("Failed to install image: %v", err)
373+
return status.Errorf(codes.Internal, "failed to install image: %v", err)
374+
}
375+
log.V(1).Infof("Package %s installed successfully", pkg.Package.Filename)
376+
// Currently, Installing the image will automatically set it as the next boot image
377+
log.V(1).Infof("Package %s set as next boot image", pkg.Package.Filename)
378+
}
379+
380+
// Send response to client
381+
if err := rs.SendAndClose(&syspb.SetPackageResponse{}); err != nil {
382+
log.Errorf("Failed to send response: %v", err)
306383
return err
307384
}
308-
log.V(1).Info("gNOI: SetPackage")
309-
return status.Errorf(codes.Unimplemented, "Method system.SetPackage is unimplemented.")
385+
386+
log.V(1).Infof("SetPackage completed successfully for %s", pkg.Package.Filename)
387+
return nil
310388
}
311389

312390
// SwitchControlProcessor implements the corresponding RPC.

0 commit comments

Comments
 (0)