github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/cmd/restore.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "context" 19 "path/filepath" 20 21 "github.com/google/subcommands" 22 "golang.org/x/sys/unix" 23 "github.com/SagerNet/gvisor/runsc/config" 24 "github.com/SagerNet/gvisor/runsc/container" 25 "github.com/SagerNet/gvisor/runsc/flag" 26 "github.com/SagerNet/gvisor/runsc/specutils" 27 ) 28 29 // Restore implements subcommands.Command for the "restore" command. 30 type Restore struct { 31 // Restore flags are a super-set of those for Create. 32 Create 33 34 // imagePath is the path to the saved container image 35 imagePath string 36 37 // detach indicates that runsc has to start a process and exit without waiting it. 38 detach bool 39 } 40 41 // Name implements subcommands.Command.Name. 42 func (*Restore) Name() string { 43 return "restore" 44 } 45 46 // Synopsis implements subcommands.Command.Synopsis. 47 func (*Restore) Synopsis() string { 48 return "restore a saved state of container (experimental)" 49 } 50 51 // Usage implements subcommands.Command.Usage. 52 func (*Restore) Usage() string { 53 return `restore [flags] <container id> - restore saved state of container. 54 ` 55 } 56 57 // SetFlags implements subcommands.Command.SetFlags. 58 func (r *Restore) SetFlags(f *flag.FlagSet) { 59 r.Create.SetFlags(f) 60 f.StringVar(&r.imagePath, "image-path", "", "directory path to saved container image") 61 f.BoolVar(&r.detach, "detach", false, "detach from the container's process") 62 63 // Unimplemented flags necessary for compatibility with docker. 64 65 var nsr bool 66 f.BoolVar(&nsr, "no-subreaper", false, "ignored") 67 68 var wp string 69 f.StringVar(&wp, "work-path", "", "ignored") 70 } 71 72 // Execute implements subcommands.Command.Execute. 73 func (r *Restore) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { 74 if f.NArg() != 1 { 75 f.Usage() 76 return subcommands.ExitUsageError 77 } 78 79 id := f.Arg(0) 80 conf := args[0].(*config.Config) 81 waitStatus := args[1].(*unix.WaitStatus) 82 83 if conf.Rootless { 84 return Errorf("Rootless mode not supported with %q", r.Name()) 85 } 86 87 bundleDir := r.bundleDir 88 if bundleDir == "" { 89 bundleDir = getwdOrDie() 90 } 91 spec, err := specutils.ReadSpec(bundleDir, conf) 92 if err != nil { 93 return Errorf("reading spec: %v", err) 94 } 95 specutils.LogSpec(spec) 96 97 if r.imagePath == "" { 98 return Errorf("image-path flag must be provided") 99 } 100 101 conf.RestoreFile = filepath.Join(r.imagePath, checkpointFileName) 102 103 runArgs := container.Args{ 104 ID: id, 105 Spec: spec, 106 BundleDir: bundleDir, 107 ConsoleSocket: r.consoleSocket, 108 PIDFile: r.pidFile, 109 UserLog: r.userLog, 110 Attached: !r.detach, 111 } 112 ws, err := container.Run(conf, runArgs) 113 if err != nil { 114 return Errorf("running container: %v", err) 115 } 116 *waitStatus = ws 117 118 return subcommands.ExitSuccess 119 }