k8s.io/kubernetes@v1.29.3/pkg/kubelet/winstats/winstats.go (about) 1 //go:build windows 2 // +build windows 3 4 /* 5 Copyright 2017 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 // Package winstats provides a client to get node and pod level stats on windows 21 package winstats 22 23 import ( 24 "syscall" 25 "time" 26 "unsafe" 27 28 cadvisorapi "github.com/google/cadvisor/info/v1" 29 cadvisorapiv2 "github.com/google/cadvisor/info/v2" 30 ) 31 32 var ( 33 procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW") 34 ) 35 36 // Client is an interface that is used to get stats information. 37 type Client interface { 38 WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) 39 WinMachineInfo() (*cadvisorapi.MachineInfo, error) 40 WinVersionInfo() (*cadvisorapi.VersionInfo, error) 41 GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) 42 } 43 44 // StatsClient is a client that implements the Client interface 45 type StatsClient struct { 46 client winNodeStatsClient 47 } 48 49 type winNodeStatsClient interface { 50 startMonitoring() error 51 getNodeMetrics() (nodeMetrics, error) 52 getNodeInfo() nodeInfo 53 getMachineInfo() (*cadvisorapi.MachineInfo, error) 54 getVersionInfo() (*cadvisorapi.VersionInfo, error) 55 } 56 57 type nodeMetrics struct { 58 cpuUsageCoreNanoSeconds uint64 59 cpuUsageNanoCores uint64 60 memoryPrivWorkingSetBytes uint64 61 memoryCommittedBytes uint64 62 timeStamp time.Time 63 interfaceStats []cadvisorapi.InterfaceStats 64 } 65 66 type nodeInfo struct { 67 memoryPhysicalCapacityBytes uint64 68 kernelVersion string 69 osImageVersion string 70 // startTime is the time when the node was started 71 startTime time.Time 72 } 73 74 type cpuUsageCoreNanoSecondsCache struct { 75 latestValue uint64 76 previousValue uint64 77 } 78 79 // newClient constructs a Client. 80 func newClient(statsNodeClient winNodeStatsClient) (Client, error) { 81 statsClient := new(StatsClient) 82 statsClient.client = statsNodeClient 83 84 err := statsClient.client.startMonitoring() 85 if err != nil { 86 return nil, err 87 } 88 89 return statsClient, nil 90 } 91 92 // WinContainerInfos returns a map of container infos. The map contains node and 93 // pod level stats. Analogous to cadvisor GetContainerInfoV2 method. 94 func (c *StatsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) { 95 infos := make(map[string]cadvisorapiv2.ContainerInfo) 96 rootContainerInfo, err := c.createRootContainerInfo() 97 if err != nil { 98 return nil, err 99 } 100 101 infos["/"] = *rootContainerInfo 102 103 return infos, nil 104 } 105 106 // WinMachineInfo returns a cadvisorapi.MachineInfo with details about the 107 // node machine. Analogous to cadvisor MachineInfo method. 108 func (c *StatsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) { 109 return c.client.getMachineInfo() 110 } 111 112 // WinVersionInfo returns a cadvisorapi.VersionInfo with version info of 113 // the kernel and docker runtime. Analogous to cadvisor VersionInfo method. 114 func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) { 115 return c.client.getVersionInfo() 116 } 117 118 func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) { 119 nodeMetrics, err := c.client.getNodeMetrics() 120 if err != nil { 121 return nil, err 122 } 123 124 var stats []*cadvisorapiv2.ContainerStats 125 stats = append(stats, &cadvisorapiv2.ContainerStats{ 126 Timestamp: nodeMetrics.timeStamp, 127 Cpu: &cadvisorapi.CpuStats{ 128 Usage: cadvisorapi.CpuUsage{ 129 Total: nodeMetrics.cpuUsageCoreNanoSeconds, 130 }, 131 }, 132 CpuInst: &cadvisorapiv2.CpuInstStats{ 133 Usage: cadvisorapiv2.CpuInstUsage{ 134 Total: nodeMetrics.cpuUsageNanoCores, 135 }, 136 }, 137 Memory: &cadvisorapi.MemoryStats{ 138 WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes, 139 Usage: nodeMetrics.memoryCommittedBytes, 140 }, 141 Network: &cadvisorapiv2.NetworkStats{ 142 Interfaces: nodeMetrics.interfaceStats, 143 }, 144 }) 145 146 nodeInfo := c.client.getNodeInfo() 147 rootInfo := cadvisorapiv2.ContainerInfo{ 148 Spec: cadvisorapiv2.ContainerSpec{ 149 CreationTime: nodeInfo.startTime, 150 HasCpu: true, 151 HasMemory: true, 152 HasNetwork: true, 153 Memory: cadvisorapiv2.MemorySpec{ 154 Limit: nodeInfo.memoryPhysicalCapacityBytes, 155 }, 156 }, 157 Stats: stats, 158 } 159 160 return &rootInfo, nil 161 } 162 163 // GetDirFsInfo returns filesystem capacity and usage information. 164 func (c *StatsClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) { 165 var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64 166 var err error 167 168 ret, _, err := syscall.Syscall6( 169 procGetDiskFreeSpaceEx.Addr(), 170 4, 171 uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 172 uintptr(unsafe.Pointer(&freeBytesAvailable)), 173 uintptr(unsafe.Pointer(&totalNumberOfBytes)), 174 uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)), 175 0, 176 0, 177 ) 178 if ret == 0 { 179 return cadvisorapiv2.FsInfo{}, err 180 } 181 182 return cadvisorapiv2.FsInfo{ 183 Timestamp: time.Now(), 184 Capacity: uint64(totalNumberOfBytes), 185 Available: uint64(freeBytesAvailable), 186 Usage: uint64(totalNumberOfBytes - freeBytesAvailable), 187 }, nil 188 }