github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/daemon/checkpoint.go (about) 1 package daemon 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "github.com/docker/docker/api" 11 "github.com/docker/docker/api/types" 12 ) 13 14 var ( 15 validCheckpointNameChars = api.RestrictedNameChars 16 validCheckpointNamePattern = api.RestrictedNamePattern 17 ) 18 19 // getCheckpointDir verifies checkpoint directory for create,remove, list options and checks if checkpoint already exists 20 func getCheckpointDir(checkDir, checkpointID string, ctrName string, ctrID string, ctrCheckpointDir string, create bool) (string, error) { 21 var checkpointDir string 22 var err2 error 23 if checkDir != "" { 24 checkpointDir = filepath.Join(checkDir, ctrID, "checkpoints") 25 } else { 26 checkpointDir = ctrCheckpointDir 27 } 28 checkpointAbsDir := filepath.Join(checkpointDir, checkpointID) 29 stat, err := os.Stat(checkpointAbsDir) 30 if create { 31 switch { 32 case err == nil && stat.IsDir(): 33 err2 = fmt.Errorf("checkpoint with name %s already exists for container %s", checkpointID, ctrName) 34 case err != nil && os.IsNotExist(err): 35 err2 = nil 36 case err != nil: 37 err2 = err 38 case err == nil: 39 err2 = fmt.Errorf("%s exists and is not a directory", checkpointAbsDir) 40 } 41 } else { 42 switch { 43 case err != nil: 44 err2 = fmt.Errorf("checkpoint %s does not exists for container %s", checkpointID, ctrName) 45 case err == nil && stat.IsDir(): 46 err2 = nil 47 case err == nil: 48 err2 = fmt.Errorf("%s exists and is not a directory", checkpointAbsDir) 49 } 50 } 51 return checkpointDir, err2 52 } 53 54 // CheckpointCreate checkpoints the process running in a container with CRIU 55 func (daemon *Daemon) CheckpointCreate(name string, config types.CheckpointCreateOptions) error { 56 container, err := daemon.GetContainer(name) 57 if err != nil { 58 return err 59 } 60 61 if !container.IsRunning() { 62 return fmt.Errorf("Container %s not running", name) 63 } 64 65 if !validCheckpointNamePattern.MatchString(config.CheckpointID) { 66 return fmt.Errorf("Invalid checkpoint ID (%s), only %s are allowed", config.CheckpointID, validCheckpointNameChars) 67 } 68 69 checkpointDir, err := getCheckpointDir(config.CheckpointDir, config.CheckpointID, name, container.ID, container.CheckpointDir(), true) 70 if err != nil { 71 return fmt.Errorf("cannot checkpoint container %s: %s", name, err) 72 } 73 74 err = daemon.containerd.CreateCheckpoint(container.ID, config.CheckpointID, checkpointDir, config.Exit) 75 if err != nil { 76 return fmt.Errorf("Cannot checkpoint container %s: %s", name, err) 77 } 78 79 daemon.LogContainerEvent(container, "checkpoint") 80 81 return nil 82 } 83 84 // CheckpointDelete deletes the specified checkpoint 85 func (daemon *Daemon) CheckpointDelete(name string, config types.CheckpointDeleteOptions) error { 86 container, err := daemon.GetContainer(name) 87 if err != nil { 88 return err 89 } 90 checkpointDir, err := getCheckpointDir(config.CheckpointDir, config.CheckpointID, name, container.ID, container.CheckpointDir(), false) 91 if err == nil { 92 return os.RemoveAll(filepath.Join(checkpointDir, config.CheckpointID)) 93 } 94 return err 95 } 96 97 // CheckpointList lists all checkpoints of the specified container 98 func (daemon *Daemon) CheckpointList(name string, config types.CheckpointListOptions) ([]types.Checkpoint, error) { 99 var out []types.Checkpoint 100 101 container, err := daemon.GetContainer(name) 102 if err != nil { 103 return nil, err 104 } 105 106 checkpointDir, err := getCheckpointDir(config.CheckpointDir, "", name, container.ID, container.CheckpointDir(), false) 107 if err != nil { 108 return nil, err 109 } 110 111 if err := os.MkdirAll(checkpointDir, 0755); err != nil { 112 return nil, err 113 } 114 115 dirs, err := ioutil.ReadDir(checkpointDir) 116 if err != nil { 117 return nil, err 118 } 119 120 for _, d := range dirs { 121 if !d.IsDir() { 122 continue 123 } 124 path := filepath.Join(checkpointDir, d.Name(), "config.json") 125 data, err := ioutil.ReadFile(path) 126 if err != nil { 127 return nil, err 128 } 129 var cpt types.Checkpoint 130 if err := json.Unmarshal(data, &cpt); err != nil { 131 return nil, err 132 } 133 out = append(out, cpt) 134 } 135 136 return out, nil 137 }