Merge pull request #802 from jcvenegas/fix-memory-update

memory: update: Update state using the memory removed
This commit is contained in:
Sebastien Boeuf 2018-10-02 15:23:11 -07:00 committed by GitHub
commit c061fe1ff5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 19 deletions

View File

@ -1301,9 +1301,13 @@ func (c *Container) memHotplugValid(mem uint32) (uint32, error) {
return uint32(math.Ceil(float64(mem)/float64(memorySectionSizeMB))) * memorySectionSizeMB, nil return uint32(math.Ceil(float64(mem)/float64(memorySectionSizeMB))) * memorySectionSizeMB, nil
} }
func (c *Container) updateMemoryResources(oldResources, newResources ContainerResources) error { func (c *Container) updateMemoryResources(oldResources ContainerResources, newResources *ContainerResources) error {
oldMemMB := oldResources.MemMB oldMemMB := oldResources.MemMB
newMemMB := newResources.MemMB newMemMB := newResources.MemMB
c.Logger().WithFields(logrus.Fields{
"old-mem": fmt.Sprintf("%dMB", oldMemMB),
"new-mem": fmt.Sprintf("%dMB", newMemMB),
}).Debug("Request update memory")
if oldMemMB == newMemMB { if oldMemMB == newMemMB {
c.Logger().WithFields(logrus.Fields{ c.Logger().WithFields(logrus.Fields{
@ -1325,16 +1329,37 @@ func (c *Container) updateMemoryResources(oldResources, newResources ContainerRe
addMemDevice := &memoryDevice{ addMemDevice := &memoryDevice{
sizeMB: int(memHotplugMB), sizeMB: int(memHotplugMB),
} }
_, err = c.sandbox.hypervisor.hotplugAddDevice(addMemDevice, memoryDev) data, err := c.sandbox.hypervisor.hotplugAddDevice(addMemDevice, memoryDev)
if err != nil { if err != nil {
return err return err
} }
newResources.MemMB = newMemMB memoryAdded, ok := data.(int)
if !ok {
return fmt.Errorf("Could not get the memory added, got %+v", data)
}
newResources.MemMB = oldMemMB + uint32(memoryAdded)
if err := c.sandbox.agent.onlineCPUMem(0, false); err != nil { if err := c.sandbox.agent.onlineCPUMem(0, false); err != nil {
return err return err
} }
} }
// hot remove memory unsupported if oldMemMB > newMemMB {
// Try to remove a memory device with the difference
// from new memory and old memory
removeMem := &memoryDevice{
sizeMB: int(oldMemMB - newMemMB),
}
data, err := c.sandbox.hypervisor.hotplugRemoveDevice(removeMem, memoryDev)
if err != nil {
return err
}
memoryRemoved, ok := data.(int)
if !ok {
return fmt.Errorf("Could not get the memory added, got %+v", data)
}
newResources.MemMB = oldMemMB - uint32(memoryRemoved)
newResources.MemMB = oldResources.MemMB
}
return nil return nil
} }
@ -1358,7 +1383,7 @@ func (c *Container) updateResources(oldResources, newResources ContainerResource
// Memory is not updated if memory limit not set // Memory is not updated if memory limit not set
if newResources.MemMB != 0 { if newResources.MemMB != 0 {
if err := c.updateMemoryResources(oldResources, newResources); err != nil { if err := c.updateMemoryResources(oldResources, &newResources); err != nil {
return err return err
} }

View File

@ -64,6 +64,9 @@ func (m *mockHypervisor) hotplugAddDevice(devInfo interface{}, devType deviceTyp
switch devType { switch devType {
case cpuDev: case cpuDev:
return m.vCPUs, nil return m.vCPUs, nil
case memoryDev:
memdev := devInfo.(*memoryDevice)
return memdev.sizeMB, nil
} }
return nil, nil return nil, nil
} }

View File

@ -7,7 +7,6 @@ package virtcontainers
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
@ -913,7 +912,7 @@ func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operati
return nil, q.hotplugVFIODevice(device, op) return nil, q.hotplugVFIODevice(device, op)
case memoryDev: case memoryDev:
memdev := devInfo.(*memoryDevice) memdev := devInfo.(*memoryDevice)
return nil, q.hotplugMemory(memdev, op) return q.hotplugMemory(memdev, op)
case netDev: case netDev:
device := devInfo.(*VirtualEndpoint) device := devInfo.(*VirtualEndpoint)
return nil, q.hotplugNetDevice(device, op) return nil, q.hotplugNetDevice(device, op)
@ -1047,24 +1046,27 @@ func (q *qemu) hotplugRemoveCPUs(amount uint32) (uint32, error) {
return amount, q.storage.storeHypervisorState(q.id, q.state) return amount, q.storage.storeHypervisorState(q.id, q.state)
} }
func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error { func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) (int, error) {
if memDev.sizeMB < 0 { if memDev.sizeMB < 0 {
return fmt.Errorf("cannot hotplug negative size (%d) memory", memDev.sizeMB) return 0, fmt.Errorf("cannot hotplug negative size (%d) memory", memDev.sizeMB)
} }
// We do not support memory hot unplug. // We do not support memory hot unplug.
if op == removeDevice { if op == removeDevice {
return errors.New("cannot hot unplug memory device") // Dont fail for now, until we fix it.
// We return that we only unplugged 0
q.Logger().Warn("hot-remove VM memory not supported")
return 0, nil
} }
err := q.qmpSetup() err := q.qmpSetup()
if err != nil { if err != nil {
return err return 0, err
} }
maxMem, err := q.hostMemMB() maxMem, err := q.hostMemMB()
if err != nil { if err != nil {
return err return 0, err
} }
// calculate current memory // calculate current memory
@ -1072,13 +1074,13 @@ func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error {
// Don't exceed the maximum amount of memory // Don't exceed the maximum amount of memory
if currentMemory+memDev.sizeMB > int(maxMem) { if currentMemory+memDev.sizeMB > int(maxMem) {
return fmt.Errorf("Unable to hotplug %d MiB memory, the SB has %d MiB and the maximum amount is %d MiB", 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, q.config.MemorySize) memDev.sizeMB, currentMemory, q.config.MemorySize)
} }
memoryDevices, err := q.qmpMonitorCh.qmp.ExecQueryMemoryDevices(q.qmpMonitorCh.ctx) memoryDevices, err := q.qmpMonitorCh.qmp.ExecQueryMemoryDevices(q.qmpMonitorCh.ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to query memory devices: %v", err) return 0, fmt.Errorf("failed to query memory devices: %v", err)
} }
if len(memoryDevices) != 0 { if len(memoryDevices) != 0 {
@ -1088,15 +1090,15 @@ func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error {
return q.hotplugAddMemory(memDev) return q.hotplugAddMemory(memDev)
} }
func (q *qemu) hotplugAddMemory(memDev *memoryDevice) error { func (q *qemu) hotplugAddMemory(memDev *memoryDevice) (int, error) {
err := q.qmpMonitorCh.qmp.ExecHotplugMemory(q.qmpMonitorCh.ctx, "memory-backend-ram", "mem"+strconv.Itoa(memDev.slot), "", memDev.sizeMB) err := q.qmpMonitorCh.qmp.ExecHotplugMemory(q.qmpMonitorCh.ctx, "memory-backend-ram", "mem"+strconv.Itoa(memDev.slot), "", memDev.sizeMB)
if err != nil { if err != nil {
q.Logger().WithError(err).Error("hotplug memory") q.Logger().WithError(err).Error("hotplug memory")
return err return 0, err
} }
q.state.HotpluggedMemory += memDev.sizeMB q.state.HotpluggedMemory += memDev.sizeMB
return q.storage.storeHypervisorState(q.id, q.state) return memDev.sizeMB, q.storage.storeHypervisorState(q.id, q.state)
} }
func (q *qemu) pauseSandbox() error { func (q *qemu) pauseSandbox() error {

View File

@ -348,8 +348,10 @@ func TestHotplugRemoveMemory(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
qemuConfig := newQemuConfig() qemuConfig := newQemuConfig()
fs := &filesystem{}
q := &qemu{ q := &qemu{
config: qemuConfig, config: qemuConfig,
storage: fs,
} }
_, err := q.hotplugRemoveDevice(&memoryDevice{0, 128}, memoryDev) _, err := q.hotplugRemoveDevice(&memoryDevice{0, 128}, memoryDev)
@ -360,8 +362,10 @@ func TestHotplugUnsupportedDeviceType(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
qemuConfig := newQemuConfig() qemuConfig := newQemuConfig()
fs := &filesystem{}
q := &qemu{ q := &qemu{
config: qemuConfig, config: qemuConfig,
storage: fs,
} }
_, err := q.hotplugAddDevice(&memoryDevice{0, 128}, fsDev) _, err := q.hotplugAddDevice(&memoryDevice{0, 128}, fsDev)