1package runhcs 2 3import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 "strings" 8 9 irunhcs "github.com/Microsoft/hcsshim/internal/runhcs" 10 runc "github.com/containerd/go-runc" 11) 12 13// CreateOpts is set of options that can be used with the Create command. 14type CreateOpts struct { 15 runc.IO 16 // PidFile is the path to the file to write the process id to. 17 PidFile string 18 // ShimLog is the path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-shim-log) for the launched shim process. 19 ShimLog string 20 // VMLog is the path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-vm-log) for the launched VM shim process. 21 VMLog string 22 // VMConsole is the path to the pipe for the VM's console (e.g. \\.\pipe\debugpipe) 23 VMConsole string 24} 25 26func (opt *CreateOpts) args() ([]string, error) { 27 var out []string 28 if opt.PidFile != "" { 29 abs, err := filepath.Abs(opt.PidFile) 30 if err != nil { 31 return nil, err 32 } 33 out = append(out, "--pid-file", abs) 34 } 35 if opt.ShimLog != "" { 36 if strings.HasPrefix(opt.ShimLog, irunhcs.SafePipePrefix) { 37 out = append(out, "--shim-log", opt.ShimLog) 38 } else { 39 abs, err := filepath.Abs(opt.ShimLog) 40 if err != nil { 41 return nil, err 42 } 43 out = append(out, "--shim-log", abs) 44 } 45 } 46 if opt.VMLog != "" { 47 if strings.HasPrefix(opt.VMLog, irunhcs.SafePipePrefix) { 48 out = append(out, "--vm-log", opt.VMLog) 49 } else { 50 abs, err := filepath.Abs(opt.VMLog) 51 if err != nil { 52 return nil, err 53 } 54 out = append(out, "--vm-log", abs) 55 } 56 } 57 if opt.VMConsole != "" { 58 out = append(out, "--vm-console", opt.VMConsole) 59 } 60 return out, nil 61} 62 63// Create creates a new container and returns its pid if it was created 64// successfully. 65func (r *Runhcs) Create(context context.Context, id, bundle string, opts *CreateOpts) error { 66 args := []string{"create", "--bundle", bundle} 67 if opts != nil { 68 oargs, err := opts.args() 69 if err != nil { 70 return err 71 } 72 args = append(args, oargs...) 73 } 74 cmd := r.command(context, append(args, id)...) 75 if opts != nil && opts.IO != nil { 76 opts.Set(cmd) 77 } 78 if cmd.Stdout == nil && cmd.Stderr == nil { 79 data, err := cmdOutput(cmd, true) 80 if err != nil { 81 return fmt.Errorf("%s: %s", err, data) 82 } 83 return nil 84 } 85 ec, err := runc.Monitor.Start(cmd) 86 if err != nil { 87 return err 88 } 89 if opts != nil && opts.IO != nil { 90 if c, ok := opts.IO.(runc.StartCloser); ok { 91 if err := c.CloseAfterStart(); err != nil { 92 return err 93 } 94 } 95 } 96 status, err := runc.Monitor.Wait(cmd, ec) 97 if err == nil && status != 0 { 98 err = fmt.Errorf("%s did not terminate sucessfully", cmd.Args[0]) 99 } 100 return nil 101} 102