mirror of https://github.com/k3s-io/k3s
173 lines
4.8 KiB
Go
173 lines
4.8 KiB
Go
|
// +build windows
|
||
|
|
||
|
/*
|
||
|
Copyright 2017 The Kubernetes Authors.
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
*/
|
||
|
|
||
|
// Package winstats provides a client to get node and pod level stats on windows
|
||
|
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 {
|
||
|
client winNodeStatsClient
|
||
|
}
|
||
|
|
||
|
type winNodeStatsClient interface {
|
||
|
startMonitoring() error
|
||
|
getNodeMetrics() (nodeMetrics, error)
|
||
|
getNodeInfo() nodeInfo
|
||
|
getMachineInfo() (*cadvisorapi.MachineInfo, error)
|
||
|
getVersionInfo() (*cadvisorapi.VersionInfo, error)
|
||
|
}
|
||
|
|
||
|
type nodeMetrics struct {
|
||
|
cpuUsageCoreNanoSeconds uint64
|
||
|
memoryPrivWorkingSetBytes uint64
|
||
|
memoryCommittedBytes uint64
|
||
|
timeStamp time.Time
|
||
|
}
|
||
|
|
||
|
type nodeInfo struct {
|
||
|
memoryPhysicalCapacityBytes uint64
|
||
|
kernelVersion string
|
||
|
osImageVersion string
|
||
|
// startTime is the time when the node was started
|
||
|
startTime time.Time
|
||
|
}
|
||
|
|
||
|
// newClient constructs a Client.
|
||
|
func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
|
||
|
statsClient := new(StatsClient)
|
||
|
statsClient.client = statsNodeClient
|
||
|
|
||
|
err := statsClient.client.startMonitoring()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return statsClient, nil
|
||
|
}
|
||
|
|
||
|
// 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) {
|
||
|
infos := make(map[string]cadvisorapiv2.ContainerInfo)
|
||
|
rootContainerInfo, err := c.createRootContainerInfo()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
infos["/"] = *rootContainerInfo
|
||
|
|
||
|
return infos, nil
|
||
|
}
|
||
|
|
||
|
// WinMachineInfo returns a cadvisorapi.MachineInfo with details about the
|
||
|
// node machine. Analogous to cadvisor MachineInfo method.
|
||
|
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) {
|
||
|
return c.client.getVersionInfo()
|
||
|
}
|
||
|
|
||
|
func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
|
||
|
nodeMetrics, err := c.client.getNodeMetrics()
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
var stats []*cadvisorapiv2.ContainerStats
|
||
|
|
||
|
stats = append(stats, &cadvisorapiv2.ContainerStats{
|
||
|
Timestamp: nodeMetrics.timeStamp,
|
||
|
Cpu: &cadvisorapi.CpuStats{
|
||
|
Usage: cadvisorapi.CpuUsage{
|
||
|
Total: nodeMetrics.cpuUsageCoreNanoSeconds,
|
||
|
},
|
||
|
},
|
||
|
Memory: &cadvisorapi.MemoryStats{
|
||
|
WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes,
|
||
|
Usage: nodeMetrics.memoryCommittedBytes,
|
||
|
},
|
||
|
})
|
||
|
|
||
|
nodeInfo := c.client.getNodeInfo()
|
||
|
rootInfo := cadvisorapiv2.ContainerInfo{
|
||
|
Spec: cadvisorapiv2.ContainerSpec{
|
||
|
CreationTime: nodeInfo.startTime,
|
||
|
HasCpu: true,
|
||
|
HasMemory: true,
|
||
|
Memory: cadvisorapiv2.MemorySpec{
|
||
|
Limit: nodeInfo.memoryPhysicalCapacityBytes,
|
||
|
},
|
||
|
},
|
||
|
Stats: stats,
|
||
|
}
|
||
|
|
||
|
return &rootInfo, nil
|
||
|
}
|
||
|
|
||
|
// GetDirFsInfo returns filesystem capacity and usage information.
|
||
|
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
|
||
|
}
|