virtcontainers: Jailer: Add jailer support for firecracker

Firecracker provides a jailer to constrain the VMM. Use this
jailer to launch the firecracker VMM instead of launching it
directly from the kata-runtime.

The jailer will ensure that the firecracker VMM will run
in its own network and mount namespace. All assets required
by the VMM have to be present within these namespaces.
The assets need to be copied or bind mounted into the chroot
location setup by jailer in order for firecracker to access
these resouces. This includes files, device nodes and all
other assets.

Jailer automatically sets up the jail to have access to
kvm and vhost-vsock.

If a jailer is not available (i.e. not setup in the toml)
for a given hypervisor the runtime will act as the jailer.

Also enhance the hypervisor interface and unit tests to
include the network namespace. This allows the hypervisor
to choose how and where to lauch the VMM process, vs
virtcontainers directly launching the VMM process.

Fixes: #1129

Signed-off-by: Manohar Castelino <manohar.r.castelino@intel.com>
This commit is contained in:
Manohar Castelino 2019-01-23 16:11:22 -08:00
parent 5e67e04666
commit 78ea50c36c
14 changed files with 298 additions and 47 deletions

View File

@ -10,6 +10,7 @@ package katautils
var defaultHypervisorPath = "/usr/bin/qemu-lite-system-x86_64"
var defaultHypervisorCtlPath = "/usr/bin/acrnctl"
var defaultJailerPath = "/usr/bin/jailer"
var defaultImagePath = "/usr/share/kata-containers/kata-containers.img"
var defaultKernelPath = "/usr/share/kata-containers/vmlinuz.container"
var defaultInitrdPath = "/usr/share/kata-containers/kata-containers-initrd.img"

View File

@ -84,6 +84,7 @@ type factory struct {
type hypervisor struct {
Path string `toml:"path"`
JailerPath string `toml:"jailer_path"`
Kernel string `toml:"kernel"`
CtlPath string `toml:"ctlpath"`
Initrd string `toml:"initrd"`
@ -175,6 +176,16 @@ func (h hypervisor) ctlpath() (string, error) {
return ResolvePath(p)
}
func (h hypervisor) jailerPath() (string, error) {
p := h.JailerPath
if h.JailerPath == "" {
return "", nil
}
return ResolvePath(p)
}
func (h hypervisor) kernel() (string, error) {
p := h.Kernel
@ -463,6 +474,11 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
return vc.HypervisorConfig{}, err
}
jailer, err := h.jailerPath()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernel, err := h.kernel()
if err != nil {
return vc.HypervisorConfig{}, err
@ -491,6 +507,7 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
return vc.HypervisorConfig{
HypervisorPath: hypervisor,
JailerPath: jailer,
KernelPath: kernel,
InitrdPath: initrd,
ImagePath: image,
@ -915,6 +932,7 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
func GetDefaultHypervisorConfig() vc.HypervisorConfig {
return vc.HypervisorConfig{
HypervisorPath: defaultHypervisorPath,
JailerPath: defaultJailerPath,
KernelPath: defaultKernelPath,
ImagePath: defaultImagePath,
InitrdPath: defaultInitrdPath,

View File

@ -278,7 +278,7 @@ func (a *acrn) createDummyVirtioBlkDev(devices []Device) ([]Device, error) {
}
// createSandbox is the Hypervisor sandbox creation.
func (a *acrn) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
func (a *acrn) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
// Save the tracing context
a.ctx = ctx

View File

@ -251,7 +251,7 @@ func TestAcrnCreateSandbox(t *testing.T) {
t.Fatalf("Could not create hypervisor file %s: %v", testAcrnPath, err)
}
if err := a.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
if err := a.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}

View File

@ -11,6 +11,7 @@ import (
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
"strconv"
@ -44,8 +45,12 @@ const (
const (
//fcTimeout is the maximum amount of time in seconds to wait for the VMM to respond
fcTimeout = 10
fireSocket = "firecracker.sock"
fcTimeout = 10
fcSocket = "api.socket"
//Name of the files within jailer root
//Having predefined names helps with cleanup
fcKernel = "vmlinux"
fcRootfs = "rootfs"
fcStopSandboxTimeout = 15
// This indicates the number of block devices that can be attached to the
// firecracker guest VM.
@ -102,18 +107,27 @@ func (s *firecrackerState) set(state vmmState) {
// firecracker is an Hypervisor interface implementation for the firecracker hypervisor.
type firecracker struct {
id string //Unique ID per pod. Normally maps to the sandbox id
state firecrackerState
info FirecrackerInfo
id string //Unique ID per pod. Normally maps to the sandbox id
vmPath string //All jailed VM assets need to be under this
chrootBaseDir string //chroot base for the jailer
jailerRoot string
socketPath string
netNSPath string
uid string //UID and GID to be used for the VMM
gid string
info FirecrackerInfo
firecrackerd *exec.Cmd //Tracks the firecracker process itself
fcClient *client.Firecracker //Tracks the current active connection
socketPath string
connection *client.Firecracker //Tracks the current active connection
store *store.VCStore
ctx context.Context
config HypervisorConfig
pendingDevices []firecrackerDevice // Devices to be added when the FC API is ready
ctx context.Context
state firecrackerState
jailed bool //Set to true if jailer is enabled
}
type firecrackerDevice struct {
@ -140,9 +154,47 @@ func (fc *firecracker) trace(name string) (opentracing.Span, context.Context) {
return span, ctx
}
// bindMount bind mounts a source in to a destination. This will
// do some bookkeeping:
// * evaluate all symlinks
// * ensure the source exists
// * recursively create the destination
func (fc *firecracker) bindMount(ctx context.Context, source, destination string, readonly bool) error {
span, _ := trace(ctx, "bindMount")
defer span.Finish()
if source == "" {
return fmt.Errorf("source must be specified")
}
if destination == "" {
return fmt.Errorf("destination must be specified")
}
absSource, err := filepath.EvalSymlinks(source)
if err != nil {
return fmt.Errorf("Could not resolve symlink for source %v", source)
}
if err := ensureDestinationExists(absSource, destination); err != nil {
return fmt.Errorf("Could not create destination mount point %v: %v", destination, err)
}
if err := syscall.Mount(absSource, destination, "bind", syscall.MS_BIND|syscall.MS_SLAVE, ""); err != nil {
return fmt.Errorf("Could not bind mount %v to %v: %v", absSource, destination, err)
}
// For readonly bind mounts, we need to remount with the readonly flag.
// This is needed as only very recent versions of libmount/util-linux support "bind,ro"
if readonly {
return syscall.Mount(absSource, destination, "bind", uintptr(syscall.MS_BIND|syscall.MS_SLAVE|syscall.MS_REMOUNT|syscall.MS_RDONLY), "")
}
return nil
}
// For firecracker this call only sets the internal structure up.
// The sandbox will be created and started through startSandbox().
func (fc *firecracker) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, vcStore *store.VCStore) error {
func (fc *firecracker) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, vcStore *store.VCStore) error {
fc.ctx = ctx
span, _ := fc.trace("createSandbox")
@ -151,10 +203,34 @@ func (fc *firecracker) createSandbox(ctx context.Context, id string, hypervisorC
//TODO: check validity of the hypervisor config provided
//https://github.com/kata-containers/runtime/issues/1065
fc.id = id
fc.socketPath = filepath.Join(store.SandboxRuntimeRootPath(fc.id), fireSocket)
fc.store = vcStore
fc.config = *hypervisorConfig
fc.state.set(notReady)
fc.config = *hypervisorConfig
// When running with jailer all resources need to be under
// a specific location and that location needs to have
// exec permission (i.e. should not be mounted noexec, e.g. /run, /var/run)
// Also unix domain socket names have a hard limit
// #define UNIX_PATH_MAX 108
// Keep it short and live within the jailer expected paths
// <chroot_base>/<exec_file_name>/<id>/
// Also jailer based on the id implicitly sets up cgroups under
// <cgroups_base>/<exec_file_name>/<id>/
hypervisorName := filepath.Base(hypervisorConfig.HypervisorPath)
//store.ConfigStoragePath cannot be used as we need exec perms
fc.chrootBaseDir = filepath.Join("/var/lib/", store.StoragePathSuffix)
fc.vmPath = filepath.Join(fc.chrootBaseDir, hypervisorName, fc.id)
fc.jailerRoot = filepath.Join(fc.vmPath, "root") // auto created by jailer
fc.socketPath = filepath.Join(fc.jailerRoot, fcSocket)
// So we need to repopulate this at startSandbox where it is valid
fc.netNSPath = networkNS.NetNsPath
// Till we create lower privileged kata user run as root
// https://github.com/kata-containers/runtime/issues/1869
fc.uid = "0"
fc.gid = "0"
// No need to return an error from there since there might be nothing
// to fetch if this is the first time the hypervisor is created.
@ -239,9 +315,62 @@ func (fc *firecracker) fcInit(timeout int) error {
span, _ := fc.trace("fcInit")
defer span.Finish()
args := []string{"--api-sock", fc.socketPath}
if fc.config.JailerPath != "" {
fc.jailed = true
}
cmd := exec.Command(fc.config.HypervisorPath, args...)
// Fetch sandbox network to be able to access it from the sandbox structure.
var networkNS NetworkNamespace
if err := fc.store.Load(store.Network, &networkNS); err == nil {
if networkNS.NetNsPath == "" {
fc.Logger().WithField("NETWORK NAMESPACE NULL", networkNS).Warn()
}
fc.netNSPath = networkNS.NetNsPath
}
err := os.MkdirAll(fc.jailerRoot, store.DirMode)
if err != nil {
return err
}
defer func() {
if err != nil {
if err := os.RemoveAll(fc.vmPath); err != nil {
fc.Logger().WithError(err).Error("Fail to clean up vm directory")
}
}
}()
var args []string
var cmd *exec.Cmd
//https://github.com/firecracker-microvm/firecracker/blob/master/docs/jailer.md#jailer-usage
//--seccomp-level specifies whether seccomp filters should be installed and how restrictive they should be. Possible values are:
//0 : disabled.
//1 : basic filtering. This prohibits syscalls not whitelisted by Firecracker.
//2 (default): advanced filtering. This adds further checks on some of the parameters of the allowed syscalls.
if fc.jailed {
args = []string{
"--id", fc.id,
"--node", "0", //FIXME: Comprehend NUMA topology or explicit ignore
"--seccomp-level", "2",
"--exec-file", fc.config.HypervisorPath,
"--uid", "0", //https://github.com/kata-containers/runtime/issues/1869
"--gid", "0",
"--chroot-base-dir", fc.chrootBaseDir,
"--daemonize",
}
if fc.netNSPath != "" {
args = append(args, "--netns", fc.netNSPath)
}
cmd = exec.Command(fc.config.JailerPath, args...)
} else {
args = []string{"--api-sock", fc.socketPath}
cmd = exec.Command(fc.config.HypervisorPath, args...)
}
fc.Logger().WithField("hypervisor args", args).Debug()
fc.Logger().WithField("hypervisor cmd", cmd).Debug()
if err := cmd.Start(); err != nil {
fc.Logger().WithField("Error starting firecracker", err).Debug()
return err
@ -249,7 +378,7 @@ func (fc *firecracker) fcInit(timeout int) error {
fc.info.PID = cmd.Process.Pid
fc.firecrackerd = cmd
fc.fcClient = fc.newFireClient()
fc.connection = fc.newFireClient()
if err := fc.waitVMM(timeout); err != nil {
fc.Logger().WithField("fcInit failed:", err).Debug()
@ -314,11 +443,31 @@ func (fc *firecracker) client() *client.Firecracker {
span, _ := fc.trace("client")
defer span.Finish()
if fc.fcClient == nil {
fc.fcClient = fc.newFireClient()
if fc.connection == nil {
fc.connection = fc.newFireClient()
}
return fc.fcClient
return fc.connection
}
func (fc *firecracker) fcJailResource(src, dst string) (string, error) {
if src == "" || dst == "" {
return "", fmt.Errorf("fcJailResource: invalid jail locations: src:%v, dst:%v",
src, dst)
}
jailedLocation := filepath.Join(fc.jailerRoot, dst)
if err := fc.bindMount(context.Background(), src, jailedLocation, false); err != nil {
fc.Logger().WithField("bindMount failed", err).Error()
return "", err
}
if !fc.jailed {
return jailedLocation, nil
}
// This is the path within the jailed root
absPath := filepath.Join("/", dst)
return absPath, nil
}
func (fc *firecracker) fcSetBootSource(path, params string) error {
@ -327,37 +476,47 @@ func (fc *firecracker) fcSetBootSource(path, params string) error {
fc.Logger().WithFields(logrus.Fields{"kernel-path": path,
"kernel-params": params}).Debug("fcSetBootSource")
kernelPath, err := fc.fcJailResource(path, fcKernel)
if err != nil {
return err
}
bootSrcParams := ops.NewPutGuestBootSourceParams()
src := &models.BootSource{
KernelImagePath: &path,
KernelImagePath: &kernelPath,
BootArgs: params,
}
bootSrcParams.SetBody(src)
_, err := fc.client().Operations.PutGuestBootSource(bootSrcParams)
_, err = fc.client().Operations.PutGuestBootSource(bootSrcParams)
return err
}
func (fc *firecracker) fcSetVMRootfs(path string) error {
span, _ := fc.trace("fcSetVMRootfs")
defer span.Finish()
fc.Logger().WithField("VM-rootfs-path", path).Debug()
jailedRootfs, err := fc.fcJailResource(path, fcRootfs)
if err != nil {
return err
}
driveID := "rootfs"
driveParams := ops.NewPutGuestDriveByIDParams()
driveParams.SetDriveID(driveID)
isReadOnly := true
//Add it as a regular block device
//This allows us to use a paritioned root block device
//This allows us to use a partitoned root block device
isRootDevice := false
// This is the path within the jailed root
drive := &models.Drive{
DriveID: &driveID,
IsReadOnly: &isReadOnly,
IsRootDevice: &isRootDevice,
PathOnHost: &path,
PathOnHost: &jailedRootfs,
}
driveParams.SetBody(drive)
_, err := fc.client().Operations.PutGuestDriveByID(driveParams)
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
return err
}
@ -386,7 +545,7 @@ func (fc *firecracker) fcStartVM() error {
fc.Logger().Info("Starting VM")
fc.fcClient = fc.newFireClient()
fc.connection = fc.newFireClient()
actionParams := ops.NewCreateSyncActionParams()
actionType := "InstanceStart"
@ -400,7 +559,6 @@ func (fc *firecracker) fcStartVM() error {
}
fc.state.set(vmReady)
return nil
}
@ -436,7 +594,6 @@ func (fc *firecracker) startSandbox(timeout int) error {
kernelParams := append(fc.config.KernelParams, fcKernelParams...)
strParams := SerializeParams(kernelParams, "=")
formattedParams := strings.Join(strParams, " ")
fc.fcSetBootSource(kernelPath, formattedParams)
image, err := fc.config.InitrdAssetPath()
@ -483,7 +640,8 @@ func (fc *firecracker) createDiskPool() error {
isRootDevice := false
// Create a temporary file as a placeholder backend for the drive
hostURL, err := fc.store.Raw("")
//hostURL, err := fc.store.Raw("")
hostURL, err := fc.store.Raw(driveID)
if err != nil {
return err
}
@ -494,11 +652,17 @@ func (fc *firecracker) createDiskPool() error {
return err
}
jailedDrive, err := fc.fcJailResource(u.Path, driveID)
if err != nil {
fc.Logger().WithField("createDiskPool failed", err).Error()
return err
}
drive := &models.Drive{
DriveID: &driveID,
IsReadOnly: &isReadOnly,
IsRootDevice: &isRootDevice,
PathOnHost: &u.Path,
PathOnHost: &jailedDrive,
}
driveParams.SetBody(drive)
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
@ -510,6 +674,39 @@ func (fc *firecracker) createDiskPool() error {
return nil
}
func (fc *firecracker) umountResource(jailedPath string) {
hostPath := filepath.Join(fc.jailerRoot, jailedPath)
err := syscall.Unmount(hostPath, syscall.MNT_DETACH)
if err != nil {
fc.Logger().WithField("umountResource failed", err).Info()
}
}
// cleanup all jail artifacts
func (fc *firecracker) cleanupJail() {
span, _ := fc.trace("cleanupJail")
defer span.Finish()
fc.umountResource(fcKernel)
fc.umountResource(fcRootfs)
for i := 0; i < fcDiskPoolSize; i++ {
fc.umountResource(fcDriveIndexToID(i))
}
//Run through the list second time as may have bindmounted
//to the same location twice. In the future this needs to
//be tracked so that we do not do this blindly
for i := 0; i < fcDiskPoolSize; i++ {
fc.umountResource(fcDriveIndexToID(i))
}
fc.Logger().WithField("cleaningJail", fc.vmPath).Info()
if err := os.RemoveAll(fc.vmPath); err != nil {
fc.Logger().WithField("cleanupJail failed", err).Error()
}
}
// stopSandbox will stop the Sandbox's VM.
func (fc *firecracker) stopSandbox() (err error) {
span, _ := fc.trace("stopSandbox")
@ -581,14 +778,21 @@ func (fc *firecracker) fcAddBlockDrive(drive config.BlockDrive) error {
driveParams.SetDriveID(driveID)
isReadOnly := false
isRootDevice := false
jailedDrive, err := fc.fcJailResource(drive.File, driveID)
if err != nil {
fc.Logger().WithField("fcAddBlockDrive failed", err).Error()
return err
}
driveFc := &models.Drive{
DriveID: &driveID,
IsReadOnly: &isReadOnly,
IsRootDevice: &isRootDevice,
PathOnHost: &drive.File,
PathOnHost: &jailedDrive,
}
driveParams.SetBody(driveFc)
_, err := fc.client().Operations.PutGuestDriveByID(driveParams)
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
return err
}
@ -603,13 +807,18 @@ func (fc *firecracker) fcUpdateBlockDrive(drive config.BlockDrive) error {
driveParams := ops.NewPatchGuestDriveByIDParams()
driveParams.SetDriveID(driveID)
jailedDrive, err := fc.fcJailResource(drive.File, driveID)
if err != nil {
fc.Logger().WithField("fcUpdateBlockDrive failed", err).Error()
return err
}
driveFc := &models.PartialDrive{
DriveID: &driveID,
PathOnHost: &drive.File, //This is the only property that can be modified
PathOnHost: &jailedDrive, //This is the only property that can be modified
}
driveParams.SetBody(driveFc)
_, err := fc.client().Operations.PatchGuestDriveByID(driveParams)
if err != nil {
if _, err := fc.client().Operations.PatchGuestDriveByID(driveParams); err != nil {
return err
}
@ -764,6 +973,7 @@ func (fc *firecracker) getThreadIDs() (vcpuThreadIDs, error) {
}
func (fc *firecracker) cleanup() error {
fc.cleanupJail()
return nil
}

View File

@ -225,6 +225,9 @@ type HypervisorConfig struct {
// HypervisorCtlPath is the hypervisor ctl executable host path.
HypervisorCtlPath string
// JailerPath is the jailer executable host path.
JailerPath string
// BlockDeviceDriver specifies the driver to be used for block device
// either VirtioSCSI or VirtioBlock with the default driver being defaultBlockDriver
BlockDeviceDriver string
@ -445,6 +448,8 @@ func (conf *HypervisorConfig) assetPath(t types.AssetType) (string, error) {
return conf.HypervisorPath, nil
case types.HypervisorCtlAsset:
return conf.HypervisorCtlPath, nil
case types.JailerAsset:
return conf.JailerPath, nil
case types.FirmwareAsset:
return conf.FirmwarePath, nil
default:
@ -497,6 +502,11 @@ func (conf *HypervisorConfig) HypervisorCtlAssetPath() (string, error) {
return conf.assetPath(types.HypervisorCtlAsset)
}
// JailerAssetPath returns the VM Jailer path
func (conf *HypervisorConfig) JailerAssetPath() (string, error) {
return conf.assetPath(types.JailerAsset)
}
// CustomHypervisorAsset returns true if the hypervisor asset is a custom one, false otherwise.
func (conf *HypervisorConfig) CustomHypervisorAsset() bool {
return conf.isCustomAsset(types.HypervisorAsset)
@ -640,7 +650,7 @@ func RunningOnVMM(cpuInfoPath string) (bool, error) {
// hypervisor is the virtcontainers hypervisor interface.
// The default hypervisor implementation is Qemu.
type hypervisor interface {
createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error
createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, store *store.VCStore) error
startSandbox(timeout int) error
stopSandbox() error
pauseSandbox() error

View File

@ -26,7 +26,7 @@ func (m *mockHypervisor) hypervisorConfig() HypervisorConfig {
return HypervisorConfig{}
}
func (m *mockHypervisor) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
func (m *mockHypervisor) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
err := hypervisorConfig.valid()
if err != nil {
return err

View File

@ -28,7 +28,7 @@ func TestMockHypervisorCreateSandbox(t *testing.T) {
ctx := context.Background()
// wrong config
if err := m.createSandbox(ctx, sandbox.config.ID, &sandbox.config.HypervisorConfig, nil); err == nil {
if err := m.createSandbox(ctx, sandbox.config.ID, NetworkNamespace{}, &sandbox.config.HypervisorConfig, nil); err == nil {
t.Fatal()
}
@ -38,7 +38,7 @@ func TestMockHypervisorCreateSandbox(t *testing.T) {
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
}
if err := m.createSandbox(ctx, sandbox.config.ID, &sandbox.config.HypervisorConfig, nil); err != nil {
if err := m.createSandbox(ctx, sandbox.config.ID, NetworkNamespace{}, &sandbox.config.HypervisorConfig, nil); err != nil {
t.Fatal(err)
}
}

View File

@ -20,6 +20,9 @@ const (
// HypervisorPath is a sandbox annotation for passing a per container path pointing at the hypervisor that will run the container VM.
HypervisorPath = vcAnnotationsPrefix + "HypervisorPath"
// JailerPath is a sandbox annotation for passing a per container path pointing at the jailer that will constrain the container VM.
JailerPath = vcAnnotationsPrefix + "JailerPath"
// FirmwarePath is a sandbox annotation for passing a per container path pointing at the guest firmware that will run the container VM.
FirmwarePath = vcAnnotationsPrefix + "FirmwarePath"
@ -35,6 +38,9 @@ const (
// HypervisorHash is an sandbox annotation for passing a container hypervisor binary SHA-512 hash value.
HypervisorHash = vcAnnotationsPrefix + "HypervisorHash"
// JailerHash is an sandbox annotation for passing a jailer binary SHA-512 hash value.
JailerHash = vcAnnotationsPrefix + "JailerHash"
// FirmwareHash is an sandbox annotation for passing a container guest firmware SHA-512 hash value.
FirmwareHash = vcAnnotationsPrefix + "FirmwareHash"

View File

@ -442,7 +442,7 @@ func (q *qemu) setupFileBackedMem(knobs *govmmQemu.Knobs, memory *govmmQemu.Memo
}
// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
func (q *qemu) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
// Save the tracing context
q.ctx = ctx

View File

@ -104,7 +104,7 @@ func TestQemuCreateSandbox(t *testing.T) {
t.Fatalf("Could not create parent directory %s: %v", parentDir, err)
}
if err := q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
if err := q.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
@ -148,7 +148,7 @@ func TestQemuCreateSandboxMissingParentDirFail(t *testing.T) {
t.Fatal(err)
}
if err := q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
if err := q.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatalf("Qemu createSandbox() is not expected to fail because of missing parent directory for storage: %v", err)
}
}
@ -505,7 +505,7 @@ func TestQemuFileBackedMem(t *testing.T) {
}
q := &qemu{}
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
if err = q.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, true)
@ -522,7 +522,7 @@ func TestQemuFileBackedMem(t *testing.T) {
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
sandbox.config.HypervisorConfig.MemoryPath = fallbackFileBackedMemDir
err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store)
err = q.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store)
expectErr := errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")
assert.Equal(expectErr, err)
@ -534,7 +534,7 @@ func TestQemuFileBackedMem(t *testing.T) {
}
q = &qemu{}
sandbox.config.HypervisorConfig.FileBackedMemRootDir = "/tmp/xyzabc"
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
if err = q.createSandbox(context.Background(), sandbox.id, NetworkNamespace{}, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)

View File

@ -574,7 +574,7 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor
}
}()
if err = s.hypervisor.createSandbox(ctx, s.id, &sandboxConfig.HypervisorConfig, s.store); err != nil {
if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.store); err != nil {
return nil, err
}

View File

@ -29,6 +29,8 @@ func (t AssetType) Annotations() (string, string, error) {
return annotations.InitrdPath, annotations.InitrdHash, nil
case HypervisorAsset:
return annotations.HypervisorPath, annotations.HypervisorHash, nil
case JailerAsset:
return annotations.JailerPath, annotations.JailerHash, nil
case FirmwareAsset:
return annotations.FirmwarePath, annotations.FirmwareHash, nil
}
@ -51,6 +53,8 @@ const (
// HypervisorCtlAsset is an hypervisor control asset.
HypervisorCtlAsset AssetType = "hypervisorctl"
// JailerAsset is an jailer asset.
JailerAsset AssetType = "jailer"
// FirmwareAsset is a firmware asset.
FirmwareAsset AssetType = "firmware"
@ -88,6 +92,8 @@ func (a *Asset) Valid() bool {
return true
case HypervisorAsset:
return true
case JailerAsset:
return true
case FirmwareAsset:
return true
}

View File

@ -172,7 +172,7 @@ func NewVM(ctx context.Context, config VMConfig) (*VM, error) {
}
}()
if err = hypervisor.createSandbox(ctx, id, &config.HypervisorConfig, vcStore); err != nil {
if err = hypervisor.createSandbox(ctx, id, NetworkNamespace{}, &config.HypervisorConfig, vcStore); err != nil {
return nil, err
}