@@ -25,6 +25,7 @@ import (
25
25
"testing"
26
26
27
27
"github.com/moby/sys/userns"
28
+ "github.com/opencontainers/runtime-spec/specs-go"
28
29
"gotest.tools/v3/assert"
29
30
30
31
"github.com/containerd/cgroups/v3"
@@ -421,3 +422,125 @@ func TestRunBlkioWeightCgroupV2(t *testing.T) {
421
422
base .Cmd ("update" , containerName , "--blkio-weight" , "400" ).AssertOK ()
422
423
base .Cmd ("exec" , containerName , "cat" , "io.bfq.weight" ).AssertOutExactly ("default 400\n " )
423
424
}
425
+
426
+ func TestRunBlkioSettingCgroupV2 (t * testing.T ) {
427
+ t .Parallel ()
428
+ if cgroups .Mode () != cgroups .Unified {
429
+ t .Skip ("test requires cgroup v2" )
430
+ }
431
+
432
+ // TODO: Fix logic to check if bfq is set as the scheduler for the block device
433
+ //
434
+ // if _, err := os.Stat("/sys/module/bfq"); err != nil {
435
+ // t.Skipf("test requires \"bfq\" module to be loaded: %v", err)
436
+ // }
437
+ testCase := nerdtest .Setup ()
438
+ testCase .Require = require .Not (nerdtest .Docker )
439
+
440
+ base := testutil .NewBase (t )
441
+ info := base .Info ()
442
+ switch info .CgroupDriver {
443
+ case "none" , "" :
444
+ t .Skip ("test requires cgroup driver" )
445
+ }
446
+
447
+ tests := []struct {
448
+ name string
449
+ args []string
450
+ validate func (t * testing.T , blockIO * specs.LinuxBlockIO )
451
+ }{
452
+ {
453
+ name : "blkio-weight" ,
454
+ args : []string {"--blkio-weight" , "150" },
455
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
456
+ assert .Equal (t , uint16 (150 ), * blockIO .Weight )
457
+ },
458
+ },
459
+ {
460
+ name : "blkio-weight-device" ,
461
+ args : []string {"--blkio-weight-device" , "/dev/sda:100" },
462
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
463
+ assert .Equal (t , 1 , len (blockIO .WeightDevice ))
464
+ assert .Equal (t , uint16 (100 ), * blockIO .WeightDevice [0 ].Weight )
465
+ },
466
+ },
467
+ {
468
+ name : "device-read-bps" ,
469
+ args : []string {"--device-read-bps" , "/dev/sda:1048576" },
470
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
471
+ assert .Equal (t , 1 , len (blockIO .ThrottleReadBpsDevice ))
472
+ assert .Equal (t , uint64 (1048576 ), blockIO .ThrottleReadBpsDevice [0 ].Rate )
473
+ },
474
+ },
475
+ {
476
+ name : "device-write-bps" ,
477
+ args : []string {"--device-write-bps" , "/dev/sda:2097152" },
478
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
479
+ assert .Equal (t , 1 , len (blockIO .ThrottleWriteBpsDevice ))
480
+ assert .Equal (t , uint64 (2097152 ), blockIO .ThrottleWriteBpsDevice [0 ].Rate )
481
+ },
482
+ },
483
+ {
484
+ name : "device-read-iops" ,
485
+ args : []string {"--device-read-iops" , "/dev/sda:1000" },
486
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
487
+ assert .Equal (t , 1 , len (blockIO .ThrottleReadIOPSDevice ))
488
+ assert .Equal (t , uint64 (1000 ), blockIO .ThrottleReadIOPSDevice [0 ].Rate )
489
+ },
490
+ },
491
+ {
492
+ name : "device-write-iops" ,
493
+ args : []string {"--device-write-iops" , "/dev/sda:2000" },
494
+ validate : func (t * testing.T , blockIO * specs.LinuxBlockIO ) {
495
+ assert .Equal (t , 1 , len (blockIO .ThrottleWriteIOPSDevice ))
496
+ assert .Equal (t , uint64 (2000 ), blockIO .ThrottleWriteIOPSDevice [0 ].Rate )
497
+ },
498
+ },
499
+ }
500
+
501
+ for _ , tt := range tests {
502
+ tt := tt // capture range variable
503
+ t .Run (tt .name , func (t * testing.T ) {
504
+ t .Parallel ()
505
+ containerName := testutil .Identifier (t )
506
+
507
+ args := []string {"run" , "-d" , "--name" , containerName }
508
+ args = append (args , tt .args ... )
509
+ args = append (args , testutil .AlpineImage , "sleep" , "infinity" )
510
+ base .Cmd (args ... ).AssertOK ()
511
+ t .Cleanup (func () {
512
+ base .Cmd ("rm" , "-f" , containerName ).Run ()
513
+ })
514
+
515
+ // Connect to containerd
516
+ addr := base .ContainerdAddress ()
517
+ client , err := containerd .New (addr , containerd .WithDefaultNamespace (testutil .Namespace ))
518
+ assert .NilError (t , err )
519
+ ctx := context .Background ()
520
+
521
+ // Get container ID
522
+ var cid string
523
+ walker := & containerwalker.ContainerWalker {
524
+ Client : client ,
525
+ OnFound : func (ctx context.Context , found containerwalker.Found ) error {
526
+ if found .MatchCount > 1 {
527
+ return fmt .Errorf ("multiple IDs found with provided prefix: %s" , found .Req )
528
+ }
529
+ cid = found .Container .ID ()
530
+ return nil
531
+ },
532
+ }
533
+ err = walker .WalkAll (ctx , []string {containerName }, true )
534
+ assert .NilError (t , err )
535
+
536
+ // Get container spec
537
+ container , err := client .LoadContainer (ctx , cid )
538
+ assert .NilError (t , err )
539
+ spec , err := container .Spec (ctx )
540
+ assert .NilError (t , err )
541
+
542
+ // Run the validation function
543
+ tt .validate (t , spec .Linux .Resources .BlockIO )
544
+ })
545
+ }
546
+ }
0 commit comments