@@ -105,10 +105,25 @@ reboot
105105 autopkgtestRebootPrepareScript = `#!/bin/bash
106106set -euo pipefail
107107exec /usr/local/bin/kolet reboot-request "$1"
108+ `
109+
110+ // Soft-reboot support
111+ autopkgTestSoftRebootPath = "/tmp/autopkgtest-soft-reboot"
112+ autopkgtestSoftRebootScript = `#!/bin/bash
113+ set -xeuo pipefail
114+ /usr/local/bin/kolet soft-reboot-request "$1"
115+ systemctl soft-reboot
116+ `
117+ autopkgTestSoftRebootPreparePath = "/tmp/autopkgtest-soft-reboot-prepare"
118+
119+ autopkgtestSoftRebootPrepareScript = `#!/bin/bash
120+ set -euo pipefail
121+ exec /usr/local/bin/kolet soft-reboot-request "$1"
108122`
109123
110124 // File used to communicate between the script and the kolet runner internally
111- rebootRequestFifo = "/run/kolet-reboot"
125+ rebootRequestFifo = "/run/kolet-reboot"
126+ softRebootRequestFifo = "/run/kolet-soft-reboot"
112127)
113128
114129var (
@@ -140,6 +155,13 @@ var (
140155 SilenceUsage : true ,
141156 }
142157
158+ cmdSoftReboot = & cobra.Command {
159+ Use : "soft-reboot-request MARK" ,
160+ Short : "Request a soft reboot" ,
161+ RunE : runSoftReboot ,
162+ SilenceUsage : true ,
163+ }
164+
143165 cmdHttpd = & cobra.Command {
144166 Use : "httpd" ,
145167 Short : "Start an HTTP server to serve the contents of the file system" ,
@@ -259,6 +281,20 @@ func initiateReboot(mark string) error {
259281 return nil
260282}
261283
284+ func initiateSoftReboot (mark string ) error {
285+ systemdjournal .Print (systemdjournal .PriInfo , "Processing soft-reboot request" )
286+ res := kola.KoletResult {
287+ SoftReboot : string (mark ),
288+ }
289+ buf , err := json .Marshal (& res )
290+ if err != nil {
291+ return errors .Wrapf (err , "serializing KoletResult" )
292+ }
293+ fmt .Println (string (buf ))
294+ systemdjournal .Print (systemdjournal .PriInfo , "Acknowledged soft-reboot request with mark: %s" , buf )
295+ return nil
296+ }
297+
262298func runExtUnit (cmd * cobra.Command , args []string ) error {
263299 rebootOff , _ := cmd .Flags ().GetBool ("deny-reboots" )
264300 // Write the autopkgtest wrappers
@@ -268,10 +304,18 @@ func runExtUnit(cmd *cobra.Command, args []string) error {
268304 if err := os .WriteFile (autopkgTestRebootPreparePath , []byte (autopkgtestRebootPrepareScript ), 0755 ); err != nil {
269305 return err
270306 }
307+ // Write the soft-reboot autopkgtest wrappers
308+ if err := os .WriteFile (autopkgTestSoftRebootPath , []byte (autopkgtestSoftRebootScript ), 0755 ); err != nil {
309+ return err
310+ }
311+ if err := os .WriteFile (autopkgTestSoftRebootPreparePath , []byte (autopkgtestSoftRebootPrepareScript ), 0755 ); err != nil {
312+ return err
313+ }
271314
272315 // Create the reboot cmdline -> login FIFO for the reboot mark and
273316 // proxy it into a channel
274317 rebootChan := make (chan string )
318+ softRebootChan := make (chan string )
275319 errChan := make (chan error )
276320
277321 // We want to prevent certain tests (like non-exclusive tests) from rebooting
@@ -293,6 +337,25 @@ func runExtUnit(cmd *cobra.Command, args []string) error {
293337 }
294338 rebootChan <- string (buf )
295339 }()
340+
341+ // Create soft-reboot FIFO and channel
342+ err = exec .Command ("mkfifo" , softRebootRequestFifo ).Run ()
343+ if err != nil {
344+ return err
345+ }
346+ go func () {
347+ softRebootReader , err := os .Open (softRebootRequestFifo )
348+ if err != nil {
349+ errChan <- err
350+ return
351+ }
352+ defer softRebootReader .Close ()
353+ buf , err := io .ReadAll (softRebootReader )
354+ if err != nil {
355+ errChan <- err
356+ }
357+ softRebootChan <- string (buf )
358+ }()
296359 }
297360
298361 ctx := context .Background ()
@@ -334,6 +397,8 @@ func runExtUnit(cmd *cobra.Command, args []string) error {
334397 return err
335398 case reboot := <- rebootChan :
336399 return initiateReboot (reboot )
400+ case softReboot := <- softRebootChan :
401+ return initiateSoftReboot (softReboot )
337402 case m := <- unitevents :
338403 for n := range m {
339404 if n == unitname {
@@ -387,6 +452,35 @@ func runReboot(cmd *cobra.Command, args []string) error {
387452 return nil
388453}
389454
455+ // runSoftReboot handles soft-reboot requests similar to runReboot but for systemctl soft-reboot
456+ func runSoftReboot (cmd * cobra.Command , args []string ) error {
457+ if _ , err := os .Stat (softRebootRequestFifo ); os .IsNotExist (err ) {
458+ return errors .New ("Soft-reboots are not supported for this test, softRebootRequestFifo does not exist." )
459+ }
460+
461+ mark := args [0 ]
462+ systemdjournal .Print (systemdjournal .PriInfo , "Requesting soft-reboot with mark: %s" , mark )
463+ err := exec .Command ("mkfifo" , kola .KoletRebootAckFifo ).Run ()
464+ if err != nil {
465+ return err
466+ }
467+ err = os .WriteFile (softRebootRequestFifo , []byte (mark ), 0644 )
468+ if err != nil {
469+ return err
470+ }
471+ f , err := os .Open (kola .KoletRebootAckFifo )
472+ if err != nil {
473+ return err
474+ }
475+ buf := make ([]byte , 1 )
476+ _ , err = f .Read (buf )
477+ if err != nil {
478+ return err
479+ }
480+ systemdjournal .Print (systemdjournal .PriInfo , "Soft-reboot request acknowledged" )
481+ return nil
482+ }
483+
390484func runHttpd (cmd * cobra.Command , args []string ) error {
391485 port , _ := cmd .Flags ().GetString ("port" )
392486 path , _ := cmd .Flags ().GetString ("path" )
@@ -403,6 +497,8 @@ func main() {
403497 root .AddCommand (cmdRunExtUnit )
404498 cmdReboot .Args = cobra .ExactArgs (1 )
405499 root .AddCommand (cmdReboot )
500+ cmdSoftReboot .Args = cobra .ExactArgs (1 )
501+ root .AddCommand (cmdSoftReboot )
406502 cmdHttpd .Flags ().StringP ("port" , "" , "80" , "port" )
407503 cmdHttpd .Flags ().StringP ("path" , "" , "./" , "path to filesystem contents to serve" )
408504 cmdHttpd .Args = cobra .ExactArgs (0 )
0 commit comments