mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-19 01:39:48 +00:00
Merge pull request #4540 from fidencio/topic/default_maxmemory
Add `default_maxmemory` config option
This commit is contained in:
commit
aa561b49f5
@ -158,6 +158,8 @@ DEFMEMSZ := 2048
|
||||
# - vm template memory
|
||||
# - hugepage memory
|
||||
DEFMEMSLOTS := 10
|
||||
# Default maximum memory in MiB
|
||||
DEFMAXMEMSZ := 0
|
||||
#Default number of bridges
|
||||
DEFBRIDGES := 1
|
||||
DEFENABLEANNOTATIONS := [\"enable_iommu\"]
|
||||
@ -442,6 +444,7 @@ USER_VARS += DEFMAXVCPUS
|
||||
USER_VARS += DEFMAXVCPUS_ACRN
|
||||
USER_VARS += DEFMEMSZ
|
||||
USER_VARS += DEFMEMSLOTS
|
||||
USER_VARS += DEFMAXMEMSZ
|
||||
USER_VARS += DEFBRIDGES
|
||||
USER_VARS += DEFNETWORKMODEL_ACRN
|
||||
USER_VARS += DEFNETWORKMODEL_CLH
|
||||
|
@ -105,6 +105,12 @@ default_memory = @DEFMEMSZ@
|
||||
# This is will determine the times that memory will be hotadded to sandbox/VM.
|
||||
#memory_slots = @DEFMEMSLOTS@
|
||||
|
||||
# Default maximum memory in MiB per SB / VM
|
||||
# unspecified or == 0 --> will be set to the actual amount of physical RAM
|
||||
# > 0 <= amount of physical RAM --> will be set to the specified number
|
||||
# > amount of physical RAM --> will be set to the actual amount of physical RAM
|
||||
default_maxmemory = @DEFMAXMEMSZ@
|
||||
|
||||
# Shared file system type:
|
||||
# - virtio-fs (default)
|
||||
# - virtio-fs-nydus
|
||||
|
@ -91,6 +91,7 @@ default_bridges = @DEFBRIDGES@
|
||||
# Default memory size in MiB for SB/VM.
|
||||
# If unspecified then it will be set @DEFMEMSZ@ MiB.
|
||||
default_memory = @DEFMEMSZ@
|
||||
|
||||
#
|
||||
# Default memory slots per SB/VM.
|
||||
# If unspecified then it will be set @DEFMEMSLOTS@.
|
||||
@ -104,6 +105,12 @@ default_memory = @DEFMEMSZ@
|
||||
# Default 0
|
||||
#memory_offset = 0
|
||||
|
||||
# Default maximum memory in MiB per SB / VM
|
||||
# unspecified or == 0 --> will be set to the actual amount of physical RAM
|
||||
# > 0 <= amount of physical RAM --> will be set to the specified number
|
||||
# > amount of physical RAM --> will be set to the actual amount of physical RAM
|
||||
default_maxmemory = @DEFMAXMEMSZ@
|
||||
|
||||
# Block storage driver to be used for the hypervisor in case the container
|
||||
# rootfs is backed by a block device. This is virtio-scsi, virtio-blk
|
||||
# or nvdimm.
|
||||
|
@ -134,6 +134,12 @@ default_memory = @DEFMEMSZ@
|
||||
# This is will determine the times that memory will be hotadded to sandbox/VM.
|
||||
#memory_slots = @DEFMEMSLOTS@
|
||||
|
||||
# Default maximum memory in MiB per SB / VM
|
||||
# unspecified or == 0 --> will be set to the actual amount of physical RAM
|
||||
# > 0 <= amount of physical RAM --> will be set to the specified number
|
||||
# > amount of physical RAM --> will be set to the actual amount of physical RAM
|
||||
default_maxmemory = @DEFMAXMEMSZ@
|
||||
|
||||
# The size in MiB will be plused to max memory of hypervisor.
|
||||
# It is the memory address space for the NVDIMM devie.
|
||||
# If set block storage driver (block_device_driver) to "nvdimm",
|
||||
|
@ -33,6 +33,7 @@ require (
|
||||
github.com/opencontainers/runc v1.1.2
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/selinux v1.10.1
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.11.1
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
|
@ -767,6 +767,8 @@ github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGq
|
||||
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
@ -226,6 +226,7 @@ type RuntimeConfigOptions struct {
|
||||
DefaultVCPUCount uint32
|
||||
DefaultMaxVCPUCount uint32
|
||||
DefaultMemSize uint32
|
||||
DefaultMaxMemorySize uint64
|
||||
DefaultMsize9p uint32
|
||||
DisableBlock bool
|
||||
EnableIOThreads bool
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
exp "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/experimental"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
||||
"github.com/pbnjay/memory"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -121,6 +122,7 @@ type hypervisor struct {
|
||||
DefaultMaxVCPUs uint32 `toml:"default_maxvcpus"`
|
||||
MemorySize uint32 `toml:"default_memory"`
|
||||
MemSlots uint32 `toml:"memory_slots"`
|
||||
DefaultMaxMemorySize uint64 `toml:"default_maxmemory"`
|
||||
DefaultBridges uint32 `toml:"default_bridges"`
|
||||
Msize9p uint32 `toml:"msize_9p"`
|
||||
PCIeRootPort uint32 `toml:"pcie_root_port"`
|
||||
@ -400,6 +402,20 @@ func (h hypervisor) defaultMemOffset() uint64 {
|
||||
return offset
|
||||
}
|
||||
|
||||
func (h hypervisor) defaultMaxMemSz() uint64 {
|
||||
hostMemory := memory.TotalMemory() / 1024 / 1024 //MiB
|
||||
|
||||
if h.DefaultMaxMemorySize == 0 {
|
||||
return hostMemory
|
||||
}
|
||||
|
||||
if h.DefaultMaxMemorySize > hostMemory {
|
||||
return hostMemory
|
||||
}
|
||||
|
||||
return h.DefaultMaxMemorySize
|
||||
}
|
||||
|
||||
func (h hypervisor) defaultBridges() uint32 {
|
||||
if h.DefaultBridges == 0 {
|
||||
return defaultBridgesCount
|
||||
@ -622,6 +638,7 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
DefaultMaxVCPUs: h.defaultMaxVCPUs(),
|
||||
MemorySize: h.defaultMemSz(),
|
||||
MemSlots: h.defaultMemSlots(),
|
||||
DefaultMaxMemorySize: h.defaultMaxMemSz(),
|
||||
EntropySource: h.GetEntropySource(),
|
||||
EntropySourceList: h.EntropySourceList,
|
||||
DefaultBridges: h.defaultBridges(),
|
||||
@ -728,6 +745,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
MemorySize: h.defaultMemSz(),
|
||||
MemSlots: h.defaultMemSlots(),
|
||||
MemOffset: h.defaultMemOffset(),
|
||||
DefaultMaxMemorySize: h.defaultMaxMemSz(),
|
||||
VirtioMem: h.VirtioMem,
|
||||
EntropySource: h.GetEntropySource(),
|
||||
EntropySourceList: h.EntropySourceList,
|
||||
@ -825,6 +843,7 @@ func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
DefaultMaxVCPUs: h.defaultMaxVCPUs(),
|
||||
MemorySize: h.defaultMemSz(),
|
||||
MemSlots: h.defaultMemSlots(),
|
||||
DefaultMaxMemorySize: h.defaultMaxMemSz(),
|
||||
EntropySource: h.GetEntropySource(),
|
||||
EntropySourceList: h.EntropySourceList,
|
||||
DefaultBridges: h.defaultBridges(),
|
||||
@ -907,6 +926,7 @@ func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
MemorySize: h.defaultMemSz(),
|
||||
MemSlots: h.defaultMemSlots(),
|
||||
MemOffset: h.defaultMemOffset(),
|
||||
DefaultMaxMemorySize: h.defaultMaxMemSz(),
|
||||
VirtioMem: h.VirtioMem,
|
||||
EntropySource: h.GetEntropySource(),
|
||||
EntropySourceList: h.EntropySourceList,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/oci"
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
||||
"github.com/pbnjay/memory"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -85,6 +86,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
||||
sharedFS := "virtio-9p"
|
||||
virtioFSdaemon := path.Join(dir, "virtiofsd")
|
||||
epcSize := int64(0)
|
||||
maxMemory := uint64(memory.TotalMemory() / 1024 / 1024)
|
||||
|
||||
configFileOptions := ktu.RuntimeConfigOptions{
|
||||
Hypervisor: "qemu",
|
||||
@ -104,6 +106,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
||||
DefaultVCPUCount: defaultVCPUCount,
|
||||
DefaultMaxVCPUCount: defaultMaxVCPUCount,
|
||||
DefaultMemSize: defaultMemSize,
|
||||
DefaultMaxMemorySize: maxMemory,
|
||||
DefaultMsize9p: defaultMsize9p,
|
||||
HypervisorDebug: hypervisorDebug,
|
||||
RuntimeDebug: runtimeDebug,
|
||||
@ -153,6 +156,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
||||
NumVCPUs: defaultVCPUCount,
|
||||
DefaultMaxVCPUs: getCurrentCpuNum(),
|
||||
MemorySize: defaultMemSize,
|
||||
DefaultMaxMemorySize: maxMemory,
|
||||
DisableBlockDeviceUse: disableBlockDevice,
|
||||
BlockDeviceDriver: defaultBlockDeviceDriver,
|
||||
DefaultBridges: defaultBridgesCount,
|
||||
|
29
src/runtime/vendor/github.com/pbnjay/memory/LICENSE
generated
vendored
Normal file
29
src/runtime/vendor/github.com/pbnjay/memory/LICENSE
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017, Jeremy Jay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
41
src/runtime/vendor/github.com/pbnjay/memory/README.md
generated
vendored
Normal file
41
src/runtime/vendor/github.com/pbnjay/memory/README.md
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# memory
|
||||
|
||||
Package `memory` provides two methods reporting total physical system memory
|
||||
accessible to the kernel, and free memory available to the running application.
|
||||
|
||||
This package has no external dependency besides the standard library and default operating system tools.
|
||||
|
||||
Documentation:
|
||||
[](https://godoc.org/github.com/pbnjay/memory)
|
||||
|
||||
This is useful for dynamic code to minimize thrashing and other contention, similar to the stdlib `runtime.NumCPU`
|
||||
See some history of the proposal at https://github.com/golang/go/issues/21816
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```go
|
||||
fmt.Printf("Total system memory: %d\n", memory.TotalMemory())
|
||||
fmt.Printf("Free memory: %d\n", memory.FreeMemory())
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Tested/working on:
|
||||
- macOS 10.12.6 (16G29), 10.15.7 (19H2)
|
||||
- Windows 10 1511 (10586.1045)
|
||||
- Linux RHEL (3.10.0-327.3.1.el7.x86_64)
|
||||
- Raspberry Pi 3 (ARMv8) on Raspbian, ODROID-C1+ (ARMv7) on Ubuntu, C.H.I.P
|
||||
(ARMv7).
|
||||
- Amazon Linux 2 aarch64 (m6a.large, 4.14.203-156.332.amzn2.aarch64)
|
||||
|
||||
Tested on virtual machines:
|
||||
- Windows 7 SP1 386
|
||||
- Debian stretch 386
|
||||
- NetBSD 7.1 amd64 + 386
|
||||
- OpenBSD 6.1 amd64 + 386
|
||||
- FreeBSD 11.1 amd64 + 386
|
||||
- DragonFly BSD 4.8.1 amd64
|
||||
|
||||
If you have access to untested systems please test and report success/bugs.
|
24
src/runtime/vendor/github.com/pbnjay/memory/doc.go
generated
vendored
Normal file
24
src/runtime/vendor/github.com/pbnjay/memory/doc.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Package memory provides a single method reporting total system memory
|
||||
// accessible to the kernel.
|
||||
package memory
|
||||
|
||||
// TotalMemory returns the total accessible system memory in bytes.
|
||||
//
|
||||
// The total accessible memory is installed physical memory size minus reserved
|
||||
// areas for the kernel and hardware, if such reservations are reported by
|
||||
// the operating system.
|
||||
//
|
||||
// If accessible memory size could not be determined, then 0 is returned.
|
||||
func TotalMemory() uint64 {
|
||||
return sysTotalMemory()
|
||||
}
|
||||
|
||||
// FreeMemory returns the total free system memory in bytes.
|
||||
//
|
||||
// The total free memory is installed physical memory size minus reserved
|
||||
// areas for other applications running on the same system.
|
||||
//
|
||||
// If free memory size could not be determined, then 0 is returned.
|
||||
func FreeMemory() uint64 {
|
||||
return sysFreeMemory()
|
||||
}
|
3
src/runtime/vendor/github.com/pbnjay/memory/go.mod
generated
vendored
Normal file
3
src/runtime/vendor/github.com/pbnjay/memory/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/pbnjay/memory
|
||||
|
||||
go 1.16
|
19
src/runtime/vendor/github.com/pbnjay/memory/memory_bsd.go
generated
vendored
Normal file
19
src/runtime/vendor/github.com/pbnjay/memory/memory_bsd.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
// +build freebsd openbsd dragonfly netbsd
|
||||
|
||||
package memory
|
||||
|
||||
func sysTotalMemory() uint64 {
|
||||
s, err := sysctlUint64("hw.physmem")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func sysFreeMemory() uint64 {
|
||||
s, err := sysctlUint64("hw.usermem")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return s
|
||||
}
|
49
src/runtime/vendor/github.com/pbnjay/memory/memory_darwin.go
generated
vendored
Normal file
49
src/runtime/vendor/github.com/pbnjay/memory/memory_darwin.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
// +build darwin
|
||||
|
||||
package memory
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func sysTotalMemory() uint64 {
|
||||
s, err := sysctlUint64("hw.memsize")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func sysFreeMemory() uint64 {
|
||||
cmd := exec.Command("vm_stat")
|
||||
outBytes, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
rePageSize := regexp.MustCompile("page size of ([0-9]*) bytes")
|
||||
reFreePages := regexp.MustCompile("Pages free: *([0-9]*)\\.")
|
||||
|
||||
// default: page size of 4096 bytes
|
||||
matches := rePageSize.FindSubmatchIndex(outBytes)
|
||||
pageSize := uint64(4096)
|
||||
if len(matches) == 4 {
|
||||
pageSize, err = strconv.ParseUint(string(outBytes[matches[2]:matches[3]]), 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// ex: Pages free: 1126961.
|
||||
matches = reFreePages.FindSubmatchIndex(outBytes)
|
||||
freePages := uint64(0)
|
||||
if len(matches) == 4 {
|
||||
freePages, err = strconv.ParseUint(string(outBytes[matches[2]:matches[3]]), 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return freePages * pageSize
|
||||
}
|
29
src/runtime/vendor/github.com/pbnjay/memory/memory_linux.go
generated
vendored
Normal file
29
src/runtime/vendor/github.com/pbnjay/memory/memory_linux.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// +build linux
|
||||
|
||||
package memory
|
||||
|
||||
import "syscall"
|
||||
|
||||
func sysTotalMemory() uint64 {
|
||||
in := &syscall.Sysinfo_t{}
|
||||
err := syscall.Sysinfo(in)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
// If this is a 32-bit system, then these fields are
|
||||
// uint32 instead of uint64.
|
||||
// So we always convert to uint64 to match signature.
|
||||
return uint64(in.Totalram) * uint64(in.Unit)
|
||||
}
|
||||
|
||||
func sysFreeMemory() uint64 {
|
||||
in := &syscall.Sysinfo_t{}
|
||||
err := syscall.Sysinfo(in)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
// If this is a 32-bit system, then these fields are
|
||||
// uint32 instead of uint64.
|
||||
// So we always convert to uint64 to match signature.
|
||||
return uint64(in.Freeram) * uint64(in.Unit)
|
||||
}
|
60
src/runtime/vendor/github.com/pbnjay/memory/memory_windows.go
generated
vendored
Normal file
60
src/runtime/vendor/github.com/pbnjay/memory/memory_windows.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
// +build windows
|
||||
|
||||
package memory
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// omitting a few fields for brevity...
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
|
||||
type memStatusEx struct {
|
||||
dwLength uint32
|
||||
dwMemoryLoad uint32
|
||||
ullTotalPhys uint64
|
||||
ullAvailPhys uint64
|
||||
unused [5]uint64
|
||||
}
|
||||
|
||||
func sysTotalMemory() uint64 {
|
||||
kernel32, err := syscall.LoadDLL("kernel32.dll")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
// GetPhysicallyInstalledSystemMemory is simpler, but broken on
|
||||
// older versions of windows (and uses this under the hood anyway).
|
||||
globalMemoryStatusEx, err := kernel32.FindProc("GlobalMemoryStatusEx")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
msx := &memStatusEx{
|
||||
dwLength: 64,
|
||||
}
|
||||
r, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx)))
|
||||
if r == 0 {
|
||||
return 0
|
||||
}
|
||||
return msx.ullTotalPhys
|
||||
}
|
||||
|
||||
func sysFreeMemory() uint64 {
|
||||
kernel32, err := syscall.LoadDLL("kernel32.dll")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
// GetPhysicallyInstalledSystemMemory is simpler, but broken on
|
||||
// older versions of windows (and uses this under the hood anyway).
|
||||
globalMemoryStatusEx, err := kernel32.FindProc("GlobalMemoryStatusEx")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
msx := &memStatusEx{
|
||||
dwLength: 64,
|
||||
}
|
||||
r, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx)))
|
||||
if r == 0 {
|
||||
return 0
|
||||
}
|
||||
return msx.ullAvailPhys
|
||||
}
|
21
src/runtime/vendor/github.com/pbnjay/memory/memsysctl.go
generated
vendored
Normal file
21
src/runtime/vendor/github.com/pbnjay/memory/memsysctl.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// +build darwin freebsd openbsd dragonfly netbsd
|
||||
|
||||
package memory
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func sysctlUint64(name string) (uint64, error) {
|
||||
s, err := syscall.Sysctl(name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// hack because the string conversion above drops a \0
|
||||
b := []byte(s)
|
||||
if len(b) < 8 {
|
||||
b = append(b, 0)
|
||||
}
|
||||
return *(*uint64)(unsafe.Pointer(&b[0])), nil
|
||||
}
|
10
src/runtime/vendor/github.com/pbnjay/memory/stub.go
generated
vendored
Normal file
10
src/runtime/vendor/github.com/pbnjay/memory/stub.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// +build !linux,!darwin,!windows,!freebsd,!dragonfly,!netbsd,!openbsd
|
||||
|
||||
package memory
|
||||
|
||||
func sysTotalMemory() uint64 {
|
||||
return 0
|
||||
}
|
||||
func sysFreeMemory() uint64 {
|
||||
return 0
|
||||
}
|
3
src/runtime/vendor/modules.txt
vendored
3
src/runtime/vendor/modules.txt
vendored
@ -260,6 +260,9 @@ github.com/opencontainers/selinux/go-selinux
|
||||
github.com/opencontainers/selinux/go-selinux/label
|
||||
github.com/opencontainers/selinux/pkg/pwalk
|
||||
github.com/opencontainers/selinux/pkg/pwalkdir
|
||||
# github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
|
||||
## explicit
|
||||
github.com/pbnjay/memory
|
||||
# github.com/pkg/errors v0.9.1
|
||||
## explicit
|
||||
github.com/pkg/errors
|
||||
|
@ -475,12 +475,9 @@ func (clh *cloudHypervisor) CreateVM(ctx context.Context, id string, network Net
|
||||
// Enable hugepages if needed
|
||||
clh.vmconfig.Memory.Hugepages = func(b bool) *bool { return &b }(clh.config.HugePages)
|
||||
if !clh.config.ConfidentialGuest {
|
||||
hostMemKb, err := GetHostMemorySizeKb(procMemInfo)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
hotplugSize := clh.config.DefaultMaxMemorySize
|
||||
// OpenAPI only supports int64 values
|
||||
clh.vmconfig.Memory.HotplugSize = func(i int64) *int64 { return &i }(int64((utils.MemUnit(hostMemKb) * utils.KiB).ToBytes()))
|
||||
clh.vmconfig.Memory.HotplugSize = func(i int64) *int64 { return &i }(int64((utils.MemUnit(hotplugSize) * utils.MiB).ToBytes()))
|
||||
}
|
||||
// Set initial amount of cpu's for the virtual machine
|
||||
clh.vmconfig.Cpus = chclient.NewCpusConfig(int32(clh.config.NumVCPUs), int32(clh.config.DefaultMaxVCPUs))
|
||||
@ -877,6 +874,11 @@ func (clh *cloudHypervisor) ResizeMemory(ctx context.Context, reqMemMB uint32, m
|
||||
return 0, MemoryDevice{}, err
|
||||
}
|
||||
|
||||
maxHotplugSize := utils.MemUnit(*info.Config.Memory.HotplugSize) * utils.Byte
|
||||
if reqMemMB > uint32(maxHotplugSize.ToMiB()) {
|
||||
reqMemMB = uint32(maxHotplugSize.ToMiB())
|
||||
}
|
||||
|
||||
currentMem := utils.MemUnit(info.Config.Memory.Size) * utils.Byte
|
||||
newMem := utils.MemUnit(reqMemMB) * utils.MiB
|
||||
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -50,7 +49,6 @@ const (
|
||||
// MockHypervisor is a mock hypervisor for testing purposes
|
||||
MockHypervisor HypervisorType = "mock"
|
||||
|
||||
procMemInfo = "/proc/meminfo"
|
||||
procCPUInfo = "/proc/cpuinfo"
|
||||
|
||||
defaultVCPUs = 1
|
||||
@ -441,6 +439,9 @@ type HypervisorConfig struct {
|
||||
// DefaultMem specifies default memory size in MiB for the VM.
|
||||
MemorySize uint32
|
||||
|
||||
// DefaultMaxMemorySize specifies the maximum amount of RAM in MiB for the VM.
|
||||
DefaultMaxMemorySize uint64
|
||||
|
||||
// DefaultBridges specifies default number of bridges for the VM.
|
||||
// Bridges can be used to hot plug devices
|
||||
DefaultBridges uint32
|
||||
@ -741,39 +742,6 @@ func DeserializeParams(parameters []string) []Param {
|
||||
return params
|
||||
}
|
||||
|
||||
func GetHostMemorySizeKb(memInfoPath string) (uint64, error) {
|
||||
f, err := os.Open(memInfoPath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
// Expected format: ["MemTotal:", "1234", "kB"]
|
||||
parts := strings.Fields(scanner.Text())
|
||||
|
||||
// Sanity checks: Skip malformed entries.
|
||||
if len(parts) < 3 || parts[0] != "MemTotal:" || parts[2] != "kB" {
|
||||
continue
|
||||
}
|
||||
|
||||
sizeKb, err := strconv.ParseUint(parts[1], 0, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return sizeKb, nil
|
||||
}
|
||||
|
||||
// Handle errors that may have occurred during the reading of the file.
|
||||
if err := scanner.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("unable get MemTotal from %s", memInfoPath)
|
||||
}
|
||||
|
||||
// CheckCmdline checks whether an option or parameter is present in the kernel command line.
|
||||
// Search is case-insensitive.
|
||||
// Takes path to file that contains the kernel command line, desired option, and permitted values
|
||||
|
@ -8,7 +8,6 @@ package virtcontainers
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
@ -254,55 +253,6 @@ func TestAddKernelParamInvalid(t *testing.T) {
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestGetHostMemorySizeKb(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
type testData struct {
|
||||
contents string
|
||||
expectedResult int
|
||||
expectError bool
|
||||
}
|
||||
|
||||
data := []testData{
|
||||
{
|
||||
`
|
||||
MemTotal: 1 kB
|
||||
MemFree: 2 kB
|
||||
SwapTotal: 3 kB
|
||||
SwapFree: 4 kB
|
||||
`,
|
||||
1024,
|
||||
false,
|
||||
},
|
||||
{
|
||||
`
|
||||
MemFree: 2 kB
|
||||
SwapTotal: 3 kB
|
||||
SwapFree: 4 kB
|
||||
`,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
file := filepath.Join(dir, "meminfo")
|
||||
_, err := GetHostMemorySizeKb(file)
|
||||
assert.Error(err)
|
||||
|
||||
for _, d := range data {
|
||||
err = os.WriteFile(file, []byte(d.contents), os.FileMode(0640))
|
||||
assert.NoError(err)
|
||||
defer os.Remove(file)
|
||||
|
||||
hostMemKb, err := GetHostMemorySizeKb(file)
|
||||
|
||||
assert.False((d.expectError && err == nil))
|
||||
assert.False((!d.expectError && err != nil))
|
||||
assert.NotEqual(hostMemKb, d.expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckCmdline(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
@ -302,24 +302,8 @@ func (q *qemu) cpuTopology() govmmQemu.SMP {
|
||||
return q.arch.cpuTopology(q.config.NumVCPUs, q.config.DefaultMaxVCPUs)
|
||||
}
|
||||
|
||||
func (q *qemu) hostMemMB() (uint64, error) {
|
||||
hostMemKb, err := GetHostMemorySizeKb(procMemInfo)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("Unable to read memory info: %s", err)
|
||||
}
|
||||
if hostMemKb == 0 {
|
||||
return 0, fmt.Errorf("Error host memory size 0")
|
||||
}
|
||||
|
||||
return hostMemKb / 1024, nil
|
||||
}
|
||||
|
||||
func (q *qemu) memoryTopology() (govmmQemu.Memory, error) {
|
||||
hostMemMb, err := q.hostMemMB()
|
||||
if err != nil {
|
||||
return govmmQemu.Memory{}, err
|
||||
}
|
||||
|
||||
hostMemMb := q.config.DefaultMaxMemorySize
|
||||
memMb := uint64(q.config.MemorySize)
|
||||
|
||||
return q.arch.memoryTopology(memMb, hostMemMb, uint8(q.config.MemSlots)), nil
|
||||
@ -773,12 +757,8 @@ func (q *qemu) getMemArgs() (bool, string, string, error) {
|
||||
}
|
||||
|
||||
func (q *qemu) setupVirtioMem(ctx context.Context) error {
|
||||
maxMem, err := q.hostMemMB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// backend memory size must be multiple of 4Mib
|
||||
sizeMB := (int(maxMem) - int(q.config.MemorySize)) >> 2 << 2
|
||||
sizeMB := (int(q.config.DefaultMaxMemorySize) - int(q.config.MemorySize)) >> 2 << 2
|
||||
|
||||
share, target, memoryBack, err := q.getMemArgs()
|
||||
if err != nil {
|
||||
@ -1964,8 +1944,6 @@ func (q *qemu) hotplugMemory(memDev *MemoryDevice, op Operation) (int, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
currentMemory := int(q.config.MemorySize) + q.state.HotpluggedMemory
|
||||
|
||||
if memDev.SizeMB == 0 {
|
||||
memLog.Debug("hotplug is not required")
|
||||
return 0, nil
|
||||
@ -1979,17 +1957,7 @@ func (q *qemu) hotplugMemory(memDev *MemoryDevice, op Operation) (int, error) {
|
||||
return 0, nil
|
||||
case AddDevice:
|
||||
memLog.WithField("operation", "add").Debugf("Requested to add memory: %d MB", memDev.SizeMB)
|
||||
maxMem, err := q.hostMemMB()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Don't exceed the maximum amount of memory
|
||||
if currentMemory+memDev.SizeMB > int(maxMem) {
|
||||
// Fixme: return a typed error
|
||||
return 0, fmt.Errorf("Unable to hotplug %d MiB memory, the SB has %d MiB and the maximum amount is %d MiB",
|
||||
memDev.SizeMB, currentMemory, maxMem)
|
||||
}
|
||||
memoryAdded, err := q.hotplugAddMemory(memDev)
|
||||
if err != nil {
|
||||
return memoryAdded, err
|
||||
@ -2225,6 +2193,11 @@ func (q *qemu) ResizeMemory(ctx context.Context, reqMemMB uint32, memoryBlockSiz
|
||||
case currentMemory < reqMemMB:
|
||||
//hotplug
|
||||
addMemMB := reqMemMB - currentMemory
|
||||
|
||||
if currentMemory+addMemMB > uint32(q.config.DefaultMaxMemorySize) {
|
||||
addMemMB = uint32(q.config.DefaultMaxMemorySize) - currentMemory
|
||||
}
|
||||
|
||||
memHotplugMB, err := calcHotplugMemMiBSize(addMemMB, memoryBlockSizeMB)
|
||||
if err != nil {
|
||||
return currentMemory, MemoryDevice{}, err
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
||||
"github.com/pbnjay/memory"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -172,6 +173,7 @@ func TestQemuCPUTopology(t *testing.T) {
|
||||
|
||||
func TestQemuMemoryTopology(t *testing.T) {
|
||||
mem := uint32(1000)
|
||||
maxMem := memory.TotalMemory() / 1024 / 1024 //MiB
|
||||
slots := uint32(8)
|
||||
assert := assert.New(t)
|
||||
|
||||
@ -180,12 +182,11 @@ func TestQemuMemoryTopology(t *testing.T) {
|
||||
config: HypervisorConfig{
|
||||
MemorySize: mem,
|
||||
MemSlots: slots,
|
||||
DefaultMaxMemorySize: maxMem,
|
||||
},
|
||||
}
|
||||
|
||||
hostMemKb, err := GetHostMemorySizeKb(procMemInfo)
|
||||
assert.NoError(err)
|
||||
memMax := fmt.Sprintf("%dM", int(float64(hostMemKb)/1024))
|
||||
memMax := fmt.Sprintf("%dM", int(maxMem))
|
||||
|
||||
expectedOut := govmmQemu.Memory{
|
||||
Size: fmt.Sprintf("%dM", mem),
|
||||
|
Loading…
Reference in New Issue
Block a user