| 295 | } |
| 296 | |
| 297 | func (c *Container) Checkpoint(criuOpts *CriuOpts) error { |
| 298 | const logFile = "dump.log" |
| 299 | c.m.Lock() |
| 300 | defer c.m.Unlock() |
| 301 | |
| 302 | // Checkpoint is unlikely to work if os.Geteuid() != 0 || system.RunningInUserNS(). |
| 303 | // (CLI prints a warning) |
| 304 | // TODO(avagin): Figure out how to make this work nicely. CRIU 2.0 has |
| 305 | // support for doing unprivileged dumps, but the setup of |
| 306 | // rootless containers might make this complicated. |
| 307 | |
| 308 | // We are relying on the CRIU version RPC which was introduced with CRIU 3.0.0 |
| 309 | if err := c.checkCriuVersion(30000); err != nil { |
| 310 | return err |
| 311 | } |
| 312 | |
| 313 | if criuOpts.ImagesDirectory == "" { |
| 314 | return errors.New("invalid directory to save checkpoint") |
| 315 | } |
| 316 | |
| 317 | cgMode, err := criuCgMode(criuOpts.ManageCgroupsMode) |
| 318 | if err != nil { |
| 319 | return err |
| 320 | } |
| 321 | |
| 322 | // Since a container can be C/R'ed multiple times, |
| 323 | // the checkpoint directory may already exist. |
| 324 | if err := os.Mkdir(criuOpts.ImagesDirectory, 0o700); err != nil && !errors.Is(err, os.ErrExist) { |
| 325 | return err |
| 326 | } |
| 327 | |
| 328 | logDir := criuOpts.ImagesDirectory |
| 329 | imageDir, err := os.Open(criuOpts.ImagesDirectory) |
| 330 | if err != nil { |
| 331 | return err |
| 332 | } |
| 333 | defer imageDir.Close() |
| 334 | |
| 335 | rpcOpts := criurpc.CriuOpts{ |
| 336 | ImagesDirFd: mkPtr(int32(imageDir.Fd())), |
| 337 | LogLevel: mkPtr(int32(4)), |
| 338 | LogFile: mkPtr(logFile), |
| 339 | Root: mkPtr(c.config.Rootfs), |
| 340 | ManageCgroups: mkPtr(true), // Obsoleted by ManageCgroupsMode. |
| 341 | ManageCgroupsMode: &cgMode, |
| 342 | NotifyScripts: mkPtr(true), |
| 343 | Pid: mkPtr(int32(c.initProcess.pid())), |
| 344 | ShellJob: mkPtr(criuOpts.ShellJob), |
| 345 | LeaveRunning: mkPtr(criuOpts.LeaveRunning), |
| 346 | TcpEstablished: mkPtr(criuOpts.TcpEstablished), |
| 347 | TcpSkipInFlight: mkPtr(criuOpts.TcpSkipInFlight), |
| 348 | LinkRemap: mkPtr(criuOpts.LinkRemap), |
| 349 | ExtUnixSk: mkPtr(criuOpts.ExternalUnixConnections), |
| 350 | FileLocks: mkPtr(criuOpts.FileLocks), |
| 351 | EmptyNs: mkPtr(criuOpts.EmptyNs), |
| 352 | OrphanPtsMaster: mkPtr(true), |
| 353 | AutoDedup: mkPtr(criuOpts.AutoDedup), |
| 354 | LazyPages: mkPtr(criuOpts.LazyPages), |