diff --git a/.gitignore b/.gitignore index d70506f2..3c42991f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,26 @@ +# Build directory build/ + +# Debian packaging files debian/.debhelper/ debian/files debian/sonic-telemetry.debhelper.log debian/sonic-telemetry.substvars debian/sonic-telemetry/ -vendor -src -cvl -translib +debian/sonic-gnmi.debhelper.log +debian/sonic-gnmi.substvars +debian/sonic-gnmi/ + +# Vendor directory +vendor/ + +# Source directories +src/ +cvl/ +translib/ + +# SWSS common generated files +swsscommon/swsscommon.go +swsscommon/swsscommon.i +swsscommon/swsscommon_wrap.cxx +swsscommon/swsscommon_wrap.h \ No newline at end of file diff --git a/common_utils/context.go b/common_utils/context.go index bbf7665b..a57fef73 100644 --- a/common_utils/context.go +++ b/common_utils/context.go @@ -54,6 +54,7 @@ const ( DBUS_STOP_SERVICE DBUS_RESTART_SERVICE DBUS_FILE_STAT + DBUS_HALT_SYSTEM DBUS_IMAGE_DOWNLOAD DBUS_IMAGE_INSTALL COUNTER_SIZE @@ -93,6 +94,8 @@ func (c CounterType) String() string { return "DBUS restart service" case DBUS_FILE_STAT: return "DBUS file stat" + case DBUS_HALT_SYSTEM: + return "DBUS halt system" case DBUS_IMAGE_DOWNLOAD: return "DBUS image download" case DBUS_IMAGE_INSTALL: diff --git a/gnmi_server/gnoi.go b/gnmi_server/gnoi.go index f11a9a81..4c3aad6c 100644 --- a/gnmi_server/gnoi.go +++ b/gnmi_server/gnoi.go @@ -139,6 +139,20 @@ func (srv *SystemServer) KillProcess(ctx context.Context, req *gnoi_system_pb.Ki return &resp, nil } +func HaltSystem() error { + sc,err := ssc.NewDbusClient() + if err != nil { + return err + } + + log.V(2).Infof("Halting the system..") + err = sc.HaltSystem() + if err != nil { + log.V(2).Infof("Failed to Halt the system %v", err); + } + return err +} + func RebootSystem(fileName string) error { log.V(2).Infof("Rebooting with %s...", fileName) sc, err := ssc.NewDbusClient() @@ -158,18 +172,30 @@ func (srv *SystemServer) Reboot(ctx context.Context, req *gnoi_system_pb.RebootR } log.V(1).Info("gNOI: Reboot") log.V(1).Info("Request:", req) - log.V(1).Info("Reboot system now, delay is ignored...") - // TODO: Support GNOI reboot delay - // Delay in nanoseconds before issuing reboot. - // https://github.com/openconfig/gnoi/blob/master/system/system.proto#L102-L115 - config_db_json, err := io.ReadFile(fileName) - if errors.Is(err, os.ErrNotExist) { - fileName = "" - } - err = RebootSystem(string(config_db_json)) - if err != nil { - return nil, err + + // Check the reboot type + switch req.GetMethod() { + case gnoi_system_pb.RebootMethod_HALT: + log.V(1).Info("Reboot method is HALT. Halting the system...") + err = HaltSystem() + if err != nil { + return nil, err + } + default: + log.V(1).Info("Reboot system now, delay is ignored...") + // TODO: Support GNOI reboot delay + // Delay in nanoseconds before issuing reboot. + // https://github.com/openconfig/gnoi/blob/master/system/system.proto#L102-L115 + config_db_json, err := io.ReadFile(fileName) + if errors.Is(err, os.ErrNotExist) { + fileName = "" + } + err = RebootSystem(string(config_db_json)) + if err != nil { + return nil, err + } } + var resp gnoi_system_pb.RebootResponse return &resp, nil } diff --git a/sonic_service_client/dbus_client.go b/sonic_service_client/dbus_client.go index a7868867..0a84b167 100644 --- a/sonic_service_client/dbus_client.go +++ b/sonic_service_client/dbus_client.go @@ -20,6 +20,7 @@ type Service interface { StopService(service string) error RestartService(service string) error GetFileStat(path string) (map[string]string, error) + HaltSystem() error DownloadImage(url string, save_as string) error InstallImage(where string) error } @@ -195,6 +196,24 @@ func (c *DbusClient) GetFileStat(path string) (map[string]string, error) { return data, nil } +func (c *DbusClient) HaltSystem() error { + // Increment the counter for the DBUS_HALT_SYSTEM event + common_utils.IncCounter(common_utils.DBUS_HALT_SYSTEM) + + // Set the module name and update the D-Bus properties + modName := "systemd" + busName := c.busNamePrefix + modName + busPath := c.busPathPrefix + modName + intName := c.intNamePrefix + modName + ".execute_reboot" + + //Set the method to HALT(3) the system + const RebootMethod_HALT = 3 + + // Invoke the D-Bus API to execute the halt command + _, err := DbusApi(busName, busPath, intName, 10, RebootMethod_HALT) + return err +} + func (c *DbusClient) DownloadImage(url string, save_as string) error { common_utils.IncCounter(common_utils.DBUS_IMAGE_DOWNLOAD) modName := "image_service" diff --git a/test/test_gnoi.py b/test/test_gnoi.py index 61b7c067..f8ceccf3 100644 --- a/test/test_gnoi.py +++ b/test/test_gnoi.py @@ -21,6 +21,17 @@ def test_gnoi_reboot(self): assert ret == 0, 'Fail to read counter' assert new_cnt == old_cnt+1, 'DBUS API is not invoked' + def test_gnoi_reboot_halt(self): + ret, old_cnt = gnmi_dump('DBUS halt system') + assert ret == 0, 'Fail to read counter' + + ret, msg = gnoi_reboot(3, 0, 'Test halt system') + assert ret == 0, msg + + ret, new_cnt = gnmi_dump('DBUS halt system') + assert ret == 0, 'Fail to read counter' + assert new_cnt == old_cnt+1, 'DBUS API is not invoked' + def test_gnoi_rebootstatus(self): ret, msg = gnoi_rebootstatus() assert ret != 0, 'RebootStatus should fail' + msg @@ -74,4 +85,4 @@ def test_gnoi_restartprocess_invalid(self): ret, new_cnt = gnmi_dump('DBUS restart service') assert ret == 0, 'Fail to read counter' - assert new_cnt == old_cnt, 'DBUS API invoked unexpectedly' \ No newline at end of file + assert new_cnt == old_cnt, 'DBUS API invoked unexpectedly'