Template: enable template for arm64

Now, template feature can't work on arm64. When using bypass-shared-memory
cap to saving sandbox as a template, new sandbox cloning from the template
will fail. From initial investigation, it maybe a qemu issue. Further
research should be done.
To enable template on arm64, this patch adds a switch to offer the capability
to open or close the bypass-shared-memory cap.
While closing bypass-shared-memory cap, saving vm will occupy more space
and consume more time. So increase 300M for mount size and bump the time
waiting for migration to 10 seconds.

Fixes: #1336

Signed-off-by: Jianyong Wu  <jianyong.wu@arm.com>
This commit is contained in:
Jianyong Wu 2019-04-10 05:10:34 -04:00
parent d63b7c92a8
commit 98687a3463
11 changed files with 100 additions and 11 deletions

View File

@ -90,7 +90,7 @@ func (t *template) prepareTemplateFiles() error {
return err return err
} }
flags := uintptr(syscall.MS_NOSUID | syscall.MS_NODEV) flags := uintptr(syscall.MS_NOSUID | syscall.MS_NODEV)
opts := fmt.Sprintf("size=%dM", t.config.HypervisorConfig.MemorySize+8) opts := fmt.Sprintf("size=%dM", t.config.HypervisorConfig.MemorySize+templateDeviceStateSize)
if err = syscall.Mount("tmpfs", t.statePath, "tmpfs", flags, opts); err != nil { if err = syscall.Mount("tmpfs", t.statePath, "tmpfs", flags, opts); err != nil {
t.close() t.close()
return err return err

View File

@ -0,0 +1,14 @@
// Copyright (c) 2019 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// template implements base vm factory with vm templating.
package template
// templateDeviceStateSize denotes device state size when
// mount tmpfs.
// when bypass-shared-memory is not support like arm64,
// creating template will occupy more space. That's why we
// put it here.
const templateDeviceStateSize = 8

View File

@ -0,0 +1,14 @@
// Copyright (c) 2019 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// template implements base vm factory with vm templating.
package template
// templateDeviceStateSize denotes device state size when
// mount tmpfs.
// when bypass-shared-memory is not support like arm64,
// creating template will occupy more space. That's why we
// put it here.
const templateDeviceStateSize = 300

View File

@ -0,0 +1,14 @@
// Copyright (c) 2019 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// template implements base vm factory with vm templating.
package template
// templateDeviceStateSize denotes device state size when
// mount tmpfs.
// when bypass-shared-memory is not support like arm64,
// creating template will occupy more space. That's why we
// put it here.
const templateDeviceStateSize = 8

View File

@ -0,0 +1,14 @@
// Copyright (c) 2019 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// template implements base vm factory with vm templating.
package template
// templateDeviceStateSize denotes device state size when
// mount tmpfs.
// when bypass-shared-memory is not support like arm64,
// creating template will occupy more space. That's why we
// put it here.
const templateDeviceStateSize = 8

View File

@ -89,10 +89,8 @@ const (
consoleSocket = "console.sock" consoleSocket = "console.sock"
qmpSocket = "qmp.sock" qmpSocket = "qmp.sock"
qmpCapErrMsg = "Failed to negoatiate QMP capabilities" qmpCapErrMsg = "Failed to negoatiate QMP capabilities"
qmpCapMigrationBypassSharedMemory = "bypass-shared-memory" qmpExecCatCmd = "exec:cat"
qmpExecCatCmd = "exec:cat"
qmpMigrationWaitTimeout = 5 * time.Second
scsiControllerID = "scsi0" scsiControllerID = "scsi0"
rngID = "rng0" rngID = "rng0"
@ -1320,12 +1318,7 @@ func (q *qemu) saveSandbox() error {
// BootToBeTemplate sets the VM to be a template that other VMs can clone from. We would want to // BootToBeTemplate sets the VM to be a template that other VMs can clone from. We would want to
// bypass shared memory when saving the VM to a local file through migration exec. // bypass shared memory when saving the VM to a local file through migration exec.
if q.config.BootToBeTemplate { if q.config.BootToBeTemplate {
err = q.qmpMonitorCh.qmp.ExecSetMigrationCaps(q.qmpMonitorCh.ctx, []map[string]interface{}{ err := q.arch.setBypassSharedMemoryMigrationCaps(q.qmpMonitorCh.ctx, q.qmpMonitorCh.qmp)
{
"capability": qmpCapMigrationBypassSharedMemory,
"state": true,
},
})
if err != nil { if err != nil {
q.Logger().WithError(err).Error("set migration bypass shared memory") q.Logger().WithError(err).Error("set migration bypass shared memory")
return err return err

View File

@ -7,6 +7,7 @@ package virtcontainers
import ( import (
"os" "os"
"time"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
@ -24,6 +25,10 @@ const defaultQemuMachineType = QemuPC
const defaultQemuMachineOptions = "accel=kvm,kernel_irqchip,nvdimm" const defaultQemuMachineOptions = "accel=kvm,kernel_irqchip,nvdimm"
const qmpCapMigrationBypassSharedMemory = "bypass-shared-memory"
const qmpMigrationWaitTimeout = 5 * time.Second
var qemuPaths = map[string]string{ var qemuPaths = map[string]string{
QemuPCLite: "/usr/bin/qemu-lite-system-x86_64", QemuPCLite: "/usr/bin/qemu-lite-system-x86_64",
QemuPC: defaultQemuPath, QemuPC: defaultQemuPath,

View File

@ -6,6 +6,7 @@
package virtcontainers package virtcontainers
import ( import (
"context"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
@ -100,6 +101,9 @@ type qemuArch interface {
// supportGuestMemoryHotplug returns if the guest supports memory hotplug // supportGuestMemoryHotplug returns if the guest supports memory hotplug
supportGuestMemoryHotplug() bool supportGuestMemoryHotplug() bool
// setBypassSharedMemoryMigrationCaps set bypass-shared-memory capability for migration
setBypassSharedMemoryMigrationCaps(context.Context, *govmmQemu.QMP) error
} }
type qemuArchBase struct { type qemuArchBase struct {
@ -570,3 +574,13 @@ func (q *qemuArchBase) handleImagePath(config HypervisorConfig) {
func (q *qemuArchBase) supportGuestMemoryHotplug() bool { func (q *qemuArchBase) supportGuestMemoryHotplug() bool {
return true return true
} }
func (q *qemuArchBase) setBypassSharedMemoryMigrationCaps(ctx context.Context, qmp *govmmQemu.QMP) error {
err := qmp.ExecSetMigrationCaps(ctx, []map[string]interface{}{
{
"capability": qmpCapMigrationBypassSharedMemory,
"state": true,
},
})
return err
}

View File

@ -6,10 +6,12 @@
package virtcontainers package virtcontainers
import ( import (
"context"
"io/ioutil" "io/ioutil"
"os" "os"
"runtime" "runtime"
"strings" "strings"
"time"
govmmQemu "github.com/intel/govmm/qemu" govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
@ -25,6 +27,10 @@ const defaultQemuPath = "/usr/bin/qemu-system-aarch64"
const defaultQemuMachineType = QemuVirt const defaultQemuMachineType = QemuVirt
const qmpMigrationWaitTimeout = 10 * time.Second
const qmpCapMigrationBypassSharedMemory = "bypass-shared-memory"
var defaultQemuMachineOptions = "usb=off,accel=kvm,nvdimm,gic-version=" + getGuestGICVersion() var defaultQemuMachineOptions = "usb=off,accel=kvm,nvdimm,gic-version=" + getGuestGICVersion()
var qemuPaths = map[string]string{ var qemuPaths = map[string]string{
@ -189,3 +195,8 @@ func (q *qemuArm64) appendImage(devices []govmmQemu.Device, path string) ([]govm
return devices, nil return devices, nil
} }
func (q *qemuArm64) setBypassSharedMemoryMigrationCaps(_ context.Context, _ *govmmQemu.QMP) error {
// bypass-shared-memory not support in arm64 for now
return nil
}

View File

@ -8,6 +8,7 @@ package virtcontainers
import ( import (
"encoding/hex" "encoding/hex"
"os" "os"
"time"
govmmQemu "github.com/intel/govmm/qemu" govmmQemu "github.com/intel/govmm/qemu"
deviceConfig "github.com/kata-containers/runtime/virtcontainers/device/config" deviceConfig "github.com/kata-containers/runtime/virtcontainers/device/config"
@ -29,6 +30,10 @@ const defaultQemuMachineOptions = "accel=kvm,usb=off"
const defaultMemMaxPPC64le = 32256 // Restrict MemMax to 32Gb on PPC64le const defaultMemMaxPPC64le = 32256 // Restrict MemMax to 32Gb on PPC64le
const qmpCapMigrationBypassSharedMemory = "bypass-shared-memory"
const qmpMigrationWaitTimeout = 5 * time.Second
var qemuPaths = map[string]string{ var qemuPaths = map[string]string{
QemuPseries: defaultQemuPath, QemuPseries: defaultQemuPath,
} }

View File

@ -7,6 +7,7 @@ package virtcontainers
import ( import (
"fmt" "fmt"
"time"
govmmQemu "github.com/intel/govmm/qemu" govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
@ -25,6 +26,10 @@ const defaultQemuMachineOptions = "accel=kvm"
const virtioSerialCCW = "virtio-serial-ccw" const virtioSerialCCW = "virtio-serial-ccw"
const qmpCapMigrationBypassSharedMemory = "bypass-shared-memory"
const qmpMigrationWaitTimeout = 5 * time.Second
var qemuPaths = map[string]string{ var qemuPaths = map[string]string{
QemuCCWVirtio: defaultQemuPath, QemuCCWVirtio: defaultQemuPath,
} }