@@ -7,20 +7,28 @@ import (
77 "io/ioutil"
88 "os"
99 "path"
10+ "path/filepath"
1011 "strconv"
1112 "strings"
13+ "syscall"
1214 "time"
1315
1416 apitypes "github.com/alibaba/pouch/apis/types"
1517 anno "github.com/alibaba/pouch/cri/annotations"
1618 "github.com/alibaba/pouch/daemon/mgr"
1719 "github.com/alibaba/pouch/pkg/utils"
18- "github.com/go-openapi/strfmt"
1920
21+ "github.com/containerd/cgroups"
22+ containerdmount "github.com/containerd/containerd/mount"
23+ "github.com/containerd/typeurl"
24+ "github.com/go-openapi/strfmt"
2025 "golang.org/x/net/context"
26+ "golang.org/x/sys/unix"
2127 "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
2228)
2329
30+ const uuidDir = "/dev/disk/by-uuid"
31+
2432func parseUint32 (s string ) (uint32 , error ) {
2533 n , err := strconv .ParseUint (s , 10 , 32 )
2634 if err != nil {
@@ -265,6 +273,10 @@ func makeSandboxPouchConfig(config *runtime.PodSandboxConfig, image string) (*ap
265273 return nil , err
266274 }
267275
276+ // Apply resource options.
277+ if lc := config .GetLinux (); lc != nil {
278+ hc .CgroupParent = lc .CgroupParent
279+ }
268280 return createConfig , nil
269281}
270282
@@ -284,11 +296,17 @@ func toCriSandbox(c *mgr.Container) (*runtime.PodSandbox, error) {
284296 return nil , err
285297 }
286298 labels , annotations := extractLabels (c .Config .Labels )
299+
300+ createdAt , err := toCriTimestamp (c .Created )
301+ if err != nil {
302+ return nil , fmt .Errorf ("failed to parse create timestamp for container %q: %v" , c .ID , err )
303+ }
304+
287305 return & runtime.PodSandbox {
288- Id : c .ID ,
289- Metadata : metadata ,
290- State : state ,
291- // TODO: fill "CreatedAt" when it is appropriate.
306+ Id : c .ID ,
307+ Metadata : metadata ,
308+ State : state ,
309+ CreatedAt : createdAt ,
292310 Labels : labels ,
293311 Annotations : annotations ,
294312 }, nil
@@ -625,15 +643,26 @@ func (c *CriManager) updateCreateConfig(createConfig *apitypes.ContainerCreateCo
625643 }
626644
627645 if lc := config .GetLinux (); lc != nil {
628- // TODO: resource restriction.
646+ resources := lc .GetResources ()
647+ if resources != nil {
648+ createConfig .HostConfig .Resources .CPUPeriod = resources .GetCpuPeriod ()
649+ createConfig .HostConfig .Resources .CPUQuota = resources .GetCpuQuota ()
650+ createConfig .HostConfig .Resources .CPUShares = resources .GetCpuShares ()
651+ createConfig .HostConfig .Resources .Memory = resources .GetMemoryLimitInBytes ()
652+ createConfig .HostConfig .Resources .CpusetCpus = resources .GetCpusetCpus ()
653+ createConfig .HostConfig .Resources .CpusetMems = resources .GetCpusetMems ()
654+ }
629655
630656 // Apply security context.
631657 if err := applyContainerSecurityContext (lc , podSandboxID , & createConfig .ContainerConfig , createConfig .HostConfig ); err != nil {
632658 return fmt .Errorf ("failed to apply container security context for container %q: %v" , config .Metadata .Name , err )
633659 }
634660 }
635661
636- // TODO: apply cgroupParent derived from the sandbox config.
662+ // Apply cgroupsParent derived from the sandbox config.
663+ if sandboxConfig .GetLinux ().GetCgroupParent () != "" {
664+ createConfig .HostConfig .CgroupParent = sandboxConfig .GetLinux ().GetCgroupParent ()
665+ }
637666
638667 return nil
639668}
@@ -660,16 +689,20 @@ func toCriContainer(c *mgr.Container) (*runtime.Container, error) {
660689 labels , annotations := extractLabels (c .Config .Labels )
661690 sandboxID := c .Config .Labels [sandboxIDLabelKey ]
662691
692+ createdAt , err := toCriTimestamp (c .Created )
693+ if err != nil {
694+ return nil , fmt .Errorf ("failed to parse create timestamp for container %q: %v" , c .ID , err )
695+ }
663696 return & runtime.Container {
664697 Id : c .ID ,
665698 PodSandboxId : sandboxID ,
666699 Metadata : metadata ,
667700 Image : & runtime.ImageSpec {Image : c .Config .Image },
668701 ImageRef : c .Image ,
669702 State : state ,
670- // TODO: fill "CreatedAt" when it is appropriate.
671- Labels : labels ,
672- Annotations : annotations ,
703+ CreatedAt : createdAt ,
704+ Labels : labels ,
705+ Annotations : annotations ,
673706 }, nil
674707}
675708
@@ -787,3 +820,123 @@ func parseUserFromImageUser(id string) string {
787820 // no group, just return the id
788821 return id
789822}
823+
824+ func (c * CriManager ) getContainerMetrics (ctx context.Context , meta * mgr.Container ) (* runtime.ContainerStats , error ) {
825+ var usedBytes , inodesUsed uint64
826+
827+ stats , err := c .ContainerMgr .Stats (ctx , meta .ID )
828+ if err != nil {
829+ return nil , fmt .Errorf ("failed to get stats of container %q: %v" , meta .ID , err )
830+ }
831+
832+ // snapshot key may not equals container ID later
833+ sn , err := c .SnapshotStore .Get (meta .ID )
834+ if err == nil {
835+ usedBytes = sn .Size
836+ inodesUsed = sn .Inodes
837+ }
838+
839+ cs := & runtime.ContainerStats {}
840+ cs .WritableLayer = & runtime.FilesystemUsage {
841+ Timestamp : sn .Timestamp ,
842+ StorageId : & runtime.StorageIdentifier {
843+ Uuid : c .ImageFSUUID ,
844+ },
845+ UsedBytes : & runtime.UInt64Value {usedBytes },
846+ InodesUsed : & runtime.UInt64Value {inodesUsed },
847+ }
848+
849+ metadata , err := parseContainerName (meta .Name )
850+ if err != nil {
851+ return nil , fmt .Errorf ("failed to get metadata of container %q: %v" , meta .ID , err )
852+ }
853+
854+ labels , annotations := extractLabels (meta .Config .Labels )
855+
856+ cs .Attributes = & runtime.ContainerAttributes {
857+ Id : meta .ID ,
858+ Metadata : metadata ,
859+ Labels : labels ,
860+ Annotations : annotations ,
861+ }
862+
863+ if stats != nil {
864+ s , err := typeurl .UnmarshalAny (stats .Data )
865+ if err != nil {
866+ return nil , fmt .Errorf ("failed to extract container metrics: %v" , err )
867+ }
868+ metrics := s .(* cgroups.Metrics )
869+ if metrics .CPU != nil && metrics .CPU .Usage != nil {
870+ cs .Cpu = & runtime.CpuUsage {
871+ Timestamp : stats .Timestamp .UnixNano (),
872+ UsageCoreNanoSeconds : & runtime.UInt64Value {metrics .CPU .Usage .Total },
873+ }
874+ }
875+ if metrics .Memory != nil && metrics .Memory .Usage != nil {
876+ cs .Memory = & runtime.MemoryUsage {
877+ Timestamp : stats .Timestamp .UnixNano (),
878+ WorkingSetBytes : & runtime.UInt64Value {metrics .Memory .Usage .Usage },
879+ }
880+ }
881+ }
882+
883+ return cs , nil
884+ }
885+
886+ // imageFSPath returns containerd image filesystem path.
887+ func imageFSPath (rootDir , snapshotter string ) string {
888+ return filepath .Join (rootDir , fmt .Sprintf ("%s.%s" , snapshotPlugin , snapshotter ))
889+ }
890+
891+ // getDeviceUUID gets device uuid for a given path.
892+ func getDeviceUUID (path string ) (string , error ) {
893+ mount , err := lookupMount (path )
894+ if err != nil {
895+ return "" , err
896+ }
897+ rdev := unix .Mkdev (uint32 (mount .Major ), uint32 (mount .Minor ))
898+ return deviceUUID (rdev )
899+ }
900+
901+ // lookupMount gets mount info of a given path.
902+ func lookupMount (path string ) (containerdmount.Info , error ) {
903+ return containerdmount .Lookup (path )
904+ }
905+
906+ // deviceUUID gets device uuid of a device. The passed in rdev should
907+ // be linux device number.
908+ func deviceUUID (rdev uint64 ) (string , error ) {
909+ files , err := ioutil .ReadDir (uuidDir )
910+ if err != nil {
911+ return "" , err
912+ }
913+ for _ , file := range files {
914+ path := filepath .Join (uuidDir , file .Name ())
915+
916+ trdev , err := blkrdev (path )
917+ if err != nil {
918+ continue
919+ }
920+
921+ if rdev == trdev {
922+ return file .Name (), nil
923+ }
924+ }
925+
926+ return "" , fmt .Errorf ("device %d not found" , rdev )
927+ }
928+
929+ // blkdev returns the rdev of a block device or an error if not a block device
930+ func blkrdev (device string ) (uint64 , error ) {
931+ info , err := os .Stat (device )
932+ if err != nil {
933+ return 0 , err
934+ }
935+ if stat , ok := info .Sys ().(* syscall.Stat_t ); ok {
936+ if (stat .Mode & syscall .S_IFMT ) != syscall .S_IFBLK {
937+ return 0 , fmt .Errorf ("%s is not a block device" , device )
938+ }
939+ return stat .Rdev , nil
940+ }
941+ return 0 , fmt .Errorf ("cannot get stat of device %s" , device )
942+ }
0 commit comments