Merge pull request #2050 from devimc/topic/virtcontainers/fixFC018

Support Firecracker 0.18
This commit is contained in:
Eric Ernst 2019-09-23 06:52:29 -07:00 committed by GitHub
commit 22a3ca1c36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 644 additions and 280 deletions

4
Gopkg.lock generated
View File

@ -397,7 +397,7 @@
revision = "8cba5a8e5f2816f26f9dc34b8ea968279a5a76eb" revision = "8cba5a8e5f2816f26f9dc34b8ea968279a5a76eb"
[[projects]] [[projects]]
digest = "1:22e399f891fccaac4700943a9465f2623bb361653d5e0d4a9974573cd5e69070" digest = "1:54e0385cece7064d8afd967e0987e52cd8b261c8c7e22d84e8b25719d7379e74"
name = "github.com/kata-containers/agent" name = "github.com/kata-containers/agent"
packages = [ packages = [
"pkg/types", "pkg/types",
@ -405,7 +405,7 @@
"protocols/grpc", "protocols/grpc",
] ]
pruneopts = "NUT" pruneopts = "NUT"
revision = "94e2a254a94a77c02280f4f84d7f82269be163ce" revision = "3ffb7ca1067565a45ee9fbfcb109eb85e7e899af"
[[projects]] [[projects]]
branch = "master" branch = "master"

View File

@ -52,7 +52,7 @@
[[constraint]] [[constraint]]
name = "github.com/kata-containers/agent" name = "github.com/kata-containers/agent"
revision = "94e2a254a94a77c02280f4f84d7f82269be163ce" revision = "3ffb7ca1067565a45ee9fbfcb109eb85e7e899af"
[[constraint]] [[constraint]]
name = "github.com/containerd/cri-containerd" name = "github.com/containerd/cri-containerd"

View File

@ -29,11 +29,14 @@ import (
const ( const (
unixSocketScheme = "unix" unixSocketScheme = "unix"
vsockSocketScheme = "vsock" vsockSocketScheme = "vsock"
hybridVSockScheme = "hvsock"
) )
var defaultDialTimeout = 15 * time.Second var defaultDialTimeout = 15 * time.Second
var defaultCloseTimeout = 5 * time.Second var defaultCloseTimeout = 5 * time.Second
var hybridVSockPort uint32
// AgentClient is an agent gRPC client connection wrapper for agentgrpc.AgentServiceClient // AgentClient is an agent gRPC client connection wrapper for agentgrpc.AgentServiceClient
type AgentClient struct { type AgentClient struct {
agentgrpc.AgentServiceClient agentgrpc.AgentServiceClient
@ -77,6 +80,9 @@ type dialer func(string, time.Duration) (net.Conn, error)
// - unix://<unix socket path> // - unix://<unix socket path>
// - vsock://<cid>:<port> // - vsock://<cid>:<port>
// - <unix socket path> // - <unix socket path>
// - hvsock://<path>:<port>. Firecracker implements the virtio-vsock device
// model, and mediates communication between AF_UNIX sockets (on the host end)
// and AF_VSOCK sockets (on the guest end).
func NewAgentClient(ctx context.Context, sock string, enableYamux bool) (*AgentClient, error) { func NewAgentClient(ctx context.Context, sock string, enableYamux bool) (*AgentClient, error) {
grpcAddr, parsedAddr, err := parse(sock) grpcAddr, parsedAddr, err := parse(sock)
if err != nil { if err != nil {
@ -158,6 +164,21 @@ func parse(sock string) (string, *url.URL, error) {
} else { } else {
grpcAddr = unixSocketScheme + ":///" + addr.Host + "/" + addr.Path grpcAddr = unixSocketScheme + ":///" + addr.Host + "/" + addr.Path
} }
case hybridVSockScheme:
if addr.Path == "" {
return "", nil, grpcStatus.Errorf(codes.InvalidArgument, "Invalid hybrid vsock scheme: %s", sock)
}
hvsocket := strings.Split(addr.Path, ":")
if len(hvsocket) != 2 {
return "", nil, grpcStatus.Errorf(codes.InvalidArgument, "Invalid hybrid vsock scheme: %s", sock)
}
// Save port since agent dialer not sent the port to the hybridVSock dialer
var port uint64
if port, err = strconv.ParseUint(hvsocket[1], 10, 32); err != nil {
return "", nil, grpcStatus.Errorf(codes.InvalidArgument, "Invalid hybrid vsock port %s: %v", sock, err)
}
hybridVSockPort = uint32(port)
grpcAddr = hybridVSockScheme + ":" + hvsocket[0]
default: default:
return "", nil, grpcStatus.Errorf(codes.InvalidArgument, "Invalid scheme: %s", sock) return "", nil, grpcStatus.Errorf(codes.InvalidArgument, "Invalid scheme: %s", sock)
} }
@ -190,6 +211,8 @@ func agentDialer(addr *url.URL, enableYamux bool) dialer {
switch addr.Scheme { switch addr.Scheme {
case vsockSocketScheme: case vsockSocketScheme:
d = vsockDialer d = vsockDialer
case hybridVSockScheme:
d = hybridVSockDialer
case unixSocketScheme: case unixSocketScheme:
fallthrough fallthrough
default: default:
@ -274,6 +297,18 @@ func parseGrpcVsockAddr(sock string) (uint32, uint32, error) {
return uint32(cid), uint32(port), nil return uint32(cid), uint32(port), nil
} }
func parseGrpcHybridVSockAddr(sock string) (string, error) {
sp := strings.Split(sock, ":")
if len(sp) != 2 {
return "", grpcStatus.Errorf(codes.InvalidArgument, "Invalid hybrid vsock address: %s", sock)
}
if sp[0] != hybridVSockScheme {
return "", grpcStatus.Errorf(codes.InvalidArgument, "Invalid hybrid vsock URL scheme: %s", sock)
}
return sp[1], nil
}
// This would bypass the grpc dialer backoff strategy and handle dial timeout // This would bypass the grpc dialer backoff strategy and handle dial timeout
// internally. Because we do not have a large number of concurrent dialers, // internally. Because we do not have a large number of concurrent dialers,
// it is not reasonable to have such aggressive backoffs which would kill kata // it is not reasonable to have such aggressive backoffs which would kill kata
@ -335,3 +370,37 @@ func vsockDialer(sock string, timeout time.Duration) (net.Conn, error) {
return commonDialer(timeout, dialFunc, timeoutErr) return commonDialer(timeout, dialFunc, timeoutErr)
} }
func hybridVSockDialer(sock string, timeout time.Duration) (net.Conn, error) {
udsPath, err := parseGrpcHybridVSockAddr(sock)
if err != nil {
return nil, err
}
dialFunc := func() (net.Conn, error) {
conn, err := net.DialTimeout("unix", udsPath, timeout)
if err != nil {
return nil, err
}
// Once the connection is opened, the following command MUST BE sent,
// the hypervisor needs to know the port number where the agent is listening in order to
// create the connection
if _, err = conn.Write([]byte(fmt.Sprintf("CONNECT %d\n", hybridVSockPort))); err != nil {
conn.Close()
return nil, err
}
// Read EOT (End of transmission) byte
eot := make([]byte, 32)
if _, err = conn.Read(eot); err != nil {
// Just close the connection, gRPC will dial again
// without errors
conn.Close()
}
return conn, nil
}
timeoutErr := grpcStatus.Errorf(codes.DeadlineExceeded, "timed out connecting to hybrid vsocket %s", sock)
return commonDialer(timeout, dialFunc, timeoutErr)
}

View File

@ -76,7 +76,7 @@ assets:
uscan-url: >- uscan-url: >-
https://github.com/firecracker-microvm/firecracker/tags https://github.com/firecracker-microvm/firecracker/tags
.*/v?(\d\S+)\.tar\.gz .*/v?(\d\S+)\.tar\.gz
version: "v0.17.0" version: "v0.18.0"
nemu: nemu:
description: "Reduced-emulation VMM that uses KVM" description: "Reduced-emulation VMM that uses KVM"

View File

@ -547,7 +547,7 @@ func (a *acrn) addDevice(devInfo interface{}, devType deviceType) error {
err = nil err = nil
case types.Socket: case types.Socket:
a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v) a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v)
case kataVSOCK: case types.VSock:
// Not supported. return success // Not supported. return success
err = nil err = nil
case Endpoint: case Endpoint:
@ -657,3 +657,7 @@ func (a *acrn) check() error {
return nil return nil
} }
func (a *acrn) generateSocket(id string, useVsock bool) (interface{}, error) {
return generateVMSocket(id, useVsock)
}

View File

@ -121,6 +121,7 @@ func newTestSandboxConfigNoop() SandboxConfig {
func newTestSandboxConfigKataAgent() SandboxConfig { func newTestSandboxConfigKataAgent() SandboxConfig {
sandboxConfig := newTestSandboxConfigNoop() sandboxConfig := newTestSandboxConfigNoop()
sandboxConfig.AgentType = KataContainersAgent sandboxConfig.AgentType = KataContainersAgent
sandboxConfig.AgentConfig = KataAgentConfig{}
sandboxConfig.Containers = nil sandboxConfig.Containers = nil
return sandboxConfig return sandboxConfig

View File

@ -30,7 +30,9 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/blang/semver"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
fcmodels "github.com/kata-containers/runtime/virtcontainers/pkg/firecracker/client/models"
"github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/kata-containers/runtime/virtcontainers/utils" "github.com/kata-containers/runtime/virtcontainers/utils"
@ -58,8 +60,17 @@ const (
// We attach a pool of placeholder drives before the guest has started, and then // We attach a pool of placeholder drives before the guest has started, and then
// patch the replace placeholder drives with drives with actual contents. // patch the replace placeholder drives with drives with actual contents.
fcDiskPoolSize = 8 fcDiskPoolSize = 8
defaultHybridVSocketName = "kata.hvsock"
// This is the first usable vsock context ID. All the vsocks can use the same
// ID, since it's only used in the guest.
defaultGuestVSockCID = int64(0x3)
) )
// Specify the minimum version of firecracker supported
var fcMinSupportedVersion = semver.MustParse("0.18.0")
var fcKernelParams = append(commonVirtioblkKernelRootParams, []Param{ var fcKernelParams = append(commonVirtioblkKernelRootParams, []Param{
// The boot source is the first partition of the first block device added // The boot source is the first partition of the first block device added
{"pci", "off"}, {"pci", "off"},
@ -261,6 +272,8 @@ func (fc *firecracker) newFireClient() *client.Firecracker {
} }
transport := httptransport.New(client.DefaultHost, client.DefaultBasePath, client.DefaultSchemes) transport := httptransport.New(client.DefaultHost, client.DefaultBasePath, client.DefaultSchemes)
transport.SetLogger(fc.Logger())
transport.SetDebug(fc.Logger().Logger.Level == logrus.DebugLevel)
transport.Transport = socketTransport transport.Transport = socketTransport
httpClient.SetTransport(transport) httpClient.SetTransport(transport)
@ -288,6 +301,23 @@ func (fc *firecracker) vmRunning() bool {
} }
} }
func (fc *firecracker) checkVersion(vmmInfo *fcmodels.InstanceInfo) error {
if vmmInfo == nil || vmmInfo.VmmVersion == nil {
return fmt.Errorf("Unknown firecracker version")
}
v, err := semver.Make(*vmmInfo.VmmVersion)
if err != nil {
return fmt.Errorf("Malformed firecracker version: %v", err)
}
if v.LT(fcMinSupportedVersion) {
return fmt.Errorf("version %v is not supported. Minimum supported version of firecracker is %v", v.String(), fcMinSupportedVersion.String())
}
return nil
}
// waitVMM will wait for timeout seconds for the VMM to be up and running. // waitVMM will wait for timeout seconds for the VMM to be up and running.
// This does not mean that the VM is up and running. It only indicates that the VMM is up and // This does not mean that the VM is up and running. It only indicates that the VMM is up and
// running and able to handle commands to setup and launch a VM // running and able to handle commands to setup and launch a VM
@ -301,8 +331,11 @@ func (fc *firecracker) waitVMM(timeout int) error {
timeStart := time.Now() timeStart := time.Now()
for { for {
_, err := fc.client().Operations.DescribeInstance(nil) vmmInfo, err := fc.client().Operations.DescribeInstance(nil)
if err == nil { if err == nil {
if err := fc.checkVersion(vmmInfo.Payload); err != nil {
return err
}
return nil return nil
} }
@ -735,28 +768,33 @@ func (fc *firecracker) resumeSandbox() error {
return nil return nil
} }
func (fc *firecracker) fcAddVsock(vs kataVSOCK) error { func (fc *firecracker) fcAddVsock(hvs types.HybridVSock) error {
span, _ := fc.trace("fcAddVsock") span, _ := fc.trace("fcAddVsock")
defer span.Finish() defer span.Finish()
udsPath := hvs.UdsPath
if fc.jailed {
udsPath = filepath.Join("/", defaultHybridVSocketName)
}
vsockParams := ops.NewPutGuestVsockByIDParams() vsockParams := ops.NewPutGuestVsockByIDParams()
vsockID := "root" vsockID := "root"
ctxID := int64(vs.contextID) ctxID := defaultGuestVSockCID
vsock := &models.Vsock{ vsock := &models.Vsock{
GuestCid: &ctxID, GuestCid: &ctxID,
ID: &vsockID, UdsPath: &udsPath,
VsockID: &vsockID,
} }
vsockParams.SetID(vsockID) vsockParams.SetID(vsockID)
vsockParams.SetBody(vsock) vsockParams.SetBody(vsock)
_, _, err := fc.client().Operations.PutGuestVsockByID(vsockParams)
_, err := fc.client().Operations.PutGuestVsockByID(vsockParams)
if err != nil { if err != nil {
return err return err
} }
//Still racy. There is no way to send an fd to the firecracker
//REST API. We could release this just before we start the instance
//but even that will not eliminate the race
vs.vhostFd.Close()
return nil return nil
} }
func (fc *firecracker) fcAddNetDevice(endpoint Endpoint) error { func (fc *firecracker) fcAddNetDevice(endpoint Endpoint) error {
@ -874,8 +912,8 @@ func (fc *firecracker) addDevice(devInfo interface{}, devType deviceType) error
case config.BlockDrive: case config.BlockDrive:
fc.Logger().WithField("device-type-blockdrive", devInfo).Info("Adding device") fc.Logger().WithField("device-type-blockdrive", devInfo).Info("Adding device")
return fc.fcAddBlockDrive(v) return fc.fcAddBlockDrive(v)
case kataVSOCK: case types.HybridVSock:
fc.Logger().WithField("device-type-vsock", devInfo).Info("Adding device") fc.Logger().WithField("device-type-hybrid-vsock", devInfo).Info("Adding device")
return fc.fcAddVsock(v) return fc.fcAddVsock(v)
default: default:
fc.Logger().WithField("unknown-device-type", devInfo).Error("Adding device") fc.Logger().WithField("unknown-device-type", devInfo).Error("Adding device")
@ -1014,3 +1052,17 @@ func (fc *firecracker) check() error {
return nil return nil
} }
func (fc *firecracker) generateSocket(id string, useVsock bool) (interface{}, error) {
if !useVsock {
return nil, fmt.Errorf("Can't start firecracker: vsocks is disabled")
}
fc.Logger().Debug("Using hybrid-vsock endpoint")
udsPath := filepath.Join(fc.jailerRoot, defaultHybridVSocketName)
return types.HybridVSock{
UdsPath: udsPath,
Port: uint32(vSockPort),
}, nil
}

31
virtcontainers/fc_test.go Normal file
View File

@ -0,0 +1,31 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"testing"
"github.com/kata-containers/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert"
)
func TestFCGenerateSocket(t *testing.T) {
assert := assert.New(t)
fc := firecracker{}
i, err := fc.generateSocket("a", false)
assert.Error(err)
assert.Nil(i)
i, err = fc.generateSocket("a", true)
assert.NoError(err)
assert.NotNil(i)
hvsock, ok := i.(types.HybridVSock)
assert.True(ok)
assert.NotEmpty(hvsock.UdsPath)
assert.NotZero(hvsock.Port)
}

View File

@ -10,6 +10,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -18,6 +19,7 @@ import (
persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api"
"github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/kata-containers/runtime/virtcontainers/utils"
) )
// HypervisorType describes an hypervisor type. // HypervisorType describes an hypervisor type.
@ -52,6 +54,15 @@ const (
defaultBridges = 1 defaultBridges = 1
defaultBlockDriver = config.VirtioSCSI defaultBlockDriver = config.VirtioSCSI
defaultSocketName = "kata.sock"
defaultSocketDeviceID = "channel0"
defaultSocketChannelName = "agent.channel.0"
defaultSocketID = "charch0"
// port numbers below 1024 are called privileged ports. Only a process with
// CAP_NET_BIND_SERVICE capability may bind to these port numbers.
vSockPort = 1024
) )
// In some architectures the maximum number of vCPUs depends on the number of physical cores. // In some architectures the maximum number of vCPUs depends on the number of physical cores.
@ -104,6 +115,10 @@ const (
// memoryDevice is memory device type // memoryDevice is memory device type
memoryDev memoryDev
// hybridVirtioVsockDev is a hybrid virtio-vsock device supported
// only on certain hypervisors, like firecracker.
hybridVirtioVsockDev
) )
type memoryDevice struct { type memoryDevice struct {
@ -659,6 +674,33 @@ func getHypervisorPid(h hypervisor) int {
return pids[0] return pids[0]
} }
func generateVMSocket(id string, useVsock bool) (interface{}, error) {
if useVsock {
vhostFd, contextID, err := utils.FindContextID()
if err != nil {
return nil, err
}
return types.VSock{
VhostFd: vhostFd,
ContextID: contextID,
Port: uint32(vSockPort),
}, nil
}
path, err := utils.BuildSocketPath(filepath.Join(store.RunVMStoragePath, id), defaultSocketName)
if err != nil {
return nil, err
}
return types.Socket{
DeviceID: defaultSocketDeviceID,
ID: defaultSocketID,
HostPath: path,
Name: defaultSocketChannelName,
}, nil
}
// hypervisor is the virtcontainers hypervisor interface. // hypervisor is the virtcontainers hypervisor interface.
// The default hypervisor implementation is Qemu. // The default hypervisor implementation is Qemu.
type hypervisor interface { type hypervisor interface {
@ -688,4 +730,7 @@ type hypervisor interface {
save() persistapi.HypervisorState save() persistapi.HypervisorState
load(persistapi.HypervisorState) load(persistapi.HypervisorState)
// generate the socket to communicate the host and guest
generateSocket(id string, useVsock bool) (interface{}, error)
} }

View File

@ -12,6 +12,8 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
ktu "github.com/kata-containers/runtime/pkg/katatestutils"
"github.com/kata-containers/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -435,3 +437,28 @@ func genericTestRunningOnVMM(t *testing.T, data []testNestedVMMData) {
assert.Equal(running, d.expected) assert.Equal(running, d.expected)
} }
} }
func TestGenerateVMSocket(t *testing.T) {
assert := assert.New(t)
s, err := generateVMSocket("a", false)
assert.NoError(err)
socket, ok := s.(types.Socket)
assert.True(ok)
assert.NotEmpty(socket.DeviceID)
assert.NotEmpty(socket.ID)
assert.NotEmpty(socket.HostPath)
assert.NotEmpty(socket.Name)
if tc.NotValid(ktu.NeedRoot()) {
t.Skip(testDisabledAsNonRoot)
}
s, err = generateVMSocket("a", true)
assert.NoError(err)
vsock, ok := s.(types.VSock)
assert.True(ok)
defer assert.NoError(vsock.VhostFd.Close())
assert.NotZero(vsock.VhostFd)
assert.NotZero(vsock.ContextID)
assert.NotZero(vsock.Port)
}

View File

@ -31,7 +31,6 @@ import (
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
"github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/kata-containers/runtime/virtcontainers/utils"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -53,25 +52,17 @@ const (
) )
var ( var (
checkRequestTimeout = 30 * time.Second checkRequestTimeout = 30 * time.Second
defaultRequestTimeout = 60 * time.Second defaultRequestTimeout = 60 * time.Second
defaultKataSocketName = "kata.sock" errorMissingProxy = errors.New("Missing proxy pointer")
defaultKataChannel = "agent.channel.0" errorMissingOCISpec = errors.New("Missing OCI specification")
defaultKataDeviceID = "channel0" kataHostSharedDir = "/run/kata-containers/shared/sandboxes/"
defaultKataID = "charch0" kataGuestSharedDir = "/run/kata-containers/shared/containers/"
errorMissingProxy = errors.New("Missing proxy pointer") mountGuest9pTag = "kataShared"
errorMissingOCISpec = errors.New("Missing OCI specification") kataGuestSandboxDir = "/run/kata-containers/sandbox/"
kataHostSharedDir = "/run/kata-containers/shared/sandboxes/" type9pFs = "9p"
kataGuestSharedDir = "/run/kata-containers/shared/containers/" typeVirtioFS = "virtio_fs"
mountGuest9pTag = "kataShared" typeVirtioFSNoCache = "none"
kataGuestSandboxDir = "/run/kata-containers/sandbox/"
type9pFs = "9p"
typeVirtioFS = "virtio_fs"
typeVirtioFSNoCache = "none"
vsockSocketScheme = "vsock"
// port numbers below 1024 are called privileged ports. Only a process with
// CAP_NET_BIND_SERVICE capability may bind to these port numbers.
vSockPort = 1024
kata9pDevType = "9p" kata9pDevType = "9p"
kataMmioBlkDevType = "mmioblk" kataMmioBlkDevType = "mmioblk"
kataBlkDevType = "blk" kataBlkDevType = "blk"
@ -145,16 +136,6 @@ type KataAgentConfig struct {
KernelModules []string KernelModules []string
} }
type kataVSOCK struct {
contextID uint64
port uint32
vhostFd *os.File
}
func (s *kataVSOCK) String() string {
return fmt.Sprintf("%s://%d:%d", vsockSocketScheme, s.contextID, s.port)
}
// KataAgentState is the structure describing the data stored from this // KataAgentState is the structure describing the data stored from this
// agent implementation. // agent implementation.
type KataAgentState struct { type KataAgentState struct {
@ -208,31 +189,6 @@ func (k *kataAgent) getSharePath(id string) string {
return filepath.Join(kataHostSharedDir, id) return filepath.Join(kataHostSharedDir, id)
} }
func (k *kataAgent) generateVMSocket(id string, c KataAgentConfig) error {
if c.UseVSock {
// We want to go through VSOCK. The VM VSOCK endpoint will be our gRPC.
k.Logger().Debug("agent: Using vsock VM socket endpoint")
// We dont know yet the context ID - set empty vsock configuration
k.vmSocket = kataVSOCK{}
} else {
k.Logger().Debug("agent: Using unix socket form VM socket endpoint")
// We need to generate a host UNIX socket path for the emulated serial port.
kataSock, err := utils.BuildSocketPath(k.getVMPath(id), defaultKataSocketName)
if err != nil {
return err
}
k.vmSocket = types.Socket{
DeviceID: defaultKataDeviceID,
ID: defaultKataID,
HostPath: kataSock,
Name: defaultKataChannel,
}
}
return nil
}
// KataAgentSetDefaultTraceConfigOptions validates agent trace options and // KataAgentSetDefaultTraceConfigOptions validates agent trace options and
// sets defaults. // sets defaults.
func KataAgentSetDefaultTraceConfigOptions(config *KataAgentConfig) error { func KataAgentSetDefaultTraceConfigOptions(config *KataAgentConfig) error {
@ -303,10 +259,6 @@ func (k *kataAgent) init(ctx context.Context, sandbox *Sandbox, config interface
switch c := config.(type) { switch c := config.(type) {
case KataAgentConfig: case KataAgentConfig:
if err := k.generateVMSocket(sandbox.id, c); err != nil {
return false, err
}
disableVMShutdown = k.handleTraceSettings(c) disableVMShutdown = k.handleTraceSettings(c)
k.keepConn = c.LongLiveConn k.keepConn = c.LongLiveConn
k.kmodules = c.KernelModules k.kmodules = c.KernelModules
@ -340,7 +292,9 @@ func (k *kataAgent) agentURL() (string, error) {
switch s := k.vmSocket.(type) { switch s := k.vmSocket.(type) {
case types.Socket: case types.Socket:
return s.HostPath, nil return s.HostPath, nil
case kataVSOCK: case types.VSock:
return s.String(), nil
case types.HybridVSock:
return s.String(), nil return s.String(), nil
default: default:
return "", fmt.Errorf("Invalid socket type") return "", fmt.Errorf("Invalid socket type")
@ -357,10 +311,11 @@ func (k *kataAgent) capabilities() types.Capabilities {
} }
func (k *kataAgent) internalConfigure(h hypervisor, id, sharePath string, builtin bool, config interface{}) error { func (k *kataAgent) internalConfigure(h hypervisor, id, sharePath string, builtin bool, config interface{}) error {
var err error
if config != nil { if config != nil {
switch c := config.(type) { switch c := config.(type) {
case KataAgentConfig: case KataAgentConfig:
if err := k.generateVMSocket(id, c); err != nil { if k.vmSocket, err = h.generateSocket(id, c.UseVSock); err != nil {
return err return err
} }
k.keepConn = c.LongLiveConn k.keepConn = c.LongLiveConn
@ -388,16 +343,15 @@ func (k *kataAgent) configure(h hypervisor, id, sharePath string, builtin bool,
if err != nil { if err != nil {
return err return err
} }
case kataVSOCK: case types.VSock:
s.vhostFd, s.contextID, err = utils.FindContextID()
if err != nil {
return err
}
s.port = uint32(vSockPort)
if err = h.addDevice(s, vSockPCIDev); err != nil { if err = h.addDevice(s, vSockPCIDev); err != nil {
return err return err
} }
k.vmSocket = s case types.HybridVSock:
err = h.addDevice(s, hybridVirtioVsockDev)
if err != nil {
return err
}
default: default:
return vcTypes.ErrInvalidConfigType return vcTypes.ErrInvalidConfigType
} }
@ -431,7 +385,7 @@ func (k *kataAgent) createSandbox(sandbox *Sandbox) error {
span, _ := k.trace("createSandbox") span, _ := k.trace("createSandbox")
defer span.Finish() defer span.Finish()
return k.configure(sandbox.hypervisor, sandbox.id, k.getSharePath(sandbox.id), k.proxyBuiltIn, nil) return k.configure(sandbox.hypervisor, sandbox.id, k.getSharePath(sandbox.id), k.proxyBuiltIn, sandbox.config.AgentConfig)
} }
func cmdToKataProcess(cmd types.Cmd) (process *grpc.Process, err error) { func cmdToKataProcess(cmd types.Cmd) (process *grpc.Process, err error) {

View File

@ -627,25 +627,6 @@ func TestAgentPathAPI(t *testing.T) {
path1 = k1.getSharePath(id) path1 = k1.getSharePath(id)
path2 = k2.getSharePath(id) path2 = k2.getSharePath(id)
assert.Equal(path1, path2) assert.Equal(path1, path2)
// generateVMSocket
c := KataAgentConfig{}
err := k1.generateVMSocket(id, c)
assert.Nil(err)
err = k2.generateVMSocket(id, c)
assert.Nil(err)
assert.Equal(k1, k2)
err = k1.generateVMSocket(id, c)
assert.Nil(err)
_, ok := k1.vmSocket.(types.Socket)
assert.True(ok)
c.UseVSock = true
err = k2.generateVMSocket(id, c)
assert.Nil(err)
_, ok = k2.vmSocket.(kataVSOCK)
assert.True(ok)
} }
func TestAgentConfigure(t *testing.T) { func TestAgentConfigure(t *testing.T) {
@ -843,20 +824,19 @@ func TestKataAgentSetProxy(t *testing.T) {
func TestKataGetAgentUrl(t *testing.T) { func TestKataGetAgentUrl(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
var err error
k := &kataAgent{} k := &kataAgent{vmSocket: types.Socket{HostPath: "/abc"}}
err := k.generateVMSocket("foobar", KataAgentConfig{}) assert.NoError(err)
assert.Nil(err)
url, err := k.getAgentURL() url, err := k.getAgentURL()
assert.Nil(err) assert.Nil(err)
assert.NotEmpty(url) assert.NotEmpty(url)
err = k.generateVMSocket("foobar", KataAgentConfig{UseVSock: true}) k.vmSocket = types.VSock{}
assert.Nil(err) assert.NoError(err)
url, err = k.getAgentURL() url, err = k.getAgentURL()
assert.Nil(err) assert.Nil(err)
assert.NotEmpty(url) assert.NotEmpty(url)
} }
func TestKataCopyFile(t *testing.T) { func TestKataCopyFile(t *testing.T) {

View File

@ -125,3 +125,7 @@ func (m *mockHypervisor) load(s persistapi.HypervisorState) {}
func (m *mockHypervisor) check() error { func (m *mockHypervisor) check() error {
return nil return nil
} }
func (m *mockHypervisor) generateSocket(id string, useVsock bool) (interface{}, error) {
return types.Socket{HostPath: "/tmp/socket", Name: "socket"}, nil
}

View File

@ -88,3 +88,11 @@ func TestMockHypervisorCheck(t *testing.T) {
assert.NoError(t, m.check()) assert.NoError(t, m.check())
} }
func TestMockGenerateSocket(t *testing.T) {
var m *mockHypervisor
i, err := m.generateSocket("a", true)
assert.NoError(t, err)
assert.NotNil(t, i)
}

View File

@ -13,7 +13,7 @@ import (
"github.com/go-openapi/validate" "github.com/go-openapi/validate"
) )
// Vsock vsock // Vsock Defines a vsock device, backed by a set of Unix Domain Sockets, on the host side. For host-initiated connections, Firecracker will be listening on the Unix socket identified by the path `uds_path`. Firecracker will create this socket, bind and listen on it. Host-initiated connections will be performed by connection to this socket and issuing a connection forwarding request to the desired guest-side vsock port (i.e. `CONNECT 52\n`, to connect to port 52). For guest-initiated connections, Firecracker will expect host software to be bound and listening on Unix sockets at `uds_path_<PORT>`. E.g. "/path/to/host_vsock.sock_52" for port number 52.
// swagger:model Vsock // swagger:model Vsock
type Vsock struct { type Vsock struct {
@ -22,9 +22,13 @@ type Vsock struct {
// Minimum: 3 // Minimum: 3
GuestCid *int64 `json:"guest_cid"` GuestCid *int64 `json:"guest_cid"`
// id // Path to UNIX domain socket, used to proxy vsock connections.
// Required: true // Required: true
ID *string `json:"id"` UdsPath *string `json:"uds_path"`
// vsock id
// Required: true
VsockID *string `json:"vsock_id"`
} }
// Validate validates this vsock // Validate validates this vsock
@ -35,7 +39,11 @@ func (m *Vsock) Validate(formats strfmt.Registry) error {
res = append(res, err) res = append(res, err)
} }
if err := m.validateID(formats); err != nil { if err := m.validateUdsPath(formats); err != nil {
res = append(res, err)
}
if err := m.validateVsockID(formats); err != nil {
res = append(res, err) res = append(res, err)
} }
@ -58,9 +66,18 @@ func (m *Vsock) validateGuestCid(formats strfmt.Registry) error {
return nil return nil
} }
func (m *Vsock) validateID(formats strfmt.Registry) error { func (m *Vsock) validateUdsPath(formats strfmt.Registry) error {
if err := validate.Required("id", "body", m.ID); err != nil { if err := validate.Required("uds_path", "body", m.UdsPath); err != nil {
return err
}
return nil
}
func (m *Vsock) validateVsockID(formats strfmt.Registry) error {
if err := validate.Required("vsock_id", "body", m.VsockID); err != nil {
return err return err
} }

View File

@ -24,21 +24,18 @@ type CreateSyncActionReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *CreateSyncActionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *CreateSyncActionReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewCreateSyncActionNoContent() result := NewCreateSyncActionNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewCreateSyncActionBadRequest() result := NewCreateSyncActionBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewCreateSyncActionDefault(response.Code()) result := NewCreateSyncActionDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *CreateSyncActionBadRequest) Error() string {
return fmt.Sprintf("[PUT /actions][%d] createSyncActionBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /actions][%d] createSyncActionBadRequest %+v", 400, o.Payload)
} }
func (o *CreateSyncActionBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *CreateSyncActionBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *CreateSyncActionBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *CreateSyncActionDefault) Error() string {
return fmt.Sprintf("[PUT /actions][%d] createSyncAction default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /actions][%d] createSyncAction default %+v", o._statusCode, o.Payload)
} }
func (o *CreateSyncActionDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *CreateSyncActionDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *CreateSyncActionDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,14 +24,12 @@ type DescribeInstanceReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *DescribeInstanceReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *DescribeInstanceReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 200: case 200:
result := NewDescribeInstanceOK() result := NewDescribeInstanceOK()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
default: default:
result := NewDescribeInstanceDefault(response.Code()) result := NewDescribeInstanceDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -61,6 +59,10 @@ func (o *DescribeInstanceOK) Error() string {
return fmt.Sprintf("[GET /][%d] describeInstanceOK %+v", 200, o.Payload) return fmt.Sprintf("[GET /][%d] describeInstanceOK %+v", 200, o.Payload)
} }
func (o *DescribeInstanceOK) GetPayload() *models.InstanceInfo {
return o.Payload
}
func (o *DescribeInstanceOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *DescribeInstanceOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.InstanceInfo) o.Payload = new(models.InstanceInfo)
@ -99,6 +101,10 @@ func (o *DescribeInstanceDefault) Error() string {
return fmt.Sprintf("[GET /][%d] describeInstance default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[GET /][%d] describeInstance default %+v", o._statusCode, o.Payload)
} }
func (o *DescribeInstanceDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *DescribeInstanceDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *DescribeInstanceDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,14 +24,12 @@ type GetMachineConfigurationReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *GetMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *GetMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 200: case 200:
result := NewGetMachineConfigurationOK() result := NewGetMachineConfigurationOK()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
default: default:
result := NewGetMachineConfigurationDefault(response.Code()) result := NewGetMachineConfigurationDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -61,6 +59,10 @@ func (o *GetMachineConfigurationOK) Error() string {
return fmt.Sprintf("[GET /machine-config][%d] getMachineConfigurationOK %+v", 200, o.Payload) return fmt.Sprintf("[GET /machine-config][%d] getMachineConfigurationOK %+v", 200, o.Payload)
} }
func (o *GetMachineConfigurationOK) GetPayload() *models.MachineConfiguration {
return o.Payload
}
func (o *GetMachineConfigurationOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetMachineConfigurationOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.MachineConfiguration) o.Payload = new(models.MachineConfiguration)
@ -99,6 +101,10 @@ func (o *GetMachineConfigurationDefault) Error() string {
return fmt.Sprintf("[GET /machine-config][%d] getMachineConfiguration default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[GET /machine-config][%d] getMachineConfiguration default %+v", o._statusCode, o.Payload)
} }
func (o *GetMachineConfigurationDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *GetMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type GetMmdsReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *GetMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *GetMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 200: case 200:
result := NewGetMmdsOK() result := NewGetMmdsOK()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewGetMmdsBadRequest() result := NewGetMmdsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewGetMmdsDefault(response.Code()) result := NewGetMmdsDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -68,6 +65,10 @@ func (o *GetMmdsOK) Error() string {
return fmt.Sprintf("[GET /mmds][%d] getMmdsOK %+v", 200, o.Payload) return fmt.Sprintf("[GET /mmds][%d] getMmdsOK %+v", 200, o.Payload)
} }
func (o *GetMmdsOK) GetPayload() interface{} {
return o.Payload
}
func (o *GetMmdsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetMmdsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload // response payload
@ -95,6 +96,10 @@ func (o *GetMmdsBadRequest) Error() string {
return fmt.Sprintf("[GET /mmds][%d] getMmdsBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[GET /mmds][%d] getMmdsBadRequest %+v", 400, o.Payload)
} }
func (o *GetMmdsBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *GetMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -133,6 +138,10 @@ func (o *GetMmdsDefault) Error() string {
return fmt.Sprintf("[GET /mmds][%d] GetMmds default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[GET /mmds][%d] GetMmds default %+v", o._statusCode, o.Payload)
} }
func (o *GetMmdsDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *GetMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *GetMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -48,8 +48,13 @@ func (a *Client) GetMmds(params *GetMmdsParams) (*GetMmdsOK, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*GetMmdsOK), nil success, ok := result.(*GetMmdsOK)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*GetMmdsDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -76,8 +81,13 @@ func (a *Client) PatchMmds(params *PatchMmdsParams) (*PatchMmdsNoContent, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PatchMmdsNoContent), nil success, ok := result.(*PatchMmdsNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PatchMmdsDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -104,8 +114,13 @@ func (a *Client) PutMmds(params *PutMmdsParams) (*PutMmdsNoContent, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutMmdsNoContent), nil success, ok := result.(*PutMmdsNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutMmdsDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -132,8 +147,13 @@ func (a *Client) CreateSyncAction(params *CreateSyncActionParams) (*CreateSyncAc
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*CreateSyncActionNoContent), nil success, ok := result.(*CreateSyncActionNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*CreateSyncActionDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -160,8 +180,13 @@ func (a *Client) DescribeInstance(params *DescribeInstanceParams) (*DescribeInst
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*DescribeInstanceOK), nil success, ok := result.(*DescribeInstanceOK)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*DescribeInstanceDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -190,8 +215,13 @@ func (a *Client) GetMachineConfiguration(params *GetMachineConfigurationParams)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*GetMachineConfigurationOK), nil success, ok := result.(*GetMachineConfigurationOK)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*GetMachineConfigurationDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -220,8 +250,13 @@ func (a *Client) PatchGuestDriveByID(params *PatchGuestDriveByIDParams) (*PatchG
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PatchGuestDriveByIDNoContent), nil success, ok := result.(*PatchGuestDriveByIDNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PatchGuestDriveByIDDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -250,8 +285,13 @@ func (a *Client) PatchGuestNetworkInterfaceByID(params *PatchGuestNetworkInterfa
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PatchGuestNetworkInterfaceByIDNoContent), nil success, ok := result.(*PatchGuestNetworkInterfaceByIDNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PatchGuestNetworkInterfaceByIDDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -280,8 +320,13 @@ func (a *Client) PatchMachineConfiguration(params *PatchMachineConfigurationPara
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PatchMachineConfigurationNoContent), nil success, ok := result.(*PatchMachineConfigurationNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PatchMachineConfigurationDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -310,8 +355,13 @@ func (a *Client) PutGuestBootSource(params *PutGuestBootSourceParams) (*PutGuest
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutGuestBootSourceNoContent), nil success, ok := result.(*PutGuestBootSourceNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutGuestBootSourceDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -340,8 +390,13 @@ func (a *Client) PutGuestDriveByID(params *PutGuestDriveByIDParams) (*PutGuestDr
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutGuestDriveByIDNoContent), nil success, ok := result.(*PutGuestDriveByIDNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutGuestDriveByIDDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -370,8 +425,13 @@ func (a *Client) PutGuestNetworkInterfaceByID(params *PutGuestNetworkInterfaceBy
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutGuestNetworkInterfaceByIDNoContent), nil success, ok := result.(*PutGuestNetworkInterfaceByIDNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutGuestNetworkInterfaceByIDDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -379,7 +439,7 @@ PutGuestVsockByID creates new vsock with ID specified by the id parameter
If the vsock device with the specified ID already exists, its body will be updated based on the new input. May fail if update is not possible. If the vsock device with the specified ID already exists, its body will be updated based on the new input. May fail if update is not possible.
*/ */
func (a *Client) PutGuestVsockByID(params *PutGuestVsockByIDParams) (*PutGuestVsockByIDCreated, *PutGuestVsockByIDNoContent, error) { func (a *Client) PutGuestVsockByID(params *PutGuestVsockByIDParams) (*PutGuestVsockByIDNoContent, error) {
// TODO: Validate the params before sending // TODO: Validate the params before sending
if params == nil { if params == nil {
params = NewPutGuestVsockByIDParams() params = NewPutGuestVsockByIDParams()
@ -398,16 +458,15 @@ func (a *Client) PutGuestVsockByID(params *PutGuestVsockByIDParams) (*PutGuestVs
Client: params.HTTPClient, Client: params.HTTPClient,
}) })
if err != nil { if err != nil {
return nil, nil, err return nil, err
} }
switch value := result.(type) { success, ok := result.(*PutGuestVsockByIDNoContent)
case *PutGuestVsockByIDCreated: if ok {
return value, nil, nil return success, nil
case *PutGuestVsockByIDNoContent:
return nil, value, nil
} }
return nil, nil, nil // unexpected success response
unexpectedSuccess := result.(*PutGuestVsockByIDDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -434,8 +493,13 @@ func (a *Client) PutLogger(params *PutLoggerParams) (*PutLoggerNoContent, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutLoggerNoContent), nil success, ok := result.(*PutLoggerNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutLoggerDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
/* /*
@ -464,8 +528,13 @@ func (a *Client) PutMachineConfiguration(params *PutMachineConfigurationParams)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return result.(*PutMachineConfigurationNoContent), nil success, ok := result.(*PutMachineConfigurationNoContent)
if ok {
return success, nil
}
// unexpected success response
unexpectedSuccess := result.(*PutMachineConfigurationDefault)
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
} }
// SetTransport changes the transport on the client // SetTransport changes the transport on the client

View File

@ -24,21 +24,18 @@ type PatchGuestDriveByIDReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PatchGuestDriveByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PatchGuestDriveByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPatchGuestDriveByIDNoContent() result := NewPatchGuestDriveByIDNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPatchGuestDriveByIDBadRequest() result := NewPatchGuestDriveByIDBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPatchGuestDriveByIDDefault(response.Code()) result := NewPatchGuestDriveByIDDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PatchGuestDriveByIDBadRequest) Error() string {
return fmt.Sprintf("[PATCH /drives/{drive_id}][%d] patchGuestDriveByIdBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PATCH /drives/{drive_id}][%d] patchGuestDriveByIdBadRequest %+v", 400, o.Payload)
} }
func (o *PatchGuestDriveByIDBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchGuestDriveByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchGuestDriveByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PatchGuestDriveByIDDefault) Error() string {
return fmt.Sprintf("[PATCH /drives/{drive_id}][%d] patchGuestDriveByID default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PATCH /drives/{drive_id}][%d] patchGuestDriveByID default %+v", o._statusCode, o.Payload)
} }
func (o *PatchGuestDriveByIDDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchGuestDriveByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchGuestDriveByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PatchGuestNetworkInterfaceByIDReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PatchGuestNetworkInterfaceByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PatchGuestNetworkInterfaceByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPatchGuestNetworkInterfaceByIDNoContent() result := NewPatchGuestNetworkInterfaceByIDNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPatchGuestNetworkInterfaceByIDBadRequest() result := NewPatchGuestNetworkInterfaceByIDBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPatchGuestNetworkInterfaceByIDDefault(response.Code()) result := NewPatchGuestNetworkInterfaceByIDDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PatchGuestNetworkInterfaceByIDBadRequest) Error() string {
return fmt.Sprintf("[PATCH /network-interfaces/{iface_id}][%d] patchGuestNetworkInterfaceByIdBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PATCH /network-interfaces/{iface_id}][%d] patchGuestNetworkInterfaceByIdBadRequest %+v", 400, o.Payload)
} }
func (o *PatchGuestNetworkInterfaceByIDBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchGuestNetworkInterfaceByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchGuestNetworkInterfaceByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PatchGuestNetworkInterfaceByIDDefault) Error() string {
return fmt.Sprintf("[PATCH /network-interfaces/{iface_id}][%d] patchGuestNetworkInterfaceByID default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PATCH /network-interfaces/{iface_id}][%d] patchGuestNetworkInterfaceByID default %+v", o._statusCode, o.Payload)
} }
func (o *PatchGuestNetworkInterfaceByIDDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchGuestNetworkInterfaceByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchGuestNetworkInterfaceByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PatchMachineConfigurationReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PatchMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PatchMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPatchMachineConfigurationNoContent() result := NewPatchMachineConfigurationNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPatchMachineConfigurationBadRequest() result := NewPatchMachineConfigurationBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPatchMachineConfigurationDefault(response.Code()) result := NewPatchMachineConfigurationDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PatchMachineConfigurationBadRequest) Error() string {
return fmt.Sprintf("[PATCH /machine-config][%d] patchMachineConfigurationBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PATCH /machine-config][%d] patchMachineConfigurationBadRequest %+v", 400, o.Payload)
} }
func (o *PatchMachineConfigurationBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchMachineConfigurationBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchMachineConfigurationBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PatchMachineConfigurationDefault) Error() string {
return fmt.Sprintf("[PATCH /machine-config][%d] patchMachineConfiguration default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PATCH /machine-config][%d] patchMachineConfiguration default %+v", o._statusCode, o.Payload)
} }
func (o *PatchMachineConfigurationDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PatchMmdsReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PatchMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PatchMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPatchMmdsNoContent() result := NewPatchMmdsNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPatchMmdsBadRequest() result := NewPatchMmdsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPatchMmdsDefault(response.Code()) result := NewPatchMmdsDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PatchMmdsBadRequest) Error() string {
return fmt.Sprintf("[PATCH /mmds][%d] patchMmdsBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PATCH /mmds][%d] patchMmdsBadRequest %+v", 400, o.Payload)
} }
func (o *PatchMmdsBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PatchMmdsDefault) Error() string {
return fmt.Sprintf("[PATCH /mmds][%d] PatchMmds default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PATCH /mmds][%d] PatchMmds default %+v", o._statusCode, o.Payload)
} }
func (o *PatchMmdsDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PatchMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PatchMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutGuestBootSourceReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutGuestBootSourceReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutGuestBootSourceReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutGuestBootSourceNoContent() result := NewPutGuestBootSourceNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutGuestBootSourceBadRequest() result := NewPutGuestBootSourceBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutGuestBootSourceDefault(response.Code()) result := NewPutGuestBootSourceDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutGuestBootSourceBadRequest) Error() string {
return fmt.Sprintf("[PUT /boot-source][%d] putGuestBootSourceBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /boot-source][%d] putGuestBootSourceBadRequest %+v", 400, o.Payload)
} }
func (o *PutGuestBootSourceBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestBootSourceBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestBootSourceBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutGuestBootSourceDefault) Error() string {
return fmt.Sprintf("[PUT /boot-source][%d] putGuestBootSource default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /boot-source][%d] putGuestBootSource default %+v", o._statusCode, o.Payload)
} }
func (o *PutGuestBootSourceDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestBootSourceDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestBootSourceDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutGuestDriveByIDReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutGuestDriveByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutGuestDriveByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutGuestDriveByIDNoContent() result := NewPutGuestDriveByIDNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutGuestDriveByIDBadRequest() result := NewPutGuestDriveByIDBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutGuestDriveByIDDefault(response.Code()) result := NewPutGuestDriveByIDDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutGuestDriveByIDBadRequest) Error() string {
return fmt.Sprintf("[PUT /drives/{drive_id}][%d] putGuestDriveByIdBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /drives/{drive_id}][%d] putGuestDriveByIdBadRequest %+v", 400, o.Payload)
} }
func (o *PutGuestDriveByIDBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestDriveByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestDriveByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutGuestDriveByIDDefault) Error() string {
return fmt.Sprintf("[PUT /drives/{drive_id}][%d] putGuestDriveByID default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /drives/{drive_id}][%d] putGuestDriveByID default %+v", o._statusCode, o.Payload)
} }
func (o *PutGuestDriveByIDDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestDriveByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestDriveByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutGuestNetworkInterfaceByIDReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutGuestNetworkInterfaceByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutGuestNetworkInterfaceByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutGuestNetworkInterfaceByIDNoContent() result := NewPutGuestNetworkInterfaceByIDNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutGuestNetworkInterfaceByIDBadRequest() result := NewPutGuestNetworkInterfaceByIDBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutGuestNetworkInterfaceByIDDefault(response.Code()) result := NewPutGuestNetworkInterfaceByIDDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutGuestNetworkInterfaceByIDBadRequest) Error() string {
return fmt.Sprintf("[PUT /network-interfaces/{iface_id}][%d] putGuestNetworkInterfaceByIdBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /network-interfaces/{iface_id}][%d] putGuestNetworkInterfaceByIdBadRequest %+v", 400, o.Payload)
} }
func (o *PutGuestNetworkInterfaceByIDBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestNetworkInterfaceByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestNetworkInterfaceByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutGuestNetworkInterfaceByIDDefault) Error() string {
return fmt.Sprintf("[PUT /network-interfaces/{iface_id}][%d] putGuestNetworkInterfaceByID default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /network-interfaces/{iface_id}][%d] putGuestNetworkInterfaceByID default %+v", o._statusCode, o.Payload)
} }
func (o *PutGuestNetworkInterfaceByIDDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestNetworkInterfaceByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestNetworkInterfaceByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,28 +24,18 @@ type PutGuestVsockByIDReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutGuestVsockByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutGuestVsockByIDReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 201:
result := NewPutGuestVsockByIDCreated()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 204: case 204:
result := NewPutGuestVsockByIDNoContent() result := NewPutGuestVsockByIDNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutGuestVsockByIDBadRequest() result := NewPutGuestVsockByIDBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutGuestVsockByIDDefault(response.Code()) result := NewPutGuestVsockByIDDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -58,27 +48,6 @@ func (o *PutGuestVsockByIDReader) ReadResponse(response runtime.ClientResponse,
} }
} }
// NewPutGuestVsockByIDCreated creates a PutGuestVsockByIDCreated with default headers values
func NewPutGuestVsockByIDCreated() *PutGuestVsockByIDCreated {
return &PutGuestVsockByIDCreated{}
}
/*PutGuestVsockByIDCreated handles this case with default header values.
Vsock created
*/
type PutGuestVsockByIDCreated struct {
}
func (o *PutGuestVsockByIDCreated) Error() string {
return fmt.Sprintf("[PUT /vsocks/{id}][%d] putGuestVsockByIdCreated ", 201)
}
func (o *PutGuestVsockByIDCreated) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewPutGuestVsockByIDNoContent creates a PutGuestVsockByIDNoContent with default headers values // NewPutGuestVsockByIDNoContent creates a PutGuestVsockByIDNoContent with default headers values
func NewPutGuestVsockByIDNoContent() *PutGuestVsockByIDNoContent { func NewPutGuestVsockByIDNoContent() *PutGuestVsockByIDNoContent {
return &PutGuestVsockByIDNoContent{} return &PutGuestVsockByIDNoContent{}
@ -86,7 +55,7 @@ func NewPutGuestVsockByIDNoContent() *PutGuestVsockByIDNoContent {
/*PutGuestVsockByIDNoContent handles this case with default header values. /*PutGuestVsockByIDNoContent handles this case with default header values.
Vsock updated Vsock created/updated
*/ */
type PutGuestVsockByIDNoContent struct { type PutGuestVsockByIDNoContent struct {
} }
@ -117,6 +86,10 @@ func (o *PutGuestVsockByIDBadRequest) Error() string {
return fmt.Sprintf("[PUT /vsocks/{id}][%d] putGuestVsockByIdBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /vsocks/{id}][%d] putGuestVsockByIdBadRequest %+v", 400, o.Payload)
} }
func (o *PutGuestVsockByIDBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestVsockByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestVsockByIDBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -155,6 +128,10 @@ func (o *PutGuestVsockByIDDefault) Error() string {
return fmt.Sprintf("[PUT /vsocks/{id}][%d] putGuestVsockByID default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /vsocks/{id}][%d] putGuestVsockByID default %+v", o._statusCode, o.Payload)
} }
func (o *PutGuestVsockByIDDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutGuestVsockByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutGuestVsockByIDDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutLoggerReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutLoggerReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutLoggerReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutLoggerNoContent() result := NewPutLoggerNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutLoggerBadRequest() result := NewPutLoggerBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutLoggerDefault(response.Code()) result := NewPutLoggerDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutLoggerBadRequest) Error() string {
return fmt.Sprintf("[PUT /logger][%d] putLoggerBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /logger][%d] putLoggerBadRequest %+v", 400, o.Payload)
} }
func (o *PutLoggerBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutLoggerBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutLoggerBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutLoggerDefault) Error() string {
return fmt.Sprintf("[PUT /logger][%d] putLogger default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /logger][%d] putLogger default %+v", o._statusCode, o.Payload)
} }
func (o *PutLoggerDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutLoggerDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutLoggerDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutMachineConfigurationReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutMachineConfigurationReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutMachineConfigurationNoContent() result := NewPutMachineConfigurationNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutMachineConfigurationBadRequest() result := NewPutMachineConfigurationBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutMachineConfigurationDefault(response.Code()) result := NewPutMachineConfigurationDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutMachineConfigurationBadRequest) Error() string {
return fmt.Sprintf("[PUT /machine-config][%d] putMachineConfigurationBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /machine-config][%d] putMachineConfigurationBadRequest %+v", 400, o.Payload)
} }
func (o *PutMachineConfigurationBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutMachineConfigurationBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutMachineConfigurationBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutMachineConfigurationDefault) Error() string {
return fmt.Sprintf("[PUT /machine-config][%d] putMachineConfiguration default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /machine-config][%d] putMachineConfiguration default %+v", o._statusCode, o.Payload)
} }
func (o *PutMachineConfigurationDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutMachineConfigurationDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -24,21 +24,18 @@ type PutMmdsReader struct {
// ReadResponse reads a server response into the received o. // ReadResponse reads a server response into the received o.
func (o *PutMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { func (o *PutMmdsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() { switch response.Code() {
case 204: case 204:
result := NewPutMmdsNoContent() result := NewPutMmdsNoContent()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
case 400: case 400:
result := NewPutMmdsBadRequest() result := NewPutMmdsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err return nil, err
} }
return nil, result return nil, result
default: default:
result := NewPutMmdsDefault(response.Code()) result := NewPutMmdsDefault(response.Code())
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -89,6 +86,10 @@ func (o *PutMmdsBadRequest) Error() string {
return fmt.Sprintf("[PUT /mmds][%d] putMmdsBadRequest %+v", 400, o.Payload) return fmt.Sprintf("[PUT /mmds][%d] putMmdsBadRequest %+v", 400, o.Payload)
} }
func (o *PutMmdsBadRequest) GetPayload() *models.Error {
return o.Payload
}
func (o *PutMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutMmdsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)
@ -127,6 +128,10 @@ func (o *PutMmdsDefault) Error() string {
return fmt.Sprintf("[PUT /mmds][%d] PutMmds default %+v", o._statusCode, o.Payload) return fmt.Sprintf("[PUT /mmds][%d] PutMmds default %+v", o._statusCode, o.Payload)
} }
func (o *PutMmdsDefault) GetPayload() *models.Error {
return o.Payload
}
func (o *PutMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *PutMmdsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.Error) o.Payload = new(models.Error)

View File

@ -5,8 +5,7 @@ info:
The API is accessible through HTTP calls on specific URLs The API is accessible through HTTP calls on specific URLs
carrying JSON modeled data. carrying JSON modeled data.
The transport medium is a Unix Domain Socket. The transport medium is a Unix Domain Socket.
This API has definitions for experimental features like vsock. version: 0.18.0
version: 0.17.0
termsOfService: "" termsOfService: ""
contact: contact:
email: "compute-capsule@amazon.com" email: "compute-capsule@amazon.com"
@ -355,37 +354,35 @@ paths:
$ref: "#/definitions/Error" $ref: "#/definitions/Error"
/vsocks/{id}: /vsocks/{id}:
put: put:
summary: Creates new vsock with ID specified by the id parameter. summary: Creates new vsock with ID specified by the id parameter.
description: description:
If the vsock device with the specified ID already exists, its body will If the vsock device with the specified ID already exists, its body will
be updated based on the new input. May fail if update is not possible. be updated based on the new input. May fail if update is not possible.
operationId: putGuestVsockByID operationId: putGuestVsockByID
parameters: parameters:
- name: id - name: id
in: path in: path
description: The id of the vsock device description: The id of the vsock device
required: true required: true
type: string type: string
- name: body - name: body
in: body in: body
description: Guest vsock properties description: Guest vsock properties
required: true required: true
schema: schema:
$ref: "#/definitions/Vsock" $ref: "#/definitions/Vsock"
responses: responses:
201: 204:
description: Vsock created description: Vsock created/updated
204: 400:
description: Vsock updated description: Vsock cannot be created due to bad input
400: schema:
description: Vsock cannot be created due to bad input $ref: "#/definitions/Error"
schema: default:
$ref: "#/definitions/Error" description: Internal server error
default: schema:
description: Internal server error $ref: "#/definitions/Error"
schema:
$ref: "#/definitions/Error"
definitions: definitions:
BootSource: BootSource:
@ -648,14 +645,28 @@ definitions:
minimum: 0 minimum: 0
Vsock: Vsock:
type: object type: object
required: description:
- id Defines a vsock device, backed by a set of Unix Domain Sockets, on the host side.
- guest_cid For host-initiated connections, Firecracker will be listening on the Unix socket
properties: identified by the path `uds_path`. Firecracker will create this socket, bind and
id: listen on it. Host-initiated connections will be performed by connection to this
type: string socket and issuing a connection forwarding request to the desired guest-side vsock
guest_cid: port (i.e. `CONNECT 52\n`, to connect to port 52).
type: integer For guest-initiated connections, Firecracker will expect host software to be
minimum: 3 bound and listening on Unix sockets at `uds_path_<PORT>`.
description: Guest Vsock CID E.g. "/path/to/host_vsock.sock_52" for port number 52.
required:
- vsock_id
- guest_cid
- uds_path
properties:
vsock_id:
type: string
guest_cid:
type: integer
minimum: 3
description: Guest Vsock CID
uds_path:
type: string
description: Path to UNIX domain socket, used to proxy vsock connections.

View File

@ -1599,8 +1599,8 @@ func (q *qemu) addDevice(devInfo interface{}, devType deviceType) error {
} }
case types.Socket: case types.Socket:
q.qemuConfig.Devices = q.arch.appendSocket(q.qemuConfig.Devices, v) q.qemuConfig.Devices = q.arch.appendSocket(q.qemuConfig.Devices, v)
case kataVSOCK: case types.VSock:
q.fds = append(q.fds, v.vhostFd) q.fds = append(q.fds, v.VhostFd)
q.qemuConfig.Devices, err = q.arch.appendVSock(q.qemuConfig.Devices, v) q.qemuConfig.Devices, err = q.arch.appendVSock(q.qemuConfig.Devices, v)
case Endpoint: case Endpoint:
q.qemuConfig.Devices, err = q.arch.appendNetwork(q.qemuConfig.Devices, v) q.qemuConfig.Devices, err = q.arch.appendNetwork(q.qemuConfig.Devices, v)
@ -2069,3 +2069,7 @@ func (q *qemu) check() error {
return nil return nil
} }
func (q *qemu) generateSocket(id string, useVsock bool) (interface{}, error) {
return generateVMSocket(id, useVsock)
}

View File

@ -80,7 +80,7 @@ type qemuArch interface {
appendSocket(devices []govmmQemu.Device, socket types.Socket) []govmmQemu.Device appendSocket(devices []govmmQemu.Device, socket types.Socket) []govmmQemu.Device
// appendVSock appends a vsock PCI to devices // appendVSock appends a vsock PCI to devices
appendVSock(devices []govmmQemu.Device, vsock kataVSOCK) ([]govmmQemu.Device, error) appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error)
// appendNetwork appends a endpoint device to devices // appendNetwork appends a endpoint device to devices
appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error)
@ -451,12 +451,12 @@ func (q *qemuArchBase) appendSocket(devices []govmmQemu.Device, socket types.Soc
return devices return devices
} }
func (q *qemuArchBase) appendVSock(devices []govmmQemu.Device, vsock kataVSOCK) ([]govmmQemu.Device, error) { func (q *qemuArchBase) appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error) {
devices = append(devices, devices = append(devices,
govmmQemu.VSOCKDevice{ govmmQemu.VSOCKDevice{
ID: fmt.Sprintf("vsock-%d", vsock.contextID), ID: fmt.Sprintf("vsock-%d", vsock.ContextID),
ContextID: vsock.contextID, ContextID: vsock.ContextID,
VHostFD: vsock.vhostFd, VHostFD: vsock.VhostFd,
DisableModern: q.nestedRun, DisableModern: q.nestedRun,
}, },
) )

View File

@ -274,10 +274,10 @@ func TestQemuAddDeviceKataVSOCK(t *testing.T) {
}, },
} }
vsock := kataVSOCK{ vsock := types.VSock{
contextID: contextID, ContextID: contextID,
port: port, Port: port,
vhostFd: vsockFile, VhostFd: vsockFile,
} }
testQemuAddDevice(t, vsock, vSockPCIDev, expectedOut) testQemuAddDevice(t, vsock, vSockPCIDev, expectedOut)

View File

@ -7,6 +7,7 @@ package types
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
@ -29,6 +30,11 @@ const (
StateStopped StateString = "stopped" StateStopped StateString = "stopped"
) )
const (
HybridVSockScheme = "hvsock"
VSockScheme = "vsock"
)
// SandboxState is a sandbox state structure // SandboxState is a sandbox state structure
type SandboxState struct { type SandboxState struct {
State StateString `json:"state"` State StateString `json:"state"`
@ -161,6 +167,35 @@ func (v *Volumes) String() string {
return strings.Join(volSlice, " ") return strings.Join(volSlice, " ")
} }
// VSock defines a virtio-socket to communicate between
// the host and any process inside the VM.
// This kind of socket is not supported in all hypervisors.
// QEMU and NEMU support it.
type VSock struct {
ContextID uint64
Port uint32
VhostFd *os.File
}
func (s *VSock) String() string {
return fmt.Sprintf("%s://%d:%d", VSockScheme, s.ContextID, s.Port)
}
// HybridVSock defines a hybrid vsocket to communicate between
// the host and any process inside the VM.
// This is a virtio-vsock implementation based on AF_VSOCK on the
// guest side and multiple AF_UNIX sockets on the host side.
// This kind of socket is not supported in all hypervisors.
// Firecracker supports it.
type HybridVSock struct {
UdsPath string
Port uint32
}
func (s *HybridVSock) String() string {
return fmt.Sprintf("%s://%s:%d", HybridVSockScheme, s.UdsPath, s.Port)
}
// Socket defines a socket to communicate between // Socket defines a socket to communicate between
// the host and any process inside the VM. // the host and any process inside the VM.
type Socket struct { type Socket struct {