github.com/wozhu6104/docker@v20.10.10+incompatible/daemon/checkpoint.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/daemon/names" 12 ) 13 14 var ( 15 validCheckpointNameChars = names.RestrictedNameChars 16 validCheckpointNamePattern = names.RestrictedNamePattern 17 ) 18 19 // getCheckpointDir verifies checkpoint directory for create,remove, list options and checks if checkpoint already exists 20 func getCheckpointDir(checkDir, checkpointID, ctrName, ctrID, ctrCheckpointDir string, create bool) (string, error) { 21 var checkpointDir string 22 var err2 error 23 if checkDir != "" { 24 checkpointDir = checkDir 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 = os.MkdirAll(checkpointAbsDir, 0700) 36 case err != nil: 37 err2 = err 38 default: 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 exist for container %s", checkpointID, ctrName) 45 case stat.IsDir(): 46 err2 = nil 47 default: 48 err2 = fmt.Errorf("%s exists and is not a directory", checkpointAbsDir) 49 } 50 } 51 return checkpointAbsDir, 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(context.Background(), container.ID, checkpointDir, config.Exit) 75 if err != nil { 76 os.RemoveAll(checkpointDir) 77 return fmt.Errorf("Cannot checkpoint container %s: %s", name, err) 78 } 79 80 daemon.LogContainerEvent(container, "checkpoint") 81 82 return nil 83 } 84 85 // CheckpointDelete deletes the specified checkpoint 86 func (daemon *Daemon) CheckpointDelete(name string, config types.CheckpointDeleteOptions) error { 87 container, err := daemon.GetContainer(name) 88 if err != nil { 89 return err 90 } 91 checkpointDir, err := getCheckpointDir(config.CheckpointDir, config.CheckpointID, name, container.ID, container.CheckpointDir(), false) 92 if err == nil { 93 return os.RemoveAll(checkpointDir) 94 } 95 return err 96 } 97 98 // CheckpointList lists all checkpoints of the specified container 99 func (daemon *Daemon) CheckpointList(name string, config types.CheckpointListOptions) ([]types.Checkpoint, error) { 100 var out []types.Checkpoint 101 102 container, err := daemon.GetContainer(name) 103 if err != nil { 104 return nil, err 105 } 106 107 checkpointDir, err := getCheckpointDir(config.CheckpointDir, "", name, container.ID, container.CheckpointDir(), false) 108 if err != nil { 109 return nil, err 110 } 111 112 if err := os.MkdirAll(checkpointDir, 0755); err != nil { 113 return nil, err 114 } 115 116 dirs, err := ioutil.ReadDir(checkpointDir) 117 if err != nil { 118 return nil, err 119 } 120 121 for _, d := range dirs { 122 if !d.IsDir() { 123 continue 124 } 125 cpt := types.Checkpoint{Name: d.Name()} 126 out = append(out, cpt) 127 } 128 129 return out, nil 130 }