Add loading of existing container

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-09-30 13:51:10 -07:00
parent 06e42ec370
commit 23adfe42f9
4 changed files with 94 additions and 9 deletions

View file

@ -42,6 +42,43 @@ func NewContainer(root, id string, m Mount, s *specs.Spec, driver ExecutionDrive
}, nil }, nil
} }
func LoadContainer(root, id string, driver ExecutionDriver) (*Container, error) {
path := filepath.Join(root, id)
spec, err := loadSpec(path)
if err != nil {
return nil, err
}
process, err := driver.Load(id)
if err != nil {
return nil, err
}
// TODO: load exec processes
return &Container{
id: id,
path: path,
s: spec,
driver: driver,
init: &Process{
d: process,
driver: driver,
},
}, nil
}
func loadSpec(path string) (*specs.Spec, error) {
f, err := os.Open(filepath.Join(path, "config.json"))
if err != nil {
return nil, err
}
var s specs.Spec
err = json.NewDecoder(f).Decode(&s)
f.Close()
if err != nil {
return nil, err
}
return &s, nil
}
type Container struct { type Container struct {
mu sync.Mutex mu sync.Mutex
id string id string

View file

@ -29,7 +29,11 @@ func getContainerRootfs() containerkit.Mount {
func runContainer() error { func runContainer() error {
// create a new runc runtime that implements the ExecutionDriver interface // create a new runc runtime that implements the ExecutionDriver interface
driver, err := oci.New("/run/runc", "runc", "/tmp/runc") driver, err := oci.New(oci.Opts{
Root: "/run/runc",
Name: "runc",
LogFile: "/tmp/runc",
})
if err != nil { if err != nil {
return err return err
} }
@ -89,6 +93,15 @@ func runContainer() error {
logrus.Infof("process %d returned with %d", i, procStatus) logrus.Infof("process %d returned with %d", i, procStatus)
} }
container, err = containerkit.LoadContainer(
"/var/lib/containerkit", /* container root */
"test", /* container id */
driver, /* the exec driver to use for the container */
)
if err != nil {
return err
}
// wait for it to exit and get the exit status // wait for it to exit and get the exit status
logrus.Info("wait container") logrus.Info("wait container")
status, err := container.Wait() status, err := container.Wait()
@ -151,7 +164,7 @@ func spec(id string) *specs.Spec {
}, },
Process: specs.Process{ Process: specs.Process{
Env: env, Env: env,
Args: []string{"sleep", "10"}, Args: []string{"sleep", "30"},
Terminal: false, Terminal: false,
Cwd: "/", Cwd: "/",
NoNewPrivileges: true, NoNewPrivileges: true,

View file

@ -11,4 +11,5 @@ type ExecutionDriver interface {
Start(*Container) error Start(*Container) error
Delete(*Container) error Delete(*Container) error
Exec(*Container, *Process) (ProcessDelegate, error) Exec(*Container, *Process) (ProcessDelegate, error)
Load(id string) (ProcessDelegate, error)
} }

View file

@ -9,18 +9,27 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"syscall" "syscall"
"time"
"github.com/docker/containerkit" "github.com/docker/containerkit"
) )
func New(root, name, log string) (*OCIRuntime, error) { type Opts struct {
if err := os.MkdirAll(root, 0711); err != nil { Name string
Root string
Args []string
LogFile string
}
func New(opts Opts) (*OCIRuntime, error) {
if err := os.MkdirAll(opts.Root, 0711); err != nil {
return nil, err return nil, err
} }
return &OCIRuntime{ return &OCIRuntime{
root: root, root: opts.Root,
log: log, log: opts.LogFile,
name: name, name: opts.Name,
args: opts.Args,
}, nil }, nil
} }
@ -32,6 +41,8 @@ type OCIRuntime struct {
name string name string
// log is the path to the log files for the containers // log is the path to the log files for the containers
log string log string
// args specifies additional arguments to the OCI runtime
args []string
} }
func (r *OCIRuntime) Create(c *containerkit.Container) (containerkit.ProcessDelegate, error) { func (r *OCIRuntime) Create(c *containerkit.Container) (containerkit.ProcessDelegate, error) {
@ -88,11 +99,34 @@ func (r *OCIRuntime) Exec(c *containerkit.Container, p *containerkit.Process) (c
return newProcess(i) return newProcess(i)
} }
type state struct {
ID string `json:"id"`
Pid int `json:"pid"`
Status string `json:"status"`
Bundle string `json:"bundle"`
Rootfs string `json:"rootfs"`
Created time.Time `json:"created"`
Annotations map[string]string `json:"annotations"`
}
func (r *OCIRuntime) Load(id string) (containerkit.ProcessDelegate, error) {
data, err := r.command("state", id).Output()
if err != nil {
return nil, err
}
var s state
if err := json.Unmarshal(data, &s); err != nil {
return nil, err
}
return newProcess(s.Pid)
}
func (r *OCIRuntime) command(args ...string) *exec.Cmd { func (r *OCIRuntime) command(args ...string) *exec.Cmd {
return exec.Command(r.name, append([]string{ baseArgs := append([]string{
"--root", r.root, "--root", r.root,
"--log", r.log, "--log", r.log,
}, args...)...) }, r.args...)
return exec.Command(r.name, append(baseArgs, args...)...)
} }
func newProcess(pid int) (*process, error) { func newProcess(pid int) (*process, error) {