mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-01 07:47:15 +00:00
Merge pull request #1186 from nitkon/Hotplug
ppc64le: Fix hotplug issue
This commit is contained in:
commit
530360d515
8
Gopkg.lock
generated
8
Gopkg.lock
generated
@ -204,10 +204,9 @@
|
||||
version = "v0.3.3"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:58b18038f51b6f79865fd00e3d883949c9507ede577cd9c4e743ed56cc454122"
|
||||
digest = "1:351337e3b022de09e72306f1f9711314cc4bd407c15e8d328e218c655fd55731"
|
||||
name = "github.com/firecracker-microvm/firecracker-go-sdk"
|
||||
packages = [
|
||||
".",
|
||||
"client",
|
||||
"client/models",
|
||||
"client/operations",
|
||||
@ -377,11 +376,11 @@
|
||||
revision = "3520598351bb3500a49ae9563f5539666ae0a27c"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:15f0da05538e2445b354c620555231448849b7ece222c45578668d0dfd6bec93"
|
||||
digest = "1:270961b1d5e664d4939ffae00b990e256d92bb5039cae69208211a84c72fe5f5"
|
||||
name = "github.com/intel/govmm"
|
||||
packages = ["qemu"]
|
||||
pruneopts = "NUT"
|
||||
revision = "737f03de595e216116264cc74a58e5f2a1df789a"
|
||||
revision = "78d079db6d1f3e32e3ed7578a54baa6257b058a7"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:590bfb6f8d5741fa38bb3022f55588fb7e06389f6b7b6692a965e0e5a4363fb1"
|
||||
@ -701,7 +700,6 @@
|
||||
"github.com/containernetworking/plugins/pkg/ns",
|
||||
"github.com/dlespiau/covertool/pkg/cover",
|
||||
"github.com/docker/go-units",
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk",
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk/client",
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk/client/models",
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk/client/operations",
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/intel/govmm"
|
||||
revision = "737f03de595e216116264cc74a58e5f2a1df789a"
|
||||
revision = "78d079db6d1f3e32e3ed7578a54baa6257b058a7"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kata-containers/agent"
|
||||
|
155
vendor/github.com/firecracker-microvm/firecracker-go-sdk/command_builder.go
generated
vendored
155
vendor/github.com/firecracker-microvm/firecracker-go-sdk/command_builder.go
generated
vendored
@ -1,155 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var defaultFirecrackerVMMCommandBuilder = VMCommandBuilder{}.
|
||||
WithBin("firecracker").
|
||||
WithStdin(os.Stdin).
|
||||
WithStdout(os.Stdout).
|
||||
WithStderr(os.Stderr)
|
||||
|
||||
// VMCommandBuilder is a utility for building an exec.Cmd that represents how to
|
||||
// start the Firecracker VMM.
|
||||
type VMCommandBuilder struct {
|
||||
bin string
|
||||
args []string
|
||||
socketPath string
|
||||
stdin io.Reader
|
||||
stdout io.Writer
|
||||
stderr io.Writer
|
||||
}
|
||||
|
||||
// Args returns all args that will be passed to exec.Command
|
||||
func (b VMCommandBuilder) Args() []string {
|
||||
return b.args
|
||||
}
|
||||
|
||||
// WithArgs specifies which arguments to pass through to the
|
||||
// firecracker exec.Command
|
||||
func (b VMCommandBuilder) WithArgs(args []string) VMCommandBuilder {
|
||||
b.args = args
|
||||
return b
|
||||
}
|
||||
|
||||
// AddArgs will append the provided args to the given command
|
||||
func (b VMCommandBuilder) AddArgs(args ...string) VMCommandBuilder {
|
||||
b.args = append(b.args, args...)
|
||||
return b
|
||||
}
|
||||
|
||||
// Bin return the bin that was set
|
||||
func (b VMCommandBuilder) Bin() string {
|
||||
return b.bin
|
||||
}
|
||||
|
||||
// WithBin specifies which binary for firecracker to use
|
||||
func (b VMCommandBuilder) WithBin(bin string) VMCommandBuilder {
|
||||
b.bin = bin
|
||||
return b
|
||||
}
|
||||
|
||||
// SocketPath returns the specified socket path
|
||||
func (b VMCommandBuilder) SocketPath() []string {
|
||||
if len(b.socketPath) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return []string{
|
||||
"--api-sock",
|
||||
b.socketPath,
|
||||
}
|
||||
}
|
||||
|
||||
// WithSocketPath specifies the socket path to be used when
|
||||
// creating the firecracker exec.Command
|
||||
func (b VMCommandBuilder) WithSocketPath(path string) VMCommandBuilder {
|
||||
b.socketPath = path
|
||||
return b
|
||||
}
|
||||
|
||||
// Stdout will return the stdout that will be used when creating
|
||||
// the firecracker exec.Command
|
||||
func (b VMCommandBuilder) Stdout() io.Writer {
|
||||
return b.stdout
|
||||
}
|
||||
|
||||
// WithStdout specifies which io.Writer to use in place of the
|
||||
// os.Stdout in the firecracker exec.Command.
|
||||
func (b VMCommandBuilder) WithStdout(stdout io.Writer) VMCommandBuilder {
|
||||
b.stdout = stdout
|
||||
return b
|
||||
}
|
||||
|
||||
// Stderr will return the stderr that will be used when creating
|
||||
// the firecracker exec.Command
|
||||
func (b VMCommandBuilder) Stderr() io.Writer {
|
||||
return b.stderr
|
||||
}
|
||||
|
||||
// WithStderr specifies which io.Writer to use in place of the
|
||||
// os.Stderr in the firecracker exec.Command.
|
||||
func (b VMCommandBuilder) WithStderr(stderr io.Writer) VMCommandBuilder {
|
||||
b.stderr = stderr
|
||||
return b
|
||||
}
|
||||
|
||||
// Stdin will return the stdin that will be used when creating
|
||||
// the firecracker exec.Command
|
||||
func (b VMCommandBuilder) Stdin() io.Reader {
|
||||
return b.stdin
|
||||
}
|
||||
|
||||
// WithStdin specifies which io.Reader to use in place of the
|
||||
// os.Stdin in the firecracker exec.Command.
|
||||
func (b VMCommandBuilder) WithStdin(stdin io.Reader) VMCommandBuilder {
|
||||
b.stdin = stdin
|
||||
return b
|
||||
}
|
||||
|
||||
// Build will build a firecracker command using the specific arguments
|
||||
// specified in the builder.
|
||||
func (b VMCommandBuilder) Build(ctx context.Context) *exec.Cmd {
|
||||
args := []string{}
|
||||
if socketPath := b.SocketPath(); socketPath != nil {
|
||||
args = append(args, socketPath...)
|
||||
}
|
||||
if v := b.Args(); v != nil {
|
||||
args = append(args, v...)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(
|
||||
ctx,
|
||||
b.Bin(),
|
||||
args...,
|
||||
)
|
||||
|
||||
if stdout := b.Stdout(); stdout != nil {
|
||||
cmd.Stdout = stdout
|
||||
}
|
||||
if stderr := b.Stderr(); stderr != nil {
|
||||
cmd.Stderr = stderr
|
||||
}
|
||||
if stdin := b.Stdin(); stdin != nil {
|
||||
cmd.Stdin = stdin
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
29
vendor/github.com/firecracker-microvm/firecracker-go-sdk/doc.go
generated
vendored
29
vendor/github.com/firecracker-microvm/firecracker-go-sdk/doc.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
/*
|
||||
Package firecracker provides a library to interact with the Firecracker API.
|
||||
|
||||
Firecracker is an open-source virtualization technology that is purpose-built
|
||||
for creating and managing secure, multi-tenant containers and functions-based
|
||||
services. See https://firecracker-microvm.github.io/ for more details.
|
||||
|
||||
This library requires Go 1.11 and can be used with Go modules.
|
||||
|
||||
BUG(aws): There are some Firecracker features that are not yet supported by the
|
||||
SDK. These are tracked as GitHub issues with the firecracker-feature label:
|
||||
https://github.com/firecracker-microvm/firecracker-go-sdk/issues?q=is%3Aissue+is%3Aopen+label%3Afirecracker-feature
|
||||
|
||||
This library is licensed under the Apache 2.0 License.
|
||||
*/
|
||||
package firecracker
|
65
vendor/github.com/firecracker-microvm/firecracker-go-sdk/drives.go
generated
vendored
65
vendor/github.com/firecracker-microvm/firecracker-go-sdk/drives.go
generated
vendored
@ -1,65 +0,0 @@
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
|
||||
)
|
||||
|
||||
const rootDriveName = "root-drive"
|
||||
|
||||
// DrivesBuilder is a builder that will build an array of drives used to set up
|
||||
// the firecracker microVM. The DriveID will be an incrementing number starting
|
||||
// at one
|
||||
type DrivesBuilder struct {
|
||||
rootDrive models.Drive
|
||||
drives []models.Drive
|
||||
}
|
||||
|
||||
// NewDrivesBuilder will return a new DrivesBuilder with a given rootfs.
|
||||
func NewDrivesBuilder(rootDrivePath string) DrivesBuilder {
|
||||
return DrivesBuilder{}.WithRootDrive(rootDrivePath)
|
||||
}
|
||||
|
||||
// DriveOpt represents an optional function used to allow for specific
|
||||
// customization of the models.Drive structure.
|
||||
type DriveOpt func(*models.Drive)
|
||||
|
||||
// WithRootDrive will set the given builder with the a new root path. The root
|
||||
// drive will be set to read and write by default.
|
||||
func (b DrivesBuilder) WithRootDrive(rootDrivePath string, opts ...DriveOpt) DrivesBuilder {
|
||||
b.rootDrive = models.Drive{
|
||||
DriveID: String(rootDriveName),
|
||||
PathOnHost: &rootDrivePath,
|
||||
IsRootDevice: Bool(true),
|
||||
IsReadOnly: Bool(false),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&b.rootDrive)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// AddDrive will add a new drive to the given builder.
|
||||
func (b DrivesBuilder) AddDrive(path string, readOnly bool, opts ...DriveOpt) DrivesBuilder {
|
||||
drive := models.Drive{
|
||||
DriveID: String(strconv.Itoa(len(b.drives))),
|
||||
PathOnHost: &path,
|
||||
IsRootDevice: Bool(false),
|
||||
IsReadOnly: &readOnly,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&drive)
|
||||
}
|
||||
|
||||
b.drives = append(b.drives, drive)
|
||||
return b
|
||||
}
|
||||
|
||||
// Build will construct an array of drives with the root drive at the very end.
|
||||
func (b DrivesBuilder) Build() []models.Drive {
|
||||
return append(b.drives, b.rootDrive)
|
||||
}
|
150
vendor/github.com/firecracker-microvm/firecracker-go-sdk/firecracker.go
generated
vendored
150
vendor/github.com/firecracker-microvm/firecracker-go-sdk/firecracker.go
generated
vendored
@ -1,150 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk/client"
|
||||
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
|
||||
ops "github.com/firecracker-microvm/firecracker-go-sdk/client/operations"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
)
|
||||
|
||||
const firecrackerRequestTimeout = 500 * time.Millisecond
|
||||
|
||||
// FirecrackerClient is a client for interacting with the Firecracker API
|
||||
type FirecrackerClient struct {
|
||||
client *client.Firecracker
|
||||
}
|
||||
|
||||
// NewFirecrackerClient creates a FirecrackerClient
|
||||
func NewFirecrackerClient(socketPath string, logger *logrus.Entry, debug bool) *FirecrackerClient {
|
||||
httpClient := client.NewHTTPClient(strfmt.NewFormats())
|
||||
|
||||
socketTransport := &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, path string) (net.Conn, error) {
|
||||
addr, err := net.ResolveUnixAddr("unix", socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return net.DialUnix("unix", nil, addr)
|
||||
},
|
||||
}
|
||||
|
||||
transport := httptransport.New(client.DefaultHost, client.DefaultBasePath, client.DefaultSchemes)
|
||||
transport.Transport = socketTransport
|
||||
|
||||
if debug {
|
||||
transport.SetDebug(debug)
|
||||
}
|
||||
|
||||
if logger != nil {
|
||||
transport.SetLogger(logger)
|
||||
}
|
||||
|
||||
httpClient.SetTransport(transport)
|
||||
|
||||
return &FirecrackerClient{client: httpClient}
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutLogger(ctx context.Context, logger *models.Logger) (*ops.PutLoggerNoContent, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, firecrackerRequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
loggerParams := ops.NewPutLoggerParamsWithContext(timeout)
|
||||
loggerParams.SetBody(logger)
|
||||
|
||||
return f.client.Operations.PutLogger(loggerParams)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutMachineConfiguration(ctx context.Context, cfg *models.MachineConfiguration) (*ops.PutMachineConfigurationNoContent, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, firecrackerRequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
mc := ops.NewPutMachineConfigurationParamsWithContext(timeout)
|
||||
mc.SetBody(cfg)
|
||||
|
||||
return f.client.Operations.PutMachineConfiguration(mc)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutGuestBootSource(ctx context.Context, source *models.BootSource) (*ops.PutGuestBootSourceNoContent, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, firecrackerRequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
bootSource := ops.NewPutGuestBootSourceParamsWithContext(timeout)
|
||||
bootSource.SetBody(source)
|
||||
|
||||
return f.client.Operations.PutGuestBootSource(bootSource)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutGuestNetworkInterfaceByID(ctx context.Context, ifaceID string, ifaceCfg *models.NetworkInterface) (*ops.PutGuestNetworkInterfaceByIDNoContent, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, firecrackerRequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
cfg := ops.NewPutGuestNetworkInterfaceByIDParamsWithContext(timeout)
|
||||
cfg.SetBody(ifaceCfg)
|
||||
cfg.SetIfaceID(ifaceID)
|
||||
|
||||
return f.client.Operations.PutGuestNetworkInterfaceByID(cfg)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutGuestDriveByID(ctx context.Context, driveID string, drive *models.Drive) (*ops.PutGuestDriveByIDNoContent, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, 250*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
params := ops.NewPutGuestDriveByIDParamsWithContext(timeout)
|
||||
params.SetDriveID(driveID)
|
||||
params.SetBody(drive)
|
||||
|
||||
return f.client.Operations.PutGuestDriveByID(params)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutGuestVsockByID(ctx context.Context, vsockID string, vsock *models.Vsock) (*ops.PutGuestVsockByIDCreated, *ops.PutGuestVsockByIDNoContent, error) {
|
||||
params := ops.NewPutGuestVsockByIDParams()
|
||||
params.SetContext(ctx)
|
||||
params.SetID(vsockID)
|
||||
params.SetBody(vsock)
|
||||
return f.client.Operations.PutGuestVsockByID(params)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) CreateSyncAction(ctx context.Context, info *models.InstanceActionInfo) (*ops.CreateSyncActionNoContent, error) {
|
||||
params := ops.NewCreateSyncActionParams()
|
||||
params.SetContext(ctx)
|
||||
params.SetInfo(info)
|
||||
|
||||
return f.client.Operations.CreateSyncAction(params)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsNoContent, error) {
|
||||
params := ops.NewPutMmdsParams()
|
||||
params.SetContext(ctx)
|
||||
params.SetBody(metadata)
|
||||
|
||||
return f.client.Operations.PutMmds(params)
|
||||
}
|
||||
|
||||
func (f *FirecrackerClient) GetMachineConfig() (*ops.GetMachineConfigOK, error) {
|
||||
p := ops.NewGetMachineConfigParams()
|
||||
p.SetTimeout(firecrackerRequestTimeout)
|
||||
|
||||
return f.client.Operations.GetMachineConfig(p)
|
||||
}
|
237
vendor/github.com/firecracker-microvm/firecracker-go-sdk/handlers.go
generated
vendored
237
vendor/github.com/firecracker-microvm/firecracker-go-sdk/handlers.go
generated
vendored
@ -1,237 +0,0 @@
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Handler name constants
|
||||
const (
|
||||
StartVMMHandlerName = "fcinit.StartVMM"
|
||||
BootstrapLoggingHandlerName = "fcinit.BootstrapLogging"
|
||||
CreateMachineHandlerName = "fcinit.CreateMachine"
|
||||
CreateBootSourceHandlerName = "fcinit.CreateBootSource"
|
||||
AttachDrivesHandlerName = "fcinit.AttachDrives"
|
||||
CreateNetworkInterfacesHandlerName = "fcinit.CreateNetworkInterfaces"
|
||||
AddVsocksHandlerName = "fcinit.AddVsocks"
|
||||
SetMetadataHandlerName = "fcinit.SetMetadata"
|
||||
|
||||
ValidateCfgHandlerName = "validate.Cfg"
|
||||
)
|
||||
|
||||
// StartVMMHandler is a named handler that will handle starting of the VMM.
|
||||
// This handler will also set the exit channel on completion.
|
||||
var StartVMMHandler = Handler{
|
||||
Name: StartVMMHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.startVMM(ctx)
|
||||
},
|
||||
}
|
||||
|
||||
// BootstrapLoggingHandler is a named handler that will set up fifo logging of
|
||||
// firecracker process.
|
||||
var BootstrapLoggingHandler = Handler{
|
||||
Name: BootstrapLoggingHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
if err := m.setupLogging(ctx); err != nil {
|
||||
m.logger.Warnf("setupLogging() returned %s. Continuing anyway.", err)
|
||||
} else {
|
||||
m.logger.Debugf("setup logging: success")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// CreateMachineHandler is a named handler that will "create" the machine and
|
||||
// upload any necessary configuration to the firecracker process.
|
||||
var CreateMachineHandler = Handler{
|
||||
Name: CreateMachineHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.createMachine(ctx)
|
||||
},
|
||||
}
|
||||
|
||||
// CreateBootSourceHandler is a named handler that will set up the booting
|
||||
// process of the firecracker process.
|
||||
var CreateBootSourceHandler = Handler{
|
||||
Name: CreateBootSourceHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.createBootSource(ctx, m.cfg.KernelImagePath, m.cfg.KernelArgs)
|
||||
},
|
||||
}
|
||||
|
||||
// AttachDrivesHandler is a named handler that will attach all drives for the
|
||||
// firecracker process.
|
||||
var AttachDrivesHandler = Handler{
|
||||
Name: AttachDrivesHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.attachDrives(ctx, m.cfg.Drives...)
|
||||
},
|
||||
}
|
||||
|
||||
// CreateNetworkInterfacesHandler is a named handler that sets up network
|
||||
// interfaces to the firecracker process.
|
||||
var CreateNetworkInterfacesHandler = Handler{
|
||||
Name: CreateNetworkInterfacesHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.createNetworkInterfaces(ctx, m.cfg.NetworkInterfaces...)
|
||||
},
|
||||
}
|
||||
|
||||
// AddVsocksHandler is a named handler that adds vsocks to the firecracker
|
||||
// process.
|
||||
var AddVsocksHandler = Handler{
|
||||
Name: AddVsocksHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.addVsocks(ctx, m.cfg.VsockDevices...)
|
||||
},
|
||||
}
|
||||
|
||||
// NewSetMetadataHandler is a named handler that puts the metadata into the
|
||||
// firecracker process.
|
||||
func NewSetMetadataHandler(metadata interface{}) Handler {
|
||||
return Handler{
|
||||
Name: SetMetadataHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
return m.SetMetadata(ctx, m.Metadata)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var defaultValidationHandlerList = HandlerList{}.Append(
|
||||
Handler{
|
||||
Name: ValidateCfgHandlerName,
|
||||
Fn: func(ctx context.Context, m *Machine) error {
|
||||
// ensure that the configuration is valid for the
|
||||
// FcInit handlers.
|
||||
return m.cfg.Validate()
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
var defaultFcInitHandlerList = HandlerList{}.Append(
|
||||
StartVMMHandler,
|
||||
BootstrapLoggingHandler,
|
||||
CreateMachineHandler,
|
||||
CreateBootSourceHandler,
|
||||
AttachDrivesHandler,
|
||||
CreateNetworkInterfacesHandler,
|
||||
AddVsocksHandler,
|
||||
)
|
||||
|
||||
var defaultHandlers = Handlers{
|
||||
Validation: defaultValidationHandlerList,
|
||||
FcInit: defaultFcInitHandlerList,
|
||||
}
|
||||
|
||||
// Handler represents a named handler that contains a name and a function which
|
||||
// is used to execute during the initialization process of a machine.
|
||||
type Handler struct {
|
||||
Name string
|
||||
Fn func(context.Context, *Machine) error
|
||||
}
|
||||
|
||||
// Handlers is a container that houses categories of handler lists.
|
||||
type Handlers struct {
|
||||
Validation HandlerList
|
||||
FcInit HandlerList
|
||||
}
|
||||
|
||||
// Run will execute all handlers in the Handlers object by flattening the lists
|
||||
// into a single list and running.
|
||||
func (h Handlers) Run(ctx context.Context, m *Machine) error {
|
||||
l := HandlerList{}.Append(
|
||||
h.Validation.list...,
|
||||
).Append(
|
||||
h.FcInit.list...,
|
||||
)
|
||||
|
||||
return l.Run(ctx, m)
|
||||
}
|
||||
|
||||
// HandlerList represents a list of named handler that can be used to execute a
|
||||
// flow of instructions for a given machine.
|
||||
type HandlerList struct {
|
||||
list []Handler
|
||||
}
|
||||
|
||||
// Append will append a new handler to the handler list.
|
||||
func (l HandlerList) Append(handlers ...Handler) HandlerList {
|
||||
l.list = append(l.list, handlers...)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// Len return the length of the given handler list
|
||||
func (l HandlerList) Len() int {
|
||||
return len(l.list)
|
||||
}
|
||||
|
||||
// Has will iterate through the handler list and check to see if the the named
|
||||
// handler exists.
|
||||
func (l HandlerList) Has(name string) bool {
|
||||
for _, h := range l.list {
|
||||
if h.Name == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Swap will replace all elements of the given name with the new handler.
|
||||
func (l HandlerList) Swap(handler Handler) HandlerList {
|
||||
newList := HandlerList{}
|
||||
for _, h := range l.list {
|
||||
if h.Name == handler.Name {
|
||||
newList.list = append(newList.list, handler)
|
||||
continue
|
||||
}
|
||||
|
||||
newList.list = append(newList.list, h)
|
||||
}
|
||||
|
||||
return newList
|
||||
}
|
||||
|
||||
// Swappend will either append, if there isn't an element within the handler
|
||||
// list, otherwise it will replace all elements with the given name.
|
||||
func (l HandlerList) Swappend(handler Handler) HandlerList {
|
||||
if l.Has(handler.Name) {
|
||||
return l.Swap(handler)
|
||||
}
|
||||
|
||||
return l.Append(handler)
|
||||
}
|
||||
|
||||
// Remove will return an updated handler with all instances of the specific
|
||||
// named handler being removed.
|
||||
func (l HandlerList) Remove(name string) HandlerList {
|
||||
newList := HandlerList{}
|
||||
for _, h := range l.list {
|
||||
if h.Name != name {
|
||||
newList.list = append(newList.list, h)
|
||||
}
|
||||
}
|
||||
|
||||
return newList
|
||||
}
|
||||
|
||||
// Clear clears all named handler in the list.
|
||||
func (l HandlerList) Clear() HandlerList {
|
||||
l.list = l.list[0:0]
|
||||
return l
|
||||
}
|
||||
|
||||
// Run will execute each instruction in the handler list. If an error occurs in
|
||||
// any of the handlers, then the list will halt execution and return the error.
|
||||
func (l HandlerList) Run(ctx context.Context, m *Machine) error {
|
||||
for _, handler := range l.list {
|
||||
m.logger.Debugf("Running handler %s", handler.Name)
|
||||
if err := handler.Fn(ctx, m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
607
vendor/github.com/firecracker-microvm/firecracker-go-sdk/machine.go
generated
vendored
607
vendor/github.com/firecracker-microvm/firecracker-go-sdk/machine.go
generated
vendored
@ -1,607 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
|
||||
ops "github.com/firecracker-microvm/firecracker-go-sdk/client/operations"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
userAgent = "firecracker-go-sdk"
|
||||
)
|
||||
|
||||
// Firecracker is an interface that can be used to mock
|
||||
// out an Firecracker agent for testing purposes.
|
||||
type Firecracker interface {
|
||||
PutLogger(ctx context.Context, logger *models.Logger) (*ops.PutLoggerNoContent, error)
|
||||
PutMachineConfiguration(ctx context.Context, cfg *models.MachineConfiguration) (*ops.PutMachineConfigurationNoContent, error)
|
||||
PutGuestBootSource(ctx context.Context, source *models.BootSource) (*ops.PutGuestBootSourceNoContent, error)
|
||||
PutGuestNetworkInterfaceByID(ctx context.Context, ifaceID string, ifaceCfg *models.NetworkInterface) (*ops.PutGuestNetworkInterfaceByIDNoContent, error)
|
||||
PutGuestDriveByID(ctx context.Context, driveID string, drive *models.Drive) (*ops.PutGuestDriveByIDNoContent, error)
|
||||
PutGuestVsockByID(ctx context.Context, vsockID string, vsock *models.Vsock) (*ops.PutGuestVsockByIDCreated, *ops.PutGuestVsockByIDNoContent, error)
|
||||
CreateSyncAction(ctx context.Context, info *models.InstanceActionInfo) (*ops.CreateSyncActionNoContent, error)
|
||||
PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsNoContent, error)
|
||||
GetMachineConfig() (*ops.GetMachineConfigOK, error)
|
||||
}
|
||||
|
||||
// Config is a collection of user-configurable VMM settings
|
||||
type Config struct {
|
||||
// SocketPath defines the file path where the Firecracker control socket
|
||||
// should be created.
|
||||
SocketPath string
|
||||
|
||||
// LogFifo defines the file path where the Firecracker log named-pipe should
|
||||
// be located.
|
||||
LogFifo string
|
||||
|
||||
// LogLevel defines the verbosity of Firecracker logging. Valid values are
|
||||
// "Error", "Warning", "Info", and "Debug", and are case-sensitive.
|
||||
LogLevel string
|
||||
|
||||
// MetricsFifo defines the file path where the Firecracker metrics
|
||||
// named-pipe should be located.
|
||||
MetricsFifo string
|
||||
|
||||
// KernelImagePath defines the file path where the kernel image is located.
|
||||
// The kernel image must be an uncompressed ELF image.
|
||||
KernelImagePath string
|
||||
|
||||
// KernelArgs defines the command-line arguments that should be passed to
|
||||
// the kernel.
|
||||
KernelArgs string
|
||||
|
||||
// Drives specifies BlockDevices that should be made available to the
|
||||
// microVM.
|
||||
Drives []models.Drive
|
||||
|
||||
// NetworkInterfaces specifies the tap devices that should be made available
|
||||
// to the microVM.
|
||||
NetworkInterfaces []NetworkInterface
|
||||
|
||||
// FifoLogWriter is an io.Writer that is used to redirect the contents of the
|
||||
// fifo log to the writer.
|
||||
FifoLogWriter io.Writer
|
||||
|
||||
// VsockDevices specifies the vsock devices that should be made available to
|
||||
// the microVM.
|
||||
VsockDevices []VsockDevice
|
||||
|
||||
// Debug enables debug-level logging for the SDK.
|
||||
Debug bool
|
||||
|
||||
// MachineCfg represents the firecracker microVM process configuration
|
||||
MachineCfg models.MachineConfiguration
|
||||
|
||||
// DisableValidation allows for easier mock testing by disabling the
|
||||
// validation of configuration performed by the SDK.
|
||||
DisableValidation bool
|
||||
}
|
||||
|
||||
// Validate will ensure that the required fields are set and that
|
||||
// the fields are valid values.
|
||||
func (cfg *Config) Validate() error {
|
||||
if cfg.DisableValidation {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := os.Stat(cfg.KernelImagePath); err != nil {
|
||||
return fmt.Errorf("failed to stat kernal image path, %q: %v", cfg.KernelImagePath, err)
|
||||
}
|
||||
|
||||
rootPath := ""
|
||||
for _, drive := range cfg.Drives {
|
||||
if BoolValue(drive.IsRootDevice) {
|
||||
rootPath = StringValue(drive.PathOnHost)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(rootPath); err != nil {
|
||||
return fmt.Errorf("failed to stat host path, %q: %v", rootPath, err)
|
||||
}
|
||||
|
||||
// Check the non-existence of some files:
|
||||
if _, err := os.Stat(cfg.SocketPath); err == nil {
|
||||
return fmt.Errorf("socket %s already exists", cfg.SocketPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Machine is the main object for manipulating Firecracker microVMs
|
||||
type Machine struct {
|
||||
cfg Config
|
||||
client Firecracker
|
||||
cmd *exec.Cmd
|
||||
logger *log.Entry
|
||||
machineConfig models.MachineConfiguration // The actual machine config as reported by Firecracker
|
||||
|
||||
// Metadata is the associated metadata that will be sent to the firecracker
|
||||
// process
|
||||
Metadata interface{}
|
||||
errCh chan error
|
||||
Handlers Handlers
|
||||
}
|
||||
|
||||
// Logger returns a logrus logger appropriate for logging hypervisor messages
|
||||
func (m *Machine) Logger() *log.Entry {
|
||||
return m.logger.WithField("subsystem", userAgent)
|
||||
}
|
||||
|
||||
// NetworkInterface represents a Firecracker microVM's network interface.
|
||||
type NetworkInterface struct {
|
||||
// MacAddress defines the MAC address that should be assigned to the network
|
||||
// interface inside the microVM.
|
||||
MacAddress string
|
||||
// HostDevName defines the file path of the tap device on the host.
|
||||
HostDevName string
|
||||
// AllowMMDS makes the Firecracker MMDS available on this network interface.
|
||||
AllowMDDS bool
|
||||
}
|
||||
|
||||
// VsockDevice represents a vsock connection between the host and the guest
|
||||
// microVM.
|
||||
type VsockDevice struct {
|
||||
// Path defines the filesystem path of the vsock device on the host.
|
||||
Path string
|
||||
// CID defines the 32-bit Context Identifier for the vsock device. See
|
||||
// the vsock(7) manual page for more information.
|
||||
CID uint32
|
||||
}
|
||||
|
||||
// SocketPath returns the filesystem path to the socket used for VMM
|
||||
// communication
|
||||
func (m Machine) socketPath() string {
|
||||
return m.cfg.SocketPath
|
||||
}
|
||||
|
||||
// LogFile returns the filesystem path of the VMM log
|
||||
func (m Machine) LogFile() string {
|
||||
return m.cfg.LogFifo
|
||||
}
|
||||
|
||||
// LogLevel returns the VMM log level.
|
||||
func (m Machine) LogLevel() string {
|
||||
return m.cfg.LogLevel
|
||||
}
|
||||
|
||||
// NewMachine initializes a new Machine instance and performs validation of the
|
||||
// provided Config.
|
||||
func NewMachine(ctx context.Context, cfg Config, opts ...Opt) (*Machine, error) {
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := &Machine{}
|
||||
logger := log.New()
|
||||
|
||||
if cfg.Debug {
|
||||
logger.SetLevel(log.DebugLevel)
|
||||
}
|
||||
|
||||
m.logger = log.NewEntry(logger)
|
||||
m.cmd = defaultFirecrackerVMMCommandBuilder.
|
||||
WithSocketPath(cfg.SocketPath).
|
||||
Build(ctx)
|
||||
m.Handlers = defaultHandlers
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(m)
|
||||
}
|
||||
|
||||
if m.client == nil {
|
||||
m.client = NewFirecrackerClient(cfg.SocketPath, m.logger, cfg.Debug)
|
||||
}
|
||||
|
||||
m.cfg = cfg
|
||||
|
||||
m.logger.Debug("Called NewMachine()")
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Start will iterate through the handler list and call each handler. If an
|
||||
// error occurred during handler execution, that error will be returned. If the
|
||||
// handlers succeed, then this will start the VMM instance.
|
||||
func (m *Machine) Start(ctx context.Context) error {
|
||||
m.logger.Debug("Called Machine.Start()")
|
||||
if err := m.Handlers.Run(ctx, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.StartInstance(ctx)
|
||||
}
|
||||
|
||||
// Wait will wait until the firecracker process has finished
|
||||
func (m *Machine) Wait(ctx context.Context) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case err := <-m.errCh:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Machine) addVsocks(ctx context.Context, vsocks ...VsockDevice) error {
|
||||
for _, dev := range m.cfg.VsockDevices {
|
||||
if err := m.addVsock(ctx, dev); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Machine) createNetworkInterfaces(ctx context.Context, ifaces ...NetworkInterface) error {
|
||||
for id, iface := range ifaces {
|
||||
if err := m.createNetworkInterface(ctx, iface, id+1); err != nil {
|
||||
return err
|
||||
}
|
||||
m.logger.Debugf("createNetworkInterface returned for %s", iface.HostDevName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Machine) attachDrives(ctx context.Context, drives ...models.Drive) error {
|
||||
for _, dev := range drives {
|
||||
if err := m.attachDrive(ctx, dev); err != nil {
|
||||
m.logger.Errorf("While attaching drive %s, got error %s", StringValue(dev.PathOnHost), err)
|
||||
return err
|
||||
}
|
||||
m.logger.Debugf("attachDrive returned for %s", StringValue(dev.PathOnHost))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// startVMM starts the firecracker vmm process and configures logging.
|
||||
func (m *Machine) startVMM(ctx context.Context) error {
|
||||
m.logger.Printf("Called startVMM(), setting up a VMM on %s", m.cfg.SocketPath)
|
||||
|
||||
m.errCh = make(chan error)
|
||||
|
||||
err := m.cmd.Start()
|
||||
if err != nil {
|
||||
m.logger.Errorf("Failed to start VMM: %s", err)
|
||||
return err
|
||||
}
|
||||
m.logger.Debugf("VMM started socket path is %s", m.cfg.SocketPath)
|
||||
|
||||
go func() {
|
||||
if err := m.cmd.Wait(); err != nil {
|
||||
m.logger.Warnf("firecracker exited: %s", err.Error())
|
||||
} else {
|
||||
m.logger.Printf("firecracker exited: status=0")
|
||||
}
|
||||
|
||||
os.Remove(m.cfg.SocketPath)
|
||||
os.Remove(m.cfg.LogFifo)
|
||||
os.Remove(m.cfg.MetricsFifo)
|
||||
m.errCh <- err
|
||||
}()
|
||||
|
||||
// Set up a signal handler and pass INT, QUIT, and TERM through to firecracker
|
||||
vmchan := make(chan error)
|
||||
sigchan := make(chan os.Signal)
|
||||
signal.Notify(sigchan, os.Interrupt,
|
||||
syscall.SIGQUIT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGABRT)
|
||||
m.logger.Debugf("Setting up signal handler")
|
||||
go func() {
|
||||
select {
|
||||
case sig := <-sigchan:
|
||||
m.logger.Printf("Caught signal %s", sig)
|
||||
m.cmd.Process.Signal(sig)
|
||||
case err = <-vmchan:
|
||||
m.errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for firecracker to initialize:
|
||||
err = m.waitForSocket(3*time.Second, m.errCh)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Firecracker did not create API socket %s: %s", m.cfg.SocketPath, err)
|
||||
err = errors.New(msg)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Debugf("returning from startVMM()")
|
||||
return nil
|
||||
}
|
||||
|
||||
//StopVMM stops the current VMM.
|
||||
func (m *Machine) StopVMM() error {
|
||||
return m.stopVMM()
|
||||
}
|
||||
|
||||
func (m *Machine) stopVMM() error {
|
||||
if m.cmd != nil && m.cmd.Process != nil {
|
||||
log.Debug("stopVMM(): sending sigterm to firecracker")
|
||||
return m.cmd.Process.Signal(syscall.SIGTERM)
|
||||
}
|
||||
log.Debug("stopVMM(): no firecracker process running, not sending a signal")
|
||||
|
||||
// don't return an error if the process isn't even running
|
||||
return nil
|
||||
}
|
||||
|
||||
// createFifos sets up the firecracker logging and metrics FIFOs
|
||||
func createFifos(logFifo, metricsFifo string) error {
|
||||
log.Debugf("Creating FIFO %s", logFifo)
|
||||
if err := syscall.Mkfifo(logFifo, 0700); err != nil {
|
||||
return fmt.Errorf("Failed to create log fifo: %v", err)
|
||||
}
|
||||
|
||||
log.Debugf("Creating metric FIFO %s", metricsFifo)
|
||||
if err := syscall.Mkfifo(metricsFifo, 0700); err != nil {
|
||||
return fmt.Errorf("Failed to create metric fifo: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Machine) setupLogging(ctx context.Context) error {
|
||||
if len(m.cfg.LogFifo) == 0 || len(m.cfg.MetricsFifo) == 0 {
|
||||
// No logging configured
|
||||
m.logger.Printf("VMM logging and metrics disabled.")
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := createFifos(m.cfg.LogFifo, m.cfg.MetricsFifo); err != nil {
|
||||
m.logger.Errorf("Unable to set up logging: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Debug("Created metrics and logging fifos.")
|
||||
|
||||
l := models.Logger{
|
||||
LogFifo: m.cfg.LogFifo,
|
||||
Level: m.cfg.LogLevel,
|
||||
MetricsFifo: m.cfg.MetricsFifo,
|
||||
ShowLevel: true,
|
||||
ShowLogOrigin: false,
|
||||
}
|
||||
|
||||
_, err := m.client.PutLogger(ctx, &l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Debugf("Configured VMM logging to %s, metrics to %s",
|
||||
m.cfg.LogFifo,
|
||||
m.cfg.MetricsFifo,
|
||||
)
|
||||
|
||||
if m.cfg.FifoLogWriter != nil {
|
||||
if err := captureFifoToFile(m.logger, m.cfg.LogFifo, m.cfg.FifoLogWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func captureFifoToFile(logger *log.Entry, fifoPath string, fifo io.Writer) error {
|
||||
// create the fifo pipe which will be used
|
||||
// to write its contents to a file.
|
||||
fifoPipe, err := os.OpenFile(fifoPath, os.O_RDONLY, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to open fifo path at %q: %v", fifoPath, err)
|
||||
}
|
||||
|
||||
if err := syscall.Unlink(fifoPath); err != nil {
|
||||
logger.Warnf("Failed to unlink %s", fifoPath)
|
||||
}
|
||||
|
||||
logger.Debugf("Capturing %q to writer", fifoPath)
|
||||
|
||||
// Uses a go routine to do a non-blocking io.Copy. The fifo
|
||||
// file should be closed when the appication has finished, since
|
||||
// the forked firecracker application will be closed resulting
|
||||
// in the pipe to return an io.EOF
|
||||
go func() {
|
||||
defer fifoPipe.Close()
|
||||
|
||||
if _, err := io.Copy(fifo, fifoPipe); err != nil {
|
||||
logger.Warnf("io.Copy failed to copy contents of fifo pipe: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Machine) createMachine(ctx context.Context) error {
|
||||
resp, err := m.client.PutMachineConfiguration(ctx, &m.cfg.MachineCfg)
|
||||
if err != nil {
|
||||
m.logger.Errorf("PutMachineConfiguration returned %s", resp.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Debug("PutMachineConfiguration returned")
|
||||
err = m.refreshMachineConfig()
|
||||
if err != nil {
|
||||
log.Errorf("Unable to inspect Firecracker MachineConfig. Continuing anyway. %s", err)
|
||||
}
|
||||
m.logger.Debug("createMachine returning")
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Machine) createBootSource(ctx context.Context, imagePath, kernelArgs string) error {
|
||||
bsrc := models.BootSource{
|
||||
KernelImagePath: &imagePath,
|
||||
BootArgs: kernelArgs,
|
||||
}
|
||||
|
||||
resp, err := m.client.PutGuestBootSource(ctx, &bsrc)
|
||||
if err == nil {
|
||||
m.logger.Printf("PutGuestBootSource: %s", resp.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Machine) createNetworkInterface(ctx context.Context, iface NetworkInterface, iid int) error {
|
||||
ifaceID := strconv.Itoa(iid)
|
||||
m.logger.Printf("Attaching NIC %s (hwaddr %s) at index %s", iface.HostDevName, iface.MacAddress, ifaceID)
|
||||
|
||||
ifaceCfg := models.NetworkInterface{
|
||||
IfaceID: &ifaceID,
|
||||
GuestMac: iface.MacAddress,
|
||||
HostDevName: iface.HostDevName,
|
||||
AllowMmdsRequests: iface.AllowMDDS,
|
||||
}
|
||||
|
||||
resp, err := m.client.PutGuestNetworkInterfaceByID(ctx, ifaceID, &ifaceCfg)
|
||||
if err == nil {
|
||||
m.logger.Printf("PutGuestNetworkInterfaceByID: %s", resp.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// attachDrive attaches a secondary block device
|
||||
func (m *Machine) attachDrive(ctx context.Context, dev models.Drive) error {
|
||||
var err error
|
||||
hostPath := StringValue(dev.PathOnHost)
|
||||
|
||||
_, err = os.Stat(hostPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Attaching drive %s, slot %s, root %t.", hostPath, StringValue(dev.DriveID), BoolValue(dev.IsRootDevice))
|
||||
respNoContent, err := m.client.PutGuestDriveByID(ctx, StringValue(dev.DriveID), &dev)
|
||||
if err == nil {
|
||||
m.logger.Printf("Attached drive %s: %s", hostPath, respNoContent.Error())
|
||||
} else {
|
||||
m.logger.Errorf("Attach drive failed: %s: %s", hostPath, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// addVsock adds a vsock to the instance
|
||||
func (m *Machine) addVsock(ctx context.Context, dev VsockDevice) error {
|
||||
vsockCfg := models.Vsock{
|
||||
GuestCid: int64(dev.CID),
|
||||
ID: &dev.Path,
|
||||
}
|
||||
resp, _, err := m.client.PutGuestVsockByID(ctx, dev.Path, &vsockCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.logger.Debugf("Attach vsock %s successful: %s", dev.Path, resp.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartInstance starts the Firecracker microVM
|
||||
func (m *Machine) StartInstance(ctx context.Context) error {
|
||||
return m.startInstance(ctx)
|
||||
}
|
||||
|
||||
func (m *Machine) startInstance(ctx context.Context) error {
|
||||
info := models.InstanceActionInfo{
|
||||
ActionType: models.InstanceActionInfoActionTypeInstanceStart,
|
||||
}
|
||||
|
||||
resp, err := m.client.CreateSyncAction(ctx, &info)
|
||||
if err == nil {
|
||||
m.logger.Printf("startInstance successful: %s", resp.Error())
|
||||
} else {
|
||||
m.logger.Errorf("Starting instance: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// EnableMetadata will append or replace the metadata handler.
|
||||
func (m *Machine) EnableMetadata(metadata interface{}) {
|
||||
m.Handlers.FcInit = m.Handlers.FcInit.Swappend(NewSetMetadataHandler(metadata))
|
||||
}
|
||||
|
||||
// SetMetadata sets the machine's metadata for MDDS
|
||||
func (m *Machine) SetMetadata(ctx context.Context, metadata interface{}) error {
|
||||
respnocontent, err := m.client.PutMmds(ctx, metadata)
|
||||
|
||||
if err == nil {
|
||||
var message string
|
||||
if respnocontent != nil {
|
||||
message = respnocontent.Error()
|
||||
}
|
||||
m.logger.Printf("SetMetadata successful: %s", message)
|
||||
} else {
|
||||
m.logger.Errorf("Setting metadata: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// refreshMachineConfig synchronizes our cached representation of the machine configuration
|
||||
// with that reported by the Firecracker API
|
||||
func (m *Machine) refreshMachineConfig() error {
|
||||
resp, err := m.client.GetMachineConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("refreshMachineConfig: %s", resp.Error())
|
||||
m.machineConfig = *resp.Payload
|
||||
return nil
|
||||
}
|
||||
|
||||
// waitForSocket waits for the given file to exist
|
||||
func (m *Machine) waitForSocket(timeout time.Duration, exitchan chan error) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
done := make(chan error)
|
||||
ticker := time.NewTicker(10 * time.Millisecond)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
done <- ctx.Err()
|
||||
return
|
||||
case err := <-exitchan:
|
||||
done <- err
|
||||
return
|
||||
case <-ticker.C:
|
||||
if _, err := os.Stat(m.cfg.SocketPath); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Send test HTTP request to make sure socket is available
|
||||
if _, err := m.client.GetMachineConfig(); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
done <- nil
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return <-done
|
||||
}
|
49
vendor/github.com/firecracker-microvm/firecracker-go-sdk/opts.go
generated
vendored
49
vendor/github.com/firecracker-microvm/firecracker-go-sdk/opts.go
generated
vendored
@ -1,49 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package firecracker
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Opt represents a functional option to help modify functionality of a Machine.
|
||||
type Opt func(*Machine)
|
||||
|
||||
// WithClient will use the client in place rather than the client constructed
|
||||
// during bootstrapping of the machine. This option is useful for mocking out
|
||||
// tests.
|
||||
func WithClient(client Firecracker) Opt {
|
||||
return func(machine *Machine) {
|
||||
machine.client = client
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogger will allow for the Machine to use the provided logger.
|
||||
func WithLogger(logger *logrus.Entry) Opt {
|
||||
return func(machine *Machine) {
|
||||
machine.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
// WithProcessRunner will allow for a specific command to be run instead of the
|
||||
// default firecracker command.
|
||||
// For example, this could be used to instead call the jailer instead of
|
||||
// firecracker directly.
|
||||
func WithProcessRunner(cmd *exec.Cmd) Opt {
|
||||
return func(machine *Machine) {
|
||||
machine.cmd = cmd
|
||||
}
|
||||
}
|
46
vendor/github.com/firecracker-microvm/firecracker-go-sdk/pointer_helpers.go
generated
vendored
46
vendor/github.com/firecracker-microvm/firecracker-go-sdk/pointer_helpers.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
package firecracker
|
||||
|
||||
// BoolValue will return a boolean value. If the pointer is nil, then false
|
||||
// will be returned.
|
||||
func BoolValue(b *bool) bool {
|
||||
if b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return *b
|
||||
}
|
||||
|
||||
// Bool will return a pointer value of the given parameter.
|
||||
func Bool(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// StringValue will return a string value. If the pointer is nil, then an empty
|
||||
// string will be returned.
|
||||
func StringValue(str *string) string {
|
||||
if str == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *str
|
||||
}
|
||||
|
||||
// String will return a pointer value of the given parameter.
|
||||
func String(str string) *string {
|
||||
return &str
|
||||
}
|
||||
|
||||
// Int64 will return a pointer value of the given parameter.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Value will return an int64 value. If the pointer is nil, then zero will
|
||||
// be returned.
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
22
vendor/github.com/firecracker-microvm/firecracker-go-sdk/swagger.go
generated
vendored
22
vendor/github.com/firecracker-microvm/firecracker-go-sdk/swagger.go
generated
vendored
@ -1,22 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"). You may
|
||||
// not use this file except in compliance with the License. A copy of the
|
||||
// License is located at
|
||||
//
|
||||
// http://aws.amazon.com/apache2.0/
|
||||
//
|
||||
// or in the "license" file accompanying this file. This file is distributed
|
||||
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
// express or implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
//go:generate find ./client ! -name swagger.yaml -type f -delete
|
||||
|
||||
// --skip-validation is used in the command-lines below to remove the network dependency that the swagger generator has
|
||||
// in attempting to validate that the email address specified in the yaml file is valid.
|
||||
|
||||
//go:generate docker run --rm --net=none -v $PWD:/work -w /work quay.io/goswagger/swagger generate model -f ./client/swagger.yaml --model-package=client/models --client-package=client --copyright-file=COPYRIGHT_HEADER --skip-validation
|
||||
//go:generate docker run --rm --net=none -v $PWD:/work -w /work quay.io/goswagger/swagger generate client -f ./client/swagger.yaml --model-package=client/models --client-package=client --copyright-file=COPYRIGHT_HEADER --skip-validation
|
||||
|
||||
package firecracker
|
8
vendor/github.com/intel/govmm/qemu/image.go
generated
vendored
8
vendor/github.com/intel/govmm/qemu/image.go
generated
vendored
@ -51,18 +51,18 @@ func CreateCloudInitISO(ctx context.Context, scratchDir, isoPath string,
|
||||
|
||||
err := os.MkdirAll(dataDirPath, 0750)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create config drive directory %s : %v",
|
||||
return fmt.Errorf("unable to create config drive directory %s : %v",
|
||||
dataDirPath, err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(metaDataPath, metaData, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create %s : %v", metaDataPath, err)
|
||||
return fmt.Errorf("unable to create %s : %v", metaDataPath, err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(userDataPath, userData, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create %s : %v", userDataPath, err)
|
||||
return fmt.Errorf("unable to create %s : %v", userDataPath, err)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "xorriso", "-as", "mkisofs", "-R", "-V", "config-2",
|
||||
@ -70,7 +70,7 @@ func CreateCloudInitISO(ctx context.Context, scratchDir, isoPath string,
|
||||
cmd.SysProcAttr = attr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create cloudinit iso image %v", err)
|
||||
return fmt.Errorf("unable to create cloudinit iso image %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
80
vendor/github.com/intel/govmm/qemu/qemu.go
generated
vendored
80
vendor/github.com/intel/govmm/qemu/qemu.go
generated
vendored
@ -260,7 +260,7 @@ func (fsdev FSDevice) QemuParams(config *Config) []string {
|
||||
var deviceParams []string
|
||||
var qemuParams []string
|
||||
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", fsdev.Driver))
|
||||
deviceParams = append(deviceParams, string(fsdev.Driver))
|
||||
if s := fsdev.Driver.disableModern(fsdev.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
|
||||
}
|
||||
@ -346,7 +346,7 @@ func (cdev CharDevice) QemuParams(config *Config) []string {
|
||||
var deviceParams []string
|
||||
var qemuParams []string
|
||||
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", cdev.Driver))
|
||||
deviceParams = append(deviceParams, string(cdev.Driver))
|
||||
if s := cdev.Driver.disableModern(cdev.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
|
||||
}
|
||||
@ -534,7 +534,7 @@ func (netdev NetDevice) QemuNetdevParams(config *Config) []string {
|
||||
netdevParams = append(netdevParams, netdev.Type.QemuNetdevParam())
|
||||
netdevParams = append(netdevParams, fmt.Sprintf(",id=%s", netdev.ID))
|
||||
|
||||
if netdev.VHost == true {
|
||||
if netdev.VHost {
|
||||
netdevParams = append(netdevParams, ",vhost=on")
|
||||
if len(netdev.VhostFDs) > 0 {
|
||||
var fdParams []string
|
||||
@ -627,7 +627,7 @@ func (dev SerialDevice) QemuParams(config *Config) []string {
|
||||
var deviceParams []string
|
||||
var qemuParams []string
|
||||
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", dev.Driver))
|
||||
deviceParams = append(deviceParams, string(dev.Driver))
|
||||
if s := dev.Driver.disableModern(dev.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
|
||||
}
|
||||
@ -705,16 +705,16 @@ func (blkdev BlockDevice) QemuParams(config *Config) []string {
|
||||
var deviceParams []string
|
||||
var qemuParams []string
|
||||
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", blkdev.Driver))
|
||||
deviceParams = append(deviceParams, string(blkdev.Driver))
|
||||
if s := blkdev.Driver.disableModern(blkdev.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
|
||||
}
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",drive=%s", blkdev.ID))
|
||||
if blkdev.SCSI == false {
|
||||
if !blkdev.SCSI {
|
||||
deviceParams = append(deviceParams, ",scsi=off")
|
||||
}
|
||||
|
||||
if blkdev.WCE == false {
|
||||
if !blkdev.WCE {
|
||||
deviceParams = append(deviceParams, ",config-wce=off")
|
||||
}
|
||||
|
||||
@ -842,11 +842,7 @@ type VFIODevice struct {
|
||||
|
||||
// Valid returns true if the VFIODevice structure is valid and complete.
|
||||
func (vfioDev VFIODevice) Valid() bool {
|
||||
if vfioDev.BDF == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return vfioDev.BDF != ""
|
||||
}
|
||||
|
||||
// QemuParams returns the qemu parameters built out of this vfio device.
|
||||
@ -889,11 +885,7 @@ type SCSIController struct {
|
||||
|
||||
// Valid returns true if the SCSIController structure is valid and complete.
|
||||
func (scsiCon SCSIController) Valid() bool {
|
||||
if scsiCon.ID == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return scsiCon.ID != ""
|
||||
}
|
||||
|
||||
// QemuParams returns the qemu parameters built out of this SCSIController device.
|
||||
@ -910,7 +902,7 @@ func (scsiCon SCSIController) QemuParams(config *Config) []string {
|
||||
devParams = append(devParams, fmt.Sprintf("addr=%s", scsiCon.Addr))
|
||||
}
|
||||
if s := driver.disableModern(scsiCon.DisableModern); s != "" {
|
||||
devParams = append(devParams, fmt.Sprintf("%s", s))
|
||||
devParams = append(devParams, s)
|
||||
}
|
||||
if scsiCon.IOThread != "" {
|
||||
devParams = append(devParams, fmt.Sprintf("iothread=%s", scsiCon.IOThread))
|
||||
@ -1057,7 +1049,7 @@ func (vsock VSOCKDevice) QemuParams(config *Config) []string {
|
||||
var qemuParams []string
|
||||
|
||||
driver := VHostVSock
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", driver))
|
||||
deviceParams = append(deviceParams, string(driver))
|
||||
if s := driver.disableModern(vsock.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
|
||||
}
|
||||
@ -1094,11 +1086,7 @@ type RngDevice struct {
|
||||
|
||||
// Valid returns true if the RngDevice structure is valid and complete.
|
||||
func (v RngDevice) Valid() bool {
|
||||
if v.ID == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return v.ID != ""
|
||||
}
|
||||
|
||||
// QemuParams returns the qemu parameters built out of the RngDevice.
|
||||
@ -1174,7 +1162,7 @@ func (b BalloonDevice) QemuParams(_ *Config) []string {
|
||||
deviceParams = append(deviceParams, "deflate-on-oom=off")
|
||||
}
|
||||
if s := driver.disableModern(b.DisableModern); s != "" {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("%s", s))
|
||||
deviceParams = append(deviceParams, string(s))
|
||||
}
|
||||
qemuParams = append(qemuParams, "-device")
|
||||
qemuParams = append(qemuParams, strings.Join(deviceParams, ","))
|
||||
@ -1184,11 +1172,7 @@ func (b BalloonDevice) QemuParams(_ *Config) []string {
|
||||
|
||||
// Valid returns true if the balloonDevice structure is valid and complete.
|
||||
func (b BalloonDevice) Valid() bool {
|
||||
if b.ID == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return b.ID != ""
|
||||
}
|
||||
|
||||
// RTCBaseType is the qemu RTC base time type.
|
||||
@ -1523,15 +1507,15 @@ func (config *Config) appendCPUModel() {
|
||||
|
||||
func (config *Config) appendQMPSockets() {
|
||||
for _, q := range config.QMPSockets {
|
||||
if q.Valid() == false {
|
||||
if !q.Valid() {
|
||||
continue
|
||||
}
|
||||
|
||||
qmpParams := append([]string{}, fmt.Sprintf("%s:", q.Type))
|
||||
qmpParams = append(qmpParams, fmt.Sprintf("%s", q.Name))
|
||||
if q.Server == true {
|
||||
qmpParams = append(qmpParams, q.Name)
|
||||
if q.Server {
|
||||
qmpParams = append(qmpParams, ",server")
|
||||
if q.NoWait == true {
|
||||
if q.NoWait {
|
||||
qmpParams = append(qmpParams, ",nowait")
|
||||
}
|
||||
}
|
||||
@ -1543,7 +1527,7 @@ func (config *Config) appendQMPSockets() {
|
||||
|
||||
func (config *Config) appendDevices() {
|
||||
for _, d := range config.Devices {
|
||||
if d.Valid() == false {
|
||||
if !d.Valid() {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -1611,7 +1595,7 @@ func (config *Config) appendCPUs() error {
|
||||
}
|
||||
|
||||
func (config *Config) appendRTC() {
|
||||
if config.RTC.Valid() == false {
|
||||
if !config.RTC.Valid() {
|
||||
return
|
||||
}
|
||||
|
||||
@ -1663,7 +1647,7 @@ func (config *Config) appendKernel() {
|
||||
}
|
||||
|
||||
func (config *Config) appendMemoryKnobs() {
|
||||
if config.Knobs.HugePages == true {
|
||||
if config.Knobs.HugePages {
|
||||
if config.Memory.Size != "" {
|
||||
dimmName := "dimm1"
|
||||
objMemParam := "memory-backend-file,id=" + dimmName + ",size=" + config.Memory.Size + ",mem-path=/dev/hugepages,share=on,prealloc=on"
|
||||
@ -1675,7 +1659,7 @@ func (config *Config) appendMemoryKnobs() {
|
||||
config.qemuParams = append(config.qemuParams, "-numa")
|
||||
config.qemuParams = append(config.qemuParams, numaMemParam)
|
||||
}
|
||||
} else if config.Knobs.MemPrealloc == true {
|
||||
} else if config.Knobs.MemPrealloc {
|
||||
if config.Memory.Size != "" {
|
||||
dimmName := "dimm1"
|
||||
objMemParam := "memory-backend-ram,id=" + dimmName + ",size=" + config.Memory.Size + ",prealloc=on"
|
||||
@ -1687,11 +1671,11 @@ func (config *Config) appendMemoryKnobs() {
|
||||
config.qemuParams = append(config.qemuParams, "-numa")
|
||||
config.qemuParams = append(config.qemuParams, numaMemParam)
|
||||
}
|
||||
} else if config.Knobs.FileBackedMem == true {
|
||||
} else if config.Knobs.FileBackedMem {
|
||||
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 {
|
||||
if config.Knobs.FileBackedMemShared {
|
||||
objMemParam += ",share=on"
|
||||
}
|
||||
numaMemParam := "node,memdev=" + dimmName
|
||||
@ -1706,45 +1690,45 @@ func (config *Config) appendMemoryKnobs() {
|
||||
}
|
||||
|
||||
func (config *Config) appendKnobs() {
|
||||
if config.Knobs.NoUserConfig == true {
|
||||
if config.Knobs.NoUserConfig {
|
||||
config.qemuParams = append(config.qemuParams, "-no-user-config")
|
||||
}
|
||||
|
||||
if config.Knobs.NoDefaults == true {
|
||||
if config.Knobs.NoDefaults {
|
||||
config.qemuParams = append(config.qemuParams, "-nodefaults")
|
||||
}
|
||||
|
||||
if config.Knobs.NoGraphic == true {
|
||||
if config.Knobs.NoGraphic {
|
||||
config.qemuParams = append(config.qemuParams, "-nographic")
|
||||
}
|
||||
|
||||
if config.Knobs.Daemonize == true {
|
||||
if config.Knobs.Daemonize {
|
||||
config.qemuParams = append(config.qemuParams, "-daemonize")
|
||||
}
|
||||
|
||||
config.appendMemoryKnobs()
|
||||
|
||||
if config.Knobs.Realtime == true {
|
||||
if config.Knobs.Realtime {
|
||||
config.qemuParams = append(config.qemuParams, "-realtime")
|
||||
// This path is redundant as the default behaviour is locked memory
|
||||
// Realtime today does not control any other feature even though
|
||||
// other features may be added in the future
|
||||
// https://lists.gnu.org/archive/html/qemu-devel/2012-12/msg03330.html
|
||||
if config.Knobs.Mlock == true {
|
||||
if config.Knobs.Mlock {
|
||||
config.qemuParams = append(config.qemuParams, "mlock=on")
|
||||
} else {
|
||||
config.qemuParams = append(config.qemuParams, "mlock=off")
|
||||
}
|
||||
} else {
|
||||
// In order to turn mlock off we need the -realtime option as well
|
||||
if config.Knobs.Mlock == false {
|
||||
if !config.Knobs.Mlock {
|
||||
//Enable realtime anyway just to get the right swapping behaviour
|
||||
config.qemuParams = append(config.qemuParams, "-realtime")
|
||||
config.qemuParams = append(config.qemuParams, "mlock=off")
|
||||
}
|
||||
}
|
||||
|
||||
if config.Knobs.Stopped == true {
|
||||
if config.Knobs.Stopped {
|
||||
config.qemuParams = append(config.qemuParams, "-S")
|
||||
}
|
||||
}
|
||||
|
51
vendor/github.com/intel/govmm/qemu/qmp.go
generated
vendored
51
vendor/github.com/intel/govmm/qemu/qmp.go
generated
vendored
@ -329,14 +329,14 @@ func (q *QMP) errorDesc(errorData interface{}) (string, error) {
|
||||
// convert error to json
|
||||
data, err := json.Marshal(errorData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to extract error information: %v", err)
|
||||
return "", fmt.Errorf("unable to extract error information: %v", err)
|
||||
}
|
||||
|
||||
// see: https://github.com/qemu/qemu/blob/stable-2.12/qapi/qmp-dispatch.c#L125
|
||||
var qmpErr map[string]string
|
||||
// convert json to qmpError
|
||||
if err = json.Unmarshal(data, &qmpErr); err != nil {
|
||||
return "", fmt.Errorf("Unable to convert json to qmpError: %v", err)
|
||||
return "", fmt.Errorf("unable to convert json to qmpError: %v", err)
|
||||
}
|
||||
|
||||
return qmpErr["desc"], nil
|
||||
@ -404,7 +404,7 @@ func (q *QMP) writeNextQMPCommand(cmdQueue *list.List) {
|
||||
encodedCmd, err := json.Marshal(&cmdData)
|
||||
if err != nil {
|
||||
cmd.res <- qmpResult{
|
||||
err: fmt.Errorf("Unable to marhsall command %s: %v",
|
||||
err: fmt.Errorf("unable to marhsall command %s: %v",
|
||||
cmd.name, err),
|
||||
}
|
||||
cmdQueue.Remove(cmdEl)
|
||||
@ -419,7 +419,7 @@ func (q *QMP) writeNextQMPCommand(cmdQueue *list.List) {
|
||||
|
||||
if err != nil {
|
||||
cmd.res <- qmpResult{
|
||||
err: fmt.Errorf("Unable to write command to qmp socket %v", err),
|
||||
err: fmt.Errorf("unable to write command to qmp socket %v", err),
|
||||
}
|
||||
cmdQueue.Remove(cmdEl)
|
||||
}
|
||||
@ -525,7 +525,7 @@ func (q *QMP) mainLoop() {
|
||||
}
|
||||
/* #nosec */
|
||||
_ = q.conn.Close()
|
||||
_ = <-fromVMCh
|
||||
<-fromVMCh
|
||||
failOutstandingCommands(cmdQueue)
|
||||
close(q.disconnectedCh)
|
||||
}()
|
||||
@ -689,12 +689,12 @@ func QMPStart(ctx context.Context, socket string, cfg QMPConfig, disconnectedCh
|
||||
case <-ctx.Done():
|
||||
q.Shutdown()
|
||||
<-disconnectedCh
|
||||
return nil, nil, fmt.Errorf("Canceled by caller")
|
||||
return nil, nil, fmt.Errorf("canceled by caller")
|
||||
case <-disconnectedCh:
|
||||
return nil, nil, fmt.Errorf("Lost connection to VM")
|
||||
return nil, nil, fmt.Errorf("lost connection to VM")
|
||||
case q.version = <-connectedCh:
|
||||
if q.version == nil {
|
||||
return nil, nil, fmt.Errorf("Failed to find QMP version information")
|
||||
return nil, nil, fmt.Errorf("failed to find QMP version information")
|
||||
}
|
||||
}
|
||||
|
||||
@ -860,7 +860,7 @@ func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, drive
|
||||
}
|
||||
|
||||
if !isSCSIDriver {
|
||||
return fmt.Errorf("Invalid SCSI driver provided %s", driver)
|
||||
return fmt.Errorf("invalid SCSI driver provided %s", driver)
|
||||
}
|
||||
|
||||
args := map[string]interface{}{
|
||||
@ -1144,14 +1144,21 @@ func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsd
|
||||
// ExecuteCPUDeviceAdd adds a CPU to a QEMU instance using the device_add command.
|
||||
// driver is the CPU model, cpuID must be a unique ID to identify the CPU, socketID is the socket number within
|
||||
// node/board the CPU belongs to, coreID is the core number within socket the CPU belongs to, threadID is the
|
||||
// thread number within core the CPU belongs to.
|
||||
// thread number within core the CPU belongs to. Note that socketID and threadID are not a requirement for
|
||||
// architecures like ppc64le.
|
||||
func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID, coreID, threadID, romfile string) error {
|
||||
args := map[string]interface{}{
|
||||
"driver": driver,
|
||||
"id": cpuID,
|
||||
"socket-id": socketID,
|
||||
"core-id": coreID,
|
||||
"thread-id": threadID,
|
||||
"driver": driver,
|
||||
"id": cpuID,
|
||||
"core-id": coreID,
|
||||
}
|
||||
|
||||
if socketID != "" {
|
||||
args["socket-id"] = socketID
|
||||
}
|
||||
|
||||
if threadID != "" {
|
||||
args["thread-id"] = threadID
|
||||
}
|
||||
|
||||
if isVirtioPCI[DeviceDriver(driver)] {
|
||||
@ -1171,13 +1178,13 @@ func (q *QMP) ExecuteQueryHotpluggableCPUs(ctx context.Context) ([]HotpluggableC
|
||||
// convert response to json
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to extract CPU information: %v", err)
|
||||
return nil, fmt.Errorf("unable to extract CPU information: %v", err)
|
||||
}
|
||||
|
||||
var cpus []HotpluggableCPU
|
||||
// convert json to []HotpluggableCPU
|
||||
if err = json.Unmarshal(data, &cpus); err != nil {
|
||||
return nil, fmt.Errorf("Unable to convert json to hotpluggable CPU: %v", err)
|
||||
return nil, fmt.Errorf("unable to convert json to hotpluggable CPU: %v", err)
|
||||
}
|
||||
|
||||
return cpus, nil
|
||||
@ -1211,7 +1218,7 @@ func (q *QMP) ExecQueryMemoryDevices(ctx context.Context) ([]MemoryDevices, erro
|
||||
// convert response to json
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to extract memory devices information: %v", err)
|
||||
return nil, fmt.Errorf("unable to extract memory devices information: %v", err)
|
||||
}
|
||||
|
||||
var memoryDevices []MemoryDevices
|
||||
@ -1235,7 +1242,7 @@ func (q *QMP) ExecQueryCpus(ctx context.Context) ([]CPUInfo, error) {
|
||||
// convert response to json
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to extract memory devices information: %v", err)
|
||||
return nil, fmt.Errorf("unable to extract memory devices information: %v", err)
|
||||
}
|
||||
|
||||
var cpuInfo []CPUInfo
|
||||
@ -1259,7 +1266,7 @@ func (q *QMP) ExecQueryCpusFast(ctx context.Context) ([]CPUInfoFast, error) {
|
||||
// convert response to json
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to extract memory devices information: %v", err)
|
||||
return nil, fmt.Errorf("unable to extract memory devices information: %v", err)
|
||||
}
|
||||
|
||||
var cpuInfoFast []CPUInfoFast
|
||||
@ -1434,12 +1441,12 @@ func (q *QMP) ExecuteQueryMigration(ctx context.Context) (MigrationStatus, error
|
||||
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return MigrationStatus{}, fmt.Errorf("Unable to extract migrate status information: %v", err)
|
||||
return MigrationStatus{}, fmt.Errorf("unable to extract migrate status information: %v", err)
|
||||
}
|
||||
|
||||
var status MigrationStatus
|
||||
if err = json.Unmarshal(data, &status); err != nil {
|
||||
return MigrationStatus{}, fmt.Errorf("Unable to convert migrate status information: %v", err)
|
||||
return MigrationStatus{}, fmt.Errorf("unable to convert migrate status information: %v", err)
|
||||
}
|
||||
|
||||
return status, nil
|
||||
|
@ -1077,6 +1077,11 @@ func (q *qemu) hotplugAddCPUs(amount uint32) (uint32, error) {
|
||||
return 0, fmt.Errorf("failed to query hotpluggable CPUs: %v", err)
|
||||
}
|
||||
|
||||
machine, err := q.arch.machine()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to query machine type: %v", err)
|
||||
}
|
||||
|
||||
var hotpluggedVCPUs uint32
|
||||
for _, hc := range hotpluggableVCPUs {
|
||||
// qom-path is the path to the CPU, non-empty means that this CPU is already in use
|
||||
@ -1090,6 +1095,13 @@ func (q *qemu) hotplugAddCPUs(amount uint32) (uint32, error) {
|
||||
socketID := fmt.Sprintf("%d", hc.Properties.Socket)
|
||||
coreID := fmt.Sprintf("%d", hc.Properties.Core)
|
||||
threadID := fmt.Sprintf("%d", hc.Properties.Thread)
|
||||
|
||||
// If CPU type is IBM pSeries, we do not set socketID and threadID
|
||||
if machine.Type == "pseries" {
|
||||
socketID = ""
|
||||
threadID = ""
|
||||
}
|
||||
|
||||
if err := q.qmpMonitorCh.qmp.ExecuteCPUDeviceAdd(q.qmpMonitorCh.ctx, driver, cpuID, socketID, coreID, threadID, romFile); err != nil {
|
||||
// don't fail, let's try with other CPU
|
||||
continue
|
||||
|
Loading…
Reference in New Issue
Block a user