11package host_service
22
33import (
4+ "context"
45 "fmt"
56 "reflect"
67 "strings"
@@ -49,15 +50,49 @@ type Service interface {
4950 // Docker services APIs
5051 LoadDockerImage (image string ) error
5152 InstallOS (req string ) (string , error )
53+ //Credentialz service APIs
54+ SSHMgmtSet (cmd string ) error
55+ GLOMEConfigSet (ctx context.Context , cmd string ) error
56+ SSHCheckpoint (action CredzCheckpointAction ) error
57+ GLOMERestoreCheckpoint (ctx context.Context ) error
58+ ConsoleSet (cmd string ) error
59+ ConsoleCheckpoint (action CredzCheckpointAction ) error
5260}
5361
62+ type CredzCheckpointAction string
63+
64+ const (
65+ CredzCPCreate CredzCheckpointAction = ".create_checkpoint"
66+ CredzCPDelete CredzCheckpointAction = ".delete_checkpoint"
67+ CredzCPRestore CredzCheckpointAction = ".restore_checkpoint"
68+ CredzGlomePushConfig CredzCheckpointAction = ".push_config"
69+ NamePrefix = "org.SONiC.HostService."
70+ PathPrefix = "/org/SONiC/HostService/"
71+ )
72+
5473type DbusClient struct {
5574 busNamePrefix string
5675 busPathPrefix string
5776 intNamePrefix string
5877 channel chan struct {}
5978}
6079
80+ type Caller interface {
81+ DbusApi (busName string , busPath string , intName string , timeout int , args ... interface {}) (interface {}, error )
82+ }
83+
84+ type DbusCaller struct {}
85+
86+ type FakeDbusCaller struct {
87+ Msg string
88+ }
89+
90+ type FailDbusCaller struct {}
91+
92+ type SpyDbusCaller struct {
93+ Command chan []string
94+ }
95+
6196func NewDbusClient () (Service , error ) {
6297 log .Infof ("DbusClient: NewDbusClient" )
6398
@@ -80,6 +115,81 @@ func (c *DbusClient) Close() error {
80115 return nil
81116}
82117
118+ func (_ * FailDbusCaller ) DbusApi (busName string , busPath string , intName string , timeout int , args ... interface {}) (interface {}, error ) {
119+ return "" , fmt .Errorf ("%v %v" , intName , args )
120+ }
121+
122+ func (c * SpyDbusCaller ) DbusApi (busName string , busPath string , intName string , timeout int , args ... interface {}) (interface {}, error ) {
123+ resp := []string {intName }
124+ for _ , el := range args {
125+ resp = append (resp , fmt .Sprintf ("%v" , el ))
126+ }
127+ c .Command <- resp
128+ return "" , nil
129+ }
130+
131+ func (_ * DbusCaller ) DbusApi (busName string , busPath string , intName string , timeout int , args ... interface {}) (interface {}, error ) {
132+ common_utils .IncCounter (common_utils .DBUS )
133+ conn , err := dbus .SystemBus ()
134+ log .V (2 ).Infof ("DBUS Call: %v %v" , intName , args )
135+ if err != nil {
136+ log .V (2 ).Infof ("Failed to connect to system bus: %v" , err )
137+ common_utils .IncCounter (common_utils .DBUS_FAIL )
138+ return nil , err
139+ }
140+
141+ ch := make (chan * dbus.Call , 1 )
142+ obj := conn .Object (busName , dbus .ObjectPath (busPath ))
143+ obj .Go (intName , 0 , ch , args ... )
144+
145+ select {
146+ case call := <- ch :
147+ if call .Err != nil {
148+ common_utils .IncCounter (common_utils .DBUS_FAIL )
149+ return nil , call .Err
150+ }
151+ result := call .Body
152+ if len (result ) == 0 {
153+ common_utils .IncCounter (common_utils .DBUS_FAIL )
154+ return nil , fmt .Errorf ("Dbus result is empty %v" , result )
155+ }
156+ if ret , ok := result [0 ].(int32 ); ok {
157+ if ret == 0 {
158+ if len (result ) != 2 {
159+ common_utils .IncCounter (common_utils .DBUS_FAIL )
160+ return nil , fmt .Errorf ("Dbus result is invalid %v" , result )
161+ }
162+ if _ , ok := result [1 ].(string ); ! ok {
163+ return nil , fmt .Errorf ("Dbus result is invalid: second element is not string." )
164+ }
165+ return result [1 ], nil
166+ } else {
167+ if len (result ) != 2 {
168+ common_utils .IncCounter (common_utils .DBUS_FAIL )
169+ return nil , fmt .Errorf ("Dbus result is invalid %v" , result )
170+ }
171+ if msg , check := result [1 ].(string ); check {
172+ common_utils .IncCounter (common_utils .DBUS_FAIL )
173+ return nil , fmt .Errorf (msg )
174+ } else if msg , check := result [1 ].(map [string ]string ); check {
175+ common_utils .IncCounter (common_utils .DBUS_FAIL )
176+ return nil , fmt .Errorf (msg ["error" ])
177+ } else {
178+ common_utils .IncCounter (common_utils .DBUS_FAIL )
179+ return nil , fmt .Errorf ("Invalid result message type %v %v" , result [1 ], reflect .TypeOf (result [1 ]))
180+ }
181+ }
182+ } else {
183+ common_utils .IncCounter (common_utils .DBUS_FAIL )
184+ return nil , fmt .Errorf ("Invalid result type %v %v" , result [0 ], reflect .TypeOf (result [0 ]))
185+ }
186+ case <- time .After (time .Duration (timeout ) * time .Second ):
187+ log .V (2 ).Infof ("DbusApi: timeout" )
188+ common_utils .IncCounter (common_utils .DBUS_FAIL )
189+ return nil , fmt .Errorf ("Timeout %v" , timeout )
190+ }
191+ }
192+
83193func DbusApi (busName string , busPath string , intName string , timeout int , args ... interface {}) (interface {}, error ) {
84194 common_utils .IncCounter (common_utils .DBUS )
85195 conn , err := dbus .SystemBus ()
@@ -424,3 +534,96 @@ func (c *DbusClient) HealthzAck(req string) (string, error) {
424534 }
425535 return strResult , nil
426536}
537+
538+ func (c * DbusClient ) ConsoleSet (cmd string ) error {
539+ modName := "gnsi_console"
540+ busName := c .busNamePrefix + modName
541+ busPath := c .busPathPrefix + modName
542+ intName := c .intNamePrefix + modName + ".set"
543+
544+ common_utils .IncCounter (common_utils .GNSI_CREDZ_SET )
545+ _ , err := DbusApi (busName , busPath , intName , 10 , []string {cmd })
546+ return err
547+ }
548+
549+ func (c * DbusClient ) SSHMgmtSet (cmd string ) error {
550+ modName := "ssh_mgmt"
551+ busName := c .busNamePrefix + modName
552+ busPath := c .busPathPrefix + modName
553+ intName := c .intNamePrefix + modName + ".set"
554+
555+ common_utils .IncCounter (common_utils .GNSI_CREDZ_SET )
556+ _ , err := DbusApi (busName , busPath , intName , 10 , []string {cmd })
557+ return err
558+ }
559+
560+ // GLOMEConfigSet is used to write the GLOME config in the host service file system.
561+ func (c * DbusClient ) GLOMEConfigSet (ctx context.Context , cmd string ) error {
562+ modName := "glome"
563+ busName := c .busNamePrefix + modName
564+ busPath := c .busPathPrefix + modName
565+ intName := c .intNamePrefix + modName + string (CredzGlomePushConfig )
566+
567+ common_utils .IncCounter (common_utils .GNSI_CREDZ_SET )
568+ timeout := 10 // Default timeout in seconds.
569+ if deadline , ok := ctx .Deadline (); ok {
570+ remaining := time .Until (deadline )
571+ if remaining <= 0 {
572+ return context .DeadlineExceeded
573+ }
574+ timeout = int (remaining .Seconds ())
575+ if timeout > 10 {
576+ timeout = 10
577+ }
578+ }
579+ _ , err := DbusApi (busName , busPath , intName , timeout , cmd )
580+ return err
581+ }
582+
583+ func (c * DbusClient ) ConsoleCheckpoint (action CredzCheckpointAction ) error {
584+ modName := "gnsi_console"
585+ busName := c .busNamePrefix + modName
586+ busPath := c .busPathPrefix + modName
587+ intName := c .intNamePrefix + modName + string (action )
588+
589+ common_utils .IncCounter (common_utils .GNSI_CREDZ_CHECKPOINT )
590+ _ , err := DbusApi (busName , busPath , intName , 10 , "" )
591+ return err
592+ }
593+
594+ func (c * DbusClient ) SSHCheckpoint (action CredzCheckpointAction ) error {
595+ modName := "ssh_mgmt"
596+ busName := c .busNamePrefix + modName
597+ busPath := c .busPathPrefix + modName
598+ intName := c .intNamePrefix + modName + string (action )
599+
600+ common_utils .IncCounter (common_utils .GNSI_CREDZ_CHECKPOINT )
601+ _ , err := DbusApi (busName , busPath , intName , 10 , "" )
602+ return err
603+ }
604+
605+ // GLOMERestoreCheckpoint is used to restore the GLOME config metadata to the
606+ // checkpoint state. This is used to rollback the GLOME config in the host
607+ // service file system.
608+ func (c * DbusClient ) GLOMERestoreCheckpoint (ctx context.Context ) error {
609+ modName := "glome"
610+ busName := c .busNamePrefix + modName
611+ busPath := c .busPathPrefix + modName
612+ intName := c .intNamePrefix + modName + string (CredzCPRestore )
613+
614+ common_utils .IncCounter (common_utils .GNSI_CREDZ_CHECKPOINT )
615+ // Default timeout in seconds. Set to 5 minutes to give enough time for rollback.
616+ timeout := 300
617+ if deadline , ok := ctx .Deadline (); ok {
618+ remaining := time .Until (deadline )
619+ if remaining <= 0 {
620+ return context .DeadlineExceeded
621+ }
622+ timeout = int (remaining .Seconds ())
623+ if timeout > 10 {
624+ timeout = 10
625+ }
626+ }
627+ _ , err := DbusApi (busName , busPath , intName , timeout )
628+ return err
629+ }
0 commit comments