From cb13ced745ee5dd4198ef6fa4791cd39cb07cf35 Mon Sep 17 00:00:00 2001 From: Piotr Skamruk Date: Wed, 22 Aug 2018 10:44:47 +0200 Subject: [PATCH] Provide info about mountpoint/fs usage in cri stats --- pkg/image/image.go | 18 ++++------------- pkg/libvirttools/virtualization.go | 31 ++++++++++++++++++++++++++---- pkg/libvirttools/volumes.go | 1 + pkg/manager/runtime.go | 18 ++++++++++++----- pkg/metadata/types/types.go | 16 ++++++++++----- 5 files changed, 56 insertions(+), 28 deletions(-) diff --git a/pkg/image/image.go b/pkg/image/image.go index c0a673bef..fc3d84958 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -30,6 +30,7 @@ import ( "github.com/golang/glog" digest "github.com/opencontainers/go-digest" + "github.com/Mirantis/virtlet/pkg/metadata/types" "github.com/Mirantis/virtlet/pkg/utils" ) @@ -57,17 +58,6 @@ type Translator func(context.Context, string) Endpoint // that are currently in use. type RefGetter func() (map[string]bool, error) -// FilesystemStats contains info about filesystem mountpoint and -// space/inodes used by images on it -type FilesystemStats struct { - // Mountpoint denotes the filesystem mount point - Mountpoint string - // UsedBytes is the number of bytes used by images - UsedBytes uint64 - // UsedInodes is the number of inodes used by images - UsedInodes uint64 -} - // Store is an interface for the image store. type Store interface { // ListImage returns the list of images in the store. @@ -101,7 +91,7 @@ type Store interface { SetRefGetter(imageRefGetter RefGetter) // FilesystemStats returns disk space and inode usage info for this store. - FilesystemStats() (*FilesystemStats, error) + FilesystemStats() (*types.FilesystemStats, error) } // VirtualSizeFunc specifies a function that returns the virtual @@ -563,7 +553,7 @@ func GetHexDigest(imageSpec string) string { // TODO: instead of returning data from filesystem we should retrieve from // metadata store sizes of images and sum them, or even retrieve precalculated // sum. That's because same filesystem could be used by other things than images. -func (s *FileStore) FilesystemStats() (*FilesystemStats, error) { +func (s *FileStore) FilesystemStats() (*types.FilesystemStats, error) { occupiedBytes, occupiedInodes, err := utils.GetFsStatsForPath(s.dir) if err != nil { return nil, err @@ -576,7 +566,7 @@ func (s *FileStore) FilesystemStats() (*FilesystemStats, error) { if err != nil { return nil, err } - return &FilesystemStats{ + return &types.FilesystemStats{ Mountpoint: mount.FSRoot, UsedBytes: occupiedBytes, UsedInodes: occupiedInodes, diff --git a/pkg/libvirttools/virtualization.go b/pkg/libvirttools/virtualization.go index 7e4af6104..e237d616b 100644 --- a/pkg/libvirttools/virtualization.go +++ b/pkg/libvirttools/virtualization.go @@ -18,7 +18,9 @@ package libvirttools import ( "fmt" + "os" "path/filepath" + "strings" "time" "github.com/golang/glog" @@ -837,9 +839,30 @@ func (v *VirtualizationTool) VMStats(containerID string) (*types.VMStats, error) } vs.CpuUsage = cpuTime - // TODO: find image created by rootfs provider, stat it and fill there - // used by it bytes/inodes. Additionally mountpoint of fs on which - // root volume is located should be found and filled there + domainxml, err := domain.XML() + if err != nil { + return nil, err + } + + rootDiskLocation := "" + for _, disk := range domainxml.Devices.Disks { + fname := disk.Source.File.File + // TODO: split file name and use HasPrefix on last part + // instead of Contains + if strings.Contains(fname, "virtlet_root_") { + rootDiskLocation = fname + } + } + if rootDiskLocation == "" { + return nil, fmt.Errorf("cannot locate root disk in domain definition") + } + + fstat, err := os.Stat(rootDiskLocation) + if err != nil { + return nil, err + } + vs.FsBytes = uint64(fstat.Size()) + return &vs, nil } @@ -878,7 +901,7 @@ func (v *VirtualizationTool) ListVMStats(filter *types.VMStatsFilter) ([]types.V // volumeOwner implementation follows -// StoragePool returns StoragePool for volumes +// StoragePool implements volumeOwner StoragePool method func (v *VirtualizationTool) StoragePool() (virt.StoragePool, error) { return ensureStoragePool(v.storageConn, v.config.VolumePoolName) } diff --git a/pkg/libvirttools/volumes.go b/pkg/libvirttools/volumes.go index 799624a64..7aa657468 100644 --- a/pkg/libvirttools/volumes.go +++ b/pkg/libvirttools/volumes.go @@ -26,6 +26,7 @@ import ( // ImageManager describes a images info provider. type ImageManager interface { GetImagePathAndVirtualSize(ref string) (string, uint64, error) + FilesystemStats() (*types.FilesystemStats, error) } type volumeOwner interface { diff --git a/pkg/manager/runtime.go b/pkg/manager/runtime.go index 597432933..0b3398a33 100644 --- a/pkg/manager/runtime.go +++ b/pkg/manager/runtime.go @@ -463,8 +463,12 @@ func (v *VirtletRuntimeService) ContainerStats(ctx context.Context, in *kubeapi. if err != nil { return nil, err } + fsstats, err := v.virtTool.ImageManager().FilesystemStats() + if err != nil { + return nil, err + } return &kubeapi.ContainerStatsResponse{ - Stats: VMStatsToCRIContainerStats(vs), + Stats: VMStatsToCRIContainerStats(*vs, fsstats.Mountpoint), }, nil } @@ -476,9 +480,13 @@ func (v *VirtletRuntimeService) ListContainerStats(ctx context.Context, in *kube if err != nil { return nil, err } + fsstats, err := v.virtTool.ImageManager().FilesystemStats() + if err != nil { + return nil, err + } var stats []*kubeapi.ContainerStats for _, vs := range vmstatsList { - stats = append(stats, VMStatsToCRIContainerStats(vs)) + stats = append(stats, VMStatsToCRIContainerStats(vs, fsstats.Mountpoint)) } return &kubeapi.ListContainerStatsResponse{ @@ -488,7 +496,7 @@ func (v *VirtletRuntimeService) ListContainerStats(ctx context.Context, in *kube // VMStatsToCRIContainerStats converts internal representation of vm/container stats // to corresponding kubeapi type object -func VMStatsToCRIContainerStats(vs types.VMStats) *kubeapi.ContainerStats { +func VMStatsToCRIContainerStats(vs types.VMStats, mountpoint string) *kubeapi.ContainerStats { return &kubeapi.ContainerStats{ Attributes: &kubeapi.ContainerAttributes{ Id: vs.ContainerID, @@ -504,10 +512,10 @@ func VMStatsToCRIContainerStats(vs types.VMStats) *kubeapi.ContainerStats { WritableLayer: &kubeapi.FilesystemUsage{ Timestamp: vs.Timestamp, FsId: &kubeapi.FilesystemIdentifier{ - Mountpoint: vs.Mountpoint, + Mountpoint: mountpoint, }, UsedBytes: &kubeapi.UInt64Value{Value: vs.FsBytes}, - InodesUsed: &kubeapi.UInt64Value{Value: vs.FsInodes}, + InodesUsed: &kubeapi.UInt64Value{Value: 1}, }, } } diff --git a/pkg/metadata/types/types.go b/pkg/metadata/types/types.go index b5ba0b4cc..77a377cfc 100644 --- a/pkg/metadata/types/types.go +++ b/pkg/metadata/types/types.go @@ -98,13 +98,8 @@ type VMStats struct { // MemoryUsage is expected to contain the amount of working set memory // in bytes what in our case will be returned using RSS value MemoryUsage uint64 - // Mountpoint on host for filesystem containing the directory in which - // rootfs of VM is stored - Mountpoint string // FsBytes represents current size of rootfs in bytes FsBytes uint64 - // FsInodes contains number of inodes used by rootfs image - FsInodes uint64 } // NamespaceOption provides options for Linux namespaces. @@ -288,3 +283,14 @@ type VMStatsFilter struct { // Match Expressions is not supported. LabelSelector map[string]string } + +// FilesystemStats contains info about filesystem mountpoint and +// space/inodes used by images on it +type FilesystemStats struct { + // Mountpoint denotes the filesystem mount point + Mountpoint string + // UsedBytes is the number of bytes used by images + UsedBytes uint64 + // UsedInodes is the number of inodes used by images + UsedInodes uint64 +}