forked from boucher/docker
/
checkpoint.go
102 lines (86 loc) · 2.82 KB
/
checkpoint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package daemon
import (
"fmt"
"github.com/docker/docker/engine"
"github.com/docker/libcontainer"
)
// Checkpoint a running container.
func (daemon *Daemon) ContainerCheckpoint(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("Usage: %s CONTAINER\n", job.Name)
}
name := job.Args[0]
container, err := daemon.Get(name)
if err != nil {
return err
}
if !container.IsRunning() {
return fmt.Errorf("Container %s not running", name)
}
opts := &libcontainer.CriuOpts{}
if job.EnvExists("ImagesDirectory") {
opts.ImagesDirectory = job.Getenv("ImagesDirectory")
}
if job.EnvExists("WorkDirectory") {
opts.WorkDirectory = job.Getenv("WorkDirectory")
}
if job.EnvExists("LeaveRunning") {
opts.LeaveRunning = job.GetenvBool("LeaveRunning")
}
if job.EnvExists("TcpEstablished") {
opts.TcpEstablished = job.GetenvBool("TcpEstablished")
}
if job.EnvExists("ExternalUnixConnections") {
opts.ExternalUnixConnections = job.GetenvBool("ExternalUnixConnections")
}
if job.EnvExists("ShellJob") {
opts.ShellJob = job.GetenvBool("ShellJob")
}
if err := container.Checkpoint(opts); err != nil {
return fmt.Errorf("Cannot checkpoint container %s: %s", name, err)
}
container.LogEvent("checkpoint")
return nil
}
// Restore a checkpointed container.
func (daemon *Daemon) ContainerRestore(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("Usage: %s CONTAINER\n", job.Name)
}
name := job.Args[0]
container, err := daemon.Get(name)
if err != nil {
return err
}
if container.IsRunning() {
return fmt.Errorf("Container %s already running", name)
}
// TODO: how should we handle the notion of checkpoint and keep running?
// right now, having ever been checkpointed is sufficient for our desires
// still requires manually calling stop before you are able to then restore
if !container.HasBeenCheckpointed() {
return fmt.Errorf("Container %s is not checkpointed", name)
}
opts := &libcontainer.CriuOpts{}
if job.EnvExists("ImagesDirectory") {
opts.ImagesDirectory = job.Getenv("ImagesDirectory")
}
if job.EnvExists("WorkDirectory") {
opts.ImagesDirectory = job.Getenv("WorkDirectory")
}
if job.EnvExists("TcpEstablished") {
opts.TcpEstablished = job.GetenvBool("TcpEstablished")
}
if job.EnvExists("ExternalUnixConnections") {
opts.ExternalUnixConnections = job.GetenvBool("ExternalUnixConnections")
}
if job.EnvExists("ShellJob") {
opts.ShellJob = job.GetenvBool("ShellJob")
}
if err = container.Restore(opts); err != nil {
container.LogEvent("die")
return fmt.Errorf("Cannot restore container %s: %s", name, err)
}
container.LogEvent("restore")
return nil
}