@@ -17,6 +17,8 @@ package ignition
1717import (
1818 "context"
1919 "fmt"
20+ "os"
21+ "os/exec"
2022 "time"
2123
2224 "github.com/pkg/errors"
@@ -37,6 +39,13 @@ func init() {
3739 Platforms : []string {"qemu" },
3840 Tags : []string {"ignition" },
3941 })
42+ register .RegisterTest (& register.Test {
43+ Name : "coreos.unique.boot.failure" ,
44+ ClusterSize : 0 ,
45+ Description : "Verify boot fails if there are pre-existing boot filesystems." ,
46+ Platforms : []string {"qemu" },
47+ Run : runBootfsFailure ,
48+ })
4049}
4150
4251func runIgnitionFailure (c cluster.TestCluster ) {
@@ -45,6 +54,12 @@ func runIgnitionFailure(c cluster.TestCluster) {
4554 }
4655}
4756
57+ func runBootfsFailure (c cluster.TestCluster ) {
58+ if err := bootfsFailure (c ); err != nil {
59+ c .Fatal (err .Error ())
60+ }
61+ }
62+
4863func ignitionFailure (c cluster.TestCluster ) error {
4964 // We can't create files in / due to the immutable bit OSTree creates, so
5065 // this is a convenient way to test Ignition failure.
@@ -101,3 +116,87 @@ func ignitionFailure(c cluster.TestCluster) error {
101116 return nil
102117 }
103118}
119+
120+ // Attach a block device which has a pre-existing boot filesystem on it
121+ func bootfsFailure (c cluster.TestCluster ) error {
122+ builder := platform .NewQemuBuilder ()
123+ defer builder .Close ()
124+ // get current path and create tmp dir
125+ fakeBoot := "fakeboot"
126+ tempPath , err := builder .TempFile (fakeBoot )
127+ if err != nil {
128+ return err
129+ }
130+ pathName := tempPath .Name ()
131+ fmt .Printf ("Temp path: %v\n " , pathName )
132+
133+ createBoot , err := os .Create (pathName )
134+ if err != nil {
135+ return err
136+ }
137+
138+ // Truncate the file to 1 gigabyte
139+ const oneGB = 1 << 30
140+ err = createBoot .Truncate (oneGB )
141+ if err != nil {
142+ return err
143+ }
144+
145+ cmd := exec .Command ("mkfs.ext4" , "-L" , "boot" , pathName )
146+ cmd .Stderr = os .Stderr
147+ if err := cmd .Run (); err != nil {
148+ c .Fatal (err )
149+ }
150+
151+ err = builder .AddDisk (& platform.Disk {
152+ BackingFile : kola .QEMUOptions .DiskImage ,
153+ BackingFormat : "raw" ,
154+ })
155+ if err != nil {
156+ return err
157+ }
158+ err = builder .AddBootDisk (& platform.Disk {
159+ BackingFile : kola .QEMUOptions .DiskImage ,
160+ })
161+
162+ if err != nil {
163+ return err
164+ }
165+ builder .MemoryMiB = 1024
166+ builder .Firmware = kola .QEMUOptions .Firmware
167+ inst , err := builder .Exec ()
168+ if err != nil {
169+ return err
170+ }
171+ defer inst .Destroy ()
172+
173+ ctx , cancel := context .WithTimeout (context .Background (), 2 * time .Minute )
174+ defer cancel ()
175+
176+ errchan := make (chan error )
177+ go func () {
178+ err := inst .WaitAll (ctx )
179+ if err == nil {
180+ err = fmt .Errorf ("bootfs unexpectedly succeeded" )
181+ } else if err == platform .ErrInitramfsEmergency {
182+ // The expected case
183+ err = nil
184+ } else {
185+ err = errors .Wrapf (err , "expected initramfs emergency.target error" )
186+ }
187+ errchan <- err
188+ }()
189+
190+ select {
191+ case <- ctx .Done ():
192+ if err := inst .Kill (); err != nil {
193+ return errors .Wrapf (err , "failed to kill the vm instance" )
194+ }
195+ return errors .Wrapf (ctx .Err (), "timed out waiting for initramfs error" )
196+ case err := <- errchan :
197+ if err != nil {
198+ return err
199+ }
200+ return nil
201+ }
202+ }
0 commit comments