Skip to content

Commit f7072c0

Browse files
committed
fix: check if the device is not mounted when wiping
Open the blockdevice in `O_EXCL` mode when wiping to ensure that we don't wipe a mounted device. This issue was discovered via #12620, when we wipe a blockdevice which is still mounted ending up in a wrong state. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
1 parent 743c3b9 commit f7072c0

File tree

4 files changed

+91
-57
lines changed

4 files changed

+91
-57
lines changed

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ require (
104104
github.com/jeromer/syslogparser v1.1.0
105105
github.com/jsimonetti/rtnetlink/v2 v2.1.0
106106
github.com/jxskiss/base62 v1.1.0
107-
github.com/klauspost/compress v1.18.2
107+
github.com/klauspost/compress v1.18.3
108108
github.com/klauspost/cpuid/v2 v2.3.0
109109
github.com/linode/go-metadata v0.2.3
110110
github.com/martinlindhe/base36 v1.1.1
@@ -140,7 +140,7 @@ require (
140140
github.com/siderolabs/discovery-client v0.1.13
141141
github.com/siderolabs/gen v0.8.6
142142
github.com/siderolabs/go-api-signature v0.3.12
143-
github.com/siderolabs/go-blockdevice/v2 v2.0.22
143+
github.com/siderolabs/go-blockdevice/v2 v2.0.23
144144
github.com/siderolabs/go-circular v0.2.3
145145
github.com/siderolabs/go-cmd v0.1.3
146146
github.com/siderolabs/go-copy v0.1.0
@@ -181,9 +181,9 @@ require (
181181
golang.org/x/net v0.48.0
182182
golang.org/x/oauth2 v0.34.0
183183
golang.org/x/sync v0.19.0
184-
golang.org/x/sys v0.39.0
184+
golang.org/x/sys v0.40.0
185185
golang.org/x/term v0.38.0
186-
golang.org/x/text v0.32.0
186+
golang.org/x/text v0.33.0
187187
golang.org/x/time v0.14.0
188188
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
189189
google.golang.org/grpc v1.77.0
@@ -317,7 +317,7 @@ require (
317317
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
318318
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
319319
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect
320-
github.com/opencontainers/selinux v1.13.0 // indirect
320+
github.com/opencontainers/selinux v1.13.1 // indirect
321321
github.com/opentracing/opentracing-go v1.2.0 // indirect
322322
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
323323
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb // indirect
@@ -360,8 +360,8 @@ require (
360360
go.yaml.in/yaml/v3 v3.0.4 // indirect
361361
golang.org/x/crypto v0.46.0 // indirect
362362
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
363-
golang.org/x/mod v0.30.0 // indirect
364-
golang.org/x/tools v0.39.0 // indirect
363+
golang.org/x/mod v0.31.0 // indirect
364+
golang.org/x/tools v0.40.0 // indirect
365365
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
366366
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
367367
google.golang.org/genproto/googleapis/api v0.0.0-20251213004720-97cd9d5aeac2 // indirect

go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRt
432432
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
433433
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
434434
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
435-
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
436-
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
435+
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
436+
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
437437
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
438438
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
439439
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -562,8 +562,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
562562
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
563563
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
564564
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
565-
github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
566-
github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
565+
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
566+
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
567567
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
568568
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
569569
github.com/packethost/packngo v0.31.0 h1:LLH90ardhULWbagBIc3I3nl2uU75io0a7AwY6hyi0S4=
@@ -643,8 +643,8 @@ github.com/siderolabs/gen v0.8.6 h1:pE6shuqov3L+5rEcAUJ/kY6iJofimljQw5G95P8a5c4=
643643
github.com/siderolabs/gen v0.8.6/go.mod h1:J9IbusbES2W6QWjtSHpDV9iPGZHc978h1+KJ4oQRspQ=
644644
github.com/siderolabs/go-api-signature v0.3.12 h1:i1X+kPh9fzo+lEjtEplZSbtq1p21vKv4FCWJcB/ozvk=
645645
github.com/siderolabs/go-api-signature v0.3.12/go.mod h1:dPLiXohup4qHX7KUgF/wwOE3lRU5uAr3ssEomNxiyxY=
646-
github.com/siderolabs/go-blockdevice/v2 v2.0.22 h1:57SsdY/xWItgJCpF/++xwPp6jIllRO7q+IyX5xp4xB0=
647-
github.com/siderolabs/go-blockdevice/v2 v2.0.22/go.mod h1:jtLk/1RMdhN9kIyVfFiSYwBvJx7Ule4lDLL+wM3tlIU=
646+
github.com/siderolabs/go-blockdevice/v2 v2.0.23 h1:20+G+4nrtD3P4Arv6pPMmypNbZ23f/98UX8R/nzhGuo=
647+
github.com/siderolabs/go-blockdevice/v2 v2.0.23/go.mod h1:8J8R+5PG4+oTq1g9zTYKFMikBx01U6gTPc5NKo7BEV8=
648648
github.com/siderolabs/go-circular v0.2.3 h1:GKkA1Tw79kEFGtWdl7WTxEUTbwtklITeiRT0V1McHrA=
649649
github.com/siderolabs/go-circular v0.2.3/go.mod h1:YBN/q9YpQphUYnBtBgPsngauSHj1TEZfgQZWZVjk1WE=
650650
github.com/siderolabs/go-cmd v0.1.3 h1:JrgZwqhJQeoec3QRON0LK+fv+0y7d0DyY7zsfkO6ciw=
@@ -835,8 +835,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
835835
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
836836
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
837837
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
838-
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
839-
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
838+
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
839+
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
840840
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
841841
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
842842
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -935,8 +935,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
935935
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
936936
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
937937
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
938-
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
939-
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
938+
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
939+
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
940940
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
941941
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
942942
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -953,8 +953,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
953953
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
954954
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
955955
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
956-
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
957-
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
956+
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
957+
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
958958
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
959959
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
960960
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -970,8 +970,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
970970
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
971971
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
972972
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
973-
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
974-
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
973+
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
974+
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
975975
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
976976
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
977977
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/app/storaged/server.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package internal
77

88
import (
99
"context"
10+
"errors"
1011
"fmt"
1112
"log"
1213
"path/filepath"
@@ -16,6 +17,7 @@ import (
1617
"github.com/cosi-project/runtime/pkg/state"
1718
blockdev "github.com/siderolabs/go-blockdevice/v2/block"
1819
"github.com/siderolabs/go-blockdevice/v2/partitioning/gpt"
20+
"golang.org/x/sys/unix"
1921
"google.golang.org/grpc/codes"
2022
"google.golang.org/grpc/status"
2123
"google.golang.org/protobuf/types/known/emptypb"
@@ -264,8 +266,15 @@ func (s *Server) wipeDevice(deviceName string, method storage.BlockDeviceWipeDes
264266
defer parentBd.Close() //nolint:errcheck
265267
}
266268

267-
bd, err := blockdev.NewFromPath(filepath.Join("/dev", deviceName), blockdev.OpenForWrite())
269+
bd, err := blockdev.NewFromPath(filepath.Join("/dev", deviceName),
270+
blockdev.OpenForWrite(),
271+
blockdev.OpenAssertNotMounted(),
272+
)
268273
if err != nil {
274+
if errors.Is(err, unix.EBUSY) {
275+
return status.Errorf(codes.FailedPrecondition, "block device %q is mounted or in use", deviceName)
276+
}
277+
269278
return status.Errorf(codes.Internal, "failed to open block device %q: %v", deviceName, err)
270279
}
271280

internal/integration/api/volumes.go

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -648,14 +648,19 @@ func (suite *VolumesSuite) TestUserVolumesPartition() {
648648
rtestutils.AssertNoResource[*block.VolumeStatus](ctx, suite.T(), suite.Client.COSI, userVolumeID)
649649
}
650650

651-
suite.Require().NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
652-
Devices: []*storage.BlockDeviceWipeDescriptor{
653-
{
654-
Device: filepath.Base(userDisks[0]),
655-
Method: storage.BlockDeviceWipeDescriptor_FAST,
651+
suite.Require().EventuallyWithT(func(collect *assert.CollectT) {
652+
// a little retry loop, as the device might be considered busy for a little while after unmounting
653+
asrt := assert.New(collect)
654+
655+
asrt.NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
656+
Devices: []*storage.BlockDeviceWipeDescriptor{
657+
{
658+
Device: filepath.Base(userDisks[0]),
659+
Method: storage.BlockDeviceWipeDescriptor_FAST,
660+
},
656661
},
657-
},
658-
}))
662+
}))
663+
}, time.Minute, time.Second, "failed to wipe disk %s", userDisks[0])
659664

660665
// wait for the discovered volume reflect wiped status
661666
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, filepath.Base(userDisks[0]),
@@ -819,14 +824,19 @@ func (suite *VolumesSuite) TestUserVolumesDisk() {
819824
rtestutils.AssertNoResource[*block.VolumeStatus](ctx, suite.T(), suite.Client.COSI, userVolumeID)
820825
}
821826

822-
suite.Require().NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
823-
Devices: []*storage.BlockDeviceWipeDescriptor{
824-
{
825-
Device: filepath.Base(userDisks[0]),
826-
Method: storage.BlockDeviceWipeDescriptor_FAST,
827+
suite.Require().EventuallyWithT(func(collect *assert.CollectT) {
828+
// a little retry loop, as the device might be considered busy for a little while after unmounting
829+
asrt := assert.New(collect)
830+
831+
asrt.NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
832+
Devices: []*storage.BlockDeviceWipeDescriptor{
833+
{
834+
Device: filepath.Base(userDisks[0]),
835+
Method: storage.BlockDeviceWipeDescriptor_FAST,
836+
},
827837
},
828-
},
829-
}))
838+
}))
839+
}, time.Minute, time.Second, "failed to wipe disk %s", userDisks[0])
830840

831841
// wait for the discovered volume reflect wiped status
832842
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, filepath.Base(userDisks[0]),
@@ -1058,14 +1068,19 @@ func (suite *VolumesSuite) TestRawVolumes() {
10581068
rtestutils.AssertNoResource[*block.VolumeStatus](ctx, suite.T(), suite.Client.COSI, rawVolumeID)
10591069
}
10601070

1061-
suite.Require().NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1062-
Devices: []*storage.BlockDeviceWipeDescriptor{
1063-
{
1064-
Device: filepath.Base(userDisks[0]),
1065-
Method: storage.BlockDeviceWipeDescriptor_FAST,
1071+
suite.Require().EventuallyWithT(func(collect *assert.CollectT) {
1072+
// a little retry loop, as the device might be considered busy for a little while after unmounting
1073+
asrt := assert.New(collect)
1074+
1075+
asrt.NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1076+
Devices: []*storage.BlockDeviceWipeDescriptor{
1077+
{
1078+
Device: filepath.Base(userDisks[0]),
1079+
Method: storage.BlockDeviceWipeDescriptor_FAST,
1080+
},
10661081
},
1067-
},
1068-
}))
1082+
}))
1083+
}, time.Minute, time.Second, "failed to wipe disk %s", userDisks[0])
10691084

10701085
// wait for the discovered volume reflect wiped status
10711086
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, filepath.Base(userDisks[0]),
@@ -1207,14 +1222,19 @@ func (suite *VolumesSuite) TestExistingVolumes() {
12071222

12081223
rtestutils.AssertNoResource[*block.VolumeStatus](ctx, suite.T(), suite.Client.COSI, existingVolumeID)
12091224

1210-
suite.Require().NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1211-
Devices: []*storage.BlockDeviceWipeDescriptor{
1212-
{
1213-
Device: filepath.Base(userDisks[0]),
1214-
Method: storage.BlockDeviceWipeDescriptor_FAST,
1225+
suite.Require().EventuallyWithT(func(collect *assert.CollectT) {
1226+
// a little retry loop, as the device might be considered busy for a little while after unmounting
1227+
asrt := assert.New(collect)
1228+
1229+
asrt.NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1230+
Devices: []*storage.BlockDeviceWipeDescriptor{
1231+
{
1232+
Device: filepath.Base(userDisks[0]),
1233+
Method: storage.BlockDeviceWipeDescriptor_FAST,
1234+
},
12151235
},
1216-
},
1217-
}))
1236+
}))
1237+
}, time.Minute, time.Second, "failed to wipe disk %s", userDisks[0])
12181238

12191239
// wait for the discovered volume reflect wiped status
12201240
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, filepath.Base(userDisks[0]),
@@ -1442,14 +1462,19 @@ func (suite *VolumesSuite) TestSwapOnOff() {
14421462
rtestutils.AssertNoResource[*block.SwapStatus](ctx, suite.T(), suite.Client.COSI, volumeStatus.TypedSpec().MountLocation)
14431463
rtestutils.AssertNoResource[*block.VolumeConfig](ctx, suite.T(), suite.Client.COSI, swapVolumeID)
14441464

1445-
suite.Require().NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1446-
Devices: []*storage.BlockDeviceWipeDescriptor{
1447-
{
1448-
Device: filepath.Base(userDisks[0]),
1449-
Method: storage.BlockDeviceWipeDescriptor_FAST,
1465+
suite.Require().EventuallyWithT(func(collect *assert.CollectT) {
1466+
// a little retry loop, as the device might be considered busy for a little while after unmounting
1467+
asrt := assert.New(collect)
1468+
1469+
asrt.NoError(suite.Client.BlockDeviceWipe(ctx, &storage.BlockDeviceWipeRequest{
1470+
Devices: []*storage.BlockDeviceWipeDescriptor{
1471+
{
1472+
Device: filepath.Base(userDisks[0]),
1473+
Method: storage.BlockDeviceWipeDescriptor_FAST,
1474+
},
14501475
},
1451-
},
1452-
}))
1476+
}))
1477+
}, time.Minute, time.Second, "failed to wipe disk %s", userDisks[0])
14531478
}
14541479

14551480
// TestZswapStatus verifies that all zswap-enabled machines have zswap running.

0 commit comments

Comments
 (0)