Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

runtime: Enable file based backend #1865

Merged
merged 1 commit into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cli/config/configuration-qemu.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ enable_iothreads = @DEFENABLEIOTHREADS@
# result in memory pre allocation
#enable_hugepages = true

# Enable file based guest memory support. The default is an empty string which
# will disable this feature. In the case of virtio-fs, this is enabled
# automatically and '/dev/shm' is used as the backing folder.
# This option will be ignored if VM templating is enabled.
#file_mem_backend = ""

# Enable swap of vm memory. Default false.
# The behaviour is undefined if mem_prealloc is also set to true
#enable_swap = true
Expand Down
1 change: 1 addition & 0 deletions pkg/katautils/config-settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const defaultBlockDeviceCacheNoflush bool = false
const defaultEnableIOThreads bool = false
const defaultEnableMemPrealloc bool = false
const defaultEnableHugePages bool = false
const defaultFileBackedMemRootDir string = ""
const defaultEnableSwap bool = false
const defaultEnableDebug bool = false
const defaultDisableNestingChecks bool = false
Expand Down
3 changes: 3 additions & 0 deletions pkg/katautils/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type hypervisor struct {
DisableBlockDeviceUse bool `toml:"disable_block_device_use"`
MemPrealloc bool `toml:"enable_mem_prealloc"`
HugePages bool `toml:"enable_hugepages"`
FileBackedMemRootDir string `toml:"file_mem_backend"`
Swap bool `toml:"enable_swap"`
Debug bool `toml:"enable_debug"`
DisableNestingChecks bool `toml:"disable_nesting_checks"`
Expand Down Expand Up @@ -584,6 +585,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
VirtioFSCache: h.VirtioFSCache,
MemPrealloc: h.MemPrealloc,
HugePages: h.HugePages,
FileBackedMemRootDir: h.FileBackedMemRootDir,
Mlock: !h.Swap,
Debug: h.Debug,
DisableNestingChecks: h.DisableNestingChecks,
Expand Down Expand Up @@ -850,6 +852,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig {
DefaultBridges: defaultBridgesCount,
MemPrealloc: defaultEnableMemPrealloc,
HugePages: defaultEnableHugePages,
FileBackedMemRootDir: defaultFileBackedMemRootDir,
Mlock: !defaultEnableSwap,
Debug: defaultEnableDebug,
DisableNestingChecks: defaultDisableNestingChecks,
Expand Down
3 changes: 3 additions & 0 deletions virtcontainers/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ type HypervisorConfig struct {
// HugePages specifies if the memory should be pre-allocated from huge pages
HugePages bool

// File based memory backend root directory
FileBackedMemRootDir string

// Realtime Used to enable/disable realtime
Realtime bool

Expand Down
3 changes: 3 additions & 0 deletions virtcontainers/persist/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ type HypervisorConfig struct {
// HugePages specifies if the memory should be pre-allocated from huge pages
HugePages bool

// File based memory backend root directory
FileBackedMemRootDir string

// Realtime Used to enable/disable realtime
Realtime bool

Expand Down
37 changes: 34 additions & 3 deletions virtcontainers/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ const (
qmpCapErrMsg = "Failed to negoatiate QMP capabilities"
qmpExecCatCmd = "exec:cat"

scsiControllerID = "scsi0"
rngID = "rng0"
vsockKernelOption = "agent.use_vsock"
scsiControllerID = "scsi0"
rngID = "rng0"
vsockKernelOption = "agent.use_vsock"
fallbackFileBackedMemDir = "/dev/shm"
)

var qemuMajorVersion int
Expand Down Expand Up @@ -423,6 +424,23 @@ func (q *qemu) setupTemplate(knobs *govmmQemu.Knobs, memory *govmmQemu.Memory) g
return incoming
}

func (q *qemu) setupFileBackedMem(knobs *govmmQemu.Knobs, memory *govmmQemu.Memory) {
var target string
if q.config.FileBackedMemRootDir != "" {
target = q.config.FileBackedMemRootDir
} else {
target = fallbackFileBackedMemDir
}
if _, err := os.Stat(target); err != nil {
q.Logger().WithError(err).Error("File backed memory location does not exist")
return
}

knobs.FileBackedMem = true
knobs.FileBackedMemShared = true
memory.Path = target
}

// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
func (q *qemu) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
// Save the tracing context
Expand Down Expand Up @@ -476,6 +494,19 @@ func (q *qemu) createSandbox(ctx context.Context, id string, hypervisorConfig *H

incoming := q.setupTemplate(&knobs, &memory)

// With the current implementations, VM templating will not work with file
// based memory (stand-alone) or virtiofs. This is because VM templating
// builds the first VM with file-backed memory and shared=on and the
// subsequent ones with shared=off. virtio-fs always requires shared=on for
// memory.
if q.config.SharedFS == config.VirtioFS || q.config.FileBackedMemRootDir != "" {
if !(q.config.BootToBeTemplate || q.config.BootFromTemplate) {
q.setupFileBackedMem(&knobs, &memory)
} else {
return errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")
}
}

rtc := govmmQemu.RTC{
Base: "utc",
DriftFix: "slew",
Expand Down
68 changes: 68 additions & 0 deletions virtcontainers/qemu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"testing"

govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -482,3 +483,70 @@ func TestQemuAddDeviceToBridge(t *testing.T) {
exceptErr = errors.New("failed to get available address from bridges")
assert.Equal(exceptErr, err)
}

func TestQemuFileBackedMem(t *testing.T) {
assert := assert.New(t)

// Check default Filebackedmem location for virtio-fs
sandbox, err := createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q := &qemu{}
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, true)
assert.Equal(q.qemuConfig.Knobs.FileBackedMemShared, true)
assert.Equal(q.qemuConfig.Memory.Path, fallbackFileBackedMemDir)

// Check failure for VM templating
sandbox, err = createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q = &qemu{}
sandbox.config.HypervisorConfig.BootToBeTemplate = true
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
sandbox.config.HypervisorConfig.MemoryPath = fallbackFileBackedMemDir

err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store)

expectErr := errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")
assert.Equal(expectErr, err)

// Check Setting of non-existent shared-mem path
sandbox, err = createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q = &qemu{}
sandbox.config.HypervisorConfig.FileBackedMemRootDir = "/tmp/xyzabc"
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)
assert.Equal(q.qemuConfig.Knobs.FileBackedMemShared, false)
assert.Equal(q.qemuConfig.Memory.Path, "")
}

func createQemuSandboxConfig() (*Sandbox, error) {

qemuConfig := newQemuConfig()
sandbox := Sandbox{
ctx: context.Background(),
id: "testSandbox",
config: &SandboxConfig{
HypervisorConfig: qemuConfig,
},
}

vcStore, err := store.NewVCSandboxStore(sandbox.ctx, sandbox.id)
if err != nil {
return &Sandbox{}, err
}
sandbox.store = vcStore

return &sandbox, nil
}