From 3551d4c0b9982e354d665679caae4788db2df431 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 6 Oct 2016 15:18:26 -0700 Subject: [PATCH] Implement live restore with shim Signed-off-by: Michael Crosby --- example/main.go | 43 ++++++++++++++++++++++++++++++++++++++----- oci/oci.go | 4 ++++ shim/process.go | 1 + shim/shim.go | 6 ++++++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/example/main.go b/example/main.go index 24f4d81a7..b620544e1 100644 --- a/example/main.go +++ b/example/main.go @@ -15,6 +15,33 @@ import ( 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 { // create a new runtime runtime that implements the ExecutionDriver interface runtime, err := shim.New(shim.Opts{ @@ -84,9 +111,7 @@ func runContainer() error { } if load { - if container, err = containerkit.LoadContainer(dockerContainer, runtime); err != nil { - return err - } + return nil } // wait for it to exit and get the exit status @@ -106,18 +131,26 @@ func runContainer() error { } var ( - exec int - load bool + exec int + load bool + reload bool ) // "Hooks do optional work. Drivers do mandatory work" func main() { flag.IntVar(&exec, "exec", 0, "run n number of execs") flag.BoolVar(&load, "load", false, "reload the container") + flag.BoolVar(&reload, "reload", false, "reload the container live") flag.Parse() if err := osutils.SetSubreaper(1); err != nil { logrus.Fatal(err) } + if reload { + if err := reloadContainer(); err != nil { + logrus.Fatal(err) + } + return + } if err := runContainer(); err != nil { logrus.Fatal(err) } diff --git a/oci/oci.go b/oci/oci.go index ed60325c4..6389784ed 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -54,6 +54,10 @@ func (r *OCIRuntime) Args() []string { return r.args } +func (r *OCIRuntime) Root() string { + return r.root +} + func (r *OCIRuntime) Create(c *containerkit.Container) (containerkit.ProcessDelegate, error) { 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()) diff --git a/shim/process.go b/shim/process.go index 25d89eb1d..fa34deb9e 100644 --- a/shim/process.go +++ b/shim/process.go @@ -184,6 +184,7 @@ func (p *process) UnmarshalJSON(b []byte) error { p.stderr = ps.Stderr p.root = ps.Root p.startTime = ps.StartTime + p.done = make(chan struct{}) pid, err := readPid(filepath.Join(p.root, "pid")) if err != nil { return err diff --git a/shim/shim.go b/shim/shim.go index 4bb15ec1b..85645b583 100644 --- a/shim/shim.go +++ b/shim/shim.go @@ -151,12 +151,14 @@ type Shim struct { } type state struct { + Root string `json:"root"` // Bundle is the path to the container's bundle Bundle string `json:"bundle"` // OCI runtime binary name Runtime string `json:"runtime"` // OCI runtime args RuntimeArgs []string `json:"runtimeArgs"` + RuntimeRoot string `json:"runtimeRoot"` // Shim binary name Name string `json:"shim"` /// NoPivotRoot option @@ -171,8 +173,10 @@ func (s *Shim) MarshalJSON() ([]byte, error) { Bundle: s.bundle, Runtime: s.runtime.Name(), RuntimeArgs: s.runtime.Args(), + RuntimeRoot: s.runtime.Root(), NoPivotRoot: s.noPivotRoot, Timeout: s.timeout, + Root: s.root, } return json.Marshal(st) } @@ -182,6 +186,7 @@ func (s *Shim) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &st); err != nil { return err } + s.root = st.Root s.name = st.Name s.bundle = st.Bundle s.timeout = st.Timeout @@ -189,6 +194,7 @@ func (s *Shim) UnmarshalJSON(b []byte) error { r, err := oci.New(oci.Opts{ Name: st.Runtime, Args: st.RuntimeArgs, + Root: st.RuntimeRoot, }) if err != nil { return err