github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/checkpoint.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "fmt" 7 "strconv" 8 "strings" 9 "syscall" 10 11 "github.com/opencontainers/runc/libcontainer" 12 "github.com/opencontainers/runtime-spec/specs-go" 13 "github.com/urfave/cli" 14 ) 15 16 var checkpointCommand = cli.Command{ 17 Name: "checkpoint", 18 Usage: "checkpoint a running container", 19 ArgsUsage: `<container-id> 20 21 Where "<container-id>" is the name for the instance of the container to be 22 checkpointed.`, 23 Description: `The checkpoint command saves the state of the container instance.`, 24 Flags: []cli.Flag{ 25 cli.StringFlag{Name: "image-path", Value: "", Usage: "path for saving criu image files"}, 26 cli.StringFlag{Name: "work-path", Value: "", Usage: "path for saving work files and logs"}, 27 cli.BoolFlag{Name: "leave-running", Usage: "leave the process running after checkpointing"}, 28 cli.BoolFlag{Name: "tcp-established", Usage: "allow open tcp connections"}, 29 cli.BoolFlag{Name: "ext-unix-sk", Usage: "allow external unix sockets"}, 30 cli.BoolFlag{Name: "shell-job", Usage: "allow shell jobs"}, 31 cli.StringFlag{Name: "page-server", Value: "", Usage: "ADDRESS:PORT of the page server"}, 32 cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"}, 33 cli.StringFlag{Name: "manage-cgroups-mode", Value: "", Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'"}, 34 cli.StringSliceFlag{Name: "empty-ns", Usage: "create a namespace, but don't restore its properies"}, 35 }, 36 Action: func(context *cli.Context) error { 37 container, err := getContainer(context) 38 if err != nil { 39 return err 40 } 41 status, err := container.Status() 42 if err != nil { 43 return err 44 } 45 if status == libcontainer.Created { 46 fatalf("Container cannot be checkpointed in created state") 47 } 48 defer destroy(container) 49 options := criuOptions(context) 50 // these are the mandatory criu options for a container 51 setPageServer(context, options) 52 setManageCgroupsMode(context, options) 53 if err := setEmptyNsMask(context, options); err != nil { 54 return err 55 } 56 if err := container.Checkpoint(options); err != nil { 57 return err 58 } 59 return nil 60 }, 61 } 62 63 func getCheckpointImagePath(context *cli.Context) string { 64 imagePath := context.String("image-path") 65 if imagePath == "" { 66 imagePath = getDefaultImagePath(context) 67 } 68 return imagePath 69 } 70 71 func setPageServer(context *cli.Context, options *libcontainer.CriuOpts) { 72 // xxx following criu opts are optional 73 // The dump image can be sent to a criu page server 74 if psOpt := context.String("page-server"); psOpt != "" { 75 addressPort := strings.Split(psOpt, ":") 76 if len(addressPort) != 2 { 77 fatal(fmt.Errorf("Use --page-server ADDRESS:PORT to specify page server")) 78 } 79 portInt, err := strconv.Atoi(addressPort[1]) 80 if err != nil { 81 fatal(fmt.Errorf("Invalid port number")) 82 } 83 options.PageServer = libcontainer.CriuPageServerInfo{ 84 Address: addressPort[0], 85 Port: int32(portInt), 86 } 87 } 88 } 89 90 func setManageCgroupsMode(context *cli.Context, options *libcontainer.CriuOpts) { 91 if cgOpt := context.String("manage-cgroups-mode"); cgOpt != "" { 92 switch cgOpt { 93 case "soft": 94 options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_SOFT 95 case "full": 96 options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_FULL 97 case "strict": 98 options.ManageCgroupsMode = libcontainer.CRIU_CG_MODE_STRICT 99 default: 100 fatal(fmt.Errorf("Invalid manage cgroups mode")) 101 } 102 } 103 } 104 105 var namespaceMapping = map[specs.NamespaceType]int{ 106 specs.NetworkNamespace: syscall.CLONE_NEWNET, 107 } 108 109 func setEmptyNsMask(context *cli.Context, options *libcontainer.CriuOpts) error { 110 var nsmask int 111 112 for _, ns := range context.StringSlice("empty-ns") { 113 f, exists := namespaceMapping[specs.NamespaceType(ns)] 114 if !exists { 115 return fmt.Errorf("namespace %q is not supported", ns) 116 } 117 nsmask |= f 118 } 119 120 options.EmptyNs = uint32(nsmask) 121 return nil 122 }