@@ -9,14 +9,17 @@ import (
99 "fmt"
1010 "net/http"
1111 "os"
12+ "os/exec"
1213 "path/filepath"
1314 "strings"
1415 "time"
1516
1617 "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
1718 "github.com/docker/go-connections/nat"
19+ "github.com/moby/moby/api/types/blkiodev"
1820 . "github.com/onsi/ginkgo/v2"
1921 . "github.com/onsi/gomega"
22+ "github.com/opencontainers/runtime-spec/specs-go"
2023 "github.com/runfinch/common-tests/command"
2124 "github.com/runfinch/common-tests/ffs"
2225 "github.com/runfinch/common-tests/option"
@@ -790,6 +793,175 @@ func ContainerCreate(opt *option.Option) {
790793 Expect (ok ).Should (BeTrue ())
791794 Expect (memSet ).Should (Equal ("0" ))
792795 })
796+
797+ It ("should create container with specified blkio settings options" , func () {
798+ // Create dummy device paths
799+ dummyDev1 := "/dev/dummy-zero1"
800+ dummyDev2 := "/dev/dummy-zero2"
801+
802+ // Create dummy devices (major number 1 for char devices)
803+ err := exec .Command ("mknod" , dummyDev1 , "c" , "1" , "5" ).Run ()
804+ Expect (err ).Should (BeNil ())
805+ err = exec .Command ("mknod" , dummyDev2 , "c" , "1" , "6" ).Run ()
806+ Expect (err ).Should (BeNil ())
807+
808+ // Cleanup dummy devices after test
809+ defer func () {
810+ exec .Command ("rm" , "-f" , dummyDev1 ).Run ()
811+ exec .Command ("rm" , "-f" , dummyDev2 ).Run ()
812+ }()
813+
814+ // define options
815+ options .Cmd = []string {"sleep" , "Infinity" }
816+ options .HostConfig .BlkioWeight = 500 // valid values: 0-1000
817+
818+ // Create WeightDevice objects for input
819+ weightDevices := []* blkiodev.WeightDevice {
820+ {
821+ Path : dummyDev1 ,
822+ Weight : 400 ,
823+ },
824+ {
825+ Path : dummyDev2 ,
826+ Weight : 300 ,
827+ },
828+ }
829+
830+ // Create ThrottleDevice objects for input
831+ readBpsDevices := []* blkiodev.ThrottleDevice {
832+ {
833+ Path : dummyDev1 ,
834+ Rate : 1048576 , // 1MB/s
835+ },
836+ }
837+
838+ writeBpsDevices := []* blkiodev.ThrottleDevice {
839+ {
840+ Path : dummyDev1 ,
841+ Rate : 2097152 , // 2MB/s
842+ },
843+ }
844+
845+ readIopsDevices := []* blkiodev.ThrottleDevice {
846+ {
847+ Path : dummyDev1 ,
848+ Rate : 1000 ,
849+ },
850+ }
851+
852+ writeIopsDevices := []* blkiodev.ThrottleDevice {
853+ {
854+ Path : dummyDev1 ,
855+ Rate : 2000 ,
856+ },
857+ }
858+
859+ // Set the original device objects in the options
860+ options .HostConfig .BlkioWeightDevice = weightDevices
861+ options .HostConfig .BlkioDeviceReadBps = readBpsDevices
862+ options .HostConfig .BlkioDeviceWriteBps = writeBpsDevices
863+ options .HostConfig .BlkioDeviceReadIOps = readIopsDevices
864+ options .HostConfig .BlkioDeviceWriteIOps = writeIopsDevices
865+
866+ // create container
867+ statusCode , ctr := createContainer (uClient , url , testContainerName , options )
868+ Expect (statusCode ).Should (Equal (http .StatusCreated ))
869+ Expect (ctr .ID ).ShouldNot (BeEmpty ())
870+
871+ // start container
872+ command .Run (opt , "start" , testContainerName )
873+
874+ // inspect container
875+ resp := command .Stdout (opt , "inspect" , testContainerName )
876+ var inspect []* dockercompat.Container
877+ err = json .Unmarshal (resp , & inspect )
878+ Expect (err ).Should (BeNil ())
879+ Expect (inspect ).Should (HaveLen (1 ))
880+
881+ // Verify blkio settings in LinuxBlkioSettings
882+ blkioSettings := inspect [0 ].HostConfig .LinuxBlkioSettings
883+ // Verify BlkioWeight
884+ Expect (blkioSettings .BlkioWeight ).Should (Equal (options .HostConfig .BlkioWeight ))
885+
886+ // Helper function to map major/minor to device path
887+ devicePathFromMajorMinor := func (major , minor int64 ) string {
888+ if major == 1 && minor == 5 {
889+ return dummyDev1
890+ }
891+ if major == 1 && minor == 6 {
892+ return dummyDev2
893+ }
894+ return fmt .Sprintf ("/dev/unknown-%d-%d" , major , minor )
895+ }
896+
897+ // Helper function to convert specs.LinuxWeightDevice to blkiodev.WeightDevice
898+ convertWeightDevice := func (wd * specs.LinuxWeightDevice ) * blkiodev.WeightDevice {
899+ if wd == nil || wd .Weight == nil {
900+ return nil
901+ }
902+ return & blkiodev.WeightDevice {
903+ Path : devicePathFromMajorMinor (wd .Major , wd .Minor ),
904+ Weight : * wd .Weight ,
905+ }
906+ }
907+
908+ // Helper function to convert specs.LinuxThrottleDevice to blkiodev.ThrottleDevice
909+ convertThrottleDevice := func (td * specs.LinuxThrottleDevice ) * blkiodev.ThrottleDevice {
910+ if td == nil {
911+ return nil
912+ }
913+ return & blkiodev.ThrottleDevice {
914+ Path : devicePathFromMajorMinor (td .Major , td .Minor ),
915+ Rate : td .Rate ,
916+ }
917+ }
918+
919+ // Convert response devices to blkiodev types
920+ responseWeightDevices := make ([]* blkiodev.WeightDevice , 0 , len (blkioSettings .BlkioWeightDevice ))
921+ for _ , d := range blkioSettings .BlkioWeightDevice {
922+ if converted := convertWeightDevice (d ); converted != nil {
923+ responseWeightDevices = append (responseWeightDevices , converted )
924+ }
925+ }
926+
927+ responseReadBpsDevices := make ([]* blkiodev.ThrottleDevice , 0 , len (blkioSettings .BlkioDeviceReadBps ))
928+ for _ , d := range blkioSettings .BlkioDeviceReadBps {
929+ if converted := convertThrottleDevice (d ); converted != nil {
930+ responseReadBpsDevices = append (responseReadBpsDevices , converted )
931+ }
932+ }
933+
934+ responseWriteBpsDevices := make ([]* blkiodev.ThrottleDevice , 0 , len (blkioSettings .BlkioDeviceWriteBps ))
935+ for _ , d := range blkioSettings .BlkioDeviceWriteBps {
936+ if converted := convertThrottleDevice (d ); converted != nil {
937+ responseWriteBpsDevices = append (responseWriteBpsDevices , converted )
938+ }
939+ }
940+
941+ responseReadIopsDevices := make ([]* blkiodev.ThrottleDevice , 0 , len (blkioSettings .BlkioDeviceReadIOps ))
942+ for _ , d := range blkioSettings .BlkioDeviceReadIOps {
943+ if converted := convertThrottleDevice (d ); converted != nil {
944+ responseReadIopsDevices = append (responseReadIopsDevices , converted )
945+ }
946+ }
947+
948+ responseWriteIopsDevices := make ([]* blkiodev.ThrottleDevice , 0 , len (blkioSettings .BlkioDeviceWriteIOps ))
949+ for _ , d := range blkioSettings .BlkioDeviceWriteIOps {
950+ if converted := convertThrottleDevice (d ); converted != nil {
951+ responseWriteIopsDevices = append (responseWriteIopsDevices , converted )
952+ }
953+ }
954+
955+ // Compare string representations
956+ for i , wd := range weightDevices {
957+ Expect (responseWeightDevices [i ].String ()).Should (Equal (wd .String ()))
958+ }
959+
960+ Expect (responseReadBpsDevices [0 ].String ()).Should (Equal (readBpsDevices [0 ].String ()))
961+ Expect (responseWriteBpsDevices [0 ].String ()).Should (Equal (writeBpsDevices [0 ].String ()))
962+ Expect (responseReadIopsDevices [0 ].String ()).Should (Equal (readIopsDevices [0 ].String ()))
963+ Expect (responseWriteIopsDevices [0 ].String ()).Should (Equal (writeIopsDevices [0 ].String ()))
964+ })
793965 })
794966}
795967
0 commit comments