Merge pull request #352 from bergwolf/runtime-port-1

port runtime commits -- wave 1
This commit is contained in:
Hui Zhu
2020-06-29 16:33:02 +08:00
committed by GitHub
10 changed files with 92 additions and 145 deletions

View File

@@ -55,6 +55,7 @@ default_vcpus = 1
# `default_maxvcpus = 8` the memory footprint will be small, but 8 will be the maximum number of
# vCPUs supported by the SB/VM. In general, we recommend that you do not edit this variable,
# unless you know what are you doing.
# NOTICE: on arm platform with gicv2 interrupt controller, set it to 8.
default_maxvcpus = @DEFMAXVCPUS@
# Bridges can be used to hot plug devices.

View File

@@ -58,6 +58,7 @@ default_vcpus = 1
# `default_maxvcpus = 8` the memory footprint will be small, but 8 will be the maximum number of
# vCPUs supported by the SB/VM. In general, we recommend that you do not edit this variable,
# unless you know what are you doing.
# NOTICE: on arm platform with gicv2 interrupt controller, set it to 8.
default_maxvcpus = @DEFMAXVCPUS@
# Bridges can be used to hot plug devices.

View File

@@ -59,6 +59,7 @@ default_vcpus = 1
# `default_maxvcpus = 8` the memory footprint will be small, but 8 will be the maximum number of
# vCPUs supported by the SB/VM. In general, we recommend that you do not edit this variable,
# unless you know what are you doing.
# NOTICE: on arm platform with gicv2 interrupt controller, set it to 8.
default_maxvcpus = @DEFMAXVCPUS@
# Bridges can be used to hot plug devices.

View File

@@ -150,6 +150,18 @@ var clhDebugKernelParams = []Param{
//
//###########################################################
func (clh *cloudHypervisor) checkVersion() error {
if clh.version.Major < supportedMajorVersion || (clh.version.Major == supportedMajorVersion && clh.version.Minor < supportedMinorVersion) {
errorMessage := fmt.Sprintf("Unsupported version: cloud-hypervisor %d.%d not supported by this driver version (%d.%d)",
clh.version.Major,
clh.version.Minor,
supportedMajorVersion,
supportedMinorVersion)
return errors.New(errorMessage)
}
return nil
}
// For cloudHypervisor this call only sets the internal structure up.
// The VM will be created and started through startSandbox().
func (clh *cloudHypervisor) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, stateful bool) error {
@@ -180,13 +192,8 @@ func (clh *cloudHypervisor) createSandbox(ctx context.Context, id string, networ
}
if clh.version.Major < supportedMajorVersion && clh.version.Minor < supportedMinorVersion {
errorMessage := fmt.Sprintf("Unsupported version: cloud-hypervisor %d.%d not supported by this driver version (%d.%d)",
clh.version.Major,
clh.version.Minor,
supportedMajorVersion,
supportedMinorVersion)
return errors.New(errorMessage)
if err := clh.checkVersion(); err != nil {
return err
}
}

View File

@@ -7,6 +7,7 @@ package virtcontainers
import (
"context"
"fmt"
"net/http"
"os"
"path/filepath"
@@ -312,3 +313,47 @@ func TestCloudHypervisorResizeMemory(t *testing.T) {
})
}
}
func TestCheckVersion(t *testing.T) {
clh := &cloudHypervisor{}
assert := assert.New(t)
testcases := []struct {
name string
major int
minor int
pass bool
}{
{
name: "minor lower than supported version",
major: supportedMajorVersion,
minor: 2,
pass: false,
},
{
name: "minor equal to supported version",
major: supportedMajorVersion,
minor: supportedMinorVersion,
pass: true,
},
{
name: "major exceeding supported version",
major: 1,
minor: supportedMinorVersion,
pass: true,
},
}
for _, tc := range testcases {
clh.version = CloudHypervisorVersion{
Major: tc.major,
Minor: tc.minor,
Revision: 0,
}
err := clh.checkVersion()
msg := fmt.Sprintf("test: %+v, clh.version: %v, result: %v", tc, clh.version, err)
if tc.pass {
assert.NoError(err, msg)
} else {
assert.Error(err, msg)
}
}
}

View File

@@ -8,13 +8,9 @@ package virtcontainers
import (
"context"
"fmt"
"io/ioutil"
"runtime"
"strings"
"time"
govmmQemu "github.com/intel/govmm/qemu"
"github.com/sirupsen/logrus"
)
type qemuArm64 struct {
@@ -28,7 +24,9 @@ const defaultQemuMachineType = QemuVirt
const qmpMigrationWaitTimeout = 10 * time.Second
var defaultQemuMachineOptions = "usb=off,accel=kvm,gic-version=" + getGuestGICVersion()
const defaultQemuMachineOptions = "usb=off,accel=kvm,gic-version=host"
var defaultGICVersion = uint32(3)
var kernelParams = []Param{
{"console", "hvc0"},
@@ -36,70 +34,11 @@ var kernelParams = []Param{
{"iommu.passthrough", "0"},
}
var supportedQemuMachine = govmmQemu.Machine {
var supportedQemuMachine = govmmQemu.Machine{
Type: QemuVirt,
Options: defaultQemuMachineOptions,
}
// Logger returns a logrus logger appropriate for logging qemu-aarch64 messages
func qemuArmLogger() *logrus.Entry {
return virtLog.WithField("subsystem", "qemu-aarch64")
}
// On ARM platform, we have different GIC interrupt controllers. Different
// GIC supports different QEMU parameters for virtual GIC and max VCPUs
var hostGICVersion = getHostGICVersion()
// We will access this file on host to detect host GIC version
var gicProfile = "/proc/interrupts"
// Detect the host GIC version.
// Success: return the number of GIC version
// Failed: return 0
func getHostGICVersion() (version uint32) {
bytes, err := ioutil.ReadFile(gicProfile)
if err != nil {
qemuArmLogger().WithField("GIC profile", gicProfile).WithError(err).Error("Failed to parse GIC profile")
return 0
}
s := string(bytes)
if strings.Contains(s, "GICv2") {
return 2
}
if strings.Contains(s, "GICv3") {
return 3
}
if strings.Contains(s, "GICv4") {
return 4
}
return 0
}
// QEMU supports GICv2, GICv3 and host parameters for gic-version. The host
// parameter will let QEMU detect GIC version by itself. This parameter
// will work properly when host GIC version is GICv2 or GICv3. But the
// detection will failed when host GIC is gicv4 or higher. In this case,
// we have to detect the host GIC version manually and force QEMU to use
// GICv3 when host GIC is GICv4 or higher.
func getGuestGICVersion() (version string) {
if hostGICVersion == 2 {
return "2"
}
if hostGICVersion >= 3 {
return "3"
}
// We can't parse valid host GIC version from GIC profile.
// But we can use "host" to ask QEMU to detect valid GIC
// through KVM API for a try.
return "host"
}
//In qemu, maximum number of vCPUs depends on the GIC version, or on how
//many redistributors we can fit into the memory map.
//related codes are under github.com/qemu/qemu/hw/arm/virt.c(Line 135 and 1306 in stable-2.11)
@@ -113,10 +52,7 @@ var gicList = map[uint32]uint32{
// MaxQemuVCPUs returns the maximum number of vCPUs supported
func MaxQemuVCPUs() uint32 {
if hostGICVersion != 0 {
return gicList[hostGICVersion]
}
return uint32(runtime.NumCPU())
return gicList[defaultGICVersion]
}
func newQemuArch(config HypervisorConfig) (qemuArch, error) {
@@ -131,13 +67,14 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) {
q := &qemuArm64{
qemuArchBase{
qemuMachine: supportedQemuMachine,
qemuExePath: defaultQemuPath,
memoryOffset: config.MemOffset,
kernelParamsNonDebug: kernelParamsNonDebug,
kernelParamsDebug: kernelParamsDebug,
kernelParams: kernelParams,
disableNvdimm: config.DisableImageNvdimm,
qemuMachine: supportedQemuMachine,
qemuExePath: defaultQemuPath,
memoryOffset: config.MemOffset,
kernelParamsNonDebug: kernelParamsNonDebug,
kernelParamsDebug: kernelParamsDebug,
kernelParams: kernelParams,
disableNvdimm: config.DisableImageNvdimm,
dax: true,
},
}

View File

@@ -9,8 +9,6 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
govmmQemu "github.com/intel/govmm/qemu"
@@ -59,50 +57,8 @@ func TestQemuArm64MemoryTopology(t *testing.T) {
func TestMaxQemuVCPUs(t *testing.T) {
assert := assert.New(t)
type testData struct {
contents string
expectedResult uint32
}
data := []testData{
{"", uint32(runtime.NumCPU())},
{" 1: 0 0 GICv2 25 Level vgic \n", uint32(8)},
{" 1: 0 0 GICv3 25 Level vgic \n", uint32(123)},
{" 1: 0 0 GICv4 25 Level vgic \n", uint32(123)},
}
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
savedGicProfile := gicProfile
testGicProfile := filepath.Join(tmpdir, "interrupts")
// override
gicProfile = testGicProfile
defer func() {
gicProfile = savedGicProfile
}()
savedHostGICVersion := hostGICVersion
defer func() {
hostGICVersion = savedHostGICVersion
}()
for _, d := range data {
err := ioutil.WriteFile(gicProfile, []byte(d.contents), os.FileMode(0640))
assert.NoError(err)
hostGICVersion = getHostGICVersion()
vCPUs := MaxQemuVCPUs()
assert.Equal(d.expectedResult, vCPUs)
}
vCPUs := MaxQemuVCPUs()
assert.Equal(uint32(123), vCPUs)
}
func TestQemuArm64AppendBridges(t *testing.T) {

View File

@@ -11,6 +11,12 @@ build:
clean:
cargo clean
test:
check:
.PHONY: \
build \
test \
check \
clean

View File

@@ -11,6 +11,12 @@ build:
clean:
cargo clean
test:
check:
.PHONY: \
build \
test \
check \
clean

View File

@@ -216,19 +216,6 @@ externals:
meta:
swarm-version: "1.12.1"
gometalinter:
description: "utility to run various golang linters"
url: "https://github.com/alecthomas/gometalinter"
uscan-url: >-
https://github.com/alecthomas/gometalinter/tags
.*/v?([\d\.]+)\.tar\.gz
version: "v2.0.5"
golangci-lint:
description: "utility to run various golang linters"
url: "https://install.goreleaser.com/github.com/golangci/golangci-lint.sh"
version: "v1.15.0"
kubernetes:
description: "Kubernetes project container manager"
url: "https://github.com/kubernetes/kubernetes"
@@ -275,7 +262,7 @@ externals:
musl:
description: |
musl is used to build rust agent.
The musl library is used to build the rust agent.
url: "https://www.musl-libc.org/"
uscan-url: >-
https://www.musl-libc.org/releases/
@@ -288,7 +275,7 @@ externals:
languages:
description: |
Details of programming languages requried to build system
Details of programming languages required to build system
components.
golang:
@@ -305,7 +292,7 @@ languages:
newest-version: "1.14.4"
rust:
description: "rust language"
description: "Rust language"
notes: "'version' is the default minimum version used by this project."
version: "1.38.0"
meta: