Skip to content

Commit

Permalink
Implemented StartInitialization, only require wait on exec.fifo
Browse files Browse the repository at this point in the history
Signed-off-by: Brandon Lum <[email protected]>
  • Loading branch information
lumjjb committed Aug 24, 2018
1 parent b885122 commit ec8d9a4
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 19 deletions.
118 changes: 102 additions & 16 deletions libcontainer/container_nabla.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package libcontainer

import (
"encoding/json"
"fmt"
"github.com/nabla-containers/runnc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/system"
Expand Down Expand Up @@ -113,6 +114,7 @@ func (c *nablaContainer) Run(process *Process) error {
}

// TODO(NABLA)
// TODO(824): Read from pipe
func (c *nablaContainer) Exec() error {
c.m.Lock()
defer c.m.Unlock()
Expand Down Expand Up @@ -146,19 +148,61 @@ func (p *nablaProcess) signal(sig os.Signal) error {
return syscall.Kill(p.pid(), s)
}

// TODO: TEMP COPY OUTDATED VERSION OF RUNC
// NewSockPair returns a new unix socket pair
func NewSockPair(name string) (parent *os.File, child *os.File, err error) {
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return nil, nil, err
}
return os.NewFile(uintptr(fds[1]), name+"-p"), os.NewFile(uintptr(fds[0]), name+"-c"), nil
}

func (c *nablaContainer) start(p *Process) error {
cmd := exec.Command(p.Args[0], p.Args[1:]...)
cmd.Stdin = p.Stdin
cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr
cmd.Dir = c.config.Rootfs
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}

// TODO(824): Create init process instead
parentPipe, childPipe, err := NewSockPair("init")
if err != nil {
return newSystemErrorWithCause(err, "creating new init pipe")
}
cmd, err := c.commandTemplate(p, childPipe)
if err != nil {
return newSystemErrorWithCause(err, "creating new command template")
}

/*
I Don't think we need this...
// We only set up rootDir if we're not doing a `runc exec`. The reason for
// this is to avoid cases where a racing, unprivileged process inside the
// container can get access to the statedir file descriptor (which would
// allow for container rootfs escape).
rootDir, err := os.Open(c.root)
if err != nil {
return err
}
cmd.ExtraFiles = append(cmd.ExtraFiles, rootDir)
cmd.Env = append(cmd.Env,
fmt.Sprintf("_LIBCONTAINER_STATEDIR=%d", stdioFdCount+len(cmd.ExtraFiles)-1))
*/

// newInitProcess
p.ops = &nablaProcess{
process: p,
cmd: cmd,
}

// TODO: Write config to pipe for child to receive JSON
defer parentPipe.Close()
config := initConfig{
Args: c.config.Args,
}

enc := json.NewEncoder(parentPipe)
if err := enc.Encode(config); err != nil {
return err
}
cmd.ExtraFiles = p.ExtraFiles
cmd.Env = append(cmd.Env,
fmt.Sprintf("_LIBCONTAINER_INITPIPE=%d", stdioFdCount+len(cmd.ExtraFiles)-2),
fmt.Sprintf("_LIBCONTAINER_STATEDIR=%d", stdioFdCount+len(cmd.ExtraFiles)-1))

if err := cmd.Start(); err != nil {
return err
Expand All @@ -168,13 +212,30 @@ func (c *nablaContainer) start(p *Process) error {
return errors.New("Cmd.Process is nil after starting")
}

p.ops = &nablaProcess{
process: p,
cmd: cmd,
}
/*
cmd := exec.Command(p.Args[0], p.Args[1:]...)
cmd.Stdin = p.Stdin
cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr
cmd.Dir = c.config.Rootfs
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.ExtraFiles = p.ExtraFiles
cmd.Env = append(cmd.Env,
fmt.Sprintf("_LIBCONTAINER_INITPIPE=%d", stdioFdCount+len(cmd.ExtraFiles)-2),
fmt.Sprintf("_LIBCONTAINER_STATEDIR=%d", stdioFdCount+len(cmd.ExtraFiles)-1))
if err := cmd.Start(); err != nil {
return err
}
if cmd.Process == nil {
return errors.New("Cmd.Process is nil after starting")
}
*/

// TODO: Create state and update state JSON
var err error
c.state.InitProcessPid = p.ops.pid()
c.state.Created = time.Now().UTC()
c.state.InitProcessStartTime, err = system.GetProcessStartTime(c.state.BaseState.InitProcessPid)
Expand All @@ -188,6 +249,31 @@ func (c *nablaContainer) start(p *Process) error {
return nil
}

func (c *nablaContainer) commandTemplate(p *Process, childPipe *os.File) (*exec.Cmd, error) {
cmd := exec.Command("/proc/self/exe", "init")
cmd.Stdin = p.Stdin
cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr
cmd.Dir = c.config.Rootfs
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.ExtraFiles = append(cmd.ExtraFiles, p.ExtraFiles...)
cmd.ExtraFiles = append(cmd.ExtraFiles, childPipe)
cmd.Env = append(cmd.Env,
fmt.Sprintf("_LIBCONTAINER_INITPIPE=%d", stdioFdCount+len(cmd.ExtraFiles)-1),
)
// NOTE: when running a container with no PID namespace and the parent process spawning the container is
// PID1 the pdeathsig is being delivered to the container's init process by the kernel for some reason
// even with the parent still running.
/* TODO: Check if needed
if c.config.ParentDeathSignal > 0 {
cmd.SysProcAttr.Pdeathsig = syscall.Signal(c.config.ParentDeathSignal)
}
*/
return cmd, nil
}

func (c *nablaContainer) currentState() (*State, error) {
// TODO: refreshState (by looking at system info and verifying state)
return c.state, nil
Expand Down
4 changes: 2 additions & 2 deletions libcontainer/factory_nabla.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"github.com/nabla-containers/runnc/libcontainer/configs"
"github.com/pkg/errors"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -135,8 +134,9 @@ func (l *NablaFactory) Load(id string) (Container, error) {
}

// TODO(NABLA)
// TODO(824): Implement actual process
func (l *NablaFactory) StartInitialization() error {
return errors.New("NablaFactory.StartInitialization not implemented")
return initNabla()
}

func (l *NablaFactory) Type() string {
Expand Down
55 changes: 55 additions & 0 deletions libcontainer/init_nabla.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package libcontainer

import (
"encoding/json"
"fmt"
"os"
"strconv"
"syscall"
"time"
)

type initConfig struct {
Args []string `json:"args"`
}

func initNabla() error {
// Ricardo special
time.Sleep(1 * time.Second)
fmt.Println("HELLO CALLING FROM START_INITIALIZATION")

var (
pipefd int
envInitPipe = os.Getenv("_LIBCONTAINER_INITPIPE")
)

// Get the INITPIPE.
pipefd, err := strconv.Atoi(envInitPipe)
if err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE=%s to int: %s", envInitPipe, err)
}

fmt.Println("Reading config from parent:")
pipe := os.NewFile(uintptr(pipefd), "pipe")
defer pipe.Close()

var config *initConfig
if err := json.NewDecoder(pipe).Decode(&config); err != nil {
return err
}

fmt.Printf("Got config: %v\n", config)

// clear the current process's environment to clean any libcontainer
// specific env vars.
os.Clearenv()

// TODO: WAIT FOR EXEC.FIFO

if err := syscall.Exec(config.Args[0], config.Args, os.Environ()); err != nil {
return err
}

return nil

}
34 changes: 34 additions & 0 deletions runnc-cli/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// +build linux

package main

import (
"fmt"
"os"
"runtime"

"github.com/nabla-containers/runnc/libcontainer"
"github.com/urfave/cli"
)

func init() {
if len(os.Args) > 1 && os.Args[1] == "init" {
runtime.GOMAXPROCS(1)
runtime.LockOSThread()
}
}

var initCommand = cli.Command{
Name: "init",
Usage: `initialize the namespaces and launch the process (do not call it outside of runc)`,
Action: func(context *cli.Context) error {
factory, _ := libcontainer.New("")
if err := factory.StartInitialization(); err != nil {
// as the error is sent back to the parent there is no need to log
// or write it to stderr because the parent process will handle this
fmt.Println("ERR: %v", err)
os.Exit(1)
}
panic("libcontainer: container init failed to exec")
},
}
2 changes: 1 addition & 1 deletion runnc-cli/runnc.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func main() {
// checkpointCommand,
// eventsCommand,
// execCommand,
// initCommand,
initCommand,
// listCommand,
// pauseCommand,
// psCommand,
Expand Down

0 comments on commit ec8d9a4

Please sign in to comment.