github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/restore.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "os" 7 "syscall" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/opencontainers/runc/libcontainer" 11 "github.com/opencontainers/runc/libcontainer/configs" 12 "github.com/opencontainers/runc/libcontainer/specconv" 13 "github.com/opencontainers/runtime-spec/specs-go" 14 "github.com/urfave/cli" 15 ) 16 17 var restoreCommand = cli.Command{ 18 Name: "restore", 19 Usage: "restore a container from a previous checkpoint", 20 ArgsUsage: `<container-id> 21 22 Where "<container-id>" is the name for the instance of the container to be 23 restored.`, 24 Description: `Restores the saved state of the container instance that was previously saved 25 using the runc checkpoint command.`, 26 Flags: []cli.Flag{ 27 cli.StringFlag{ 28 Name: "image-path", 29 Value: "", 30 Usage: "path to criu image files for restoring", 31 }, 32 cli.StringFlag{ 33 Name: "work-path", 34 Value: "", 35 Usage: "path for saving work files and logs", 36 }, 37 cli.BoolFlag{ 38 Name: "tcp-established", 39 Usage: "allow open tcp connections", 40 }, 41 cli.BoolFlag{ 42 Name: "ext-unix-sk", 43 Usage: "allow external unix sockets", 44 }, 45 cli.BoolFlag{ 46 Name: "shell-job", 47 Usage: "allow shell jobs", 48 }, 49 cli.BoolFlag{ 50 Name: "file-locks", 51 Usage: "handle file locks, for safety", 52 }, 53 cli.StringFlag{ 54 Name: "manage-cgroups-mode", 55 Value: "", 56 Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'", 57 }, 58 cli.StringFlag{ 59 Name: "bundle, b", 60 Value: "", 61 Usage: "path to the root of the bundle directory", 62 }, 63 cli.BoolFlag{ 64 Name: "detach,d", 65 Usage: "detach from the container's process", 66 }, 67 cli.StringFlag{ 68 Name: "pid-file", 69 Value: "", 70 Usage: "specify the file to write the process id to", 71 }, 72 cli.BoolFlag{ 73 Name: "no-subreaper", 74 Usage: "disable the use of the subreaper used to reap reparented processes", 75 }, 76 cli.BoolFlag{ 77 Name: "no-pivot", 78 Usage: "do not use pivot root to jail process inside rootfs. This should be used whenever the rootfs is on top of a ramdisk", 79 }, 80 cli.StringSliceFlag{ 81 Name: "empty-ns", 82 Usage: "create a namespace, but don't restore its properies", 83 }, 84 }, 85 Action: func(context *cli.Context) error { 86 imagePath := context.String("image-path") 87 id := context.Args().First() 88 if id == "" { 89 return errEmptyID 90 } 91 if imagePath == "" { 92 imagePath = getDefaultImagePath(context) 93 } 94 bundle := context.String("bundle") 95 if bundle != "" { 96 if err := os.Chdir(bundle); err != nil { 97 return err 98 } 99 } 100 spec, err := loadSpec(specConfig) 101 if err != nil { 102 return err 103 } 104 config, err := specconv.CreateLibcontainerConfig(&specconv.CreateOpts{ 105 CgroupName: id, 106 UseSystemdCgroup: context.GlobalBool("systemd-cgroup"), 107 NoPivotRoot: context.Bool("no-pivot"), 108 Spec: spec, 109 }) 110 if err != nil { 111 return err 112 } 113 status, err := restoreContainer(context, spec, config, imagePath) 114 if err == nil { 115 os.Exit(status) 116 } 117 return err 118 }, 119 } 120 121 func restoreContainer(context *cli.Context, spec *specs.Spec, config *configs.Config, imagePath string) (int, error) { 122 var ( 123 rootuid = 0 124 rootgid = 0 125 id = context.Args().First() 126 ) 127 factory, err := loadFactory(context) 128 if err != nil { 129 return -1, err 130 } 131 container, err := factory.Load(id) 132 if err != nil { 133 container, err = factory.Create(id, config) 134 if err != nil { 135 return -1, err 136 } 137 } 138 options := criuOptions(context) 139 140 status, err := container.Status() 141 if err != nil { 142 logrus.Error(err) 143 } 144 if status == libcontainer.Running { 145 fatalf("Container with id %s already running", id) 146 } 147 148 setManageCgroupsMode(context, options) 149 150 if err := setEmptyNsMask(context, options); err != nil { 151 return -1, err 152 } 153 154 // ensure that the container is always removed if we were the process 155 // that created it. 156 detach := context.Bool("detach") 157 if !detach { 158 defer destroy(container) 159 } 160 process := &libcontainer.Process{} 161 tty, err := setupIO(process, rootuid, rootgid, "", false, detach) 162 if err != nil { 163 return -1, err 164 } 165 defer tty.Close() 166 handler := newSignalHandler(tty, !context.Bool("no-subreaper")) 167 if err := container.Restore(process, options); err != nil { 168 return -1, err 169 } 170 if err := tty.ClosePostStart(); err != nil { 171 return -1, err 172 } 173 if pidFile := context.String("pid-file"); pidFile != "" { 174 if err := createPidFile(pidFile, process); err != nil { 175 process.Signal(syscall.SIGKILL) 176 process.Wait() 177 return -1, err 178 } 179 } 180 if detach { 181 return 0, nil 182 } 183 return handler.forward(process) 184 } 185 186 func criuOptions(context *cli.Context) *libcontainer.CriuOpts { 187 imagePath := getCheckpointImagePath(context) 188 if err := os.MkdirAll(imagePath, 0655); err != nil { 189 fatal(err) 190 } 191 return &libcontainer.CriuOpts{ 192 ImagesDirectory: imagePath, 193 WorkDirectory: context.String("work-path"), 194 LeaveRunning: context.Bool("leave-running"), 195 TcpEstablished: context.Bool("tcp-established"), 196 ExternalUnixConnections: context.Bool("ext-unix-sk"), 197 ShellJob: context.Bool("shell-job"), 198 FileLocks: context.Bool("file-locks"), 199 } 200 }