Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions cmd/urunc/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,15 @@ var createCommand = &cli.Command{
},
}

// createUnikontainer creates a Unikernel struct from bundle data,
// initializes it's base dir and state.json,
// setups terminal if required and spawns reexec process,
// waits for reexec process to notify, executes CreateRuntime hooks,
// sends ACK to reexec process
func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (err error) {
err = nil
// newUnikontainer parses the bundle and performs the host-side preparation for
// the monitor execution environment (Unikontainer, base directory, state and
// monitor resources). It never returns for a container that is not a urunc
// container: those are handed over to the real runc with an execve.
func newUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (*unikontainers.Unikontainer, error) {
containerID := cmd.Args().First()
if err = validateID(containerID); err != nil {
return err
err := validateID(containerID)
if err != nil {
return nil, err
}
metrics.SetLoggerContainerID(containerID)
metrics.Capture(m.TS00)
Expand All @@ -105,7 +104,7 @@ func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (
if bundlePath == "" {
bundlePath, err = os.Getwd()
if err != nil {
return err
return nil, err
}
}

Expand All @@ -114,21 +113,33 @@ func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (
if err != nil {
if errors.Is(err, unikontainers.ErrQueueProxy) ||
errors.Is(err, unikontainers.ErrNotUnikernel) {
// Exec runc to handle non unikernel containers
err = runcExec()
return err
// Exec runc to handle non urunc containers.
// It should never return.
return nil, runcExec()
}
return err
return nil, err
}
metrics.Capture(m.TS01)

err = unikontainer.InitialSetup()
if err != nil {
return err
return nil, err
}

metrics.Capture(m.TS02)

return unikontainer, nil
}

// createUnikontainer creates a Unikernel struct from bundle data, initializes
// it's base dir and state.json, setups terminal if required and spawns reexec
// process, waits for reexec process to notify, executes CreateRuntime hooks,
// sends ACK to reexec process
func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (err error) {
unikontainer, err := newUnikontainer(cmd, uruncCfg)
if err != nil {
return err
}

// Create socket for nsenter
initSockParent, initSockChild, err := newSockPair("init")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/unikontainers/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ func (b blockRootfs) getSharedDirs() (types.SharedfsParams, error) {
return types.SharedfsParams{}, nil
}

func (b blockRootfs) preStart() error {
func (b blockRootfs) preStartCmd() []string {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/unikontainers/initrd_rootfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ func (i initrdRootfs) getSharedDirs() (types.SharedfsParams, error) {
return types.SharedfsParams{}, nil
}

func (i initrdRootfs) preStart() error {
func (i initrdRootfs) preStartCmd() []string {
return nil
}
8 changes: 2 additions & 6 deletions pkg/unikontainers/rootfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,13 @@ import (
// TODO: Find and set the correct size for the tmpfs in the host
const tmpfsSizeForNoRootfs = "65536k"

// annotRootfsParams holds JSON RootfsParams after shim chooseGuestRootfs.
// When present in bundle config.json, Exec reuses it; otherwise Exec runs ChooseRootfs.
const annotRootfsParams = "com.urunc.internal.rootfs.params"

type rootfsBuilder interface {
preSetup() error
postSetup() error
getMounts() ([]specs.Mount, error)
getBlockDevs() ([]types.BlockDevParams, error)
getSharedDirs() (types.SharedfsParams, error)
preStart() error
preStartCmd() []string
}

// tmpfsMount creates a mount for a tmpfs in the form of "/tmp" at target
Expand Down Expand Up @@ -162,7 +158,7 @@ func (n noRootfs) getSharedDirs() (types.SharedfsParams, error) {
return types.SharedfsParams{}, nil
}

func (n noRootfs) preStart() error {
func (n noRootfs) preStartCmd() []string {
return nil
}

Expand Down
17 changes: 7 additions & 10 deletions pkg/unikontainers/shared_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package unikontainers

import (
"fmt"
"path/filepath"
"strings"

Expand Down Expand Up @@ -73,26 +72,24 @@ func (s sharedfsRootfs) getSharedDirs() (types.SharedfsParams, error) {
}, nil
}

func (s sharedfsRootfs) preStart() error {
func (s sharedfsRootfs) preStartCmd() []string {
if s.sfsType == "9pfs" {
return nil
}
// Start the virtiofsd process
args := []string{
// The virtiofsd argv, with the binary itself as the first element so it can be
// both stored in the monitor spec and spawned later by spawnProcess.
argv := []string{
s.vfsdConfig.Path,
"--socket-path=/tmp/vhostqemu",
"--shared-dir",
s.sharedPath,
}

if s.vfsdConfig.Options != "" {
args = append(args, strings.Fields(s.vfsdConfig.Options)...)
argv = append(argv, strings.Fields(s.vfsdConfig.Options)...)
}

err := spawnProcess(s.vfsdConfig.Path, args)
if err != nil {
err = fmt.Errorf("failed to start virtiofsd: %w", err)
}
return err
return argv
}

func chooseTmpfsSize(sfsType string, mem uint64) string {
Expand Down
11 changes: 11 additions & 0 deletions pkg/unikontainers/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,14 @@ type MonitorConfig struct {
DataPath string `toml:"data_path,omitempty"` // Optional path to the hypervisor data files (e.g. qemu bios stuff)
Vhost bool `toml:"vhost,omitempty"` // Optional: enable vhost for network performance optimization
}

// MonitorSpec is everything the post-pivot urunc process needs in order to
// finalize the monitor's process execution environment and exec the monitor.
type MonitorSpec struct {
ContainerID string `json:"containerID"`
UnikernelType string `json:"unikernelType"`
MonitorType string `json:"monitorType"`
MonitorCfg MonitorConfig `json:"monitorCfg"`
ExecArgs ExecArgs `json:"execArgs"`
GuestParams UnikernelParams `json:"guestParams"`
}
Loading
Loading