summaryrefslogtreecommitdiffhomepage
path: root/runsc/container
diff options
context:
space:
mode:
authorJustine Olshan <justineolshan@google.com>2018-07-18 16:57:29 -0700
committerShentubot <shentubot@google.com>2018-07-18 16:58:30 -0700
commitc05660373e8bda36ddf5181220c76f4327f2abc6 (patch)
tree019da46831903e23e9a2283e127835659dcadbfb /runsc/container
parente5d8f99c6071c09aa7bca4e79d28b26f95dc7716 (diff)
Moved restore code out of create and made to be called after create.
Docker expects containers to be created before they are restored. However, gVisor restoring requires specificactions regarding the kernel and the file system. These actions were originally in booting the sandbox. Now setting up the file system is deferred until a call to a call to runsc start. In the restore case, the kernel is destroyed and a new kernel is created in the same process, as we need the same process for Docker. These changes required careful execution of concurrent processes which required the use of a channel. Full docker integration still needs the ability to restore into the same container. PiperOrigin-RevId: 205161441 Change-Id: Ie1d2304ead7e06855319d5dc310678f701bd099f
Diffstat (limited to 'runsc/container')
-rw-r--r--runsc/container/container.go22
-rw-r--r--runsc/container/container_test.go42
2 files changed, 41 insertions, 23 deletions
diff --git a/runsc/container/container.go b/runsc/container/container.go
index c4e5bf9f6..574075b00 100644
--- a/runsc/container/container.go
+++ b/runsc/container/container.go
@@ -190,7 +190,7 @@ func List(rootDir string) ([]string, error) {
// Create creates the container in a new Sandbox process, unless the metadata
// indicates that an existing Sandbox should be used.
-func Create(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSocket, pidFile string, restoreFile string) (*Container, error) {
+func Create(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSocket, pidFile string) (*Container, error) {
log.Debugf("Create container %q in root dir: %s", id, conf.RootDir)
if err := validateID(id); err != nil {
return nil, err
@@ -221,7 +221,7 @@ func Create(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSo
log.Debugf("Creating new sandbox for container %q", id)
// Start a new sandbox for this container. Any errors after this point
// must destroy the container.
- s, err := sandbox.Create(id, spec, conf, bundleDir, consoleSocket, restoreFile)
+ s, err := sandbox.Create(id, spec, conf, bundleDir, consoleSocket)
if err != nil {
c.Destroy()
return nil, err
@@ -309,10 +309,26 @@ func (c *Container) Start(conf *boot.Config) error {
return c.save()
}
+// Restore takes a container and replaces its kernel and file system
+// to restore a container from its state file.
+func (c *Container) Restore(spec *specs.Spec, conf *boot.Config, restoreFile string) error {
+ log.Debugf("Restore container %q", c.ID)
+
+ if c.Status != Created {
+ return fmt.Errorf("cannot restore container in state %s", c.Status)
+ }
+
+ if err := c.Sandbox.Restore(c.ID, spec, conf, restoreFile); err != nil {
+ return err
+ }
+ c.Status = Running
+ return c.save()
+}
+
// Run is a helper that calls Create + Start + Wait.
func Run(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSocket, pidFile string) (syscall.WaitStatus, error) {
log.Debugf("Run container %q in root dir: %s", id, conf.RootDir)
- c, err := Create(id, spec, conf, bundleDir, consoleSocket, pidFile, "")
+ c, err := Create(id, spec, conf, bundleDir, consoleSocket, pidFile)
if err != nil {
return 0, fmt.Errorf("error creating container: %v", err)
}
diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go
index fc441e353..62a681ac2 100644
--- a/runsc/container/container_test.go
+++ b/runsc/container/container_test.go
@@ -168,7 +168,7 @@ func run(spec *specs.Spec) error {
defer os.RemoveAll(bundleDir)
// Create, start and wait for the container.
- s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
return fmt.Errorf("error creating container: %v", err)
}
@@ -213,7 +213,7 @@ func TestLifecycle(t *testing.T) {
}
// Create the container.
id := testutil.UniqueContainerID()
- if _, err := container.Create(id, spec, conf, bundleDir, "", "", ""); err != nil {
+ if _, err := container.Create(id, spec, conf, bundleDir, "", ""); err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -411,7 +411,7 @@ func TestExec(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -514,7 +514,7 @@ func TestCheckpointRestore(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -557,13 +557,14 @@ func TestCheckpointRestore(t *testing.T) {
defer outputFile2.Close()
// Restore into a new container.
- cont2, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", imagePath)
+ cont2, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
defer cont2.Destroy()
- if err := cont2.Start(conf); err != nil {
- t.Fatalf("error starting container: %v", err)
+
+ if err := cont2.Restore(spec, conf, imagePath); err != nil {
+ t.Fatalf("error restoring container: %v", err)
}
firstNum, err := readOutputNum(outputFile2, true)
@@ -588,13 +589,14 @@ func TestCheckpointRestore(t *testing.T) {
defer outputFile3.Close()
// Restore into a new container.
- cont3, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", imagePath)
+ cont3, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
defer cont3.Destroy()
- if err := cont3.Start(conf); err != nil {
- t.Fatalf("error starting container: %v", err)
+
+ if err := cont3.Restore(spec, conf, imagePath); err != nil {
+ t.Fatalf("error restoring container: %v", err)
}
firstNum2, err := readOutputNum(outputFile3, true)
@@ -604,7 +606,7 @@ func TestCheckpointRestore(t *testing.T) {
// Check that lastNum is one less than firstNum and that the container picks up from where it left off.
if lastNum+1 != firstNum2 {
- t.Errorf("error numbers not in order, previous: %d, next: %d", lastNum, firstNum)
+ t.Errorf("error numbers not in order, previous: %d, next: %d", lastNum, firstNum2)
}
}
@@ -626,7 +628,7 @@ func TestPauseResume(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -728,7 +730,7 @@ func TestPauseResumeStatus(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -795,7 +797,7 @@ func TestCapabilities(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -894,7 +896,7 @@ func TestConsoleSocket(t *testing.T) {
// Create the container and pass the socket name.
id := testutil.UniqueContainerID()
- s, err := container.Create(id, spec, conf, bundleDir, socketRelPath, "", "")
+ s, err := container.Create(id, spec, conf, bundleDir, socketRelPath, "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -1014,7 +1016,7 @@ func TestReadonlyRoot(t *testing.T) {
conf.Overlay = true
// Create, start and wait for the container.
- s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -1055,7 +1057,7 @@ func TestReadonlyMount(t *testing.T) {
conf.Overlay = true
// Create, start and wait for the container.
- s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -1095,7 +1097,7 @@ func TestAbbreviatedIDs(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- cont, err := container.Create(cid, spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(cid, spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -1165,7 +1167,7 @@ func TestMultiContainerSanity(t *testing.T) {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(bundleDir)
- cont, err := container.Create(containerIDs[i], spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(containerIDs[i], spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -1241,7 +1243,7 @@ func TestMultiContainerWait(t *testing.T) {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(bundleDir)
- cont, err := container.Create(containerIDs[i], spec, conf, bundleDir, "", "", "")
+ cont, err := container.Create(containerIDs[i], spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}