diff --git a/docs/development/build.md b/docs/development/build.md index a4ae8eaf..1cf04393 100644 --- a/docs/development/build.md +++ b/docs/development/build.md @@ -30,6 +30,20 @@ $GOPATH/src/github.com/google/cadvisor $ make test For integration tests, see the [integration testing](integration_testing.md) page. +### Non-volatile Memory Support + +cAdvisor can be linked against [libipmctl](https://github.com/intel/ipmctl) library that allows to gather information about IntelĀ® Optaneā„¢ DC Persistent memory. If you want to build cAdvisor with libipmctl support you must meet following requirements: +* `libimpctl-devel` must be installed on build system. +* `libimpctl` must be installed on all systems where cAdvisor is running. + +Detailed information about building `libipmctl` can be found in the project's [README](https://github.com/intel/ipmctl#build). Make sure to use the most up to date released version. Functionality that relies on `libipmctl` was tested against version 02.00.00.3719 of the library. + +To enable `libimpctl` support `GO_FLAGS` variable must be set: + +``` +$GOPATH/src/github.com/google/cadvisor $ GO_FLAGS="-tags=libipmctl,netgo" make build +``` + ## Running Built Binary Now you can run the built binary: @@ -37,4 +51,3 @@ Now you can run the built binary: ``` $GOPATH/src/github.com/google/cadvisor $ sudo ./cadvisor ``` - diff --git a/info/v1/machine.go b/info/v1/machine.go index 68eba48d..7c9fe697 100644 --- a/info/v1/machine.go +++ b/info/v1/machine.go @@ -176,6 +176,8 @@ type MachineInfo struct { // Memory capacity and number of DIMMs by memory type MemoryByType map[string]*MemoryInfo `json:"memory_by_type"` + NVMInfo NVMInfo `json:"nvm"` + // HugePages on this machine. HugePages []HugePagesInfo `json:"hugepages"` @@ -219,6 +221,11 @@ type MemoryInfo struct { DimmCount uint `json:"dimm_count"` } +type NVMInfo struct { + // Average power budget for NVM devices configured in BIOS. + AvgPowerBudget uint `json:"avg_power_budget"` +} + type VersionInfo struct { // Kernel version. KernelVersion string `json:"kernel_version"` diff --git a/machine/info.go b/machine/info.go index ce312a8e..a85f0e69 100644 --- a/machine/info.go +++ b/machine/info.go @@ -77,6 +77,11 @@ func Info(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) (*info.Mach return nil, err } + nvmPowerBudget, err := GetNVMAvgPowerBudget() + if err != nil { + return nil, err + } + hugePagesInfo, err := GetHugePagesInfo(hugepagesDirectory) if err != nil { return nil, err @@ -119,6 +124,7 @@ func Info(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) (*info.Mach CpuFrequency: clockSpeed, MemoryCapacity: memoryCapacity, MemoryByType: memoryByType, + NVMInfo: info.NVMInfo{AvgPowerBudget: nvmPowerBudget}, HugePages: hugePagesInfo, DiskMap: diskMap, NetworkDevices: netDevices, diff --git a/machine/machine_libipmctl.go b/machine/machine_libipmctl.go new file mode 100644 index 00000000..c0660796 --- /dev/null +++ b/machine/machine_libipmctl.go @@ -0,0 +1,69 @@ +// +build libipmctl,cgo + +// Copyright 2020 Google Inc. All Rights Reserved. +// +// 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 machine + +// #cgo pkg-config: libipmctl +// #include +import "C" +import ( + "fmt" + + "k8s.io/klog" +) + +// GetNVMAvgPowerBudget retrieves configured power budget +// (in watts) for NVM devices. When libipmct is not available +// zero is returned. +func GetNVMAvgPowerBudget() (uint, error) { + // Initialize libipmctl library. + err := C.nvm_init() + if err != C.NVM_SUCCESS { + klog.Warningf("libipmctl initialization failed with status %d", err) + return uint(0), fmt.Errorf("libipmctl initialization failed with status %d", err) + } + defer C.nvm_uninit() + + // Get number of devices on the platform + // see: https://github.com/intel/ipmctl/blob/v01.00.00.3497/src/os/nvm_api/nvm_management.h#L1478 + var count C.uint + err = C.nvm_get_number_of_devices(&count) + if err != C.NVM_SUCCESS { + klog.Warningf("Unable to get number of NVM devices. Status code: %d", err) + return uint(0), fmt.Errorf("Unable to get number of NVM devices. Status code: %d", err) + } + + // Load basic device information for all the devices + // to obtain UID of the first one. + var devices = make([]C.struct_device_discovery, count) + err = C.nvm_get_devices(&devices[0], C.uchar(count)) + if err != C.NVM_SUCCESS { + klog.Warningf("Unable to get all NVM devices. Status code: %d", err) + return uint(0), fmt.Errorf("Unable to get all NVM devices. Status code: %d", err) + } + + // Power budget is same for all the devices + // so we can rely on any of them. + var device C.struct_device_details + err = C.nvm_get_device_details(&devices[0].uid[0], &device) + if err != C.NVM_SUCCESS { + uid := C.GoString(&devices[0].uid[0]) + klog.Warningf("Unable to get details of NVM device %q. Status code: %d", uid, err) + return uint(0), fmt.Errorf("Unable to get details of NVM device %q. Status code: %d", uid, err) + } + + return uint(device.avg_power_budget / 1000), nil +} diff --git a/machine/machine_no_libipmctl.go b/machine/machine_no_libipmctl.go new file mode 100644 index 00000000..5e4af3e1 --- /dev/null +++ b/machine/machine_no_libipmctl.go @@ -0,0 +1,24 @@ +// +build !libipmctl !cgo + +// Copyright 2020 Google Inc. All Rights Reserved. +// +// 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 machine + +// GetNVMAvgPowerBudget retrieves configured power budget +// (in watts) for NVM devices. When libipmct is not available +// zero is returned. +func GetNVMAvgPowerBudget() (uint, error) { + return uint(0), nil +}