11package main
22
33import (
4+ "context"
45 "errors"
56 "fmt"
67 "net"
@@ -11,49 +12,51 @@ import (
1112 "github.com/moby/sys/userns"
1213 "github.com/opencontainers/runtime-spec/specs-go"
1314 "github.com/sirupsen/logrus"
14- "github.com/urfave/cli"
15+ "github.com/urfave/cli/v3 "
1516 "golang.org/x/sys/unix"
1617
1718 "github.com/opencontainers/runc/libcontainer"
1819)
1920
20- var checkpointCommand = cli.Command {
21+ var checkpointCommand = & cli.Command {
2122 Name : "checkpoint" ,
2223 Usage : "checkpoint a running container" ,
2324 ArgsUsage : `<container-id>
2425
2526Where "<container-id>" is the name for the instance of the container to be
2627checkpointed.` ,
2728 Description : `The checkpoint command saves the state of the container instance.` ,
29+ // Disable comma as separator for slice flags.
30+ DisableSliceFlagSeparator : true ,
2831 Flags : []cli.Flag {
29- cli.StringFlag {Name : "image-path" , Value : "" , Usage : "path for saving criu image files" },
30- cli.StringFlag {Name : "work-path" , Value : "" , Usage : "path for saving work files and logs" },
31- cli.StringFlag {Name : "parent-path" , Value : "" , Usage : "path for previous criu image files in pre-dump" },
32- cli.BoolFlag {Name : "leave-running" , Usage : "leave the process running after checkpointing" },
33- cli.BoolFlag {Name : "tcp-established" , Usage : "allow open tcp connections" },
34- cli.BoolFlag {Name : "tcp-skip-in-flight" , Usage : "skip in-flight tcp connections" },
35- cli.BoolFlag {Name : "link-remap" , Usage : "allow one to link unlinked files back when possible" },
36- cli.BoolFlag {Name : "ext-unix-sk" , Usage : "allow external unix sockets" },
37- cli.BoolFlag {Name : "shell-job" , Usage : "allow shell jobs" },
38- cli.BoolFlag {Name : "lazy-pages" , Usage : "use userfaultfd to lazily restore memory pages" },
39- cli.IntFlag {Name : "status-fd" , Value : - 1 , Usage : "criu writes \\ 0 to this FD once lazy-pages is ready" },
40- cli.StringFlag {Name : "page-server" , Value : "" , Usage : "ADDRESS:PORT of the page server" },
41- cli.BoolFlag {Name : "file-locks" , Usage : "handle file locks, for safety" },
42- cli.BoolFlag {Name : "pre-dump" , Usage : "dump container's memory information only, leave the container running after this" },
43- cli.StringFlag {Name : "manage-cgroups-mode" , Value : "" , Usage : "cgroups mode: soft|full|strict|ignore (default: soft)" },
44- cli.StringSliceFlag {Name : "empty-ns" , Usage : "create a namespace, but don't restore its properties" },
45- cli.BoolFlag {Name : "auto-dedup" , Usage : "enable auto deduplication of memory images" },
32+ & cli.StringFlag {Name : "image-path" , Value : "" , Usage : "path for saving criu image files" },
33+ & cli.StringFlag {Name : "work-path" , Value : "" , Usage : "path for saving work files and logs" },
34+ & cli.StringFlag {Name : "parent-path" , Value : "" , Usage : "path for previous criu image files in pre-dump" },
35+ & cli.BoolFlag {Name : "leave-running" , Usage : "leave the process running after checkpointing" },
36+ & cli.BoolFlag {Name : "tcp-established" , Usage : "allow open tcp connections" },
37+ & cli.BoolFlag {Name : "tcp-skip-in-flight" , Usage : "skip in-flight tcp connections" },
38+ & cli.BoolFlag {Name : "link-remap" , Usage : "allow one to link unlinked files back when possible" },
39+ & cli.BoolFlag {Name : "ext-unix-sk" , Usage : "allow external unix sockets" },
40+ & cli.BoolFlag {Name : "shell-job" , Usage : "allow shell jobs" },
41+ & cli.BoolFlag {Name : "lazy-pages" , Usage : "use userfaultfd to lazily restore memory pages" },
42+ & cli.IntFlag {Name : "status-fd" , Value : - 1 , Usage : "criu writes \\ 0 to this FD once lazy-pages is ready" },
43+ & cli.StringFlag {Name : "page-server" , Value : "" , Usage : "ADDRESS:PORT of the page server" },
44+ & cli.BoolFlag {Name : "file-locks" , Usage : "handle file locks, for safety" },
45+ & cli.BoolFlag {Name : "pre-dump" , Usage : "dump container's memory information only, leave the container running after this" },
46+ & cli.StringFlag {Name : "manage-cgroups-mode" , Value : "" , Usage : "cgroups mode: soft|full|strict|ignore (default: soft)" },
47+ & cli.StringSliceFlag {Name : "empty-ns" , Usage : "create a namespace, but don't restore its properties" },
48+ & cli.BoolFlag {Name : "auto-dedup" , Usage : "enable auto deduplication of memory images" },
4649 },
47- Action : func (context * cli.Context ) error {
48- if err := checkArgs (context , 1 , exactArgs ); err != nil {
50+ Action : func (_ context. Context , cmd * cli.Command ) error {
51+ if err := checkArgs (cmd , 1 , exactArgs ); err != nil {
4952 return err
5053 }
5154 // XXX: Currently this is untested with rootless containers.
5255 if os .Geteuid () != 0 || userns .RunningInUserNS () {
5356 logrus .Warn ("runc checkpoint is untested with rootless containers" )
5457 }
5558
56- container , err := getContainer (context )
59+ container , err := getContainer (cmd )
5760 if err != nil {
5861 return err
5962 }
@@ -64,7 +67,7 @@ checkpointed.`,
6467 if status == libcontainer .Created || status == libcontainer .Stopped {
6568 return fmt .Errorf ("Container cannot be checkpointed in %s state" , status .String ())
6669 }
67- options , err := criuOptions (context )
70+ options , err := criuOptions (cmd )
6871 if err != nil {
6972 return err
7073 }
@@ -80,8 +83,8 @@ checkpointed.`,
8083 },
8184}
8285
83- func prepareImagePaths (context * cli.Context ) (string , string , error ) {
84- imagePath := context .String ("image-path" )
86+ func prepareImagePaths (cmd * cli.Command ) (string , string , error ) {
87+ imagePath := cmd .String ("image-path" )
8588 if imagePath == "" {
8689 imagePath = getDefaultImagePath ()
8790 }
@@ -90,7 +93,7 @@ func prepareImagePaths(context *cli.Context) (string, string, error) {
9093 return "" , "" , err
9194 }
9295
93- parentPath := context .String ("parent-path" )
96+ parentPath := cmd .String ("parent-path" )
9497 if parentPath == "" {
9598 return imagePath , parentPath , nil
9699 }
@@ -112,35 +115,35 @@ func prepareImagePaths(context *cli.Context) (string, string, error) {
112115 return imagePath , parentPath , nil
113116}
114117
115- func criuOptions (context * cli.Context ) (* libcontainer.CriuOpts , error ) {
116- imagePath , parentPath , err := prepareImagePaths (context )
118+ func criuOptions (cmd * cli.Command ) (* libcontainer.CriuOpts , error ) {
119+ imagePath , parentPath , err := prepareImagePaths (cmd )
117120 if err != nil {
118121 return nil , err
119122 }
120123
121124 opts := & libcontainer.CriuOpts {
122125 ImagesDirectory : imagePath ,
123- WorkDirectory : context .String ("work-path" ),
126+ WorkDirectory : cmd .String ("work-path" ),
124127 ParentImage : parentPath ,
125- LeaveRunning : context .Bool ("leave-running" ),
126- TcpEstablished : context .Bool ("tcp-established" ),
127- TcpSkipInFlight : context .Bool ("tcp-skip-in-flight" ),
128- LinkRemap : context .Bool ("link-remap" ),
129- ExternalUnixConnections : context .Bool ("ext-unix-sk" ),
130- ShellJob : context .Bool ("shell-job" ),
131- FileLocks : context .Bool ("file-locks" ),
132- PreDump : context .Bool ("pre-dump" ),
133- AutoDedup : context .Bool ("auto-dedup" ),
134- LazyPages : context .Bool ("lazy-pages" ),
135- StatusFd : context .Int ("status-fd" ),
136- LsmProfile : context .String ("lsm-profile" ),
137- LsmMountContext : context .String ("lsm-mount-context" ),
138- ManageCgroupsMode : context .String ("manage-cgroups-mode" ),
128+ LeaveRunning : cmd .Bool ("leave-running" ),
129+ TcpEstablished : cmd .Bool ("tcp-established" ),
130+ TcpSkipInFlight : cmd .Bool ("tcp-skip-in-flight" ),
131+ LinkRemap : cmd .Bool ("link-remap" ),
132+ ExternalUnixConnections : cmd .Bool ("ext-unix-sk" ),
133+ ShellJob : cmd .Bool ("shell-job" ),
134+ FileLocks : cmd .Bool ("file-locks" ),
135+ PreDump : cmd .Bool ("pre-dump" ),
136+ AutoDedup : cmd .Bool ("auto-dedup" ),
137+ LazyPages : cmd .Bool ("lazy-pages" ),
138+ StatusFd : cmd .Int ("status-fd" ),
139+ LsmProfile : cmd .String ("lsm-profile" ),
140+ LsmMountContext : cmd .String ("lsm-mount-context" ),
141+ ManageCgroupsMode : cmd .String ("manage-cgroups-mode" ),
139142 }
140143
141144 // CRIU options below may or may not be set.
142145
143- if psOpt := context .String ("page-server" ); psOpt != "" {
146+ if psOpt := cmd .String ("page-server" ); psOpt != "" {
144147 address , port , err := net .SplitHostPort (psOpt )
145148
146149 if err != nil || address == "" || port == "" {
@@ -159,12 +162,12 @@ func criuOptions(context *cli.Context) (*libcontainer.CriuOpts, error) {
159162 // runc doesn't manage network devices and their configuration.
160163 nsmask := unix .CLONE_NEWNET
161164
162- if context .IsSet ("empty-ns" ) {
165+ if cmd .IsSet ("empty-ns" ) {
163166 namespaceMapping := map [specs.LinuxNamespaceType ]int {
164167 specs .NetworkNamespace : unix .CLONE_NEWNET ,
165168 }
166169
167- for _ , ns := range context .StringSlice ("empty-ns" ) {
170+ for _ , ns := range cmd .StringSlice ("empty-ns" ) {
168171 f , exists := namespaceMapping [specs .LinuxNamespaceType (ns )]
169172 if ! exists {
170173 return nil , fmt .Errorf ("namespace %q is not supported" , ns )
0 commit comments