From cac0263c1245e0d2ff939474c2bfba591525ed11 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Mon, 12 Feb 2018 13:52:18 +0800 Subject: [PATCH 1/3] Add GetDiskFreeSpaceEx and export winstats.StatsClient --- pkg/kubelet/winstats/BUILD | 88 ++++++++++++++------------- pkg/kubelet/winstats/winstats.go | 47 ++++++++++++-- pkg/kubelet/winstats/winstats_test.go | 2 + 3 files changed, 89 insertions(+), 48 deletions(-) diff --git a/pkg/kubelet/winstats/BUILD b/pkg/kubelet/winstats/BUILD index a52fb473ccd..0cfe7e90848 100644 --- a/pkg/kubelet/winstats/BUILD +++ b/pkg/kubelet/winstats/BUILD @@ -1,6 +1,49 @@ -package(default_visibility = ["//visibility:public"]) +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") -licenses(["notice"]) +go_library( + name = "go_default_library", + srcs = select({ + "@io_bazel_rules_go//go/platform:windows": [ + "perfcounter_nodestats.go", + "perfcounters.go", + "version.go", + "winstats.go", + ], + "//conditions:default": [], + }), + importpath = "k8s.io/kubernetes/pkg/kubelet/winstats", + visibility = ["//visibility:public"], + deps = select({ + "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/github.com/JeffAshton/win_pdh:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/google/cadvisor/info/v1:go_default_library", + "//vendor/github.com/google/cadvisor/info/v2:go_default_library", + "//vendor/golang.org/x/sys/windows:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", + ], + "//conditions:default": [], + }), +) + +go_test( + name = "go_default_test", + srcs = select({ + "@io_bazel_rules_go//go/platform:windows": [ + "winstats_test.go", + ], + "//conditions:default": [], + }), + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/github.com/google/cadvisor/info/v1:go_default_library", + "//vendor/github.com/google/cadvisor/info/v2:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + ], + "//conditions:default": [], + }), +) filegroup( name = "package-srcs", @@ -13,44 +56,5 @@ filegroup( name = "all-srcs", srcs = [":package-srcs"], tags = ["automanaged"], -) - -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "winstats.go", - ] + select({ - "@io_bazel_rules_go//go/platform:windows": [ - "perfcounter_nodestats.go", - "perfcounters.go", - "version.go", - ], - "//conditions:default": [], - }), - importpath = "k8s.io/kubernetes/pkg/kubelet/winstats", - deps = [ - "//vendor/github.com/google/cadvisor/info/v1:go_default_library", - "//vendor/github.com/google/cadvisor/info/v2:go_default_library", - ] + select({ - "@io_bazel_rules_go//go/platform:windows": [ - "//vendor/github.com/JeffAshton/win_pdh:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", - "//vendor/golang.org/x/sys/windows:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - ], - "//conditions:default": [], - }), -) - -go_test( - name = "go_default_test", - srcs = ["winstats_test.go"], - embed = [":go_default_library"], - deps = [ - "//vendor/github.com/google/cadvisor/info/v1:go_default_library", - "//vendor/github.com/google/cadvisor/info/v2:go_default_library", - "//vendor/github.com/stretchr/testify/assert:go_default_library", - ], + visibility = ["//visibility:public"], ) diff --git a/pkg/kubelet/winstats/winstats.go b/pkg/kubelet/winstats/winstats.go index b02bab4f6bd..011c056e669 100644 --- a/pkg/kubelet/winstats/winstats.go +++ b/pkg/kubelet/winstats/winstats.go @@ -1,3 +1,5 @@ +// +build windows + /* Copyright 2017 The Kubernetes Authors. @@ -18,21 +20,28 @@ limitations under the License. package winstats import ( + "syscall" "time" + "unsafe" cadvisorapi "github.com/google/cadvisor/info/v1" cadvisorapiv2 "github.com/google/cadvisor/info/v2" ) +var ( + procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW") +) + // Client is an interface that is used to get stats information. type Client interface { WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) WinMachineInfo() (*cadvisorapi.MachineInfo, error) WinVersionInfo() (*cadvisorapi.VersionInfo, error) + GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) } // StatsClient is a client that implements the Client interface -type statsClient struct { +type StatsClient struct { client winNodeStatsClient } @@ -61,7 +70,7 @@ type nodeInfo struct { // newClient constructs a Client. func newClient(statsNodeClient winNodeStatsClient) (Client, error) { - statsClient := new(statsClient) + statsClient := new(StatsClient) statsClient.client = statsNodeClient err := statsClient.client.startMonitoring() @@ -74,7 +83,7 @@ func newClient(statsNodeClient winNodeStatsClient) (Client, error) { // WinContainerInfos returns a map of container infos. The map contains node and // pod level stats. Analogous to cadvisor GetContainerInfoV2 method. -func (c *statsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) { +func (c *StatsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) { infos := make(map[string]cadvisorapiv2.ContainerInfo) rootContainerInfo, err := c.createRootContainerInfo() if err != nil { @@ -88,17 +97,17 @@ func (c *statsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInf // WinMachineInfo returns a cadvisorapi.MachineInfo with details about the // node machine. Analogous to cadvisor MachineInfo method. -func (c *statsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) { +func (c *StatsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) { return c.client.getMachineInfo() } // WinVersionInfo returns a cadvisorapi.VersionInfo with version info of // the kernel and docker runtime. Analogous to cadvisor VersionInfo method. -func (c *statsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) { +func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) { return c.client.getVersionInfo() } -func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) { +func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) { nodeMetrics, err := c.client.getNodeMetrics() if err != nil { @@ -134,3 +143,29 @@ func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e return &rootInfo, nil } + +func (c *StatsClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) { + var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64 + var err error + + ret, _, err := syscall.Syscall6( + procGetDiskFreeSpaceEx.Addr(), + 4, + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), + uintptr(unsafe.Pointer(&freeBytesAvailable)), + uintptr(unsafe.Pointer(&totalNumberOfBytes)), + uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)), + 0, + 0, + ) + if ret == 0 { + return cadvisorapiv2.FsInfo{}, err + } + + return cadvisorapiv2.FsInfo{ + Timestamp: time.Now(), + Capacity: uint64(totalNumberOfBytes), + Available: uint64(freeBytesAvailable), + Usage: uint64(totalNumberOfBytes - freeBytesAvailable), + }, nil +} diff --git a/pkg/kubelet/winstats/winstats_test.go b/pkg/kubelet/winstats/winstats_test.go index 42df2bb2d80..830f76af039 100644 --- a/pkg/kubelet/winstats/winstats_test.go +++ b/pkg/kubelet/winstats/winstats_test.go @@ -1,3 +1,5 @@ +// +build windows + /* Copyright 2017 The Kubernetes Authors. From b1361037ff812c21e1610c2e7d645fa751d5f713 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Mon, 12 Feb 2018 13:53:07 +0800 Subject: [PATCH 2/3] Set FsId and usedBytes for windows image file system --- pkg/kubelet/dockershim/BUILD | 1 + .../dockershim/docker_image_windows.go | 21 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/dockershim/BUILD b/pkg/kubelet/dockershim/BUILD index eee71bccb1a..eec1a3adc17 100644 --- a/pkg/kubelet/dockershim/BUILD +++ b/pkg/kubelet/dockershim/BUILD @@ -127,6 +127,7 @@ go_library( ] + select({ "@io_bazel_rules_go//go/platform:windows": [ "//pkg/features:go_default_library", + "//pkg/kubelet/winstats:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", ], "//conditions:default": [], diff --git a/pkg/kubelet/dockershim/docker_image_windows.go b/pkg/kubelet/dockershim/docker_image_windows.go index b6ee9e156bf..70340561483 100644 --- a/pkg/kubelet/dockershim/docker_image_windows.go +++ b/pkg/kubelet/dockershim/docker_image_windows.go @@ -21,19 +21,36 @@ package dockershim import ( "time" + "github.com/golang/glog" "golang.org/x/net/context" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" + "k8s.io/kubernetes/pkg/kubelet/winstats" ) // ImageFsInfo returns information of the filesystem that is used to store images. func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) { - // For Windows Stats to work correctly, a file system must be provided. For now, provide a fake filesystem. + info, err := ds.client.Info() + if err != nil { + glog.Errorf("Failed to get docker info: %v", err) + return nil, err + } + + statsClient := &winstats.StatsClient{} + fsinfo, err := statsClient.GetDirFsInfo(info.DockerRootDir) + if err != nil { + glog.Errorf("Failed to get dir fsInfo for %q: %v", info.DockerRootDir, err) + return nil, err + } + filesystems := []*runtimeapi.FilesystemUsage{ { Timestamp: time.Now().UnixNano(), - UsedBytes: &runtimeapi.UInt64Value{Value: 0}, + UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage}, InodesUsed: &runtimeapi.UInt64Value{Value: 0}, + FsId: &runtimeapi.FilesystemIdentifier{ + Mountpoint: info.DockerRootDir, + }, }, } From d8703eede3e3565403ab2307498af20e1477d9d0 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Mon, 12 Feb 2018 13:53:52 +0800 Subject: [PATCH 3/3] Get dirFsInfo from docker image filesystem --- pkg/kubelet/cadvisor/cadvisor_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/kubelet/cadvisor/cadvisor_windows.go b/pkg/kubelet/cadvisor/cadvisor_windows.go index b61d024b962..597721cd176 100644 --- a/pkg/kubelet/cadvisor/cadvisor_windows.go +++ b/pkg/kubelet/cadvisor/cadvisor_windows.go @@ -78,5 +78,5 @@ func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventCha } func (cu *cadvisorClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) { - return cadvisorapiv2.FsInfo{}, nil + return cu.winStatsClient.GetDirFsInfo(path) }