checkpoint.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // +build linux
  2. package runc
  3. import (
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "github.com/codegangsta/cli"
  8. "github.com/opencontainers/runc/libcontainer"
  9. )
  10. var checkpointCommand = cli.Command{
  11. Name: "checkpoint",
  12. Usage: "checkpoint a running container",
  13. ArgsUsage: `<container-id>
  14. Where "<container-id>" is the name for the instance of the container to be
  15. checkpointed.`,
  16. Description: `The checkpoint command saves the state of the container instance.`,
  17. Flags: []cli.Flag{
  18. cli.StringFlag{Name: "image-path", Value: "", Usage: "path for saving criu image files"},
  19. cli.StringFlag{Name: "work-path", Value: "", Usage: "path for saving work files and logs"},
  20. cli.BoolFlag{Name: "leave-running", Usage: "leave the process running after checkpointing"},
  21. cli.BoolFlag{Name: "tcp-established", Usage: "allow open tcp connections"},
  22. cli.BoolFlag{Name: "ext-unix-sk", Usage: "allow external unix sockets"},
  23. cli.BoolFlag{Name: "shell-job", Usage: "allow shell jobs"},
  24. cli.StringFlag{Name: "page-server", Value: "", Usage: "ADDRESS:PORT of the page server"},
  25. cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"},
  26. cli.StringFlag{Name: "manage-cgroups-mode", Value: "", Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'."},
  27. },
  28. Action: func(context *cli.Context) {
  29. container, err := getContainer(context)
  30. if err != nil {
  31. fatal(err)
  32. }
  33. defer destroy(container)
  34. options := criuOptions(context)
  35. // these are the mandatory criu options for a container
  36. setPageServer(context, options)
  37. setManageCgroupsMode(context, options)
  38. if err := container.Checkpoint(options); err != nil {
  39. fatal(err)
  40. }
  41. },
  42. }
  43. func getCheckpointImagePath(context *cli.Context) string {
  44. imagePath := context.String("image-path")
  45. if imagePath == "" {
  46. imagePath = getDefaultImagePath(context)
  47. }
  48. return imagePath
  49. }
  50. func setPageServer(context *cli.Context, options *libcontainer.CriuOpts) {
  51. // xxx following criu opts are optional
  52. // The dump image can be sent to a criu page server
  53. if psOpt := context.String("page-server"); psOpt != "" {
  54. addressPort := strings.Split(psOpt, ":")
  55. if len(addressPort) != 2 {
  56. fatal(fmt.Errorf("Use --page-server ADDRESS:PORT to specify page server"))
  57. }
  58. portInt, err := strconv.Atoi(addressPort[1])
  59. if err != nil {
  60. fatal(fmt.Errorf("Invalid port number"))
  61. }
  62. options.PageServer = libcontainer.CriuPageServerInfo{
  63. Address: addressPort[0],
  64. Port: int32(portInt),
  65. }
  66. }
  67. }
  68. func setManageCgroupsMode(context *cli.Context, options *libcontainer.CriuOpts) {
  69. if cgOpt := context.String("manage-cgroups-mode"); cgOpt != "" {
  70. switch cgOpt {
  71. case "soft":
  72. options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_SOFT
  73. case "full":
  74. options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_FULL
  75. case "strict":
  76. options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_STRICT
  77. default:
  78. fatal(fmt.Errorf("Invalid manage cgroups mode"))
  79. }
  80. }
  81. }