Merge pull request #57124 from JiangtianLi/jiangtli-memfunc

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Use GlobalMemoryStatusEx to get total physical memory on Windows node

**What this PR does / why we need it**:
This PR fixes issue #57110 due to failure in getting total physical memory on some Windows VM such as in VMWare Fusion or Virtualbox. This change uses GlobalMemoryStatusEx instead of GetPhysicallyInstalledSystemMemory to retrieve total physical memory on Windows node. The amount obtained this way is also closer in parity with reading MemTotal from /proc/meminfo on Linux node.
(thanks to @martinivanov and @marono for the help)

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #57110

**Special notes for your reviewer**:

**Release note**:

```release-note

```
pull/6/head
Kubernetes Submit Queue 2018-02-06 13:53:09 -08:00 committed by GitHub
commit 8201e4ba00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 33 additions and 15 deletions

View File

@ -23,18 +23,32 @@ import (
"os"
"runtime"
"sync"
"syscall"
"time"
"unsafe"
"github.com/golang/glog"
cadvisorapi "github.com/google/cadvisor/info/v1"
"golang.org/x/sys/windows"
"k8s.io/apimachinery/pkg/util/wait"
)
// MemoryStatusEx is the same as Windows structure MEMORYSTATUSEX
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx
type MemoryStatusEx struct {
Length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetPhysicallyInstalledSystemMemory = modkernel32.NewProc("GetPhysicallyInstalledSystemMemory")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
)
// NewPerfCounterClient creates a client using perf counters
@ -163,20 +177,24 @@ func (p *perfCounterNodeStatsClient) convertCPUValue(cpuValue uint64) uint64 {
}
func getPhysicallyInstalledSystemMemoryBytes() (uint64, error) {
var physicalMemoryKiloBytes uint64
// We use GlobalMemoryStatusEx instead of GetPhysicallyInstalledSystemMemory
// on Windows node for the following reasons:
// 1. GetPhysicallyInstalledSystemMemory retrieves the amount of physically
// installed RAM from the computer's SMBIOS firmware tables.
// https://msdn.microsoft.com/en-us/library/windows/desktop/cc300158(v=vs.85).aspx
// On some VM, it is unable to read data from SMBIOS and fails with ERROR_INVALID_DATA.
// 2. On Linux node, total physical memory is read from MemTotal in /proc/meminfo.
// GlobalMemoryStatusEx returns the amount of physical memory that is available
// for the operating system to use. The amount returned by GlobalMemoryStatusEx
// is closer in parity with Linux
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
var statex MemoryStatusEx
statex.Length = uint32(unsafe.Sizeof(statex))
ret, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&statex)))
if ok := getPhysicallyInstalledSystemMemory(&physicalMemoryKiloBytes); !ok {
if ret == 0 {
return 0, errors.New("unable to read physical memory")
}
return physicalMemoryKiloBytes * 1024, nil // convert kilobytes to bytes
}
func getPhysicallyInstalledSystemMemory(totalMemoryInKilobytes *uint64) bool {
ret, _, _ := syscall.Syscall(procGetPhysicallyInstalledSystemMemory.Addr(), 1,
uintptr(unsafe.Pointer(totalMemoryInKilobytes)),
0,
0)
return ret != 0
return statex.TotalPhys, nil
}