firecracker

package module
v0.15.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2020 License: Apache-2.0 Imports: 21 Imported by: 1

README

FORKED A basic Go interface to the Firecracker API

Build status

This package is a Go library to interact with the Firecracker API. It is designed as an abstraction of the OpenAPI-generated client that allows for convenient manipulation of Firecracker VM from Go programs.

There are some Firecracker features that are not yet supported by the SDK. These are tracked as GitHub issues with the firecracker-feature label . Contributions to address missing features are welcomed.

Developing

Please see HACKING

Building

This library requires Go 1.11 and Go modules to build. A Makefile is provided for convenience, but is not required. When using the Makefile, you can pass additional flags to the Go compiler via the EXTRAGOARGS make variable.

Tools

There's a firectl tool that provides a simple command-line interface to launching a firecracker VM. It also serves as an example client of this SDK.

Network configuration

Firecracker, by design, only supports Linux tap devices. The SDK provides facilities to attach a tap device to the Firecracker VM, but the client is responsible for further configuration.

Questions?

Please use GitHub issues to report problems, discuss roadmap items, or make feature requests.

If you've discovered an issue that may have security implications to users or developers of this software, please do not report it using GitHub issues, but instead follow Firecracker's security reporting guidelines.

Other discussion: For general discussion, please join us in the #general channel on the Firecracker Slack.

License

This library is licensed under the Apache 2.0 License.

Documentation

Overview

Package firecracker provides a library to interact with the Firecracker API.

Firecracker is an open-source virtualization technology that is purpose-built for creating and managing secure, multi-tenant containers and functions-based services. See https://firecracker-microvm.github.io/ for more details.

This library requires Go 1.11 and can be used with Go modules.

BUG(aws): There are some Firecracker features that are not yet supported by the SDK. These are tracked as GitHub issues with the firecracker-feature label: https://github.com/768bit/firecracker-go-sdk/issues?q=is%3Aissue+is%3Aopen+label%3Afirecracker-feature

This library is licensed under the Apache 2.0 License.

Index

Examples

Constants

View Source
const (
	StartVMMHandlerName                = "fcinit.StartVMM"
	BootstrapLoggingHandlerName        = "fcinit.BootstrapLogging"
	CreateLogFilesHandlerName          = "fcinit.CreateLogFilesHandler"
	CreateMachineHandlerName           = "fcinit.CreateMachine"
	CreateBootSourceHandlerName        = "fcinit.CreateBootSource"
	AttachDrivesHandlerName            = "fcinit.AttachDrives"
	CreateNetworkInterfacesHandlerName = "fcinit.CreateNetworkInterfaces"
	AddVsocksHandlerName               = "fcinit.AddVsocks"
	SetMetadataHandlerName             = "fcinit.SetMetadata"
	LinkFilesToRootFSHandlerName       = "fcinit.LinkFilesToRootFS"

	ValidateCfgHandlerName       = "validate.Cfg"
	ValidateJailerCfgHandlerName = "validate.JailerCfg"
)

Handler name constants

View Source
const Version = "0.17.0"

Version represents the current version of the SDK.

Variables

View Source
var AddVsocksHandler = Handler{
	Name: AddVsocksHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.addVsocks(ctx, m.cfg.VsockDevices...)
	},
}

AddVsocksHandler is a named handler that adds vsocks to the firecracker process.

View Source
var AttachDrivesHandler = Handler{
	Name: AttachDrivesHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.attachDrives(ctx, m.cfg.Drives...)
	},
}

AttachDrivesHandler is a named handler that will attach all drives for the firecracker process.

View Source
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
	},
}

BootstrapLoggingHandler is a named handler that will set up fifo logging of firecracker process.

View Source
var ConfigValidationHandler = Handler{
	Name: ValidateCfgHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {

		return m.cfg.Validate()
	},
}

ConfigValidationHandler is used to validate that required fields are present. This validator is to be used when the jailer is turned off.

View Source
var CreateBootSourceHandler = Handler{
	Name: CreateBootSourceHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.createBootSource(ctx, m.cfg.KernelImagePath, m.cfg.KernelArgs)
	},
}

CreateBootSourceHandler is a named handler that will set up the booting process of the firecracker process.

View Source
var CreateLogFilesHandler = Handler{
	Name: CreateLogFilesHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		logFifoPath := m.cfg.LogFifo
		metricsFifoPath := m.cfg.MetricsFifo

		if len(logFifoPath) == 0 || len(metricsFifoPath) == 0 {

			return nil
		}

		if err := createFifos(logFifoPath, metricsFifoPath); err != nil {
			m.logger.Errorf("Unable to set up logging: %s", err)
			return err
		}

		m.logger.Debug("Created metrics and logging fifos.")

		return nil
	},
}

CreateLogFilesHandler is a named handler that will create the fifo log files

View Source
var CreateMachineHandler = Handler{
	Name: CreateMachineHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.createMachine(ctx)
	},
}

CreateMachineHandler is a named handler that will "create" the machine and upload any necessary configuration to the firecracker process.

View Source
var CreateNetworkInterfacesHandler = Handler{
	Name: CreateNetworkInterfacesHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.createNetworkInterfaces(ctx, m.cfg.NetworkInterfaces...)
	},
}

CreateNetworkInterfacesHandler is a named handler that sets up network interfaces to the firecracker process.

View Source
var ErrAlreadyStarted = errors.New("firecracker: machine already started")

ErrAlreadyStarted signifies that the Machine has already started and cannot be started again.

View Source
var ErrRequiredHandlerMissing = fmt.Errorf("required handler is missing from FcInit's list")

ErrRequiredHandlerMissing occurs when a required handler is not present in the handler list.

View Source
var JailerConfigValidationHandler = Handler{
	Name: ValidateJailerCfgHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		if !m.cfg.EnableJailer {
			return nil
		}

		hasRoot := false
		for _, drive := range m.cfg.Drives {
			if BoolValue(drive.IsRootDevice) {
				hasRoot = true
				break
			}
		}

		if !hasRoot {
			return fmt.Errorf("A root drive must be present in the drive list")
		}

		if m.cfg.JailerCfg.ChrootStrategy == nil {
			return fmt.Errorf("ChrootStrategy cannot be nil")
		}

		if len(m.cfg.JailerCfg.ExecFile) == 0 {
			return fmt.Errorf("exec file must be specified when using jailer mode")
		}

		if len(m.cfg.JailerCfg.ID) == 0 {
			return fmt.Errorf("id must be specified when using jailer mode")
		}

		if m.cfg.JailerCfg.GID == nil {
			return fmt.Errorf("GID must be specified when using jailer mode")
		}

		if m.cfg.JailerCfg.UID == nil {
			return fmt.Errorf("UID must be specified when using jailer mode")
		}

		if m.cfg.JailerCfg.NumaNode == nil {
			return fmt.Errorf("ID must be specified when using jailer mode")
		}

		return nil
	},
}

JailerConfigValidationHandler is used to validate that required fields are present.

View Source
var StartVMMHandler = Handler{
	Name: StartVMMHandlerName,
	Fn: func(ctx context.Context, m *Machine) error {
		return m.startVMM(ctx)
	},
}

StartVMMHandler is a named handler that will handle starting of the VMM. This handler will also set the exit channel on completion.

Functions

func Bool

func Bool(b bool) *bool

Bool will return a pointer value of the given parameter.

func BoolValue

func BoolValue(b *bool) bool

BoolValue will return a boolean value. If the pointer is nil, then false will be returned.

func Int

func Int(v int) *int

Int will return a pointer value of the given parameters.

func Int64

func Int64(v int64) *int64

Int64 will return a pointer value of the given parameter.

func Int64Value

func Int64Value(v *int64) int64

Int64Value will return an int64 value. If the pointer is nil, then zero will be returned.

func IntValue

func IntValue(v *int) int

IntValue will return an int value. If the pointer is nil, zero will be returned.

func NewRateLimiter

func NewRateLimiter(bandwidth, ops models.TokenBucket, opts ...RateLimiterOpt) *models.RateLimiter

NewRateLimiter will construct a new RateLimiter with given parameters.

func NewUnixSocketTransport

func NewUnixSocketTransport(socketPath string, logger *logrus.Entry, debug bool) runtime.ClientTransport

NewUnixSocketTransport creates a new clientTransport configured at the specified Unix socketPath.

func String

func String(str string) *string

String will return a pointer value of the given parameter.

func StringValue

func StringValue(str *string) string

StringValue will return a string value. If the pointer is nil, then an empty string will be returned.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a client for interacting with the Firecracker API

func NewClient

func NewClient(socketPath string, logger *logrus.Entry, debug bool, opts ...ClientOpt) *Client

NewClient creates a Client

func (*Client) CreateSyncAction

CreateSyncAction is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) GetInstanceDescription

func (f *Client) GetInstanceDescription(opts ...DescribeInstanceOpt) (*ops.DescribeInstanceOK, error)

GetMachineConfiguration is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) GetMachineConfiguration

func (f *Client) GetMachineConfiguration(opts ...GetMachineConfigurationOpt) (*ops.GetMachineConfigurationOK, error)

GetMachineConfiguration is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PatchGuestDriveByID

func (f *Client) PatchGuestDriveByID(ctx context.Context, driveID, pathOnHost string, opts ...PatchGuestDriveByIDOpt) (*ops.PatchGuestDriveByIDNoContent, error)

PatchGuestDriveByID is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PatchGuestNetworkInterfaceByID

func (f *Client) PatchGuestNetworkInterfaceByID(ctx context.Context, ifaceID string, ifaceCfg *models.PartialNetworkInterface, opts ...PatchGuestNetworkInterfaceByIDOpt) (*ops.PatchGuestNetworkInterfaceByIDNoContent, error)

PatchGuestNetworkInterfaceByID is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutGuestBootSource

func (f *Client) PutGuestBootSource(ctx context.Context, source *models.BootSource, opts ...PutGuestBootSourceOpt) (*ops.PutGuestBootSourceNoContent, error)

PutGuestBootSource is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutGuestDriveByID

func (f *Client) PutGuestDriveByID(ctx context.Context, driveID string, drive *models.Drive, opts ...PutGuestDriveByIDOpt) (*ops.PutGuestDriveByIDNoContent, error)

PutGuestDriveByID is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutGuestNetworkInterfaceByID

func (f *Client) PutGuestNetworkInterfaceByID(ctx context.Context, ifaceID string, ifaceCfg *models.NetworkInterface, opts ...PutGuestNetworkInterfaceByIDOpt) (*ops.PutGuestNetworkInterfaceByIDNoContent, error)

PutGuestNetworkInterfaceByID is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutGuestVsockByID

PutGuestVsockByID is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutLogger

func (f *Client) PutLogger(ctx context.Context, logger *models.Logger, opts ...PutLoggerOpt) (*ops.PutLoggerNoContent, error)

PutLogger is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutMachineConfiguration

PutMachineConfiguration is a wrapper for the swagger generated client to make calling of the API easier.

func (*Client) PutMmds

func (f *Client) PutMmds(ctx context.Context, metadata interface{}, opts ...PutMmdsOpt) (*ops.PutMmdsNoContent, error)

PutMmds is a wrapper for the swagger generated client to make calling of the API easier.

type ClientOpt

type ClientOpt func(*Client)

ClientOpt is a functional option used to modify the client after construction.

func WithOpsClient

func WithOpsClient(opsClient ops.ClientIface) ClientOpt

WithOpsClient will return a functional option and replace the operations client. This is useful for mock and stub testing.

type Config

type Config struct {
	// SocketPath defines the file path where the Firecracker control socket
	// should be created.
	SocketPath string

	// LogFifo defines the file path where the Firecracker log named-pipe should
	// be located.
	LogFifo string

	// LogLevel defines the verbosity of Firecracker logging.  Valid values are
	// "Error", "Warning", "Info", and "Debug", and are case-sensitive.
	LogLevel string

	// MetricsFifo defines the file path where the Firecracker metrics
	// named-pipe should be located.
	MetricsFifo string

	// KernelImagePath defines the file path where the kernel image is located.
	// The kernel image must be an uncompressed ELF image.
	KernelImagePath string

	// KernelArgs defines the command-line arguments that should be passed to
	// the kernel.
	KernelArgs string

	// Drives specifies BlockDevices that should be made available to the
	// microVM.
	Drives []models.Drive

	// NetworkInterfaces specifies the tap devices that should be made available
	// to the microVM.
	NetworkInterfaces []NetworkInterface

	// FifoLogWriter is an io.Writer that is used to redirect the contents of the
	// fifo log to the writer.
	FifoLogWriter io.Writer

	// VsockDevices specifies the vsock devices that should be made available to
	// the microVM.
	VsockDevices []VsockDevice

	// Debug enables debug-level logging for the SDK.
	Debug bool

	// MachineCfg represents the firecracker microVM process configuration
	MachineCfg models.MachineConfiguration

	// DisableValidation allows for easier mock testing by disabling the
	// validation of configuration performed by the SDK.
	DisableValidation bool

	// EnableJailer will enable the jailer. By enabling the jailer, root level
	// permissions are required.
	EnableJailer bool

	// JailerCfg is configuration specific for the jailer process.
	JailerCfg JailerConfig
}

Config is a collection of user-configurable VMM settings

func (*Config) Validate

func (cfg *Config) Validate() error

Validate will ensure that the required fields are set and that the fields are valid values.

type CreateSyncActionOpt

type CreateSyncActionOpt func(*ops.CreateSyncActionParams)

CreateSyncActionOpt is a functional option to be used for the CreateSyncAction API in setting any additional optional fields.

type DescribeInstanceOpt

type DescribeInstanceOpt func(*ops.DescribeInstanceParams)

GetMachineConfigurationOpt is a functional option to be used for the GetMachineConfiguration API in setting any additional optional fields.

type DriveOpt

type DriveOpt func(*models.Drive)

DriveOpt represents an optional function used to allow for specific customization of the models.Drive structure.

type DrivesBuilder

type DrivesBuilder struct {
	// contains filtered or unexported fields
}

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

Example
drivesParams := []struct {
	Path     string
	ReadOnly bool
}{
	{
		Path:     "/first/path/drive.img",
		ReadOnly: true,
	},
	{
		Path:     "/second/path/drive.img",
		ReadOnly: false,
	},
}

// construct a new builder with the given rootfs path
b := firecracker.NewDrivesBuilder("/path/to/rootfs")
for _, param := range drivesParams {
	// add our additional drives
	b = b.AddDrive(param.Path, param.ReadOnly)
}

const socketPath = "/tmp/firecracker.sock"
cfg := firecracker.Config{
	SocketPath:      socketPath,
	KernelImagePath: "/path/to/kernel",
	// build our drives into the machine's configuration
	Drives: b.Build(),
	MachineCfg: models.MachineConfiguration{
		VcpuCount: firecracker.Int64(1),
	},
}

ctx := context.Background()
m, err := firecracker.NewMachine(ctx, cfg)
if err != nil {
	panic(fmt.Errorf("failed to create new machine: %v", err))
}

if err := m.Start(ctx); err != nil {
	panic(fmt.Errorf("failed to initialize machine: %v", err))
}

// wait for VMM to execute
if err := m.Wait(ctx); err != nil {
	panic(err)
}
Output:

Example (DriveOpt)
drives := firecracker.NewDrivesBuilder("/path/to/rootfs").
	AddDrive("/path/to/drive1.img", true).
	AddDrive("/path/to/drive2.img", false, func(drive *models.Drive) {
		// set our custom bandwidth rate limiter
		drive.RateLimiter = &models.RateLimiter{
			Bandwidth: &models.TokenBucket{
				OneTimeBurst: firecracker.Int64(1024 * 1024),
				RefillTime:   firecracker.Int64(500),
				Size:         firecracker.Int64(1024 * 1024),
			},
		}
	}).
	Build()

const socketPath = "/tmp/firecracker.sock"
cfg := firecracker.Config{
	SocketPath:      socketPath,
	KernelImagePath: "/path/to/kernel",
	// build our drives into the machine's configuration
	Drives: drives,
	MachineCfg: models.MachineConfiguration{
		VcpuCount: firecracker.Int64(1),
	},
}

ctx := context.Background()
m, err := firecracker.NewMachine(ctx, cfg)
if err != nil {
	panic(fmt.Errorf("failed to create new machine: %v", err))
}

if err := m.Start(ctx); err != nil {
	panic(fmt.Errorf("failed to initialize machine: %v", err))
}

// wait for VMM to execute
if err := m.Wait(ctx); err != nil {
	panic(err)
}
Output:

func NewDrivesBuilder

func NewDrivesBuilder(rootDrivePath string) DrivesBuilder

NewDrivesBuilder will return a new DrivesBuilder with a given rootfs.

func (DrivesBuilder) AddDrive

func (b DrivesBuilder) AddDrive(path string, readOnly bool, opts ...DriveOpt) DrivesBuilder

AddDrive will add a new drive to the given builder.

func (DrivesBuilder) Build

func (b DrivesBuilder) Build() []models.Drive

Build will construct an array of drives with the root drive at the very end.

func (DrivesBuilder) WithRootDrive

func (b DrivesBuilder) WithRootDrive(rootDrivePath string, opts ...DriveOpt) DrivesBuilder

WithRootDrive will set the given builder with the a new root path. The root drive will be set to read and write by default.

type GetMachineConfigurationOpt

type GetMachineConfigurationOpt func(*ops.GetMachineConfigurationParams)

GetMachineConfigurationOpt is a functional option to be used for the GetMachineConfiguration API in setting any additional optional fields.

type Handler

type Handler struct {
	Name string
	Fn   func(context.Context, *Machine) error
}

Handler represents a named handler that contains a name and a function which is used to execute during the initialization process of a machine.

func LinkFilesHandler

func LinkFilesHandler(rootfs, kernelImageFileName string) Handler

LinkFilesHandler creates a new link files handler that will link files to the rootfs

func NewSetMetadataHandler

func NewSetMetadataHandler(metadata interface{}) Handler

NewSetMetadataHandler is a named handler that puts the metadata into the firecracker process.

type HandlerList

type HandlerList struct {
	// contains filtered or unexported fields
}

HandlerList represents a list of named handler that can be used to execute a flow of instructions for a given machine.

func (HandlerList) Append

func (l HandlerList) Append(handlers ...Handler) HandlerList

Append will append a new handler to the handler list.

func (HandlerList) AppendAfter

func (l HandlerList) AppendAfter(name string, handler Handler) HandlerList

AppendAfter will append a given handler after the specified handler.

func (HandlerList) Clear

func (l HandlerList) Clear() HandlerList

Clear clears all named handler in the list.

func (HandlerList) Has

func (l HandlerList) Has(name string) bool

Has will iterate through the handler list and check to see if the the named handler exists.

func (HandlerList) Len

func (l HandlerList) Len() int

Len return the length of the given handler list

func (HandlerList) Remove

func (l HandlerList) Remove(name string) HandlerList

Remove will return an updated handler with all instances of the specific named handler being removed.

func (HandlerList) Run

func (l HandlerList) Run(ctx context.Context, m *Machine) error

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 (HandlerList) Swap

func (l HandlerList) Swap(handler Handler) HandlerList

Swap will replace all elements of the given name with the new handler.

func (HandlerList) Swappend

func (l HandlerList) Swappend(handler Handler) HandlerList

Swappend will either append, if there isn't an element within the handler list, otherwise it will replace all elements with the given name.

type Handlers

type Handlers struct {
	Validation HandlerList
	FcInit     HandlerList
}

Handlers is a container that houses categories of handler lists.

func (Handlers) Run

func (h Handlers) Run(ctx context.Context, m *Machine) error

Run will execute all handlers in the Handlers object by flattening the lists into a single list and running.

type HandlersAdapter

type HandlersAdapter interface {
	AdaptHandlers(*Handlers) error
}

HandlersAdapter is an interface used to modify a given set of handlers.

type JailerCommandBuilder

type JailerCommandBuilder struct {
	// contains filtered or unexported fields
}

JailerCommandBuilder will build a jailer command. This can be used to specify that a jailed firecracker executable wants to be run on the Machine.

func NewJailerCommandBuilder

func NewJailerCommandBuilder() JailerCommandBuilder

NewJailerCommandBuilder will return a new jailer command builder with the proper default value initialized.

func (JailerCommandBuilder) Args

func (b JailerCommandBuilder) Args() []string

Args returns the specified set of args to be used in command construction.

func (JailerCommandBuilder) Bin

func (b JailerCommandBuilder) Bin() string

Bin returns the jailer bin path. If bin path is empty, then the default path will be returned.

func (JailerCommandBuilder) Build

Build will build a jailer command.

func (JailerCommandBuilder) Stderr

func (b JailerCommandBuilder) Stderr() io.Writer

Stderr will return the stderr that will be used when creating the firecracker exec.Command

func (JailerCommandBuilder) Stdin

func (b JailerCommandBuilder) Stdin() io.Reader

Stdin will return the stdin that will be used when creating the firecracker exec.Command

func (JailerCommandBuilder) Stdout

func (b JailerCommandBuilder) Stdout() io.Writer

Stdout will return the stdout that will be used when creating the firecracker exec.Command

func (JailerCommandBuilder) WithBin

WithBin will set the specific bin path to the builder.

func (JailerCommandBuilder) WithChrootBaseDir

func (b JailerCommandBuilder) WithChrootBaseDir(path string) JailerCommandBuilder

WithChrootBaseDir will set the given path as the chroot base directory. This specifies where chroot jails are built and defaults to /srv/jailer.

func (JailerCommandBuilder) WithDaemonize

func (b JailerCommandBuilder) WithDaemonize(daemonize bool) JailerCommandBuilder

WithDaemonize will specify whether to set stdio to /dev/null

func (JailerCommandBuilder) WithExecFile

func (b JailerCommandBuilder) WithExecFile(path string) JailerCommandBuilder

WithExecFile will set the specified path to the builder. This represents a firecracker binary used when calling the jailer.

func (JailerCommandBuilder) WithGID

WithGID will set the specified gid to the builder.

func (JailerCommandBuilder) WithID

WithID will set the specified id to the builder.

func (JailerCommandBuilder) WithNetNS

WithNetNS will set the given path to the net namespace of the builder. This represents the path to a network namespace handle and will be used to join the associated network namepsace.

func (JailerCommandBuilder) WithNumaNode

func (b JailerCommandBuilder) WithNumaNode(node int) JailerCommandBuilder

WithNumaNode uses the specfied node for the jailer. This represents the numa node that the process will get assigned to.

func (JailerCommandBuilder) WithSeccompLevel

WithSeccompLevel will set the provided level to the builder. This represents the seccomp filters that should be installed and how restrictive they should be.

func (JailerCommandBuilder) WithStderr

func (b JailerCommandBuilder) WithStderr(stderr io.Writer) JailerCommandBuilder

WithStderr specifies which io.Writer to use in place of the os.Stderr in the firecracker exec.Command.

func (JailerCommandBuilder) WithStdin

WithStdin specifies which io.Reader to use in place of the os.Stdin in the firecracker exec.Command.

func (JailerCommandBuilder) WithStdout

func (b JailerCommandBuilder) WithStdout(stdout io.Writer) JailerCommandBuilder

WithStdout specifies which io.Writer to use in place of the os.Stdout in the firecracker exec.Command.

func (JailerCommandBuilder) WithUID

WithUID will set the specified uid to the builder.

type JailerConfig

type JailerConfig struct {
	// GID the jailer switches to as it execs the target binary.
	GID *int

	// UID the jailer switches to as it execs the target binary.
	UID *int

	// ID is the unique VM identification string, which may contain alphanumeric
	// characters and hyphens. The maximum id length is currently 64 characters
	ID string

	// NumaNode represents the NUMA node the process gets assigned to.
	NumaNode *int

	// ExecFile is the path to the Firecracker binary that will be exec-ed by
	// the jailer. The user can provide a path to any binary, but the interaction
	// with the jailer is mostly Firecracker specific.
	ExecFile string

	// JailerBinary specifies the jailer binary to be used for setting up the
	// Firecracker VM jail. If the value contains no path separators, it will
	// use the PATH environment variable to get the absolute path of the binary.
	// If the value contains path separators, the value will be used directly
	// to exec the jailer. This follows the same conventions as Golang's
	// os/exec.Command.
	//
	// If not specified it defaults to "jailer".
	JailerBinary string

	// ChrootBaseDir represents the base folder where chroot jails are built. The
	// default is /srv/jailer
	ChrootBaseDir string

	// NetNS represents the path to a network namespace handle. If present, the
	// jailer will use this to join the associated network namespace
	NetNS string

	//  Daemonize is set to true, call setsid() and redirect STDIN, STDOUT, and
	//  STDERR to /dev/null
	Daemonize bool

	// SeccompLevel specifies whether seccomp filters should be installed and how
	// restrictive they should be. Possible values are:
	//
	//	0 : (default): disabled.
	//	1 : basic filtering. This prohibits syscalls not whitelisted by Firecracker.
	//	2 : advanced filtering. This adds further checks on some of the
	//			parameters of the allowed syscalls.
	SeccompLevel SeccompLevelValue

	// ChrootStrategy will dictate how files are transfered to the root drive.
	ChrootStrategy HandlersAdapter

	// Stdout specifies the IO writer for STDOUT to use when spawning the jailer.
	Stdout io.Writer
	// Stderr specifies the IO writer for STDERR to use when spawning the jailer.
	Stderr io.Writer
	// Stdin specifies the IO reader for STDIN to use when spawning the jailer.
	Stdin io.Reader
}

JailerConfig is jailer specific configuration needed to execute the jailer.

Example (EnablingJailer)
ctx := context.Background()
vmmCtx, vmmCancel := context.WithCancel(ctx)
defer vmmCancel()

const id = "my-jailer-test"
const path = "/path/to/jailer-workspace"
pathToWorkspace := filepath.Join(path, "firecracker", id)
const kernelImagePath = "/path/to/kernel-image"

uid := 123
gid := 100

fcCfg := firecracker.Config{
	SocketPath:      "api.socket",
	KernelImagePath: kernelImagePath,
	KernelArgs:      "console=ttyS0 reboot=k panic=1 pci=off",
	Drives:          firecracker.NewDrivesBuilder("/path/to/rootfs").Build(),
	LogLevel:        "Debug",
	MachineCfg: models.MachineConfiguration{
		VcpuCount:  firecracker.Int64(1),
		HtEnabled:  firecracker.Bool(false),
		MemSizeMib: firecracker.Int64(256),
	},
	EnableJailer: true,
	JailerCfg: firecracker.JailerConfig{
		UID:            &uid,
		GID:            &gid,
		ID:             id,
		NumaNode:       firecracker.Int(0),
		ChrootBaseDir:  path,
		ChrootStrategy: firecracker.NewNaiveChrootStrategy(pathToWorkspace, kernelImagePath),
		ExecFile:       "/path/to/firecracker-binary",
	},
}

// Check if kernel image is readable
f, err := os.Open(fcCfg.KernelImagePath)
if err != nil {
	panic(fmt.Errorf("Failed to open kernel image: %v", err))
}
f.Close()

// Check each drive is readable and writable
for _, drive := range fcCfg.Drives {
	drivePath := firecracker.StringValue(drive.PathOnHost)
	f, err := os.OpenFile(drivePath, os.O_RDWR, 0666)
	if err != nil {
		panic(fmt.Errorf("Failed to open drive with read/write permissions: %v", err))
	}
	f.Close()
}

logger := log.New()
m, err := firecracker.NewMachine(vmmCtx, fcCfg, firecracker.WithLogger(log.NewEntry(logger)))
if err != nil {
	panic(err)
}

if err := m.Start(vmmCtx); err != nil {
	panic(err)
}
defer m.StopVMM()

// wait for the VMM to exit
if err := m.Wait(vmmCtx); err != nil {
	panic(err)
}
Output:

type Machine

type Machine struct {
	// Handlers holds the set of handlers that are run for validation and start
	Handlers Handlers
	// contains filtered or unexported fields
}

Machine is the main object for manipulating Firecracker microVMs

func NewMachine

func NewMachine(ctx context.Context, cfg Config, opts ...Opt) (*Machine, error)

NewMachine initializes a new Machine instance and performs validation of the provided Config.

func (*Machine) LogFile

func (m *Machine) LogFile() string

LogFile returns the filesystem path of the VMM log

func (*Machine) LogLevel

func (m *Machine) LogLevel() string

LogLevel returns the VMM log level.

func (*Machine) Logger

func (m *Machine) Logger() *log.Entry

Logger returns a logrus logger appropriate for logging hypervisor messages

func (*Machine) PID

func (m *Machine) PID() (int, error)

PID returns the machine's running process PID or an error if not running

func (*Machine) SetMetadata

func (m *Machine) SetMetadata(ctx context.Context, metadata interface{}) error

SetMetadata sets the machine's metadata for MDDS

func (*Machine) Shutdown

func (m *Machine) Shutdown(ctx context.Context) error

Shutdown requests a clean shutdown of the VM by sending CtrlAltDelete on the virtual keyboard

func (*Machine) Start

func (m *Machine) Start(ctx context.Context) error

Start will iterate through the handler list and call each handler. If an error occurred during handler execution, that error will be returned. If the handlers succeed, then this will start the VMM instance. Start may only be called once per Machine. Subsequent calls will return ErrAlreadyStarted.

func (*Machine) Stop

func (m *Machine) Stop(ctx context.Context) error

Shutdown requests a clean shutdown of the VM by sending CtrlAltDelete on the virtual keyboard

func (*Machine) StopVMM

func (m *Machine) StopVMM() error

StopVMM stops the current VMM.

func (*Machine) UpdateGuestDrive

func (m *Machine) UpdateGuestDrive(ctx context.Context, driveID, pathOnHost string, opts ...PatchGuestDriveByIDOpt) error

UpdateGuestDrive will modify the current guest drive of ID index with the new parameters of the partialDrive.

func (*Machine) UpdateGuestNetworkInterfaceRateLimit

func (m *Machine) UpdateGuestNetworkInterfaceRateLimit(ctx context.Context, ifaceID string, rateLimiters RateLimiterSet, opts ...PatchGuestNetworkInterfaceByIDOpt) error

UpdateGuestNetworkInterfaceRateLimit modifies the specified network interface's rate limits

func (*Machine) Wait

func (m *Machine) Wait(ctx context.Context) error

Wait will wait until the firecracker process has finished. Wait is safe to call concurrently, and will deliver the same error to all callers, subject to each caller's context cancellation.

type MachineIface

type MachineIface interface {
	Start(context.Context) error
	StopVMM() error
	Shutdown(context.Context) error
	Wait(context.Context) error
	SetMetadata(context.Context, interface{}) error
	UpdateGuestDrive(context.Context, string, string, ...PatchGuestDriveByIDOpt) error
	UpdateGuestNetworkInterfaceRateLimit(context.Context, string, RateLimiterSet, ...PatchGuestNetworkInterfaceByIDOpt) error
}

MachineIface can be used for mocking and testing of the Machine. The Machine is subject to change, meaning this interface would change.

type NaiveChrootStrategy

type NaiveChrootStrategy struct {
	Rootfs          string
	KernelImagePath string
}

NaiveChrootStrategy will simply hard link all files, drives and kernel image, to the root drive.

func NewNaiveChrootStrategy

func NewNaiveChrootStrategy(rootfs, kernelImagePath string) NaiveChrootStrategy

NewNaiveChrootStrategy returns a new NaivceChrootStrategy

func (NaiveChrootStrategy) AdaptHandlers

func (s NaiveChrootStrategy) AdaptHandlers(handlers *Handlers) error

AdaptHandlers will inject the LinkFilesHandler into the handler list.

type NetworkInterface

type NetworkInterface struct {
	Name string
	// MacAddress defines the MAC address that should be assigned to the network
	// interface inside the microVM.
	MacAddress string
	// HostDevName defines the file path of the tap device on the host.
	HostDevName string
	// AllowMMDS makes the Firecracker MMDS available on this network interface.
	AllowMMDS bool

	// InRateLimiter limits the incoming bytes.
	InRateLimiter *models.RateLimiter
	// OutRateLimiter limits the outgoing bytes.
	OutRateLimiter *models.RateLimiter
}

NetworkInterface represents a Firecracker microVM's network interface.

Example (RateLimiting)
// construct the limitations of the bandwidth for firecracker
bandwidthBuilder := firecracker.TokenBucketBuilder{}.
	WithInitialSize(1024 * 1024).        // Initial token amount
	WithBucketSize(1024 * 1024).         // Max number of tokens
	WithRefillDuration(30 * time.Second) // Refill rate

// construct the limitations of the number of operations per duration for firecracker
opsBuilder := firecracker.TokenBucketBuilder{}.
	WithInitialSize(5).
	WithBucketSize(5).
	WithRefillDuration(5 * time.Second)

// create the inbound rate limiter
inbound := firecracker.NewRateLimiter(bandwidthBuilder.Build(), opsBuilder.Build())

bandwidthBuilder = bandwidthBuilder.WithBucketSize(1024 * 1024 * 10)
opsBuilder = opsBuilder.
	WithBucketSize(100).
	WithInitialSize(100)
// create the outbound rate limiter
outbound := firecracker.NewRateLimiter(bandwidthBuilder.Build(), opsBuilder.Build())

networkIfaces := []firecracker.NetworkInterface{
	{
		MacAddress:     "01-23-45-67-89-AB-CD-EF",
		HostDevName:    "tap-name",
		InRateLimiter:  inbound,
		OutRateLimiter: outbound,
	},
}

cfg := firecracker.Config{
	SocketPath:      "/path/to/socket",
	KernelImagePath: "/path/to/kernel",
	Drives:          firecracker.NewDrivesBuilder("/path/to/rootfs").Build(),
	MachineCfg: models.MachineConfiguration{
		VcpuCount: firecracker.Int64(1),
	},
	NetworkInterfaces: networkIfaces,
}

ctx := context.Background()
m, err := firecracker.NewMachine(ctx, cfg)
if err != nil {
	panic(fmt.Errorf("failed to create new machine: %v", err))
}

defer os.Remove(cfg.SocketPath)

if err := m.Start(ctx); err != nil {
	panic(fmt.Errorf("failed to initialize machine: %v", err))
}

// wait for VMM to execute
if err := m.Wait(ctx); err != nil {
	panic(err)
}
Output:

type Opt

type Opt func(*Machine)

Opt represents a functional option to help modify functionality of a Machine.

func WithClient

func WithClient(client *Client) Opt

WithClient will use the client in place rather than the client constructed during bootstrapping of the machine. This option is useful for mocking out tests.

func WithLogger

func WithLogger(logger *logrus.Entry) Opt

WithLogger will allow for the Machine to use the provided logger.

func WithProcessRunner

func WithProcessRunner(cmd *exec.Cmd) Opt

WithProcessRunner will allow for a specific command to be run instead of the default firecracker command. For example, this could be used to instead call the jailer instead of firecracker directly.

Example (Logging)
const socketPath = "/tmp/firecracker.sock"

cfg := firecracker.Config{
	SocketPath:      socketPath,
	KernelImagePath: "/path/to/kernel",
	Drives:          firecracker.NewDrivesBuilder("/path/to/rootfs").Build(),
	MachineCfg: models.MachineConfiguration{
		VcpuCount: firecracker.Int64(1),
	},
}

// stdout will be directed to this file
stdoutPath := "/tmp/stdout.log"
stdout, err := os.OpenFile(stdoutPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
	panic(fmt.Errorf("failed to create stdout file: %v", err))
}

// stderr will be directed to this file
stderrPath := "/tmp/stderr.log"
stderr, err := os.OpenFile(stderrPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
	panic(fmt.Errorf("failed to create stderr file: %v", err))
}

ctx := context.Background()
// build our custom command that contains our two files to
// write to during process execution
cmd := firecracker.VMCommandBuilder{}.
	WithBin("firecracker").
	WithSocketPath(socketPath).
	WithStdout(stdout).
	WithStderr(stderr).
	Build(ctx)

m, err := firecracker.NewMachine(ctx, cfg, firecracker.WithProcessRunner(cmd))
if err != nil {
	panic(fmt.Errorf("failed to create new machine: %v", err))
}

defer os.Remove(cfg.SocketPath)

if err := m.Start(ctx); err != nil {
	panic(fmt.Errorf("failed to initialize machine: %v", err))
}

// wait for VMM to execute
if err := m.Wait(ctx); err != nil {
	panic(err)
}
Output:

type PatchGuestDriveByIDOpt

type PatchGuestDriveByIDOpt func(*ops.PatchGuestDriveByIDParams)

PatchGuestDriveByIDOpt is a functional option to be used for the PutMmds API in setting any additional optional fields.

type PatchGuestNetworkInterfaceByIDOpt

type PatchGuestNetworkInterfaceByIDOpt func(*ops.PatchGuestNetworkInterfaceByIDParams)

PatchGuestNetworkInterfaceByIDOpt is a functional option to be used for the PatchGuestNetworkInterfaceByID API in setting any additional optional fields.

type PutGuestBootSourceOpt

type PutGuestBootSourceOpt func(*ops.PutGuestBootSourceParams)

PutGuestBootSourceOpt is a functional option to be used for the PutGuestBootSource API in setting any additional optional fields.

type PutGuestDriveByIDOpt

type PutGuestDriveByIDOpt func(*ops.PutGuestDriveByIDParams)

PutGuestDriveByIDOpt is a functional option to be used for the PutGuestDriveByID API in setting any additional optional fields.

type PutGuestNetworkInterfaceByIDOpt

type PutGuestNetworkInterfaceByIDOpt func(*ops.PutGuestNetworkInterfaceByIDParams)

PutGuestNetworkInterfaceByIDOpt is a functional option to be used for the PutGuestNetworkInterfaceByID API in setting any additional optional fields.

type PutGuestVsockByIDOpt

type PutGuestVsockByIDOpt func(*ops.PutGuestVsockByIDParams)

PutGuestVsockByIDOpt is a functional option to be used for the PutGuestVsockByID API in setting any additional optional fields.

type PutLoggerOpt

type PutLoggerOpt func(*ops.PutLoggerParams)

PutLoggerOpt is a functional option to be used for the PutLogger API in setting any additional optional fields.

type PutMachineConfigurationOpt

type PutMachineConfigurationOpt func(*ops.PutMachineConfigurationParams)

PutMachineConfigurationOpt is a functional option to be used for the PutMachineConfiguration API in setting any additional optional fields.

type PutMmdsOpt

type PutMmdsOpt func(*ops.PutMmdsParams)

PutMmdsOpt is a functional option to be used for the PutMmds API in setting any additional optional fields.

type RateLimiterOpt

type RateLimiterOpt func(*models.RateLimiter)

RateLimiterOpt represents a functional option for rate limiting construction

type RateLimiterSet

type RateLimiterSet struct {
	// InRateLimiter limits the incoming bytes.
	InRateLimiter *models.RateLimiter
	// OutRateLimiter limits the outgoing bytes.
	OutRateLimiter *models.RateLimiter
}

RateLimiterSet represents a pair of RateLimiters (inbound and outbound)

type SeccompLevelValue

type SeccompLevelValue int

SeccompLevelValue represents a secure computing level type.

const (
	// SeccompLevelDisable is the default value.
	SeccompLevelDisable SeccompLevelValue = iota
	// SeccompLevelBasic prohibits syscalls not whitelisted by Firecracker.
	SeccompLevelBasic
	// SeccompLevelAdvanced adds further checks on some of the parameters of the
	// allowed syscalls.
	SeccompLevelAdvanced
)

secure computing levels

type TokenBucketBuilder

type TokenBucketBuilder struct {
	// contains filtered or unexported fields
}

TokenBucketBuilder is a builder that allows of building components of the models.RateLimiter structure.

func (TokenBucketBuilder) Build

Build will return a new token bucket

func (TokenBucketBuilder) WithBucketSize

func (b TokenBucketBuilder) WithBucketSize(size int64) TokenBucketBuilder

WithBucketSize will set the bucket size for the given token bucket

func (TokenBucketBuilder) WithInitialSize

func (b TokenBucketBuilder) WithInitialSize(size int64) TokenBucketBuilder

WithInitialSize will set the initial token bucket size

func (TokenBucketBuilder) WithRefillDuration

func (b TokenBucketBuilder) WithRefillDuration(dur time.Duration) TokenBucketBuilder

WithRefillDuration will set the given refill duration of the bucket fill rate.

type VMCommandBuilder

type VMCommandBuilder struct {
	// contains filtered or unexported fields
}

VMCommandBuilder is a utility for building an exec.Cmd that represents how to start the Firecracker VMM.

func (VMCommandBuilder) AddArgs

func (b VMCommandBuilder) AddArgs(args ...string) VMCommandBuilder

AddArgs will append the provided args to the given command

func (VMCommandBuilder) Args

func (b VMCommandBuilder) Args() []string

Args returns all args that will be passed to exec.Command

func (VMCommandBuilder) Bin

func (b VMCommandBuilder) Bin() string

Bin returns the bin that was set. If bin had not been set, then the default will be returned.

func (VMCommandBuilder) Build

func (b VMCommandBuilder) Build(ctx context.Context) *exec.Cmd

Build will build a firecracker command using the specific arguments specified in the builder.

func (VMCommandBuilder) SocketPath

func (b VMCommandBuilder) SocketPath() []string

SocketPath returns the specified socket path

func (VMCommandBuilder) Stderr

func (b VMCommandBuilder) Stderr() io.Writer

Stderr will return the stderr that will be used when creating the firecracker exec.Command

func (VMCommandBuilder) Stdin

func (b VMCommandBuilder) Stdin() io.Reader

Stdin will return the stdin that will be used when creating the firecracker exec.Command

func (VMCommandBuilder) Stdout

func (b VMCommandBuilder) Stdout() io.Writer

Stdout will return the stdout that will be used when creating the firecracker exec.Command

func (VMCommandBuilder) WithArgs

func (b VMCommandBuilder) WithArgs(args []string) VMCommandBuilder

WithArgs specifies which arguments to pass through to the firecracker exec.Command

func (VMCommandBuilder) WithBin

func (b VMCommandBuilder) WithBin(bin string) VMCommandBuilder

WithBin specifies which binary for firecracker to use

func (VMCommandBuilder) WithSocketPath

func (b VMCommandBuilder) WithSocketPath(path string) VMCommandBuilder

WithSocketPath specifies the socket path to be used when creating the firecracker exec.Command

func (VMCommandBuilder) WithStderr

func (b VMCommandBuilder) WithStderr(stderr io.Writer) VMCommandBuilder

WithStderr specifies which io.Writer to use in place of the os.Stderr in the firecracker exec.Command.

func (VMCommandBuilder) WithStdin

func (b VMCommandBuilder) WithStdin(stdin io.Reader) VMCommandBuilder

WithStdin specifies which io.Reader to use in place of the os.Stdin in the firecracker exec.Command.

func (VMCommandBuilder) WithStdout

func (b VMCommandBuilder) WithStdout(stdout io.Writer) VMCommandBuilder

WithStdout specifies which io.Writer to use in place of the os.Stdout in the firecracker exec.Command.

type VsockDevice

type VsockDevice struct {
	// Path defines the filesystem path of the vsock device on the host.
	Path string
	// CID defines the 32-bit Context Identifier for the vsock device.  See
	// the vsock(7) manual page for more information.
	CID uint32
}

VsockDevice represents a vsock connection between the host and the guest microVM.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL