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