mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-16 16:32:03 +00:00
Merge pull request #1649 from mcastelino/topic/jail
Firecracker Add jailer support for firecracker
This commit is contained in:
commit
bc15e44245
4
Makefile
4
Makefile
@ -116,6 +116,7 @@ CONFIG_FILE = configuration.toml
|
|||||||
|
|
||||||
HYPERVISOR_ACRN = acrn
|
HYPERVISOR_ACRN = acrn
|
||||||
HYPERVISOR_FC = firecracker
|
HYPERVISOR_FC = firecracker
|
||||||
|
JAILER_FC = jailer
|
||||||
HYPERVISOR_NEMU = nemu
|
HYPERVISOR_NEMU = nemu
|
||||||
HYPERVISOR_QEMU = qemu
|
HYPERVISOR_QEMU = qemu
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ QEMUPATH := $(QEMUBINDIR)/$(QEMUCMD)
|
|||||||
NEMUPATH := $(NEMUBINDIR)/$(NEMUCMD)
|
NEMUPATH := $(NEMUBINDIR)/$(NEMUCMD)
|
||||||
|
|
||||||
FCPATH = $(FCBINDIR)/$(FCCMD)
|
FCPATH = $(FCBINDIR)/$(FCCMD)
|
||||||
|
FCJAILERPATH = $(FCBINDIR)/$(FCJAILERCMD)
|
||||||
|
|
||||||
ACRNPATH := $(ACRNBINDIR)/$(ACRNCMD)
|
ACRNPATH := $(ACRNBINDIR)/$(ACRNCMD)
|
||||||
ACRNCTLPATH := $(ACRNBINDIR)/$(ACRNCTLCMD)
|
ACRNCTLPATH := $(ACRNBINDIR)/$(ACRNCTLCMD)
|
||||||
@ -355,6 +357,7 @@ USER_VARS += ACRNPATH
|
|||||||
USER_VARS += ACRNCTLPATH
|
USER_VARS += ACRNCTLPATH
|
||||||
USER_VARS += FCCMD
|
USER_VARS += FCCMD
|
||||||
USER_VARS += FCPATH
|
USER_VARS += FCPATH
|
||||||
|
USER_VARS += FCJAILERPATH
|
||||||
USER_VARS += NEMUCMD
|
USER_VARS += NEMUCMD
|
||||||
USER_VARS += NEMUPATH
|
USER_VARS += NEMUPATH
|
||||||
USER_VARS += SYSCONFIG
|
USER_VARS += SYSCONFIG
|
||||||
@ -516,6 +519,7 @@ $(GENERATED_FILES): %: %.in $(MAKEFILE_LIST) VERSION .git-commit
|
|||||||
-e "s|@CONFIG_FC_IN@|$(CONFIG_FC_IN)|g" \
|
-e "s|@CONFIG_FC_IN@|$(CONFIG_FC_IN)|g" \
|
||||||
-e "s|@CONFIG_PATH@|$(CONFIG_PATH)|g" \
|
-e "s|@CONFIG_PATH@|$(CONFIG_PATH)|g" \
|
||||||
-e "s|@FCPATH@|$(FCPATH)|g" \
|
-e "s|@FCPATH@|$(FCPATH)|g" \
|
||||||
|
-e "s|@FCJAILERPATH@|$(FCJAILERPATH)|g" \
|
||||||
-e "s|@NEMUPATH@|$(NEMUPATH)|g" \
|
-e "s|@NEMUPATH@|$(NEMUPATH)|g" \
|
||||||
-e "s|@ACRNPATH@|$(ACRNPATH)|g" \
|
-e "s|@ACRNPATH@|$(ACRNPATH)|g" \
|
||||||
-e "s|@ACRNCTLPATH@|$(ACRNCTLPATH)|g" \
|
-e "s|@ACRNCTLPATH@|$(ACRNCTLPATH)|g" \
|
||||||
|
@ -13,6 +13,8 @@ QEMUCMD := qemu-system-x86_64
|
|||||||
|
|
||||||
# Firecracker binary name
|
# Firecracker binary name
|
||||||
FCCMD := firecracker
|
FCCMD := firecracker
|
||||||
|
# Firecracker's jailer binary name
|
||||||
|
FCJAILERCMD := jailer
|
||||||
|
|
||||||
# NEMU binary name
|
# NEMU binary name
|
||||||
NEMUCMD := nemu-system-x86_64
|
NEMUCMD := nemu-system-x86_64
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
[hypervisor.firecracker]
|
[hypervisor.firecracker]
|
||||||
path = "@FCPATH@"
|
path = "@FCPATH@"
|
||||||
|
# Path for the jailer specific to firecracker
|
||||||
|
# If the jailer path is not set kata will launch firecracker
|
||||||
|
# without a jail. If the jailer is set firecracker will be
|
||||||
|
# launched in a jailed enviornment created by the jailer
|
||||||
|
jailer_path = "@FCJAILERPATH@"
|
||||||
kernel = "@KERNELPATH_FC@"
|
kernel = "@KERNELPATH_FC@"
|
||||||
image = "@IMAGEPATH@"
|
image = "@IMAGEPATH@"
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ package katautils
|
|||||||
|
|
||||||
var defaultHypervisorPath = "/usr/bin/qemu-lite-system-x86_64"
|
var defaultHypervisorPath = "/usr/bin/qemu-lite-system-x86_64"
|
||||||
var defaultHypervisorCtlPath = "/usr/bin/acrnctl"
|
var defaultHypervisorCtlPath = "/usr/bin/acrnctl"
|
||||||
|
var defaultJailerPath = "/usr/bin/jailer"
|
||||||
var defaultImagePath = "/usr/share/kata-containers/kata-containers.img"
|
var defaultImagePath = "/usr/share/kata-containers/kata-containers.img"
|
||||||
var defaultKernelPath = "/usr/share/kata-containers/vmlinuz.container"
|
var defaultKernelPath = "/usr/share/kata-containers/vmlinuz.container"
|
||||||
var defaultInitrdPath = "/usr/share/kata-containers/kata-containers-initrd.img"
|
var defaultInitrdPath = "/usr/share/kata-containers/kata-containers-initrd.img"
|
||||||
|
@ -84,6 +84,7 @@ type factory struct {
|
|||||||
|
|
||||||
type hypervisor struct {
|
type hypervisor struct {
|
||||||
Path string `toml:"path"`
|
Path string `toml:"path"`
|
||||||
|
JailerPath string `toml:"jailer_path"`
|
||||||
Kernel string `toml:"kernel"`
|
Kernel string `toml:"kernel"`
|
||||||
CtlPath string `toml:"ctlpath"`
|
CtlPath string `toml:"ctlpath"`
|
||||||
Initrd string `toml:"initrd"`
|
Initrd string `toml:"initrd"`
|
||||||
@ -175,6 +176,16 @@ func (h hypervisor) ctlpath() (string, error) {
|
|||||||
return ResolvePath(p)
|
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) {
|
func (h hypervisor) kernel() (string, error) {
|
||||||
p := h.Kernel
|
p := h.Kernel
|
||||||
|
|
||||||
@ -463,6 +474,11 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
|||||||
return vc.HypervisorConfig{}, err
|
return vc.HypervisorConfig{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jailer, err := h.jailerPath()
|
||||||
|
if err != nil {
|
||||||
|
return vc.HypervisorConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
kernel, err := h.kernel()
|
kernel, err := h.kernel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return vc.HypervisorConfig{}, err
|
return vc.HypervisorConfig{}, err
|
||||||
@ -491,6 +507,7 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
|||||||
|
|
||||||
return vc.HypervisorConfig{
|
return vc.HypervisorConfig{
|
||||||
HypervisorPath: hypervisor,
|
HypervisorPath: hypervisor,
|
||||||
|
JailerPath: jailer,
|
||||||
KernelPath: kernel,
|
KernelPath: kernel,
|
||||||
InitrdPath: initrd,
|
InitrdPath: initrd,
|
||||||
ImagePath: image,
|
ImagePath: image,
|
||||||
@ -915,6 +932,7 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
|
|||||||
func GetDefaultHypervisorConfig() vc.HypervisorConfig {
|
func GetDefaultHypervisorConfig() vc.HypervisorConfig {
|
||||||
return vc.HypervisorConfig{
|
return vc.HypervisorConfig{
|
||||||
HypervisorPath: defaultHypervisorPath,
|
HypervisorPath: defaultHypervisorPath,
|
||||||
|
JailerPath: defaultJailerPath,
|
||||||
KernelPath: defaultKernelPath,
|
KernelPath: defaultKernelPath,
|
||||||
ImagePath: defaultImagePath,
|
ImagePath: defaultImagePath,
|
||||||
InitrdPath: defaultInitrdPath,
|
InitrdPath: defaultInitrdPath,
|
||||||
|
@ -514,6 +514,8 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
proxyPath := path.Join(dir, "proxy")
|
proxyPath := path.Join(dir, "proxy")
|
||||||
hypervisorPath := path.Join(dir, "hypervisor")
|
hypervisorPath := path.Join(dir, "hypervisor")
|
||||||
defaultHypervisorPath = hypervisorPath
|
defaultHypervisorPath = hypervisorPath
|
||||||
|
jailerPath := path.Join(dir, "jailer")
|
||||||
|
defaultJailerPath = jailerPath
|
||||||
netmonPath := path.Join(dir, "netmon")
|
netmonPath := path.Join(dir, "netmon")
|
||||||
|
|
||||||
imagePath := path.Join(dir, "image.img")
|
imagePath := path.Join(dir, "image.img")
|
||||||
@ -524,12 +526,14 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
savedDefaultImagePath := defaultImagePath
|
savedDefaultImagePath := defaultImagePath
|
||||||
savedDefaultInitrdPath := defaultInitrdPath
|
savedDefaultInitrdPath := defaultInitrdPath
|
||||||
savedDefaultHypervisorPath := defaultHypervisorPath
|
savedDefaultHypervisorPath := defaultHypervisorPath
|
||||||
|
savedDefaultJailerPath := defaultJailerPath
|
||||||
savedDefaultKernelPath := defaultKernelPath
|
savedDefaultKernelPath := defaultKernelPath
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
defaultImagePath = savedDefaultImagePath
|
defaultImagePath = savedDefaultImagePath
|
||||||
defaultInitrdPath = savedDefaultInitrdPath
|
defaultInitrdPath = savedDefaultInitrdPath
|
||||||
defaultHypervisorPath = savedDefaultHypervisorPath
|
defaultHypervisorPath = savedDefaultHypervisorPath
|
||||||
|
defaultJailerPath = savedDefaultJailerPath
|
||||||
defaultKernelPath = savedDefaultKernelPath
|
defaultKernelPath = savedDefaultKernelPath
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -538,9 +542,10 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
defaultImagePath = imagePath
|
defaultImagePath = imagePath
|
||||||
defaultInitrdPath = initrdPath
|
defaultInitrdPath = initrdPath
|
||||||
defaultHypervisorPath = hypervisorPath
|
defaultHypervisorPath = hypervisorPath
|
||||||
|
defaultJailerPath = jailerPath
|
||||||
defaultKernelPath = kernelPath
|
defaultKernelPath = kernelPath
|
||||||
|
|
||||||
for _, file := range []string{defaultImagePath, defaultInitrdPath, defaultHypervisorPath, defaultKernelPath} {
|
for _, file := range []string{defaultImagePath, defaultInitrdPath, defaultHypervisorPath, defaultJailerPath, defaultKernelPath} {
|
||||||
err = WriteFile(file, "foo", testFileMode)
|
err = WriteFile(file, "foo", testFileMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -588,6 +593,11 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = createEmptyFile(jailerPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
err = createEmptyFile(netmonPath)
|
err = createEmptyFile(netmonPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@ -600,6 +610,7 @@ func TestMinimalRuntimeConfig(t *testing.T) {
|
|||||||
|
|
||||||
expectedHypervisorConfig := vc.HypervisorConfig{
|
expectedHypervisorConfig := vc.HypervisorConfig{
|
||||||
HypervisorPath: defaultHypervisorPath,
|
HypervisorPath: defaultHypervisorPath,
|
||||||
|
JailerPath: defaultJailerPath,
|
||||||
KernelPath: defaultKernelPath,
|
KernelPath: defaultKernelPath,
|
||||||
ImagePath: defaultImagePath,
|
ImagePath: defaultImagePath,
|
||||||
InitrdPath: defaultInitrdPath,
|
InitrdPath: defaultInitrdPath,
|
||||||
|
@ -278,7 +278,7 @@ func (a *acrn) createDummyVirtioBlkDev(devices []Device) ([]Device, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createSandbox is the Hypervisor sandbox creation.
|
// 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
|
// Save the tracing context
|
||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ func TestAcrnCreateSandbox(t *testing.T) {
|
|||||||
t.Fatalf("Could not create hypervisor file %s: %v", testAcrnPath, err)
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -44,8 +45,12 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
//fcTimeout is the maximum amount of time in seconds to wait for the VMM to respond
|
//fcTimeout is the maximum amount of time in seconds to wait for the VMM to respond
|
||||||
fcTimeout = 10
|
fcTimeout = 10
|
||||||
fireSocket = "firecracker.sock"
|
fcSocket = "api.socket"
|
||||||
|
//Name of the files within jailer root
|
||||||
|
//Having predefined names helps with cleanup
|
||||||
|
fcKernel = "vmlinux"
|
||||||
|
fcRootfs = "rootfs"
|
||||||
fcStopSandboxTimeout = 15
|
fcStopSandboxTimeout = 15
|
||||||
// This indicates the number of block devices that can be attached to the
|
// This indicates the number of block devices that can be attached to the
|
||||||
// firecracker guest VM.
|
// firecracker guest VM.
|
||||||
@ -102,18 +107,27 @@ func (s *firecrackerState) set(state vmmState) {
|
|||||||
|
|
||||||
// firecracker is an Hypervisor interface implementation for the firecracker hypervisor.
|
// firecracker is an Hypervisor interface implementation for the firecracker hypervisor.
|
||||||
type firecracker struct {
|
type firecracker struct {
|
||||||
id string //Unique ID per pod. Normally maps to the sandbox id
|
id string //Unique ID per pod. Normally maps to the sandbox id
|
||||||
state firecrackerState
|
vmPath string //All jailed VM assets need to be under this
|
||||||
info FirecrackerInfo
|
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
|
firecrackerd *exec.Cmd //Tracks the firecracker process itself
|
||||||
fcClient *client.Firecracker //Tracks the current active connection
|
connection *client.Firecracker //Tracks the current active connection
|
||||||
socketPath string
|
|
||||||
|
|
||||||
store *store.VCStore
|
store *store.VCStore
|
||||||
|
ctx context.Context
|
||||||
config HypervisorConfig
|
config HypervisorConfig
|
||||||
pendingDevices []firecrackerDevice // Devices to be added when the FC API is ready
|
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 {
|
type firecrackerDevice struct {
|
||||||
@ -140,9 +154,47 @@ func (fc *firecracker) trace(name string) (opentracing.Span, context.Context) {
|
|||||||
return span, ctx
|
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.
|
// For firecracker this call only sets the internal structure up.
|
||||||
// The sandbox will be created and started through startSandbox().
|
// 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
|
fc.ctx = ctx
|
||||||
|
|
||||||
span, _ := fc.trace("createSandbox")
|
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
|
//TODO: check validity of the hypervisor config provided
|
||||||
//https://github.com/kata-containers/runtime/issues/1065
|
//https://github.com/kata-containers/runtime/issues/1065
|
||||||
fc.id = id
|
fc.id = id
|
||||||
fc.socketPath = filepath.Join(store.SandboxRuntimeRootPath(fc.id), fireSocket)
|
|
||||||
fc.store = vcStore
|
fc.store = vcStore
|
||||||
fc.config = *hypervisorConfig
|
|
||||||
fc.state.set(notReady)
|
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
|
// 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.
|
// 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")
|
span, _ := fc.trace("fcInit")
|
||||||
defer span.Finish()
|
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 {
|
if err := cmd.Start(); err != nil {
|
||||||
fc.Logger().WithField("Error starting firecracker", err).Debug()
|
fc.Logger().WithField("Error starting firecracker", err).Debug()
|
||||||
return err
|
return err
|
||||||
@ -249,7 +378,7 @@ func (fc *firecracker) fcInit(timeout int) error {
|
|||||||
|
|
||||||
fc.info.PID = cmd.Process.Pid
|
fc.info.PID = cmd.Process.Pid
|
||||||
fc.firecrackerd = cmd
|
fc.firecrackerd = cmd
|
||||||
fc.fcClient = fc.newFireClient()
|
fc.connection = fc.newFireClient()
|
||||||
|
|
||||||
if err := fc.waitVMM(timeout); err != nil {
|
if err := fc.waitVMM(timeout); err != nil {
|
||||||
fc.Logger().WithField("fcInit failed:", err).Debug()
|
fc.Logger().WithField("fcInit failed:", err).Debug()
|
||||||
@ -314,11 +443,31 @@ func (fc *firecracker) client() *client.Firecracker {
|
|||||||
span, _ := fc.trace("client")
|
span, _ := fc.trace("client")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
if fc.fcClient == nil {
|
if fc.connection == nil {
|
||||||
fc.fcClient = fc.newFireClient()
|
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 {
|
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,
|
fc.Logger().WithFields(logrus.Fields{"kernel-path": path,
|
||||||
"kernel-params": params}).Debug("fcSetBootSource")
|
"kernel-params": params}).Debug("fcSetBootSource")
|
||||||
|
|
||||||
|
kernelPath, err := fc.fcJailResource(path, fcKernel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
bootSrcParams := ops.NewPutGuestBootSourceParams()
|
bootSrcParams := ops.NewPutGuestBootSourceParams()
|
||||||
src := &models.BootSource{
|
src := &models.BootSource{
|
||||||
KernelImagePath: &path,
|
KernelImagePath: &kernelPath,
|
||||||
BootArgs: params,
|
BootArgs: params,
|
||||||
}
|
}
|
||||||
bootSrcParams.SetBody(src)
|
bootSrcParams.SetBody(src)
|
||||||
|
|
||||||
_, err := fc.client().Operations.PutGuestBootSource(bootSrcParams)
|
_, err = fc.client().Operations.PutGuestBootSource(bootSrcParams)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) fcSetVMRootfs(path string) error {
|
func (fc *firecracker) fcSetVMRootfs(path string) error {
|
||||||
span, _ := fc.trace("fcSetVMRootfs")
|
span, _ := fc.trace("fcSetVMRootfs")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
fc.Logger().WithField("VM-rootfs-path", path).Debug()
|
|
||||||
|
jailedRootfs, err := fc.fcJailResource(path, fcRootfs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
driveID := "rootfs"
|
driveID := "rootfs"
|
||||||
driveParams := ops.NewPutGuestDriveByIDParams()
|
driveParams := ops.NewPutGuestDriveByIDParams()
|
||||||
driveParams.SetDriveID(driveID)
|
driveParams.SetDriveID(driveID)
|
||||||
isReadOnly := true
|
isReadOnly := true
|
||||||
//Add it as a regular block device
|
//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
|
isRootDevice := false
|
||||||
|
// This is the path within the jailed root
|
||||||
drive := &models.Drive{
|
drive := &models.Drive{
|
||||||
DriveID: &driveID,
|
DriveID: &driveID,
|
||||||
IsReadOnly: &isReadOnly,
|
IsReadOnly: &isReadOnly,
|
||||||
IsRootDevice: &isRootDevice,
|
IsRootDevice: &isRootDevice,
|
||||||
PathOnHost: &path,
|
PathOnHost: &jailedRootfs,
|
||||||
}
|
}
|
||||||
driveParams.SetBody(drive)
|
driveParams.SetBody(drive)
|
||||||
_, err := fc.client().Operations.PutGuestDriveByID(driveParams)
|
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +545,7 @@ func (fc *firecracker) fcStartVM() error {
|
|||||||
|
|
||||||
fc.Logger().Info("Starting VM")
|
fc.Logger().Info("Starting VM")
|
||||||
|
|
||||||
fc.fcClient = fc.newFireClient()
|
fc.connection = fc.newFireClient()
|
||||||
|
|
||||||
actionParams := ops.NewCreateSyncActionParams()
|
actionParams := ops.NewCreateSyncActionParams()
|
||||||
actionType := "InstanceStart"
|
actionType := "InstanceStart"
|
||||||
@ -400,7 +559,6 @@ func (fc *firecracker) fcStartVM() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fc.state.set(vmReady)
|
fc.state.set(vmReady)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,7 +594,6 @@ func (fc *firecracker) startSandbox(timeout int) error {
|
|||||||
kernelParams := append(fc.config.KernelParams, fcKernelParams...)
|
kernelParams := append(fc.config.KernelParams, fcKernelParams...)
|
||||||
strParams := SerializeParams(kernelParams, "=")
|
strParams := SerializeParams(kernelParams, "=")
|
||||||
formattedParams := strings.Join(strParams, " ")
|
formattedParams := strings.Join(strParams, " ")
|
||||||
|
|
||||||
fc.fcSetBootSource(kernelPath, formattedParams)
|
fc.fcSetBootSource(kernelPath, formattedParams)
|
||||||
|
|
||||||
image, err := fc.config.InitrdAssetPath()
|
image, err := fc.config.InitrdAssetPath()
|
||||||
@ -483,7 +640,8 @@ func (fc *firecracker) createDiskPool() error {
|
|||||||
isRootDevice := false
|
isRootDevice := false
|
||||||
|
|
||||||
// Create a temporary file as a placeholder backend for the drive
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -494,11 +652,17 @@ func (fc *firecracker) createDiskPool() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jailedDrive, err := fc.fcJailResource(u.Path, driveID)
|
||||||
|
if err != nil {
|
||||||
|
fc.Logger().WithField("createDiskPool failed", err).Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
drive := &models.Drive{
|
drive := &models.Drive{
|
||||||
DriveID: &driveID,
|
DriveID: &driveID,
|
||||||
IsReadOnly: &isReadOnly,
|
IsReadOnly: &isReadOnly,
|
||||||
IsRootDevice: &isRootDevice,
|
IsRootDevice: &isRootDevice,
|
||||||
PathOnHost: &u.Path,
|
PathOnHost: &jailedDrive,
|
||||||
}
|
}
|
||||||
driveParams.SetBody(drive)
|
driveParams.SetBody(drive)
|
||||||
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
|
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
|
||||||
@ -510,6 +674,39 @@ func (fc *firecracker) createDiskPool() error {
|
|||||||
return nil
|
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.
|
// stopSandbox will stop the Sandbox's VM.
|
||||||
func (fc *firecracker) stopSandbox() (err error) {
|
func (fc *firecracker) stopSandbox() (err error) {
|
||||||
span, _ := fc.trace("stopSandbox")
|
span, _ := fc.trace("stopSandbox")
|
||||||
@ -581,14 +778,21 @@ func (fc *firecracker) fcAddBlockDrive(drive config.BlockDrive) error {
|
|||||||
driveParams.SetDriveID(driveID)
|
driveParams.SetDriveID(driveID)
|
||||||
isReadOnly := false
|
isReadOnly := false
|
||||||
isRootDevice := 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{
|
driveFc := &models.Drive{
|
||||||
DriveID: &driveID,
|
DriveID: &driveID,
|
||||||
IsReadOnly: &isReadOnly,
|
IsReadOnly: &isReadOnly,
|
||||||
IsRootDevice: &isRootDevice,
|
IsRootDevice: &isRootDevice,
|
||||||
PathOnHost: &drive.File,
|
PathOnHost: &jailedDrive,
|
||||||
}
|
}
|
||||||
|
|
||||||
driveParams.SetBody(driveFc)
|
driveParams.SetBody(driveFc)
|
||||||
_, err := fc.client().Operations.PutGuestDriveByID(driveParams)
|
_, err = fc.client().Operations.PutGuestDriveByID(driveParams)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,13 +807,18 @@ func (fc *firecracker) fcUpdateBlockDrive(drive config.BlockDrive) error {
|
|||||||
driveParams := ops.NewPatchGuestDriveByIDParams()
|
driveParams := ops.NewPatchGuestDriveByIDParams()
|
||||||
driveParams.SetDriveID(driveID)
|
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{
|
driveFc := &models.PartialDrive{
|
||||||
DriveID: &driveID,
|
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)
|
driveParams.SetBody(driveFc)
|
||||||
_, err := fc.client().Operations.PatchGuestDriveByID(driveParams)
|
if _, err := fc.client().Operations.PatchGuestDriveByID(driveParams); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,6 +973,7 @@ func (fc *firecracker) getThreadIDs() (vcpuThreadIDs, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) cleanup() error {
|
func (fc *firecracker) cleanup() error {
|
||||||
|
fc.cleanupJail()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,9 @@ type HypervisorConfig struct {
|
|||||||
// HypervisorCtlPath is the hypervisor ctl executable host path.
|
// HypervisorCtlPath is the hypervisor ctl executable host path.
|
||||||
HypervisorCtlPath string
|
HypervisorCtlPath string
|
||||||
|
|
||||||
|
// JailerPath is the jailer executable host path.
|
||||||
|
JailerPath string
|
||||||
|
|
||||||
// BlockDeviceDriver specifies the driver to be used for block device
|
// BlockDeviceDriver specifies the driver to be used for block device
|
||||||
// either VirtioSCSI or VirtioBlock with the default driver being defaultBlockDriver
|
// either VirtioSCSI or VirtioBlock with the default driver being defaultBlockDriver
|
||||||
BlockDeviceDriver string
|
BlockDeviceDriver string
|
||||||
@ -445,6 +448,8 @@ func (conf *HypervisorConfig) assetPath(t types.AssetType) (string, error) {
|
|||||||
return conf.HypervisorPath, nil
|
return conf.HypervisorPath, nil
|
||||||
case types.HypervisorCtlAsset:
|
case types.HypervisorCtlAsset:
|
||||||
return conf.HypervisorCtlPath, nil
|
return conf.HypervisorCtlPath, nil
|
||||||
|
case types.JailerAsset:
|
||||||
|
return conf.JailerPath, nil
|
||||||
case types.FirmwareAsset:
|
case types.FirmwareAsset:
|
||||||
return conf.FirmwarePath, nil
|
return conf.FirmwarePath, nil
|
||||||
default:
|
default:
|
||||||
@ -497,6 +502,11 @@ func (conf *HypervisorConfig) HypervisorCtlAssetPath() (string, error) {
|
|||||||
return conf.assetPath(types.HypervisorCtlAsset)
|
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.
|
// CustomHypervisorAsset returns true if the hypervisor asset is a custom one, false otherwise.
|
||||||
func (conf *HypervisorConfig) CustomHypervisorAsset() bool {
|
func (conf *HypervisorConfig) CustomHypervisorAsset() bool {
|
||||||
return conf.isCustomAsset(types.HypervisorAsset)
|
return conf.isCustomAsset(types.HypervisorAsset)
|
||||||
@ -640,7 +650,7 @@ func RunningOnVMM(cpuInfoPath string) (bool, error) {
|
|||||||
// hypervisor is the virtcontainers hypervisor interface.
|
// hypervisor is the virtcontainers hypervisor interface.
|
||||||
// The default hypervisor implementation is Qemu.
|
// The default hypervisor implementation is Qemu.
|
||||||
type hypervisor interface {
|
type hypervisor interface {
|
||||||
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
|
startSandbox(timeout int) error
|
||||||
stopSandbox() error
|
stopSandbox() error
|
||||||
pauseSandbox() error
|
pauseSandbox() error
|
||||||
|
@ -26,7 +26,7 @@ func (m *mockHypervisor) hypervisorConfig() HypervisorConfig {
|
|||||||
return 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()
|
err := hypervisorConfig.valid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -28,7 +28,7 @@ func TestMockHypervisorCreateSandbox(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// wrong config
|
// 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()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ func TestMockHypervisorCreateSandbox(t *testing.T) {
|
|||||||
HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 is a sandbox annotation for passing a per container path pointing at the hypervisor that will run the container VM.
|
||||||
HypervisorPath = vcAnnotationsPrefix + "HypervisorPath"
|
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 is a sandbox annotation for passing a per container path pointing at the guest firmware that will run the container VM.
|
||||||
FirmwarePath = vcAnnotationsPrefix + "FirmwarePath"
|
FirmwarePath = vcAnnotationsPrefix + "FirmwarePath"
|
||||||
|
|
||||||
@ -35,6 +38,9 @@ const (
|
|||||||
// HypervisorHash is an sandbox annotation for passing a container hypervisor binary SHA-512 hash value.
|
// HypervisorHash is an sandbox annotation for passing a container hypervisor binary SHA-512 hash value.
|
||||||
HypervisorHash = vcAnnotationsPrefix + "HypervisorHash"
|
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 is an sandbox annotation for passing a container guest firmware SHA-512 hash value.
|
||||||
FirmwareHash = vcAnnotationsPrefix + "FirmwareHash"
|
FirmwareHash = vcAnnotationsPrefix + "FirmwareHash"
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ func (q *qemu) setupFileBackedMem(knobs *govmmQemu.Knobs, memory *govmmQemu.Memo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
|
// 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
|
// Save the tracing context
|
||||||
q.ctx = ctx
|
q.ctx = ctx
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func TestQemuCreateSandbox(t *testing.T) {
|
|||||||
t.Fatalf("Could not create parent directory %s: %v", parentDir, err)
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ func TestQemuCreateSandboxMissingParentDirFail(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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)
|
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{}
|
q := &qemu{}
|
||||||
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, true)
|
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.SharedFS = config.VirtioFS
|
||||||
sandbox.config.HypervisorConfig.MemoryPath = fallbackFileBackedMemDir
|
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")
|
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)
|
assert.Equal(expectErr, err)
|
||||||
@ -534,7 +534,7 @@ func TestQemuFileBackedMem(t *testing.T) {
|
|||||||
}
|
}
|
||||||
q = &qemu{}
|
q = &qemu{}
|
||||||
sandbox.config.HypervisorConfig.FileBackedMemRootDir = "/tmp/xyzabc"
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)
|
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)
|
||||||
|
@ -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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ func (t AssetType) Annotations() (string, string, error) {
|
|||||||
return annotations.InitrdPath, annotations.InitrdHash, nil
|
return annotations.InitrdPath, annotations.InitrdHash, nil
|
||||||
case HypervisorAsset:
|
case HypervisorAsset:
|
||||||
return annotations.HypervisorPath, annotations.HypervisorHash, nil
|
return annotations.HypervisorPath, annotations.HypervisorHash, nil
|
||||||
|
case JailerAsset:
|
||||||
|
return annotations.JailerPath, annotations.JailerHash, nil
|
||||||
case FirmwareAsset:
|
case FirmwareAsset:
|
||||||
return annotations.FirmwarePath, annotations.FirmwareHash, nil
|
return annotations.FirmwarePath, annotations.FirmwareHash, nil
|
||||||
}
|
}
|
||||||
@ -51,6 +53,8 @@ const (
|
|||||||
|
|
||||||
// HypervisorCtlAsset is an hypervisor control asset.
|
// HypervisorCtlAsset is an hypervisor control asset.
|
||||||
HypervisorCtlAsset AssetType = "hypervisorctl"
|
HypervisorCtlAsset AssetType = "hypervisorctl"
|
||||||
|
// JailerAsset is an jailer asset.
|
||||||
|
JailerAsset AssetType = "jailer"
|
||||||
|
|
||||||
// FirmwareAsset is a firmware asset.
|
// FirmwareAsset is a firmware asset.
|
||||||
FirmwareAsset AssetType = "firmware"
|
FirmwareAsset AssetType = "firmware"
|
||||||
@ -88,6 +92,8 @@ func (a *Asset) Valid() bool {
|
|||||||
return true
|
return true
|
||||||
case HypervisorAsset:
|
case HypervisorAsset:
|
||||||
return true
|
return true
|
||||||
|
case JailerAsset:
|
||||||
|
return true
|
||||||
case FirmwareAsset:
|
case FirmwareAsset:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user