Implement live restore with shim

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-10-06 15:18:26 -07:00
parent a861ae9d18
commit 3551d4c0b9
4 changed files with 49 additions and 5 deletions

View file

@ -15,6 +15,33 @@ import (
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
func reloadContainer() error {
// create a new runtime runtime that implements the ExecutionDriver interface
runtime, err := shim.Load("/run/cshim/test")
if err != nil {
return err
}
dockerContainer := &testConfig{}
container, err := containerkit.LoadContainer(dockerContainer, runtime)
if err != nil {
return err
}
// wait for it to exit and get the exit status
logrus.Info("wait container")
status, err := container.Wait()
if err != nil {
return err
}
// delete the container after it is done
logrus.Info("delete container")
if container.Delete(); err != nil {
return err
}
logrus.Infof("exit status %d", status)
return nil
}
func runContainer() error { func runContainer() error {
// create a new runtime runtime that implements the ExecutionDriver interface // create a new runtime runtime that implements the ExecutionDriver interface
runtime, err := shim.New(shim.Opts{ runtime, err := shim.New(shim.Opts{
@ -84,9 +111,7 @@ func runContainer() error {
} }
if load { if load {
if container, err = containerkit.LoadContainer(dockerContainer, runtime); err != nil { return nil
return err
}
} }
// wait for it to exit and get the exit status // wait for it to exit and get the exit status
@ -106,18 +131,26 @@ func runContainer() error {
} }
var ( var (
exec int exec int
load bool load bool
reload bool
) )
// "Hooks do optional work. Drivers do mandatory work" // "Hooks do optional work. Drivers do mandatory work"
func main() { func main() {
flag.IntVar(&exec, "exec", 0, "run n number of execs") flag.IntVar(&exec, "exec", 0, "run n number of execs")
flag.BoolVar(&load, "load", false, "reload the container") flag.BoolVar(&load, "load", false, "reload the container")
flag.BoolVar(&reload, "reload", false, "reload the container live")
flag.Parse() flag.Parse()
if err := osutils.SetSubreaper(1); err != nil { if err := osutils.SetSubreaper(1); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
if reload {
if err := reloadContainer(); err != nil {
logrus.Fatal(err)
}
return
}
if err := runContainer(); err != nil { if err := runContainer(); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }

View file

@ -54,6 +54,10 @@ func (r *OCIRuntime) Args() []string {
return r.args return r.args
} }
func (r *OCIRuntime) Root() string {
return r.root
}
func (r *OCIRuntime) Create(c *containerkit.Container) (containerkit.ProcessDelegate, error) { func (r *OCIRuntime) Create(c *containerkit.Container) (containerkit.ProcessDelegate, error) {
pidFile := fmt.Sprintf("%s/%s.pid", filepath.Join(r.root, c.ID()), "init") pidFile := fmt.Sprintf("%s/%s.pid", filepath.Join(r.root, c.ID()), "init")
cmd := r.Command("create", "--pid-file", pidFile, "--bundle", c.Path(), c.ID()) cmd := r.Command("create", "--pid-file", pidFile, "--bundle", c.Path(), c.ID())

View file

@ -184,6 +184,7 @@ func (p *process) UnmarshalJSON(b []byte) error {
p.stderr = ps.Stderr p.stderr = ps.Stderr
p.root = ps.Root p.root = ps.Root
p.startTime = ps.StartTime p.startTime = ps.StartTime
p.done = make(chan struct{})
pid, err := readPid(filepath.Join(p.root, "pid")) pid, err := readPid(filepath.Join(p.root, "pid"))
if err != nil { if err != nil {
return err return err

View file

@ -151,12 +151,14 @@ type Shim struct {
} }
type state struct { type state struct {
Root string `json:"root"`
// Bundle is the path to the container's bundle // Bundle is the path to the container's bundle
Bundle string `json:"bundle"` Bundle string `json:"bundle"`
// OCI runtime binary name // OCI runtime binary name
Runtime string `json:"runtime"` Runtime string `json:"runtime"`
// OCI runtime args // OCI runtime args
RuntimeArgs []string `json:"runtimeArgs"` RuntimeArgs []string `json:"runtimeArgs"`
RuntimeRoot string `json:"runtimeRoot"`
// Shim binary name // Shim binary name
Name string `json:"shim"` Name string `json:"shim"`
/// NoPivotRoot option /// NoPivotRoot option
@ -171,8 +173,10 @@ func (s *Shim) MarshalJSON() ([]byte, error) {
Bundle: s.bundle, Bundle: s.bundle,
Runtime: s.runtime.Name(), Runtime: s.runtime.Name(),
RuntimeArgs: s.runtime.Args(), RuntimeArgs: s.runtime.Args(),
RuntimeRoot: s.runtime.Root(),
NoPivotRoot: s.noPivotRoot, NoPivotRoot: s.noPivotRoot,
Timeout: s.timeout, Timeout: s.timeout,
Root: s.root,
} }
return json.Marshal(st) return json.Marshal(st)
} }
@ -182,6 +186,7 @@ func (s *Shim) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &st); err != nil { if err := json.Unmarshal(b, &st); err != nil {
return err return err
} }
s.root = st.Root
s.name = st.Name s.name = st.Name
s.bundle = st.Bundle s.bundle = st.Bundle
s.timeout = st.Timeout s.timeout = st.Timeout
@ -189,6 +194,7 @@ func (s *Shim) UnmarshalJSON(b []byte) error {
r, err := oci.New(oci.Opts{ r, err := oci.New(oci.Opts{
Name: st.Runtime, Name: st.Runtime,
Args: st.RuntimeArgs, Args: st.RuntimeArgs,
Root: st.RuntimeRoot,
}) })
if err != nil { if err != nil {
return err return err