mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-04 11:06:21 +00:00
firecracker: Revendor firecracker go sdk to 0.12.0
Revendor firecracker go sdk for Firecracker 0.12.0 API changes git shortlog 9614612 (HEAD -> master, origin/master, origin/HEAD) Merge pull request 653c342 Adding drives builder 3c1f5c3 Merge pr #41 c4151ff Migrate firectl to its own repository 433f262 Merge pull request #23 from xibz/fifo_logging_file 121ef9a add handler lists to handle initialization 0fd9825 Adding support for capturing fifo logs to file. 6b08ec7 Merge branch 'fc-0.12.0' 25878e7 Update for Firecracker 0.12.0 API changes ea93f77 Regenerate API client from swagger spec 00d8eee Update swagger.yaml for firecracker 0.12.0 Signed-off-by: Manohar Castelino <manohar.r.castelino@intel.com>
This commit is contained in:
parent
ec5cf18bd1
commit
5c6d94d756
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -204,7 +204,7 @@
|
|||||||
version = "v0.3.3"
|
version = "v0.3.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:61eec5f342089feaaa1690354a62102a90a64dcf7bbc4c6d840dc5edd66ae451"
|
digest = "1:58b18038f51b6f79865fd00e3d883949c9507ede577cd9c4e743ed56cc454122"
|
||||||
name = "github.com/firecracker-microvm/firecracker-go-sdk"
|
name = "github.com/firecracker-microvm/firecracker-go-sdk"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -213,7 +213,7 @@
|
|||||||
"client/operations",
|
"client/operations",
|
||||||
]
|
]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "840c1e37f5f2bbcbff1fdbfcfcea09d0bf158977"
|
revision = "961461227bddf7e40a1d690634e866c343910f86"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/firecracker-microvm/firecracker-go-sdk"
|
name = "github.com/firecracker-microvm/firecracker-go-sdk"
|
||||||
revision = "840c1e37f5f2bbcbff1fdbfcfcea09d0bf158977"
|
revision = "961461227bddf7e40a1d690634e866c343910f86"
|
||||||
|
|
||||||
[[override]]
|
[[override]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
73
vendor/github.com/firecracker-microvm/firecracker-go-sdk/client/models/device_state.go
generated
vendored
73
vendor/github.com/firecracker-microvm/firecracker-go-sdk/client/models/device_state.go
generated
vendored
@ -1,73 +0,0 @@
|
|||||||
// Code generated by go-swagger; DO NOT EDIT.
|
|
||||||
|
|
||||||
// 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 client_models
|
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
strfmt "github.com/go-openapi/strfmt"
|
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
|
||||||
"github.com/go-openapi/validate"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeviceState The valid states for a Device. So far, a device can only be in the Attached mode. Future valid values will be Detaching and Detached.
|
|
||||||
// swagger:model DeviceState
|
|
||||||
type DeviceState string
|
|
||||||
|
|
||||||
const (
|
|
||||||
|
|
||||||
// DeviceStateAttached captures enum value "Attached"
|
|
||||||
DeviceStateAttached DeviceState = "Attached"
|
|
||||||
)
|
|
||||||
|
|
||||||
// for schema
|
|
||||||
var deviceStateEnum []interface{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var res []DeviceState
|
|
||||||
if err := json.Unmarshal([]byte(`["Attached"]`), &res); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, v := range res {
|
|
||||||
deviceStateEnum = append(deviceStateEnum, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m DeviceState) validateDeviceStateEnum(path, location string, value DeviceState) error {
|
|
||||||
if err := validate.Enum(path, location, value, deviceStateEnum); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate validates this device state
|
|
||||||
func (m DeviceState) Validate(formats strfmt.Registry) error {
|
|
||||||
var res []error
|
|
||||||
|
|
||||||
// value enum
|
|
||||||
if err := m.validateDeviceStateEnum("", "body", m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(res) > 0 {
|
|
||||||
return errors.CompositeValidationError(res...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
3
vendor/github.com/firecracker-microvm/firecracker-go-sdk/client/models/logger.go
generated
vendored
3
vendor/github.com/firecracker-microvm/firecracker-go-sdk/client/models/logger.go
generated
vendored
@ -42,6 +42,9 @@ type Logger struct {
|
|||||||
// The named pipe where the JSON-formatted metrics will be flushed.
|
// The named pipe where the JSON-formatted metrics will be flushed.
|
||||||
MetricsFifo string `json:"metrics_fifo,omitempty"`
|
MetricsFifo string `json:"metrics_fifo,omitempty"`
|
||||||
|
|
||||||
|
// Additional logging options. Only "LogDirtyPages" is supported.
|
||||||
|
Options []string `json:"options"`
|
||||||
|
|
||||||
// Whether or not to output the level in the logs.
|
// Whether or not to output the level in the logs.
|
||||||
ShowLevel bool `json:"show_level,omitempty"`
|
ShowLevel bool `json:"show_level,omitempty"`
|
||||||
|
|
||||||
|
@ -46,9 +46,6 @@ type NetworkInterface struct {
|
|||||||
// rx rate limiter
|
// rx rate limiter
|
||||||
RxRateLimiter *RateLimiter `json:"rx_rate_limiter,omitempty"`
|
RxRateLimiter *RateLimiter `json:"rx_rate_limiter,omitempty"`
|
||||||
|
|
||||||
// state
|
|
||||||
State DeviceState `json:"state,omitempty"`
|
|
||||||
|
|
||||||
// tx rate limiter
|
// tx rate limiter
|
||||||
TxRateLimiter *RateLimiter `json:"tx_rate_limiter,omitempty"`
|
TxRateLimiter *RateLimiter `json:"tx_rate_limiter,omitempty"`
|
||||||
}
|
}
|
||||||
@ -65,10 +62,6 @@ func (m *NetworkInterface) Validate(formats strfmt.Registry) error {
|
|||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.validateState(formats); err != nil {
|
|
||||||
res = append(res, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := m.validateTxRateLimiter(formats); err != nil {
|
if err := m.validateTxRateLimiter(formats); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
@ -106,22 +99,6 @@ func (m *NetworkInterface) validateRxRateLimiter(formats strfmt.Registry) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *NetworkInterface) validateState(formats strfmt.Registry) error {
|
|
||||||
|
|
||||||
if swag.IsZero(m.State) { // not required
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := m.State.Validate(formats); err != nil {
|
|
||||||
if ve, ok := err.(*errors.Validation); ok {
|
|
||||||
return ve.ValidateName("state")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *NetworkInterface) validateTxRateLimiter(formats strfmt.Registry) error {
|
func (m *NetworkInterface) validateTxRateLimiter(formats strfmt.Registry) error {
|
||||||
|
|
||||||
if swag.IsZero(m.TxRateLimiter) { // not required
|
if swag.IsZero(m.TxRateLimiter) { // not required
|
||||||
|
@ -126,7 +126,7 @@ func (a *Client) PatchMmds(params *PatchMmdsParams) (*PatchMmdsNoContent, error)
|
|||||||
/*
|
/*
|
||||||
PutMmds creates a m m d s microvm metadata service data store
|
PutMmds creates a m m d s microvm metadata service data store
|
||||||
*/
|
*/
|
||||||
func (a *Client) PutMmds(params *PutMmdsParams) (*PutMmdsCreated, *PutMmdsNoContent, error) {
|
func (a *Client) PutMmds(params *PutMmdsParams) (*PutMmdsNoContent, error) {
|
||||||
// TODO: Validate the params before sending
|
// TODO: Validate the params before sending
|
||||||
if params == nil {
|
if params == nil {
|
||||||
params = NewPutMmdsParams()
|
params = NewPutMmdsParams()
|
||||||
@ -145,15 +145,9 @@ func (a *Client) PutMmds(params *PutMmdsParams) (*PutMmdsCreated, *PutMmdsNoCont
|
|||||||
Client: params.HTTPClient,
|
Client: params.HTTPClient,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch value := result.(type) {
|
return result.(*PutMmdsNoContent), nil
|
||||||
case *PutMmdsCreated:
|
|
||||||
return value, nil, nil
|
|
||||||
case *PutMmdsNoContent:
|
|
||||||
return nil, value, nil
|
|
||||||
}
|
|
||||||
return nil, nil, nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +38,6 @@ type PutMmdsReader struct {
|
|||||||
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 201:
|
|
||||||
result := NewPutMmdsCreated()
|
|
||||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
|
|
||||||
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 {
|
||||||
@ -71,27 +64,6 @@ func (o *PutMmdsReader) ReadResponse(response runtime.ClientResponse, consumer r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPutMmdsCreated creates a PutMmdsCreated with default headers values
|
|
||||||
func NewPutMmdsCreated() *PutMmdsCreated {
|
|
||||||
return &PutMmdsCreated{}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*PutMmdsCreated handles this case with default header values.
|
|
||||||
|
|
||||||
MMDS data store created
|
|
||||||
*/
|
|
||||||
type PutMmdsCreated struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *PutMmdsCreated) Error() string {
|
|
||||||
return fmt.Sprintf("[PUT /mmds][%d] putMmdsCreated ", 201)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *PutMmdsCreated) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPutMmdsNoContent creates a PutMmdsNoContent with default headers values
|
// NewPutMmdsNoContent creates a PutMmdsNoContent with default headers values
|
||||||
func NewPutMmdsNoContent() *PutMmdsNoContent {
|
func NewPutMmdsNoContent() *PutMmdsNoContent {
|
||||||
return &PutMmdsNoContent{}
|
return &PutMmdsNoContent{}
|
||||||
@ -99,7 +71,7 @@ func NewPutMmdsNoContent() *PutMmdsNoContent {
|
|||||||
|
|
||||||
/*PutMmdsNoContent handles this case with default header values.
|
/*PutMmdsNoContent handles this case with default header values.
|
||||||
|
|
||||||
MMDS data store updated.
|
MMDS data store created/updated.
|
||||||
*/
|
*/
|
||||||
type PutMmdsNoContent struct {
|
type PutMmdsNoContent struct {
|
||||||
}
|
}
|
||||||
|
65
vendor/github.com/firecracker-microvm/firecracker-go-sdk/drives.go
generated
vendored
Normal file
65
vendor/github.com/firecracker-microvm/firecracker-go-sdk/drives.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
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)
|
||||||
|
}
|
2
vendor/github.com/firecracker-microvm/firecracker-go-sdk/firecracker.go
generated
vendored
2
vendor/github.com/firecracker-microvm/firecracker-go-sdk/firecracker.go
generated
vendored
@ -134,7 +134,7 @@ func (f *FirecrackerClient) CreateSyncAction(ctx context.Context, info *models.I
|
|||||||
return f.client.Operations.CreateSyncAction(params)
|
return f.client.Operations.CreateSyncAction(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FirecrackerClient) PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsCreated, *ops.PutMmdsNoContent, error) {
|
func (f *FirecrackerClient) PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsNoContent, error) {
|
||||||
params := ops.NewPutMmdsParams()
|
params := ops.NewPutMmdsParams()
|
||||||
params.SetContext(ctx)
|
params.SetContext(ctx)
|
||||||
params.SetBody(metadata)
|
params.SetBody(metadata)
|
||||||
|
237
vendor/github.com/firecracker-microvm/firecracker-go-sdk/handlers.go
generated
vendored
Normal file
237
vendor/github.com/firecracker-microvm/firecracker-go-sdk/handlers.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
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
|
||||||
|
}
|
343
vendor/github.com/firecracker-microvm/firecracker-go-sdk/machine.go
generated
vendored
343
vendor/github.com/firecracker-microvm/firecracker-go-sdk/machine.go
generated
vendored
@ -17,6 +17,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -33,17 +34,8 @@ const (
|
|||||||
userAgent = "firecracker-go-sdk"
|
userAgent = "firecracker-go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CPUTemplate defines a set of CPU features that are exposed by Firecracker
|
// Firecracker is an interface that can be used to mock
|
||||||
type CPUTemplate = models.CPUTemplate
|
// out an Firecracker agent for testing purposes.
|
||||||
|
|
||||||
// CPUTemplates known by Firecracker. These are passed through directly from the model.
|
|
||||||
const (
|
|
||||||
CPUTemplateT2 = models.CPUTemplateT2
|
|
||||||
CPUTemplateC3 = models.CPUTemplateC3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Firecracker is an interface that can be used to mock out a Firecracker agent
|
|
||||||
// for testing purposes.
|
|
||||||
type Firecracker interface {
|
type Firecracker interface {
|
||||||
PutLogger(ctx context.Context, logger *models.Logger) (*ops.PutLoggerNoContent, error)
|
PutLogger(ctx context.Context, logger *models.Logger) (*ops.PutLoggerNoContent, error)
|
||||||
PutMachineConfiguration(ctx context.Context, cfg *models.MachineConfiguration) (*ops.PutMachineConfigurationNoContent, error)
|
PutMachineConfiguration(ctx context.Context, cfg *models.MachineConfiguration) (*ops.PutMachineConfigurationNoContent, error)
|
||||||
@ -52,7 +44,7 @@ type Firecracker interface {
|
|||||||
PutGuestDriveByID(ctx context.Context, driveID string, drive *models.Drive) (*ops.PutGuestDriveByIDNoContent, 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)
|
PutGuestVsockByID(ctx context.Context, vsockID string, vsock *models.Vsock) (*ops.PutGuestVsockByIDCreated, *ops.PutGuestVsockByIDNoContent, error)
|
||||||
CreateSyncAction(ctx context.Context, info *models.InstanceActionInfo) (*ops.CreateSyncActionNoContent, error)
|
CreateSyncAction(ctx context.Context, info *models.InstanceActionInfo) (*ops.CreateSyncActionNoContent, error)
|
||||||
PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsCreated, *ops.PutMmdsNoContent, error)
|
PutMmds(ctx context.Context, metadata interface{}) (*ops.PutMmdsNoContent, error)
|
||||||
GetMachineConfig() (*ops.GetMachineConfigOK, error)
|
GetMachineConfig() (*ops.GetMachineConfigOK, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,43 +74,27 @@ type Config struct {
|
|||||||
// the kernel.
|
// the kernel.
|
||||||
KernelArgs string
|
KernelArgs string
|
||||||
|
|
||||||
// CPUCount defines the number of CPU threads that should be available to
|
// Drives specifies BlockDevices that should be made available to the
|
||||||
// the micro-VM.
|
|
||||||
CPUCount int64
|
|
||||||
|
|
||||||
// HtEnabled defines whether hyper-threading should be enabled for the
|
|
||||||
// microVM.
|
// microVM.
|
||||||
HtEnabled bool
|
Drives []models.Drive
|
||||||
|
|
||||||
// CPUTemplate defines the Firecracker CPU template to use. Valid values
|
|
||||||
// are CPUTemplateT2 and CPUTemplateC3,
|
|
||||||
CPUTemplate CPUTemplate
|
|
||||||
|
|
||||||
// MemInMiB defines the amount of memory that should be made available to
|
|
||||||
// the microVM.
|
|
||||||
MemInMiB int64
|
|
||||||
|
|
||||||
// RootDrive specifies the BlockDevice that contains the root filesystem.
|
|
||||||
RootDrive BlockDevice
|
|
||||||
|
|
||||||
// RootPartitionUUID defines the UUID that specifies the root partition.
|
|
||||||
RootPartitionUUID string
|
|
||||||
|
|
||||||
// AdditionalDrives specifies additional BlockDevices that should be made
|
|
||||||
// available to the microVM.
|
|
||||||
AdditionalDrives []BlockDevice
|
|
||||||
|
|
||||||
// NetworkInterfaces specifies the tap devices that should be made available
|
// NetworkInterfaces specifies the tap devices that should be made available
|
||||||
// to the microVM.
|
// to the microVM.
|
||||||
NetworkInterfaces []NetworkInterface
|
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
|
// VsockDevices specifies the vsock devices that should be made available to
|
||||||
// the microVM.
|
// the microVM.
|
||||||
VsockDevices []VsockDevice
|
VsockDevices []VsockDevice
|
||||||
|
|
||||||
// Debug enables debug-level logging for the SDK.
|
// Debug enables debug-level logging for the SDK.
|
||||||
Debug bool
|
Debug bool
|
||||||
machineCfg models.MachineConfiguration
|
|
||||||
|
// MachineCfg represents the firecracker microVM process configuration
|
||||||
|
MachineCfg models.MachineConfiguration
|
||||||
|
|
||||||
// DisableValidation allows for easier mock testing by disabling the
|
// DisableValidation allows for easier mock testing by disabling the
|
||||||
// validation of configuration performed by the SDK.
|
// validation of configuration performed by the SDK.
|
||||||
@ -135,8 +111,17 @@ func (cfg *Config) Validate() error {
|
|||||||
if _, err := os.Stat(cfg.KernelImagePath); err != nil {
|
if _, err := os.Stat(cfg.KernelImagePath); err != nil {
|
||||||
return fmt.Errorf("failed to stat kernal image path, %q: %v", cfg.KernelImagePath, err)
|
return fmt.Errorf("failed to stat kernal image path, %q: %v", cfg.KernelImagePath, err)
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(cfg.RootDrive.HostPath); err != nil {
|
|
||||||
return fmt.Errorf("failed to stat host path, %q: %v", cfg.RootDrive.HostPath, 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:
|
// Check the non-existence of some files:
|
||||||
@ -154,6 +139,12 @@ type Machine struct {
|
|||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
logger *log.Entry
|
logger *log.Entry
|
||||||
machineConfig models.MachineConfiguration // The actual machine config as reported by Firecracker
|
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
|
// Logger returns a logrus logger appropriate for logging hypervisor messages
|
||||||
@ -172,15 +163,6 @@ type NetworkInterface struct {
|
|||||||
AllowMDDS bool
|
AllowMDDS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockDevice represents a host block device mapped to the Firecracker microVM.
|
|
||||||
type BlockDevice struct {
|
|
||||||
// HostPath defines the filesystem path of the block device on the host.
|
|
||||||
HostPath string
|
|
||||||
// Mode defines whether the device is writable. Valid values are "ro" and
|
|
||||||
// "rw".
|
|
||||||
Mode string
|
|
||||||
}
|
|
||||||
|
|
||||||
// VsockDevice represents a vsock connection between the host and the guest
|
// VsockDevice represents a vsock connection between the host and the guest
|
||||||
// microVM.
|
// microVM.
|
||||||
type VsockDevice struct {
|
type VsockDevice struct {
|
||||||
@ -209,122 +191,102 @@ func (m Machine) LogLevel() string {
|
|||||||
|
|
||||||
// NewMachine initializes a new Machine instance and performs validation of the
|
// NewMachine initializes a new Machine instance and performs validation of the
|
||||||
// provided Config.
|
// provided Config.
|
||||||
func NewMachine(cfg Config, opts ...Opt) (*Machine, error) {
|
func NewMachine(ctx context.Context, cfg Config, opts ...Opt) (*Machine, error) {
|
||||||
if err := cfg.Validate(); err != nil {
|
if err := cfg.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &Machine{}
|
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 {
|
for _, opt := range opts {
|
||||||
opt(m)
|
opt(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.logger == nil {
|
|
||||||
logger := log.New()
|
|
||||||
|
|
||||||
if cfg.Debug {
|
|
||||||
logger.SetLevel(log.DebugLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.logger = log.NewEntry(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.client == nil {
|
if m.client == nil {
|
||||||
m.client = NewFirecrackerClient(cfg.SocketPath, m.logger, cfg.Debug)
|
m.client = NewFirecrackerClient(cfg.SocketPath, m.logger, cfg.Debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Debug("Called NewMachine()")
|
|
||||||
|
|
||||||
m.cfg = cfg
|
m.cfg = cfg
|
||||||
m.cfg.machineCfg = models.MachineConfiguration{
|
|
||||||
VcpuCount: cfg.CPUCount,
|
|
||||||
MemSizeMib: cfg.MemInMiB,
|
|
||||||
HtEnabled: cfg.HtEnabled,
|
|
||||||
CPUTemplate: models.CPUTemplate(cfg.CPUTemplate),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
m.logger.Debug("Called NewMachine()")
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init starts the VMM and attaches drives and network interfaces.
|
// Start will iterate through the handler list and call each handler. If an
|
||||||
func (m *Machine) Init(ctx context.Context) (<-chan error, error) {
|
// error occurred during handler execution, that error will be returned. If the
|
||||||
m.logger.Debug("Called Machine.Init()")
|
// handlers succeed, then this will start the VMM instance.
|
||||||
|
func (m *Machine) Start(ctx context.Context) error {
|
||||||
if m.cmd == nil {
|
m.logger.Debug("Called Machine.Start()")
|
||||||
m.cmd = defaultFirecrackerVMMCommandBuilder.
|
if err := m.Handlers.Run(ctx, m); err != nil {
|
||||||
WithSocketPath(m.cfg.SocketPath).
|
return err
|
||||||
Build(ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errCh, err := m.startVMM(ctx)
|
return m.StartInstance(ctx)
|
||||||
if err != nil {
|
}
|
||||||
return errCh, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := m.setupLogging(ctx); err != nil {
|
// Wait will wait until the firecracker process has finished
|
||||||
m.logger.Warnf("setupLogging() returned %s. Continuing anyway.", err)
|
func (m *Machine) Wait(ctx context.Context) error {
|
||||||
} else {
|
select {
|
||||||
m.logger.Debugf("back from setupLogging")
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case err := <-m.errCh:
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = m.createMachine(ctx); err != nil {
|
func (m *Machine) addVsocks(ctx context.Context, vsocks ...VsockDevice) error {
|
||||||
m.stopVMM()
|
for _, dev := range m.cfg.VsockDevices {
|
||||||
return errCh, err
|
if err := m.addVsock(ctx, dev); err != nil {
|
||||||
}
|
return err
|
||||||
m.logger.Debug("createMachine returned")
|
|
||||||
|
|
||||||
if err = m.createBootSource(ctx, m.cfg.KernelImagePath, m.cfg.KernelArgs); err != nil {
|
|
||||||
m.stopVMM()
|
|
||||||
return errCh, err
|
|
||||||
}
|
|
||||||
m.logger.Debug("createBootSource returned")
|
|
||||||
|
|
||||||
if err = m.attachDrive(ctx, m.cfg.RootDrive, 1, true); err != nil {
|
|
||||||
m.stopVMM()
|
|
||||||
return errCh, err
|
|
||||||
}
|
|
||||||
m.logger.Debug("Root drive attachment complete")
|
|
||||||
|
|
||||||
for id, dev := range m.cfg.AdditionalDrives {
|
|
||||||
// id must be increased by 2 because firecracker uses 1-indexed arrays and the root drive occupies position 1.
|
|
||||||
err = m.attachDrive(ctx, dev, id+2, false)
|
|
||||||
if err != nil {
|
|
||||||
m.logger.Errorf("While attaching secondary drive %s, got error %s", dev.HostPath, err)
|
|
||||||
m.stopVMM()
|
|
||||||
return errCh, err
|
|
||||||
}
|
}
|
||||||
m.logger.Debugf("attachDrive returned for %s", dev.HostPath)
|
|
||||||
}
|
}
|
||||||
for id, iface := range m.cfg.NetworkInterfaces {
|
return nil
|
||||||
err = m.createNetworkInterface(ctx, iface, id+1)
|
}
|
||||||
if err != nil {
|
|
||||||
m.stopVMM()
|
func (m *Machine) createNetworkInterfaces(ctx context.Context, ifaces ...NetworkInterface) error {
|
||||||
return errCh, err
|
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)
|
m.logger.Debugf("createNetworkInterface returned for %s", iface.HostDevName)
|
||||||
}
|
}
|
||||||
for _, dev := range m.cfg.VsockDevices {
|
|
||||||
err = m.addVsock(ctx, dev)
|
return nil
|
||||||
if err != nil {
|
}
|
||||||
m.stopVMM()
|
|
||||||
return errCh, err
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Debugf("returning from Machine.Init(), RootDrive=%s", m.cfg.RootDrive.HostPath)
|
return nil
|
||||||
return errCh, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// startVMM starts the firecracker vmm process and configures logging.
|
// startVMM starts the firecracker vmm process and configures logging.
|
||||||
func (m *Machine) startVMM(ctx context.Context) (<-chan error, error) {
|
func (m *Machine) startVMM(ctx context.Context) error {
|
||||||
m.logger.Printf("Called startVMM(), setting up a VMM on %s", m.cfg.SocketPath)
|
m.logger.Printf("Called startVMM(), setting up a VMM on %s", m.cfg.SocketPath)
|
||||||
|
|
||||||
exitCh := make(chan error)
|
m.errCh = make(chan error)
|
||||||
|
|
||||||
err := m.cmd.Start()
|
err := m.cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Errorf("Failed to start VMM: %s", err)
|
m.logger.Errorf("Failed to start VMM: %s", err)
|
||||||
return exitCh, err
|
return err
|
||||||
}
|
}
|
||||||
m.logger.Debugf("VMM started socket path is %s", m.cfg.SocketPath)
|
m.logger.Debugf("VMM started socket path is %s", m.cfg.SocketPath)
|
||||||
|
|
||||||
@ -338,7 +300,7 @@ func (m *Machine) startVMM(ctx context.Context) (<-chan error, error) {
|
|||||||
os.Remove(m.cfg.SocketPath)
|
os.Remove(m.cfg.SocketPath)
|
||||||
os.Remove(m.cfg.LogFifo)
|
os.Remove(m.cfg.LogFifo)
|
||||||
os.Remove(m.cfg.MetricsFifo)
|
os.Remove(m.cfg.MetricsFifo)
|
||||||
exitCh <- err
|
m.errCh <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Set up a signal handler and pass INT, QUIT, and TERM through to firecracker
|
// Set up a signal handler and pass INT, QUIT, and TERM through to firecracker
|
||||||
@ -356,20 +318,20 @@ func (m *Machine) startVMM(ctx context.Context) (<-chan error, error) {
|
|||||||
m.logger.Printf("Caught signal %s", sig)
|
m.logger.Printf("Caught signal %s", sig)
|
||||||
m.cmd.Process.Signal(sig)
|
m.cmd.Process.Signal(sig)
|
||||||
case err = <-vmchan:
|
case err = <-vmchan:
|
||||||
exitCh <- err
|
m.errCh <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for firecracker to initialize:
|
// Wait for firecracker to initialize:
|
||||||
err = m.waitForSocket(3*time.Second, exitCh)
|
err = m.waitForSocket(3*time.Second, m.errCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Firecracker did not create API socket %s: %s", m.cfg.SocketPath, err)
|
msg := fmt.Sprintf("Firecracker did not create API socket %s: %s", m.cfg.SocketPath, err)
|
||||||
err = errors.New(msg)
|
err = errors.New(msg)
|
||||||
return exitCh, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Debugf("returning from startVMM()")
|
m.logger.Debugf("returning from startVMM()")
|
||||||
return exitCh, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//StopVMM stops the current VMM.
|
//StopVMM stops the current VMM.
|
||||||
@ -391,13 +353,15 @@ func (m *Machine) stopVMM() error {
|
|||||||
// createFifos sets up the firecracker logging and metrics FIFOs
|
// createFifos sets up the firecracker logging and metrics FIFOs
|
||||||
func createFifos(logFifo, metricsFifo string) error {
|
func createFifos(logFifo, metricsFifo string) error {
|
||||||
log.Debugf("Creating FIFO %s", logFifo)
|
log.Debugf("Creating FIFO %s", logFifo)
|
||||||
err := syscall.Mkfifo(logFifo, 0700)
|
if err := syscall.Mkfifo(logFifo, 0700); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("Failed to create log fifo: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
log.Debugf("Creating FIFO %s", metricsFifo)
|
|
||||||
err = syscall.Mkfifo(metricsFifo, 0700)
|
log.Debugf("Creating metric FIFO %s", metricsFifo)
|
||||||
return err
|
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 {
|
func (m *Machine) setupLogging(ctx context.Context) error {
|
||||||
@ -407,8 +371,7 @@ func (m *Machine) setupLogging(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := createFifos(m.cfg.LogFifo, m.cfg.MetricsFifo)
|
if err := createFifos(m.cfg.LogFifo, m.cfg.MetricsFifo); err != nil {
|
||||||
if err != nil {
|
|
||||||
m.logger.Errorf("Unable to set up logging: %s", err)
|
m.logger.Errorf("Unable to set up logging: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -423,16 +386,56 @@ func (m *Machine) setupLogging(ctx context.Context) error {
|
|||||||
ShowLogOrigin: false,
|
ShowLogOrigin: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := m.client.PutLogger(ctx, &l)
|
_, err := m.client.PutLogger(ctx, &l)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
m.logger.Printf("Configured VMM logging to %s, metrics to %s: %s",
|
return err
|
||||||
m.cfg.LogFifo, m.cfg.MetricsFifo, resp.Error())
|
|
||||||
}
|
}
|
||||||
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 {
|
func (m *Machine) createMachine(ctx context.Context) error {
|
||||||
resp, err := m.client.PutMachineConfiguration(ctx, &m.cfg.machineCfg)
|
resp, err := m.client.PutMachineConfiguration(ctx, &m.cfg.MachineCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Errorf("PutMachineConfiguration returned %s", resp.Error())
|
m.logger.Errorf("PutMachineConfiguration returned %s", resp.Error())
|
||||||
return err
|
return err
|
||||||
@ -469,7 +472,6 @@ func (m *Machine) createNetworkInterface(ctx context.Context, iface NetworkInter
|
|||||||
IfaceID: &ifaceID,
|
IfaceID: &ifaceID,
|
||||||
GuestMac: iface.MacAddress,
|
GuestMac: iface.MacAddress,
|
||||||
HostDevName: iface.HostDevName,
|
HostDevName: iface.HostDevName,
|
||||||
State: models.DeviceStateAttached,
|
|
||||||
AllowMmdsRequests: iface.AllowMDDS,
|
AllowMmdsRequests: iface.AllowMDDS,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,52 +484,25 @@ func (m *Machine) createNetworkInterface(ctx context.Context, iface NetworkInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// attachDrive attaches a secondary block device
|
// attachDrive attaches a secondary block device
|
||||||
func (m *Machine) attachDrive(ctx context.Context, dev BlockDevice, index int, root bool) error {
|
func (m *Machine) attachDrive(ctx context.Context, dev models.Drive) error {
|
||||||
var err error
|
var err error
|
||||||
|
hostPath := StringValue(dev.PathOnHost)
|
||||||
|
|
||||||
_, err = os.Stat(dev.HostPath)
|
_, err = os.Stat(hostPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
readOnly := true
|
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)
|
||||||
switch dev.Mode {
|
|
||||||
case "ro":
|
|
||||||
readOnly = true
|
|
||||||
case "rw":
|
|
||||||
readOnly = false
|
|
||||||
default:
|
|
||||||
return errors.New("invalid drive permissions")
|
|
||||||
}
|
|
||||||
|
|
||||||
driveID := strconv.Itoa(index)
|
|
||||||
d := models.Drive{
|
|
||||||
DriveID: &driveID,
|
|
||||||
PathOnHost: &dev.HostPath,
|
|
||||||
IsRootDevice: &root,
|
|
||||||
IsReadOnly: &readOnly,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(m.cfg.RootPartitionUUID) > 0 && root {
|
|
||||||
d.Partuuid = m.cfg.RootPartitionUUID
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Attaching drive %s, mode %s, slot %s, root %t.", dev.HostPath, dev.Mode, driveID, root)
|
|
||||||
|
|
||||||
respNoContent, err := m.client.PutGuestDriveByID(ctx, driveID, &d)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
m.logger.Printf("Attached drive %s: %s", dev.HostPath, respNoContent.Error())
|
m.logger.Printf("Attached drive %s: %s", hostPath, respNoContent.Error())
|
||||||
} else {
|
} else {
|
||||||
m.logger.Errorf("Attach drive failed: %s: %s", dev.HostPath, err)
|
m.logger.Errorf("Attach drive failed: %s: %s", hostPath, err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Machine) attachRootDrive(ctx context.Context, dev BlockDevice) error {
|
|
||||||
return m.attachDrive(ctx, dev, 1, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// addVsock adds a vsock to the instance
|
// addVsock adds a vsock to the instance
|
||||||
func (m *Machine) addVsock(ctx context.Context, dev VsockDevice) error {
|
func (m *Machine) addVsock(ctx context.Context, dev VsockDevice) error {
|
||||||
vsockCfg := models.Vsock{
|
vsockCfg := models.Vsock{
|
||||||
@ -561,15 +536,17 @@ func (m *Machine) startInstance(ctx context.Context) error {
|
|||||||
return 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
|
// SetMetadata sets the machine's metadata for MDDS
|
||||||
func (m *Machine) SetMetadata(ctx context.Context, metadata interface{}) error {
|
func (m *Machine) SetMetadata(ctx context.Context, metadata interface{}) error {
|
||||||
respcreated, respnocontent, err := m.client.PutMmds(ctx, metadata)
|
respnocontent, err := m.client.PutMmds(ctx, metadata)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var message string
|
var message string
|
||||||
if respcreated != nil {
|
|
||||||
message = respcreated.Error()
|
|
||||||
}
|
|
||||||
if respnocontent != nil {
|
if respnocontent != nil {
|
||||||
message = respnocontent.Error()
|
message = respnocontent.Error()
|
||||||
}
|
}
|
||||||
|
46
vendor/github.com/firecracker-microvm/firecracker-go-sdk/pointer_helpers.go
generated
vendored
Normal file
46
vendor/github.com/firecracker-microvm/firecracker-go-sdk/pointer_helpers.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user