vendor: update govmm changes

To include vm factory related commits. Full list:
54caf78 (mine/templating, templating) qmp: add hotplug memory
e66a9b4 qemu: add appendMemoryKnobs helper
8aeca15 qmp: add migrate set arguments
a03d496 qmp: add set migration capabilities
0ace417 qemu: allow to set migration incoming
723bc5f qemu: allow to create a stopped guest
283d7df qemu: add file backed memory device support

Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
Peng Tao 2018-07-05 15:25:19 +08:00
parent 47dfb7d6da
commit 0f20b6b81b
6 changed files with 299 additions and 20 deletions

4
Gopkg.lock generated
View File

@ -91,7 +91,7 @@
[[projects]]
name = "github.com/intel/govmm"
packages = ["qemu"]
revision = "9cf8ce6c6dda19d4a6d529e73714e231f6156820"
revision = "ff2401825e0930811919c86c36d64b113aa00083"
[[projects]]
name = "github.com/kata-containers/agent"
@ -263,6 +263,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "a8e90901b945488c3b660e20c076fce3345dba96b4ec15e7ca00b8a06baa16a3"
inputs-digest = "4d57a771261fe6b0e1f86bf2de82f8c39cc0047170f4277754972e2feab4796f"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -56,7 +56,7 @@
[[constraint]]
name = "github.com/intel/govmm"
revision = "9cf8ce6c6dda19d4a6d529e73714e231f6156820"
revision = "ff2401825e0930811919c86c36d64b113aa00083"
[[constraint]]
name = "github.com/kata-containers/agent"

35
vendor/github.com/docker/go-units/duration.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
// Package units provides helper function to parse and print size and time units
// in human-readable format.
package units
import (
"fmt"
"time"
)
// HumanDuration returns a human-readable approximation of a duration
// (eg. "About a minute", "4 hours ago", etc.).
func HumanDuration(d time.Duration) string {
if seconds := int(d.Seconds()); seconds < 1 {
return "Less than a second"
} else if seconds == 1 {
return "1 second"
} else if seconds < 60 {
return fmt.Sprintf("%d seconds", seconds)
} else if minutes := int(d.Minutes()); minutes == 1 {
return "About a minute"
} else if minutes < 46 {
return fmt.Sprintf("%d minutes", minutes)
} else if hours := int(d.Hours() + 0.5); hours == 1 {
return "About an hour"
} else if hours < 48 {
return fmt.Sprintf("%d hours", hours)
} else if hours < 24*7*2 {
return fmt.Sprintf("%d days", hours/24)
} else if hours < 24*30*2 {
return fmt.Sprintf("%d weeks", hours/24/7)
} else if hours < 24*365*2 {
return fmt.Sprintf("%d months", hours/24/30)
}
return fmt.Sprintf("%d years", int(d.Hours())/24/365)
}

118
vendor/github.com/docker/go-units/ulimit.go generated vendored Normal file
View File

@ -0,0 +1,118 @@
package units
import (
"fmt"
"strconv"
"strings"
)
// Ulimit is a human friendly version of Rlimit.
type Ulimit struct {
Name string
Hard int64
Soft int64
}
// Rlimit specifies the resource limits, such as max open files.
type Rlimit struct {
Type int `json:"type,omitempty"`
Hard uint64 `json:"hard,omitempty"`
Soft uint64 `json:"soft,omitempty"`
}
const (
// magic numbers for making the syscall
// some of these are defined in the syscall package, but not all.
// Also since Windows client doesn't get access to the syscall package, need to
// define these here
rlimitAs = 9
rlimitCore = 4
rlimitCPU = 0
rlimitData = 2
rlimitFsize = 1
rlimitLocks = 10
rlimitMemlock = 8
rlimitMsgqueue = 12
rlimitNice = 13
rlimitNofile = 7
rlimitNproc = 6
rlimitRss = 5
rlimitRtprio = 14
rlimitRttime = 15
rlimitSigpending = 11
rlimitStack = 3
)
var ulimitNameMapping = map[string]int{
//"as": rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
"core": rlimitCore,
"cpu": rlimitCPU,
"data": rlimitData,
"fsize": rlimitFsize,
"locks": rlimitLocks,
"memlock": rlimitMemlock,
"msgqueue": rlimitMsgqueue,
"nice": rlimitNice,
"nofile": rlimitNofile,
"nproc": rlimitNproc,
"rss": rlimitRss,
"rtprio": rlimitRtprio,
"rttime": rlimitRttime,
"sigpending": rlimitSigpending,
"stack": rlimitStack,
}
// ParseUlimit parses and returns a Ulimit from the specified string.
func ParseUlimit(val string) (*Ulimit, error) {
parts := strings.SplitN(val, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid ulimit argument: %s", val)
}
if _, exists := ulimitNameMapping[parts[0]]; !exists {
return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
}
var (
soft int64
hard = &soft // default to soft in case no hard was set
temp int64
err error
)
switch limitVals := strings.Split(parts[1], ":"); len(limitVals) {
case 2:
temp, err = strconv.ParseInt(limitVals[1], 10, 64)
if err != nil {
return nil, err
}
hard = &temp
fallthrough
case 1:
soft, err = strconv.ParseInt(limitVals[0], 10, 64)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
}
if soft > *hard {
return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, *hard)
}
return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil
}
// GetRlimit returns the RLimit corresponding to Ulimit.
func (u *Ulimit) GetRlimit() (*Rlimit, error) {
t, exists := ulimitNameMapping[u.Name]
if !exists {
return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
}
return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
}
func (u *Ulimit) String() string {
return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
}

View File

@ -1126,6 +1126,10 @@ type Memory struct {
// MaxMem is the maximum amount of memory that can be made available
// to the guest through e.g. hot pluggable memory.
MaxMem string
// Path is the file path of the memory device. It points to a local
// file path used by FileBackedMem.
Path string
}
// Kernel is the guest kernel configuration structure.
@ -1167,10 +1171,20 @@ type Knobs struct {
// MemPrealloc will allocate all the RAM upfront
MemPrealloc bool
// FileBackedMem requires Memory.Size and Memory.Path of the VM to
// be set.
FileBackedMem bool
// FileBackedMemShared will set the FileBackedMem device as shared.
FileBackedMemShared bool
// Mlock will control locking of memory
// Only active when Realtime is set to true
Mlock bool
// Stopped will not start guest CPU at startup
Stopped bool
// Realtime will enable realtime QEMU
Realtime bool
}
@ -1180,6 +1194,24 @@ type IOThread struct {
ID string
}
const (
// MigrationFD is the migration incoming type based on open file descriptor.
// Skip default 0 so that it must be set on purpose.
MigrationFD = 1
// MigrationExec is the migration incoming type based on commands.
MigrationExec = 2
)
// Incoming controls migration source preparation
type Incoming struct {
// Possible values are MigrationFD, MigrationExec
MigrationType int
// Only valid if MigrationType == MigrationFD
FD *os.File
// Only valid if MigrationType == MigrationExec
Exec string
}
// Config is the qemu configuration structure.
// It allows for passing custom settings and parameters to the qemu API.
type Config struct {
@ -1231,6 +1263,9 @@ type Config struct {
// Bios is the -bios parameter
Bios string
// Incoming controls migration source preparation
Incoming Incoming
// fds is a list of open file descriptors to be passed to the spawned qemu process
fds []*os.File
@ -1433,23 +1468,7 @@ func (config *Config) appendKernel() {
}
}
func (config *Config) appendKnobs() {
if config.Knobs.NoUserConfig == true {
config.qemuParams = append(config.qemuParams, "-no-user-config")
}
if config.Knobs.NoDefaults == true {
config.qemuParams = append(config.qemuParams, "-nodefaults")
}
if config.Knobs.NoGraphic == true {
config.qemuParams = append(config.qemuParams, "-nographic")
}
if config.Knobs.Daemonize == true {
config.qemuParams = append(config.qemuParams, "-daemonize")
}
func (config *Config) appendMemoryKnobs() {
if config.Knobs.HugePages == true {
if config.Memory.Size != "" {
dimmName := "dimm1"
@ -1474,7 +1493,42 @@ func (config *Config) appendKnobs() {
config.qemuParams = append(config.qemuParams, "-device")
config.qemuParams = append(config.qemuParams, deviceMemParam)
}
} else if config.Knobs.FileBackedMem == true {
if config.Memory.Size != "" && config.Memory.Path != "" {
dimmName := "dimm1"
objMemParam := "memory-backend-file,id=" + dimmName + ",size=" + config.Memory.Size + ",mem-path=" + config.Memory.Path
if config.Knobs.FileBackedMemShared == true {
objMemParam += ",share=on"
}
numaMemParam := "node,memdev=" + dimmName
config.qemuParams = append(config.qemuParams, "-object")
config.qemuParams = append(config.qemuParams, objMemParam)
config.qemuParams = append(config.qemuParams, "-numa")
config.qemuParams = append(config.qemuParams, numaMemParam)
}
}
}
func (config *Config) appendKnobs() {
if config.Knobs.NoUserConfig == true {
config.qemuParams = append(config.qemuParams, "-no-user-config")
}
if config.Knobs.NoDefaults == true {
config.qemuParams = append(config.qemuParams, "-nodefaults")
}
if config.Knobs.NoGraphic == true {
config.qemuParams = append(config.qemuParams, "-nographic")
}
if config.Knobs.Daemonize == true {
config.qemuParams = append(config.qemuParams, "-daemonize")
}
config.appendMemoryKnobs()
if config.Knobs.Realtime == true {
config.qemuParams = append(config.qemuParams, "-realtime")
@ -1495,6 +1549,10 @@ func (config *Config) appendKnobs() {
config.qemuParams = append(config.qemuParams, "mlock=off")
}
}
if config.Knobs.Stopped == true {
config.qemuParams = append(config.qemuParams, "-S")
}
}
func (config *Config) appendBios() {
@ -1513,6 +1571,20 @@ func (config *Config) appendIOThreads() {
}
}
func (config *Config) appendIncoming() {
var uri string
switch config.Incoming.MigrationType {
case MigrationExec:
uri = fmt.Sprintf("exec:%s", config.Incoming.Exec)
case MigrationFD:
chFDs := config.appendFDs([]*os.File{config.Incoming.FD})
uri = fmt.Sprintf("fd:%d", chFDs[0])
default:
return
}
config.qemuParams = append(config.qemuParams, "-S", "-incoming", uri)
}
// LaunchQemu can be used to launch a new qemu instance.
//
// The Config parameter contains a set of qemu parameters and settings.
@ -1537,6 +1609,7 @@ func LaunchQemu(config Config, logger QMPLog) (string, error) {
config.appendKernel()
config.appendBios()
config.appendIOThreads()
config.appendIncoming()
if err := config.appendCPUs(); err != nil {
return "", err

View File

@ -828,3 +828,56 @@ func (q *QMP) ExecuteQueryHotpluggableCPUs(ctx context.Context) ([]HotpluggableC
return cpus, nil
}
// ExecSetMigrationCaps sets migration capabilities
func (q *QMP) ExecSetMigrationCaps(ctx context.Context, caps []map[string]interface{}) error {
args := map[string]interface{}{
"capabilities": caps,
}
return q.executeCommand(ctx, "migrate-set-capabilities", args, nil)
}
// ExecSetMigrateArguments sets the command line used for migration
func (q *QMP) ExecSetMigrateArguments(ctx context.Context, url string) error {
args := map[string]interface{}{
"uri": url,
}
return q.executeCommand(ctx, "migrate", args, nil)
}
// ExecHotplugMemory adds size of MiB memory to the guest
func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string, size int) error {
args := map[string]interface{}{
"qom-type": qomtype,
"id": id,
"props": map[string]interface{}{"size": uint64(size) << 20},
}
if mempath != "" {
args["mem-path"] = mempath
}
err := q.executeCommand(ctx, "object-add", args, nil)
if err != nil {
return err
}
defer func() {
if err != nil {
q.cfg.Logger.Errorf("Unable to hotplug memory device: %v", err)
err = q.executeCommand(ctx, "object-del", map[string]interface{}{"id": id}, nil)
if err != nil {
q.cfg.Logger.Warningf("Unable to clean up memory object: %v", err)
}
}
}()
args = map[string]interface{}{
"driver": "pc-dimm",
"id": "dimm" + id,
"memdev": id,
}
err = q.executeCommand(ctx, "device_add", args, nil)
return err
}