Introduce containerd-shim-runhcs-v1 on Windows
Implements the containerd-shim-runhcs-v1 shim on Windows for the runtime v2 shim API. Signed-off-by: Justin Terry (VM) <juterry@microsoft.com>
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -176,6 +176,10 @@ bin/containerd-shim-runc-v1: cmd/containerd-shim-runc-v1 FORCE # set !cgo and om | ||||
| 	@echo "$(WHALE) bin/containerd-shim-runc-v1" | ||||
| 	@CGO_ENABLED=0 go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v1 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v1 | ||||
|  | ||||
| bin/containerd-shim-runhcs-v1: cmd/containerd-shim-runhcs-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 | ||||
| 	@echo "$(WHALE) bin/containerd-shim-runhcs-v1${BINARY_SUFFIX}" | ||||
| 	@CGO_ENABLED=0 go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runhcs-v1${BINARY_SUFFIX} ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runhcs-v1 | ||||
|  | ||||
| binaries: $(BINARIES) ## build binaries | ||||
| 	@echo "$(WHALE) $@" | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| #Windows specific settings. | ||||
| WHALE = "+" | ||||
| ONI = "-" | ||||
| COMMANDS += containerd-shim-runhcs-v1 | ||||
|  | ||||
| BINARY_SUFFIX=".exe" | ||||
|  | ||||
|   | ||||
| @@ -74,7 +74,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | ||||
| 	if fifos.Stdout != "" { | ||||
| 		l, err := winio.ListenPipe(fifos.Stdout, nil) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdout) | ||||
| 			return nil, errors.Wrapf(err, "failed to create stdout pipe %s", fifos.Stdout) | ||||
| 		} | ||||
| 		defer func(l net.Listener) { | ||||
| 			if err != nil { | ||||
|   | ||||
							
								
								
									
										28
									
								
								cmd/containerd-shim-runhcs-v1/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmd/containerd-shim-runhcs-v1/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| // +build windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/containerd/containerd/runtime/v2/runhcs" | ||||
| 	"github.com/containerd/containerd/runtime/v2/shim" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	shim.Run("io.containerd.runhcs.v1", runhcs.New) | ||||
| } | ||||
							
								
								
									
										98
									
								
								runtime/v2/runhcs/cmdutil.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								runtime/v2/runhcs/cmdutil.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| // +build windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"os/exec" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	bytesBufferPool = sync.Pool{ | ||||
| 		New: func() interface{} { | ||||
| 			return bytes.NewBuffer(nil) | ||||
| 		}, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func getBuffer() *bytes.Buffer { | ||||
| 	return bytesBufferPool.Get().(*bytes.Buffer) | ||||
| } | ||||
|  | ||||
| func putBuffer(b *bytes.Buffer) { | ||||
| 	b.Reset() | ||||
| 	bytesBufferPool.Put(b) | ||||
| } | ||||
|  | ||||
| type processExit struct { | ||||
| 	pid        uint32 | ||||
| 	exitStatus uint32 | ||||
| 	exitedAt   time.Time | ||||
| 	exitErr    error | ||||
| } | ||||
|  | ||||
| func runCmd(ctx context.Context, c *exec.Cmd) (*processExit, error) { | ||||
| 	ec, startErr := startCmd(ctx, c) | ||||
| 	if startErr != nil { | ||||
| 		return nil, startErr | ||||
| 	} | ||||
| 	er, cmdErr := waitCmd(ctx, ec) | ||||
| 	return er, cmdErr | ||||
| } | ||||
|  | ||||
| func startCmd(ctx context.Context, c *exec.Cmd) (<-chan *processExit, error) { | ||||
| 	if err := c.Start(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ec := make(chan *processExit, 1) | ||||
| 	go func() { | ||||
| 		defer close(ec) | ||||
|  | ||||
| 		var status int | ||||
| 		eerr := c.Wait() | ||||
| 		if eerr != nil { | ||||
| 			status = 255 | ||||
| 			if exitErr, ok := eerr.(*exec.ExitError); ok { | ||||
| 				if ws, ok := exitErr.Sys().(syscall.WaitStatus); ok { | ||||
| 					status = ws.ExitStatus() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ec <- &processExit{ | ||||
| 			pid:        uint32(c.Process.Pid), | ||||
| 			exitStatus: uint32(status), | ||||
| 			exitedAt:   time.Now(), | ||||
| 			exitErr:    eerr, | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return ec, nil | ||||
| } | ||||
|  | ||||
| func waitCmd(ctx context.Context, ec <-chan *processExit) (*processExit, error) { | ||||
| 	e := <-ec | ||||
| 	if e.exitStatus != 0 { | ||||
| 		return e, e.exitErr | ||||
| 	} | ||||
| 	return e, nil | ||||
| } | ||||
							
								
								
									
										159
									
								
								runtime/v2/runhcs/io.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								runtime/v2/runhcs/io.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| // +build windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/containerd/containerd/log" | ||||
| 	runc "github.com/containerd/go-runc" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| ) | ||||
|  | ||||
| type pipeSet struct { | ||||
| 	stdin  net.Conn | ||||
| 	stdout net.Conn | ||||
| 	stderr net.Conn | ||||
| } | ||||
|  | ||||
| // newPipeSet connects to the provided pipe addresses | ||||
| func newPipeSet(ctx context.Context, stdin, stdout, stderr string, terminal bool) (*pipeSet, error) { | ||||
| 	var ( | ||||
| 		err error | ||||
| 		set = &pipeSet{} | ||||
| 	) | ||||
|  | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			set.Close() | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	g, _ := errgroup.WithContext(ctx) | ||||
|  | ||||
| 	dialfn := func(name string, conn *net.Conn) error { | ||||
| 		if name == "" { | ||||
| 			return nil | ||||
| 		} | ||||
| 		dialTimeout := 3 * time.Second | ||||
| 		c, err := winio.DialPipe(name, &dialTimeout) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "failed to connect to %s", name) | ||||
| 		} | ||||
| 		*conn = c | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	g.Go(func() error { | ||||
| 		return dialfn(stdin, &set.stdin) | ||||
| 	}) | ||||
| 	g.Go(func() error { | ||||
| 		return dialfn(stdout, &set.stdout) | ||||
| 	}) | ||||
| 	g.Go(func() error { | ||||
| 		return dialfn(stderr, &set.stderr) | ||||
| 	}) | ||||
|  | ||||
| 	err = g.Wait() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return set, nil | ||||
| } | ||||
|  | ||||
| // Close terminates all successfully dialed IO connections | ||||
| func (p *pipeSet) Close() { | ||||
| 	for _, cn := range []net.Conn{p.stdin, p.stdout, p.stderr} { | ||||
| 		if cn != nil { | ||||
| 			cn.Close() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type pipeRelay struct { | ||||
| 	ctx context.Context | ||||
|  | ||||
| 	ps *pipeSet | ||||
| 	io runc.IO | ||||
|  | ||||
| 	wg   sync.WaitGroup | ||||
| 	once sync.Once | ||||
| } | ||||
|  | ||||
| func newPipeRelay(ctx context.Context, ps *pipeSet, downstream runc.IO) *pipeRelay { | ||||
| 	pr := &pipeRelay{ | ||||
| 		ctx: ctx, | ||||
| 		ps:  ps, | ||||
| 		io:  downstream, | ||||
| 	} | ||||
| 	if ps.stdin != nil { | ||||
| 		go func() { | ||||
| 			if _, err := io.Copy(downstream.Stdin(), ps.stdin); err != nil { | ||||
| 				if err != winio.ErrFileClosed { | ||||
| 					log.G(ctx).WithError(err).Error("error copying stdin to pipe") | ||||
| 				} | ||||
| 			} | ||||
| 		}() | ||||
| 	} | ||||
| 	if ps.stdout != nil { | ||||
| 		pr.wg.Add(1) | ||||
| 		go func() { | ||||
| 			if _, err := io.Copy(ps.stdout, downstream.Stdout()); err != nil { | ||||
| 				log.G(ctx).WithError(err).Error("error copying stdout from pipe") | ||||
| 			} | ||||
| 			pr.wg.Done() | ||||
| 		}() | ||||
| 	} | ||||
| 	if ps.stderr != nil { | ||||
| 		pr.wg.Add(1) | ||||
| 		go func() { | ||||
| 			if _, err := io.Copy(ps.stderr, downstream.Stderr()); err != nil { | ||||
| 				log.G(pr.ctx).WithError(err).Error("error copying stderr from pipe") | ||||
| 			} | ||||
| 			pr.wg.Done() | ||||
| 		}() | ||||
| 	} | ||||
| 	return pr | ||||
| } | ||||
|  | ||||
| func (pr *pipeRelay) wait() { | ||||
| 	pr.wg.Wait() | ||||
| } | ||||
|  | ||||
| // closeIO closes stdin to unblock an waiters | ||||
| func (pr *pipeRelay) closeIO() { | ||||
| 	if pr.ps.stdin != nil { | ||||
| 		pr.ps.Close() | ||||
| 		pr.io.Stdin().Close() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // close closes all open pipes | ||||
| func (pr *pipeRelay) close() { | ||||
| 	pr.once.Do(func() { | ||||
| 		pr.io.Close() | ||||
| 		pr.ps.Close() | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										178
									
								
								runtime/v2/runhcs/process.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								runtime/v2/runhcs/process.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| // +build windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	eventstypes "github.com/containerd/containerd/api/events" | ||||
| 	"github.com/containerd/containerd/runtime" | ||||
| ) | ||||
|  | ||||
| func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipeRelay, bundle, stdin, stdout, stderr string, terminal bool) (*process, error) { | ||||
| 	p, err := os.FindProcess(int(pid)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	process := &process{ | ||||
| 		cid:       id, | ||||
| 		id:        id, | ||||
| 		pid:       pid, | ||||
| 		bundle:    bundle, | ||||
| 		stdin:     stdin, | ||||
| 		stdout:    stdout, | ||||
| 		stderr:    stderr, | ||||
| 		terminal:  terminal, | ||||
| 		relay:     pr, | ||||
| 		waitBlock: make(chan struct{}), | ||||
| 	} | ||||
| 	// Store the default non-exited value for calls to stat | ||||
| 	process.exit.Store(&processExit{ | ||||
| 		pid:        pid, | ||||
| 		exitStatus: 255, | ||||
| 		exitedAt:   time.Time{}, | ||||
| 		exitErr:    nil, | ||||
| 	}) | ||||
| 	go waitForProcess(ctx, process, p, s) | ||||
| 	return process, nil | ||||
| } | ||||
|  | ||||
| func waitForProcess(ctx context.Context, process *process, p *os.Process, s *service) { | ||||
| 	var status int | ||||
| 	_, eerr := p.Wait() | ||||
| 	if eerr != nil { | ||||
| 		status = 255 | ||||
| 		if exitErr, ok := eerr.(*exec.ExitError); ok { | ||||
| 			if ws, ok := exitErr.Sys().(syscall.WaitStatus); ok { | ||||
| 				status = ws.ExitStatus() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	now := time.Now() | ||||
| 	process.exit.Store(&processExit{ | ||||
| 		pid:        process.pid, | ||||
| 		exitStatus: uint32(status), | ||||
| 		exitedAt:   now, | ||||
| 		exitErr:    eerr, | ||||
| 	}) | ||||
|  | ||||
| 	// Wait for the relay | ||||
| 	process.relay.wait() | ||||
|  | ||||
| 	// close the client io, and free upstream waiters | ||||
| 	process.close() | ||||
|  | ||||
| 	s.publisher.Publish( | ||||
| 		ctx, | ||||
| 		runtime.TaskExitEventTopic, | ||||
| 		&eventstypes.TaskExit{ | ||||
| 			ContainerID: process.cid, | ||||
| 			ID:          process.id, | ||||
| 			Pid:         process.pid, | ||||
| 			ExitStatus:  uint32(status), | ||||
| 			ExitedAt:    now, | ||||
| 		}) | ||||
| } | ||||
|  | ||||
| func newExecProcess(ctx context.Context, s *service, cid, id string, pr *pipeRelay, bundle, stdin, stdout, stderr string, terminal bool) (*process, error) { | ||||
| 	process := &process{ | ||||
| 		cid:       cid, | ||||
| 		id:        id, | ||||
| 		bundle:    bundle, | ||||
| 		stdin:     stdin, | ||||
| 		stdout:    stdout, | ||||
| 		stderr:    stderr, | ||||
| 		terminal:  terminal, | ||||
| 		relay:     pr, | ||||
| 		waitBlock: make(chan struct{}), | ||||
| 	} | ||||
| 	// Store the default non-exited value for calls to stat | ||||
| 	process.exit.Store(&processExit{ | ||||
| 		exitStatus: 255, | ||||
| 		exitedAt:   time.Time{}, | ||||
| 		exitErr:    nil, | ||||
| 	}) | ||||
| 	return process, nil | ||||
| } | ||||
|  | ||||
| type process struct { | ||||
| 	sync.Mutex | ||||
|  | ||||
| 	cid string | ||||
| 	id  string | ||||
| 	pid uint32 | ||||
|  | ||||
| 	bundle   string | ||||
| 	stdin    string | ||||
| 	stdout   string | ||||
| 	stderr   string | ||||
| 	terminal bool | ||||
| 	relay    *pipeRelay | ||||
|  | ||||
| 	// started track if the process has ever been started and will not be reset | ||||
| 	// for the lifetime of the process object. | ||||
| 	started bool | ||||
|  | ||||
| 	waitBlock chan struct{} | ||||
| 	// exit holds the exit value for all calls to `stat`. By default a | ||||
| 	// non-exited value is stored of status: 255, at: time 0. | ||||
| 	exit atomic.Value | ||||
|  | ||||
| 	// closeOnce is responsible for closing waitBlock and any io. | ||||
| 	closeOnce sync.Once | ||||
| } | ||||
|  | ||||
| // closeIO closes the stdin of the executing process to unblock any waiters | ||||
| func (p *process) closeIO() { | ||||
| 	p.Lock() | ||||
| 	defer p.Unlock() | ||||
|  | ||||
| 	p.relay.closeIO() | ||||
| } | ||||
|  | ||||
| // close closes all stdio and frees any waiters. This is safe to call multiple | ||||
| // times. | ||||
| func (p *process) close() { | ||||
| 	p.closeOnce.Do(func() { | ||||
| 		p.relay.close() | ||||
|  | ||||
| 		// Free any waiters | ||||
| 		close(p.waitBlock) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // stat is a non-blocking query of the current process state. | ||||
| func (p *process) stat() *processExit { | ||||
| 	er := p.exit.Load() | ||||
| 	return er.(*processExit) | ||||
| } | ||||
|  | ||||
| // wait waits for the container process to exit and returns the exit status. If | ||||
| // the process failed post start the processExit will contain the exitErr. This | ||||
| // is safe to call previous to calling start(). | ||||
| func (p *process) wait() *processExit { | ||||
| 	<-p.waitBlock | ||||
| 	return p.stat() | ||||
| } | ||||
							
								
								
									
										761
									
								
								runtime/v2/runhcs/service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										761
									
								
								runtime/v2/runhcs/service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,761 @@ | ||||
| // +build windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/cmd/go-runhcs" | ||||
| 	containerd_types "github.com/containerd/containerd/api/types" | ||||
| 	"github.com/containerd/containerd/api/types/task" | ||||
| 	"github.com/containerd/containerd/errdefs" | ||||
| 	"github.com/containerd/containerd/events" | ||||
| 	"github.com/containerd/containerd/log" | ||||
| 	"github.com/containerd/containerd/mount" | ||||
| 	"github.com/containerd/containerd/namespaces" | ||||
| 	"github.com/containerd/containerd/runtime/v2/shim" | ||||
| 	taskAPI "github.com/containerd/containerd/runtime/v2/task" | ||||
| 	"github.com/containerd/go-runc" | ||||
| 	ptypes "github.com/gogo/protobuf/types" | ||||
| 	oci "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	runhcsBinary      = "runhcs" | ||||
| 	runhcsVersion     = "0.0.1" | ||||
| 	runhcsDebugLegacy = "--debug" // TODO: JTERRY75 remove when all cmd's are complete in go-runhcs | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	empty       = &ptypes.Empty{} | ||||
| 	runhcsDebug = false | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	if logrus.GetLevel() == logrus.DebugLevel { | ||||
| 		runhcsDebug = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newRunhcs(bundle string) *runhcs.Runhcs { | ||||
| 	rhs := &runhcs.Runhcs{ | ||||
| 		Debug:     runhcsDebug, | ||||
| 		LogFormat: runhcs.JSON, | ||||
| 		Owner:     "containerd-runhcs-shim-v1", | ||||
| 	} | ||||
| 	if rhs.Debug { | ||||
| 		rhs.Log = filepath.Join(bundle, "runhcs-debug.log") | ||||
| 	} | ||||
| 	return rhs | ||||
| } | ||||
|  | ||||
| // New returns a new runhcs shim service that can be used via GRPC | ||||
| func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim, error) { | ||||
| 	return &service{ | ||||
| 		context:   ctx, | ||||
| 		id:        id, | ||||
| 		processes: make(map[string]*process), | ||||
| 		publisher: publisher, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| var _ = (taskAPI.TaskService)(&service{}) | ||||
| var _ = (shim.Shim)(&service{}) | ||||
|  | ||||
| // service is the runhcs shim implementation of the v2 TaskService over GRPC | ||||
| type service struct { | ||||
| 	mu sync.Mutex | ||||
|  | ||||
| 	context context.Context | ||||
|  | ||||
| 	id        string | ||||
| 	processes map[string]*process | ||||
|  | ||||
| 	publisher events.Publisher | ||||
| } | ||||
|  | ||||
| // getProcess attempts to get a process by id. | ||||
| // The caller MUST NOT have locked s.mu previous to calling this function. | ||||
| func (s *service) getProcess(id string) (*process, error) { | ||||
| 	s.mu.Lock() | ||||
| 	defer s.mu.Unlock() | ||||
|  | ||||
| 	return s.getProcessLocked(id) | ||||
| } | ||||
|  | ||||
| // getProcessLocked attempts to get a process by id. | ||||
| // The caller MUST protect s.mu previous to calling this function. | ||||
| func (s *service) getProcessLocked(id string) (*process, error) { | ||||
| 	var p *process | ||||
| 	var ok bool | ||||
| 	if p, ok = s.processes[id]; !ok { | ||||
| 		return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process %s", id) | ||||
| 	} | ||||
| 	return p, nil | ||||
| } | ||||
|  | ||||
| func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error) { | ||||
| 	log.G(ctx).Info("Starting Cleanup") | ||||
|  | ||||
| 	_, err := namespaces.NamespaceRequired(ctx) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	path, err := os.Getwd() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := os.RemoveAll(path); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &taskAPI.DeleteResponse{ | ||||
| 		ExitedAt:   time.Now(), | ||||
| 		ExitStatus: 255, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (s *service) StartShim(ctx context.Context, id, containerdBinary, containerdAddress string) (string, error) { | ||||
| 	ns, err := namespaces.NamespaceRequired(ctx) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	self, err := os.Executable() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	cwd, err := os.Getwd() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	socketAddress, err := shim.SocketAddress(ctx, id) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	args := []string{ | ||||
| 		"-namespace", ns, | ||||
| 		"-id", id, | ||||
| 		"-address", containerdAddress, | ||||
| 		"-publish-binary", containerdBinary, | ||||
| 		"-socket", socketAddress, | ||||
| 		"-debug", | ||||
| 	} | ||||
| 	cmd := exec.Command(self, args...) | ||||
| 	cmd.Dir = cwd | ||||
| 	cmd.Env = append(os.Environ(), "GOMAXPROCS=2") | ||||
|  | ||||
| 	if err = cmd.Start(); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			cmd.Process.Kill() | ||||
| 		} | ||||
| 	}() | ||||
| 	// TODO: JTERRY75 - Windows does not use the ExtraFiles to pass the socket | ||||
| 	// because winio does not support it which exposes a race condition between | ||||
| 	// these two processes. For now AnonDialer will retry if the file does not | ||||
| 	// exist up to the timeout waiting for the shim service to create the pipe. | ||||
| 	go cmd.Wait() | ||||
| 	if err := shim.WritePidFile("shim.pid", cmd.Process.Pid); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if err := shim.WriteAddress("address", socketAddress); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return socketAddress, nil | ||||
| } | ||||
|  | ||||
| // State returns runtime state information for a process | ||||
| func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.StateResponse, error) { | ||||
| 	s.mu.Lock() | ||||
| 	defer s.mu.Unlock() | ||||
|  | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcessLocked(r.ID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "state", r.ID) | ||||
| 	sout := getBuffer() | ||||
| 	defer putBuffer(sout) | ||||
|  | ||||
| 	cmd.Stdout = sout | ||||
| 	_, stateErr := runCmd(ctx, cmd) | ||||
| 	if stateErr != nil { | ||||
| 		return nil, stateErr | ||||
| 	} | ||||
|  | ||||
| 	// TODO: JTERRY75 merge this with runhcs declaration | ||||
| 	type containerState struct { | ||||
| 		// Version is the OCI version for the container | ||||
| 		Version string `json:"ociVersion"` | ||||
| 		// ID is the container ID | ||||
| 		ID string `json:"id"` | ||||
| 		// InitProcessPid is the init process id in the parent namespace | ||||
| 		InitProcessPid int `json:"pid"` | ||||
| 		// Status is the current status of the container, running, paused, ... | ||||
| 		Status string `json:"status"` | ||||
| 		// Bundle is the path on the filesystem to the bundle | ||||
| 		Bundle string `json:"bundle"` | ||||
| 		// Rootfs is a path to a directory containing the container's root filesystem. | ||||
| 		Rootfs string `json:"rootfs"` | ||||
| 		// Created is the unix timestamp for the creation time of the container in UTC | ||||
| 		Created time.Time `json:"created"` | ||||
| 		// Annotations is the user defined annotations added to the config. | ||||
| 		Annotations map[string]string `json:"annotations,omitempty"` | ||||
| 		// The owner of the state directory (the owner of the container). | ||||
| 		Owner string `json:"owner"` | ||||
| 	} | ||||
|  | ||||
| 	var cs containerState | ||||
| 	if err := json.NewDecoder(sout).Decode(&cs); err != nil { | ||||
| 		log.G(ctx).WithError(err).Debugf("failed to decode runhcs state output: %s", sout.Bytes()) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	status := task.StatusUnknown | ||||
| 	switch cs.Status { | ||||
| 	case "created": | ||||
| 		status = task.StatusCreated | ||||
| 	case "running": | ||||
| 		status = task.StatusRunning | ||||
| 	case "stopped": | ||||
| 		status = task.StatusStopped | ||||
| 	case "paused": | ||||
| 		status = task.StatusPaused | ||||
| 	} | ||||
| 	pe := p.stat() | ||||
| 	return &taskAPI.StateResponse{ | ||||
| 		ID:         r.ID, | ||||
| 		Bundle:     cs.Bundle, | ||||
| 		Pid:        uint32(cs.InitProcessPid), | ||||
| 		Status:     status, | ||||
| 		Stdin:      p.stdin, | ||||
| 		Stdout:     p.stdout, | ||||
| 		Stderr:     p.stderr, | ||||
| 		Terminal:   p.terminal, | ||||
| 		ExitStatus: pe.exitStatus, | ||||
| 		ExitedAt:   pe.exitedAt, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func writeMountsToConfig(bundle string, mounts []*containerd_types.Mount) error { | ||||
| 	if len(mounts) != 1 { | ||||
| 		return errors.New("Rootfs does not contain exactly 1 mount for the root file system") | ||||
| 	} | ||||
|  | ||||
| 	m := mounts[0] | ||||
| 	if m.Type != "windows-layer" && m.Type != "lcow-layer" { | ||||
| 		return errors.Errorf("unsupported mount type '%s'", m.Type) | ||||
| 	} | ||||
|  | ||||
| 	// parentLayerPaths are passed in layerN, layerN-1, ..., layer 0 | ||||
| 	// | ||||
| 	// The OCI spec expects: | ||||
| 	//   windows-layer order is layerN, layerN-1, ..., layer0, scratch | ||||
| 	//   lcow-layer    order is layer0,   layer1, ..., layerN, scratch | ||||
| 	var parentLayerPaths []string | ||||
| 	for _, option := range mounts[0].Options { | ||||
| 		if strings.HasPrefix(option, mount.ParentLayerPathsFlag) { | ||||
| 			err := json.Unmarshal([]byte(option[len(mount.ParentLayerPathsFlag):]), &parentLayerPaths) | ||||
| 			if err != nil { | ||||
| 				return errors.Wrap(err, "failed to unmarshal parent layer paths from mount") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if m.Type == "lcow-layer" { | ||||
| 		// Reverse the lcow-layer parents | ||||
| 		for i := len(parentLayerPaths)/2 - 1; i >= 0; i-- { | ||||
| 			opp := len(parentLayerPaths) - 1 - i | ||||
| 			parentLayerPaths[i], parentLayerPaths[opp] = parentLayerPaths[opp], parentLayerPaths[i] | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	cf, err := os.OpenFile(path.Join(bundle, "config.json"), os.O_RDWR, 0) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrap(err, "bundle does not contain config.json") | ||||
| 	} | ||||
| 	defer cf.Close() | ||||
| 	var spec oci.Spec | ||||
| 	if err := json.NewDecoder(cf).Decode(&spec); err != nil { | ||||
| 		return errors.Wrap(err, "bundle config.json is not valid oci spec") | ||||
| 	} | ||||
| 	if err := cf.Truncate(0); err != nil { | ||||
| 		return errors.Wrap(err, "failed to truncate config.json") | ||||
| 	} | ||||
| 	if _, err := cf.Seek(0, 0); err != nil { | ||||
| 		return errors.Wrap(err, "failed to seek to 0 in config.json") | ||||
| 	} | ||||
|  | ||||
| 	// Append the parents | ||||
| 	spec.Windows.LayerFolders = append(spec.Windows.LayerFolders, parentLayerPaths...) | ||||
| 	// Append the scratch | ||||
| 	spec.Windows.LayerFolders = append(spec.Windows.LayerFolders, m.Source) | ||||
|  | ||||
| 	if err := json.NewEncoder(cf).Encode(spec); err != nil { | ||||
| 		return errors.Wrap(err, "failed to write Mounts into config.json") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Create a new initial process and container with runhcs | ||||
| func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*taskAPI.CreateTaskResponse, error) { | ||||
| 	// Hold the lock for the entire duration to avoid duplicate process creation. | ||||
| 	s.mu.Lock() | ||||
| 	defer s.mu.Unlock() | ||||
|  | ||||
| 	if p := s.processes[r.ID]; p != nil { | ||||
| 		return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "process %s already exists", r.ID) | ||||
| 	} | ||||
| 	if r.ID != s.id { | ||||
| 		return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "init process id '%s' != shim id '%s'", r.ID, s.id) | ||||
| 	} | ||||
|  | ||||
| 	// Add the mounts to the layer paths | ||||
| 	if err := writeMountsToConfig(r.Bundle, r.Rootfs); err != nil { | ||||
| 		return nil, errdefs.ToGRPC(err) | ||||
| 	} | ||||
|  | ||||
| 	// Create the IO for the process | ||||
| 	io, err := runc.NewPipeIO() | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to create io pipes") | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			io.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	// Create the upstream IO | ||||
| 	ps, err := newPipeSet(ctx, r.Stdin, r.Stdout, r.Stderr, r.Terminal) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to connect to upstream IO") | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			ps.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	// Create the relay for them both. | ||||
| 	pr := newPipeRelay(ctx, ps, io) | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			pr.close() | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	pidfilePath := path.Join(r.Bundle, "runhcs-pidfile.pid") | ||||
| 	copts := &runhcs.CreateOpts{ | ||||
| 		IO:      io, | ||||
| 		PidFile: pidfilePath, | ||||
| 		ShimLog: path.Join(r.Bundle, "runhcs-shim.log"), | ||||
| 		VMLog:   path.Join(r.Bundle, "runhcs-vm-shim.log"), | ||||
| 	} | ||||
|  | ||||
| 	rhcs := newRunhcs(r.Bundle) | ||||
| 	err = rhcs.Create(ctx, r.ID, r.Bundle, copts) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// We successfully created the process. Convert from initpid to the container process. | ||||
| 	pid, err := runc.ReadPidFile(pidfilePath) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to read container pid from pidfile") | ||||
| 	} | ||||
|  | ||||
| 	process, err := newProcess( | ||||
| 		ctx, | ||||
| 		s, | ||||
| 		r.ID, | ||||
| 		uint32(pid), | ||||
| 		pr, | ||||
| 		r.Bundle, | ||||
| 		r.Stdin, | ||||
| 		r.Stdout, | ||||
| 		r.Stderr, | ||||
| 		r.Terminal) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s.processes[r.ID] = process | ||||
|  | ||||
| 	return &taskAPI.CreateTaskResponse{ | ||||
| 		Pid: uint32(pid), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Start a process | ||||
| func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.StartResponse, error) { | ||||
| 	log.G(ctx).Infof("Start: %s: %s", r.ID, r.ExecID) | ||||
| 	var p *process | ||||
| 	var err error | ||||
|  | ||||
| 	var id string | ||||
| 	if r.ExecID != "" { | ||||
| 		id = r.ExecID | ||||
| 	} else { | ||||
| 		id = r.ID | ||||
| 	} | ||||
|  | ||||
| 	if p, err = s.getProcess(id); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	p.Lock() | ||||
| 	defer p.Unlock() | ||||
|  | ||||
| 	if p.started { | ||||
| 		return nil, errors.New("cannot start already started container or process") | ||||
| 	} | ||||
|  | ||||
| 	rhcs := newRunhcs(p.bundle) | ||||
|  | ||||
| 	// This is a start/exec | ||||
| 	if r.ExecID != "" { | ||||
| 		execFmt := fmt.Sprintf("exec-%s-%s", r.ID, r.ExecID) | ||||
| 		pidfilePath := path.Join(p.bundle, fmt.Sprintf("runhcs-%s-pidfile.pid", execFmt)) | ||||
| 		procConfig := path.Join(p.bundle, execFmt+"config.json") | ||||
| 		eopts := &runhcs.ExecOpts{ | ||||
| 			IO:      p.relay.io, | ||||
| 			PidFile: pidfilePath, | ||||
| 			ShimLog: path.Join(p.bundle, fmt.Sprintf("runhcs-%s-shim.log", execFmt)), | ||||
| 			Detach:  true, | ||||
| 		} | ||||
|  | ||||
| 		err = rhcs.Exec(ctx, r.ID, procConfig, eopts) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "failed to exec process: %s", r.ExecID) | ||||
| 		} | ||||
|  | ||||
| 		p.started = true | ||||
|  | ||||
| 		// We successfully exec'd the process. Convert from initpid to the container process. | ||||
| 		pid, err := runc.ReadPidFile(pidfilePath) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrap(err, "failed to read container pid from pidfile") | ||||
| 		} | ||||
|  | ||||
| 		proc, err := os.FindProcess(pid) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrap(err, "failed to find exec process pid") | ||||
| 		} | ||||
| 		p.pid = uint32(pid) | ||||
| 		go waitForProcess(ctx, p, proc, s) | ||||
| 	} else { | ||||
| 		if err := rhcs.Start(ctx, p.id); err != nil { | ||||
| 			return nil, errors.Wrapf(err, "failed to start container: %s", p.id) | ||||
| 		} | ||||
|  | ||||
| 		p.started = true | ||||
|  | ||||
| 		// TODO: JTERRY75 - This is a total hack. We cant return from this call | ||||
| 		// until the state has transitioned. Because runhcs start is long lived it | ||||
| 		// will return before the actual state is "RUNNING" which causes a failure | ||||
| 		// if the 'state' query comes in and it is not in the "RUNNING" state. | ||||
| 		stateRequest := &taskAPI.StateRequest{ | ||||
| 			ID:     r.ID, | ||||
| 			ExecID: r.ExecID, | ||||
| 		} | ||||
| 		for { | ||||
| 			sr, err := s.State(ctx, stateRequest) | ||||
| 			if err != nil { | ||||
| 				log.G(ctx).WithError(err).Debug("failed to query state of container") | ||||
| 				break | ||||
| 			} | ||||
| 			// Have we transitioned states yet? Expect != created && != unknown | ||||
| 			if sr.Status != task.StatusCreated && sr.Status != task.StatusUnknown { | ||||
| 				break | ||||
| 			} | ||||
| 			time.Sleep(1 * time.Second) | ||||
| 		} | ||||
| 	} | ||||
| 	return &taskAPI.StartResponse{ | ||||
| 		Pid: p.pid, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Delete the initial process and container | ||||
| func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAPI.DeleteResponse, error) { | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcess(r.ExecID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	rhs := newRunhcs(p.bundle) | ||||
|  | ||||
| 	dopts := &runhcs.DeleteOpts{ | ||||
| 		Force: true, | ||||
| 	} | ||||
| 	if err := rhs.Delete(ctx, p.id, dopts); err != nil { | ||||
| 		return nil, errors.Wrapf(err, "failed to delete container: %s", p.id) | ||||
| 	} | ||||
|  | ||||
| 	select { | ||||
| 	case <-time.After(5 * time.Second): | ||||
| 		// Force close the container process since it didnt shutdown in time. | ||||
| 		p.close() | ||||
| 	case <-p.waitBlock: | ||||
| 	} | ||||
|  | ||||
| 	exit := p.stat() | ||||
|  | ||||
| 	s.mu.Lock() | ||||
| 	delete(s.processes, r.ID) | ||||
| 	s.mu.Unlock() | ||||
| 	return &taskAPI.DeleteResponse{ | ||||
| 		ExitedAt:   exit.exitedAt, | ||||
| 		ExitStatus: exit.exitStatus, | ||||
| 		Pid:        p.pid, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Pids returns all pids inside the container | ||||
| func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.PidsResponse, error) { | ||||
| 	return nil, errdefs.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| // Pause the container | ||||
| func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) { | ||||
| 	// TODO: Validate that 'id' is actually a valid parent container ID | ||||
| 	if _, err := s.getProcess(r.ID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "pause", r.ID) | ||||
| 	_, err := runCmd(ctx, cmd) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // Resume the container | ||||
| func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) { | ||||
| 	// TODO: Validate that 'id' is actually a valid parent container ID | ||||
| 	if _, err := s.getProcess(r.ID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "resume", r.ID) | ||||
| 	_, err := runCmd(ctx, cmd) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // Checkpoint the container | ||||
| func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*ptypes.Empty, error) { | ||||
| 	return nil, errdefs.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| // Kill a process with the provided signal | ||||
| func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Empty, error) { | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcess(r.ExecID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// TODO: JTERRY75 runhcs needs r.Signal in string form | ||||
| 	// TODO: JTERRY75 runhcs support for r.All? | ||||
| 	rhcs := newRunhcs(p.bundle) | ||||
| 	if err = rhcs.Kill(ctx, p.id, strconv.FormatUint(uint64(r.Signal), 10)); err != nil { | ||||
| 		if !strings.Contains(err.Error(), "container is not running") { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // Exec an additional process inside the container | ||||
| func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*ptypes.Empty, error) { | ||||
| 	s.mu.Lock() | ||||
| 	defer s.mu.Unlock() | ||||
|  | ||||
| 	var parent *process | ||||
| 	var err error | ||||
| 	// Get the parent container | ||||
| 	if parent, err = s.getProcessLocked(r.ID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if p := s.processes[r.ExecID]; p != nil { | ||||
| 		return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "exec process %s already exists", r.ExecID) | ||||
| 	} | ||||
|  | ||||
| 	execFmt := fmt.Sprintf("exec-%s-%s", r.ID, r.ExecID) | ||||
|  | ||||
| 	var spec oci.Process | ||||
| 	if err := json.Unmarshal(r.Spec.Value, &spec); err != nil { | ||||
| 		return nil, errors.Wrap(err, "request.Spec was not oci process") | ||||
| 	} | ||||
| 	procConfig := path.Join(parent.bundle, execFmt+"config.json") | ||||
| 	cf, err := os.OpenFile(procConfig, os.O_CREATE|os.O_WRONLY, 0) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "bundle does not contain config.json") | ||||
| 	} | ||||
| 	if err := json.NewEncoder(cf).Encode(spec); err != nil { | ||||
| 		cf.Close() | ||||
| 		return nil, errors.Wrap(err, "failed to write Mounts into config.json") | ||||
| 	} | ||||
| 	cf.Close() | ||||
|  | ||||
| 	// Create the IO for the process | ||||
| 	io, err := runc.NewPipeIO() | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to create io pipes") | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			io.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	// Create the upstream IO | ||||
| 	ps, err := newPipeSet(ctx, r.Stdin, r.Stdout, r.Stderr, r.Terminal) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to connect to upstream IO") | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			ps.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	// Create the relay for them both. | ||||
| 	pr := newPipeRelay(ctx, ps, io) | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			pr.close() | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	process, err := newExecProcess( | ||||
| 		ctx, | ||||
| 		s, | ||||
| 		r.ID, | ||||
| 		r.ExecID, | ||||
| 		pr, | ||||
| 		parent.bundle, | ||||
| 		r.Stdin, | ||||
| 		r.Stdout, | ||||
| 		r.Stderr, | ||||
| 		r.Terminal) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s.processes[r.ExecID] = process | ||||
|  | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // ResizePty of a process | ||||
| func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*ptypes.Empty, error) { | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcess(r.ExecID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cmd := exec.Command( | ||||
| 		runhcsBinary, | ||||
| 		runhcsDebugLegacy, | ||||
| 		"resize-tty", | ||||
| 		r.ID, | ||||
| 		"-p", | ||||
| 		strconv.FormatUint(uint64(p.pid), 10), | ||||
| 		strconv.FormatUint(uint64(r.Width), 10), | ||||
| 		strconv.FormatUint(uint64(r.Height), 10)) | ||||
|  | ||||
| 	_, err = runCmd(ctx, cmd) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // CloseIO of a process | ||||
| func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptypes.Empty, error) { | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcess(r.ExecID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	p.closeIO() | ||||
| 	return empty, nil | ||||
| } | ||||
|  | ||||
| // Update a running container | ||||
| func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*ptypes.Empty, error) { | ||||
| 	return nil, errdefs.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| // Wait for a process to exit | ||||
| func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (*taskAPI.WaitResponse, error) { | ||||
| 	var p *process | ||||
| 	var err error | ||||
| 	if p, err = s.getProcess(r.ExecID); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pe := p.wait() | ||||
| 	return &taskAPI.WaitResponse{ | ||||
| 		ExitedAt:   pe.exitedAt, | ||||
| 		ExitStatus: pe.exitStatus, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Stats returns statistics about the running container | ||||
| func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.StatsResponse, error) { | ||||
| 	return nil, errdefs.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| // Connect returns the runhcs shim information | ||||
| func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) { | ||||
| 	return &taskAPI.ConnectResponse{ | ||||
| 		ShimPid: uint32(os.Getpid()), | ||||
| 		TaskPid: s.processes[s.id].pid, | ||||
| 		Version: runhcsVersion, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Shutdown stops this instance of the runhcs shim | ||||
| func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) { | ||||
| 	os.Exit(0) | ||||
| 	return empty, nil | ||||
| } | ||||
| @@ -27,6 +27,7 @@ import ( | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"sync" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	winio "github.com/Microsoft/go-winio" | ||||
| 	"github.com/containerd/containerd/events" | ||||
| @@ -35,6 +36,7 @@ import ( | ||||
| 	"github.com/containerd/typeurl" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| // setupSignals creates a new signal handler for all signals | ||||
| @@ -51,8 +53,43 @@ func subreaper() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type fakeSignal struct { | ||||
| } | ||||
|  | ||||
| func (fs *fakeSignal) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (fs *fakeSignal) Signal() { | ||||
| } | ||||
|  | ||||
| func setupDumpStacks(dump chan<- os.Signal) { | ||||
| 	// TODO: JTERRY75: Make this based on events. signal.Notify(dump, syscall.SIGUSR1) | ||||
| 	// Windows does not support signals like *nix systems. So instead of | ||||
| 	// trapping on SIGUSR1 to dump stacks, we wait on a Win32 event to be | ||||
| 	// signaled. ACL'd to builtin administrators and local system | ||||
| 	event := "Global\\containerd-shim-runhcs-v1-" + fmt.Sprint(os.Getpid()) | ||||
| 	ev, _ := windows.UTF16PtrFromString(event) | ||||
| 	sd, err := winio.SddlToSecurityDescriptor("D:P(A;;GA;;;BA)(A;;GA;;;SY)") | ||||
| 	if err != nil { | ||||
| 		logrus.Errorf("failed to get security descriptor for debug stackdump event %s: %s", event, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	var sa windows.SecurityAttributes | ||||
| 	sa.Length = uint32(unsafe.Sizeof(sa)) | ||||
| 	sa.InheritHandle = 1 | ||||
| 	sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) | ||||
| 	h, err := windows.CreateEvent(&sa, 0, 0, ev) | ||||
| 	if h == 0 || err != nil { | ||||
| 		logrus.Errorf("failed to create debug stackdump event %s: %s", event, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	go func() { | ||||
| 		logrus.Debugf("Stackdump - waiting signal at %s", event) | ||||
| 		for { | ||||
| 			windows.WaitForSingleObject(h, windows.INFINITE) | ||||
| 			dump <- new(fakeSignal) | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| // serve serves the ttrpc API over a unix socket at the provided path | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031 | ||||
| github.com/containerd/go-runc 808e8444ac4633a8e5eb7314fc6b5d27051727dd | ||||
| github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 | ||||
| github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 | ||||
| github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 | ||||
| @@ -33,7 +33,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c | ||||
| github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 | ||||
| github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 | ||||
| github.com/Microsoft/go-winio v0.4.10 | ||||
| github.com/Microsoft/hcsshim v0.6.14 | ||||
| github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55 | ||||
| github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd | ||||
| google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 | ||||
| golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 | ||||
|   | ||||
							
								
								
									
										18
									
								
								vendor/github.com/Microsoft/hcsshim/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/Microsoft/hcsshim/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,12 +1,13 @@ | ||||
| # hcsshim | ||||
|  | ||||
| This package supports launching Windows Server containers from Go. It is | ||||
| primarily used in the [Docker Engine](https://github.com/docker/docker) project, | ||||
| but it can be freely used by other projects as well. | ||||
| [](https://ci.appveyor.com/project/WindowsVirtualization/hcsshim/branch/master) | ||||
|  | ||||
| This package contains the Golang interface for using the Windows [Host Compute Service](https://blogs.technet.microsoft.com/virtualization/2017/01/27/introducing-the-host-compute-service-hcs/) (HCS) to launch and manage [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/). It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS). | ||||
|  | ||||
| It is primarily used in the [Moby Project](https://github.com/moby/moby), but it can be freely used by other projects as well. | ||||
|  | ||||
| ## Contributing | ||||
| --------------- | ||||
|  | ||||
| This project welcomes contributions and suggestions.  Most contributions require you to agree to a | ||||
| Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us | ||||
| the rights to use your contribution. For details, visit https://cla.microsoft.com. | ||||
| @@ -19,6 +20,11 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope | ||||
| For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or | ||||
| contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. | ||||
|  | ||||
| ## Dependencies | ||||
|  | ||||
| This project requires Golang 1.9 or newer to build. | ||||
|  | ||||
| For system requirements to run this project, see the Microsoft docs on [Windows Container requirements](https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/system-requirements). | ||||
|  | ||||
| ## Reporting Security Issues | ||||
|  | ||||
| @@ -29,5 +35,7 @@ email to ensure we received your original message. Further information, includin | ||||
| [MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in | ||||
| the [Security TechCenter](https://technet.microsoft.com/en-us/security/default). | ||||
|  | ||||
| ------------------------------------------- | ||||
| For additional details, see [Report a Computer Security Vulnerability](https://technet.microsoft.com/en-us/security/ff852094.aspx) on Technet | ||||
|  | ||||
| --------------- | ||||
| Copyright (c) 2018 Microsoft Corp.  All rights reserved. | ||||
|   | ||||
							
								
								
									
										28
									
								
								vendor/github.com/Microsoft/hcsshim/activatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/Microsoft/hcsshim/activatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,28 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // ActivateLayer will find the layer with the given id and mount it's filesystem. | ||||
| // For a read/write layer, the mounted filesystem will appear as a volume on the | ||||
| // host, while a read-only layer is generally expected to be a no-op. | ||||
| // An activated layer must later be deactivated via DeactivateLayer. | ||||
| func ActivateLayer(info DriverInfo, id string) error { | ||||
| 	title := "hcsshim::ActivateLayer " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) | ||||
|  | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = activateLayer(&infop, id) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										201
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    APPENDIX: How to apply the Apache License to your work. | ||||
|  | ||||
|       To apply the Apache License to your work, attach the following | ||||
|       boilerplate notice, with the fields enclosed by brackets "[]" | ||||
|       replaced with your own identifying information. (Don't include | ||||
|       the brackets!)  The text should be enclosed in the appropriate | ||||
|       comment syntax for the file format. We also recommend that a | ||||
|       file or class name and description of purpose be included on the | ||||
|       same "printed page" as the copyright notice for easier | ||||
|       identification within third-party archives. | ||||
|  | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/NOTICE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/NOTICE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| go-runhcs is a fork of go-runc | ||||
|  | ||||
| The following is runc's legal notice. | ||||
|  | ||||
| --- | ||||
|  | ||||
| runc | ||||
|  | ||||
| Copyright 2012-2015 Docker, Inc. | ||||
|  | ||||
| This product includes software developed at Docker, Inc. (http://www.docker.com). | ||||
|  | ||||
| The following is courtesy of our legal counsel: | ||||
|  | ||||
| Use and transfer of Docker may be subject to certain restrictions by the | ||||
| United States and other governments. | ||||
| It is your responsibility to ensure that your use and/or transfer does not | ||||
| violate applicable laws. | ||||
|  | ||||
| For more information, please see http://www.bis.doc.gov | ||||
|  | ||||
| See also http://www.apache.org/dev/crypto.html and/or seek legal counsel. | ||||
							
								
								
									
										125
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/containerd/go-runc" | ||||
| ) | ||||
|  | ||||
| // Format is the type of log formatting options available. | ||||
| type Format string | ||||
|  | ||||
| const ( | ||||
| 	none Format = "" | ||||
| 	// Text is the default text log ouput. | ||||
| 	Text Format = "text" | ||||
| 	// JSON is the JSON formatted log output. | ||||
| 	JSON Format = "json" | ||||
|  | ||||
| 	command = "runhcs" | ||||
| ) | ||||
|  | ||||
| var bytesBufferPool = sync.Pool{ | ||||
| 	New: func() interface{} { | ||||
| 		return bytes.NewBuffer(nil) | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func getBuf() *bytes.Buffer { | ||||
| 	return bytesBufferPool.Get().(*bytes.Buffer) | ||||
| } | ||||
|  | ||||
| func putBuf(b *bytes.Buffer) { | ||||
| 	b.Reset() | ||||
| 	bytesBufferPool.Put(b) | ||||
| } | ||||
|  | ||||
| // Runhcs is the client to the runhcs cli | ||||
| type Runhcs struct { | ||||
| 	// Debug enables debug output for logging. | ||||
| 	Debug bool | ||||
| 	// Log sets the log file path where internal debug information is written. | ||||
| 	Log string | ||||
| 	// LogFormat sets the format used by logs. | ||||
| 	LogFormat Format | ||||
| 	// Owner sets the compute system owner property. | ||||
| 	Owner string | ||||
| 	// Root is the registry key root for storage of runhcs container state. | ||||
| 	Root string | ||||
| } | ||||
|  | ||||
| func (r *Runhcs) args() []string { | ||||
| 	var out []string | ||||
| 	if r.Debug { | ||||
| 		out = append(out, "--debug") | ||||
| 	} | ||||
| 	if r.Log != "" { | ||||
| 		// TODO: JTERRY75 - Should we do abs here? | ||||
| 		out = append(out, "--log", r.Log) | ||||
| 	} | ||||
| 	if r.LogFormat != none { | ||||
| 		out = append(out, "--log-format", string(r.LogFormat)) | ||||
| 	} | ||||
| 	if r.Owner != "" { | ||||
| 		out = append(out, "--owner", r.Owner) | ||||
| 	} | ||||
| 	if r.Root != "" { | ||||
| 		out = append(out, "--root", r.Root) | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| func (r *Runhcs) command(context context.Context, args ...string) *exec.Cmd { | ||||
| 	cmd := exec.CommandContext(context, command, append(r.args(), args...)...) | ||||
| 	cmd.Env = os.Environ() | ||||
| 	return cmd | ||||
| } | ||||
|  | ||||
| // runOrError will run the provided command.  If an error is | ||||
| // encountered and neither Stdout or Stderr was set the error and the | ||||
| // stderr of the command will be returned in the format of <error>: | ||||
| // <stderr> | ||||
| func (r *Runhcs) runOrError(cmd *exec.Cmd) error { | ||||
| 	if cmd.Stdout != nil || cmd.Stderr != nil { | ||||
| 		ec, err := runc.Monitor.Start(cmd) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		status, err := runc.Monitor.Wait(cmd, ec) | ||||
| 		if err == nil && status != 0 { | ||||
| 			err = fmt.Errorf("%s did not terminate sucessfully", cmd.Args[0]) | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| 	data, err := cmdOutput(cmd, true) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%s: %s", err, data) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func cmdOutput(cmd *exec.Cmd, combined bool) ([]byte, error) { | ||||
| 	b := getBuf() | ||||
| 	defer putBuf(b) | ||||
|  | ||||
| 	cmd.Stdout = b | ||||
| 	if combined { | ||||
| 		cmd.Stderr = b | ||||
| 	} | ||||
| 	ec, err := runc.Monitor.Start(cmd) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	status, err := runc.Monitor.Wait(cmd, ec) | ||||
| 	if err == nil && status != 0 { | ||||
| 		err = fmt.Errorf("%s did not terminate sucessfully", cmd.Args[0]) | ||||
| 	} | ||||
|  | ||||
| 	return b.Bytes(), err | ||||
| } | ||||
							
								
								
									
										91
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_create.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_create.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	runc "github.com/containerd/go-runc" | ||||
| ) | ||||
|  | ||||
| // CreateOpts is set of options that can be used with the Create command. | ||||
| type CreateOpts struct { | ||||
| 	runc.IO | ||||
| 	// PidFile is the path to the file to write the process id to. | ||||
| 	PidFile string | ||||
| 	// ShimLog is the path to the log file for the launched shim process. | ||||
| 	ShimLog string | ||||
| 	// VMLog is the path to the log file for the launched VM shim process. | ||||
| 	VMLog string | ||||
| 	// VMConsole is the path to the pipe for the VM's console (e.g. \\.\pipe\debugpipe) | ||||
| 	VMConsole string | ||||
| } | ||||
|  | ||||
| func (opt *CreateOpts) args() ([]string, error) { | ||||
| 	var out []string | ||||
| 	if opt.PidFile != "" { | ||||
| 		abs, err := filepath.Abs(opt.PidFile) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		out = append(out, "--pid-file", abs) | ||||
| 	} | ||||
| 	if opt.ShimLog != "" { | ||||
| 		abs, err := filepath.Abs(opt.ShimLog) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		out = append(out, "--shim-log", abs) | ||||
| 	} | ||||
| 	if opt.VMLog != "" { | ||||
| 		abs, err := filepath.Abs(opt.VMLog) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		out = append(out, "--vm-log", abs) | ||||
| 	} | ||||
| 	if opt.VMConsole != "" { | ||||
| 		out = append(out, "--vm-console", opt.VMConsole) | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Create creates a new container and returns its pid if it was created | ||||
| // successfully. | ||||
| func (r *Runhcs) Create(context context.Context, id, bundle string, opts *CreateOpts) error { | ||||
| 	args := []string{"create", "--bundle", bundle} | ||||
| 	if opts != nil { | ||||
| 		oargs, err := opts.args() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		args = append(args, oargs...) | ||||
| 	} | ||||
| 	cmd := r.command(context, append(args, id)...) | ||||
| 	if opts != nil && opts.IO != nil { | ||||
| 		opts.Set(cmd) | ||||
| 	} | ||||
| 	if cmd.Stdout == nil && cmd.Stderr == nil { | ||||
| 		data, err := cmdOutput(cmd, true) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%s: %s", err, data) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	ec, err := runc.Monitor.Start(cmd) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if opts != nil && opts.IO != nil { | ||||
| 		if c, ok := opts.IO.(runc.StartCloser); ok { | ||||
| 			if err := c.CloseAfterStart(); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	status, err := runc.Monitor.Wait(cmd, ec) | ||||
| 	if err == nil && status != 0 { | ||||
| 		err = fmt.Errorf("%s did not terminate sucessfully", cmd.Args[0]) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										33
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_delete.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_delete.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
|  | ||||
| // DeleteOpts is set of options that can be used with the Delete command. | ||||
| type DeleteOpts struct { | ||||
| 	// Force forcibly deletes the container if it is still running (uses SIGKILL). | ||||
| 	Force bool | ||||
| } | ||||
|  | ||||
| func (opt *DeleteOpts) args() ([]string, error) { | ||||
| 	var out []string | ||||
| 	if opt.Force { | ||||
| 		out = append(out, "--force") | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Delete any resources held by the container often used with detached | ||||
| // containers. | ||||
| func (r *Runhcs) Delete(context context.Context, id string, opts *DeleteOpts) error { | ||||
| 	args := []string{"delete"} | ||||
| 	if opts != nil { | ||||
| 		oargs, err := opts.args() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		args = append(args, oargs...) | ||||
| 	} | ||||
| 	return r.runOrError(r.command(context, append(args, id)...)) | ||||
| } | ||||
							
								
								
									
										82
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_exec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_exec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/containerd/go-runc" | ||||
| ) | ||||
|  | ||||
| // ExecOpts is set of options that can be used with the Exec command. | ||||
| type ExecOpts struct { | ||||
| 	runc.IO | ||||
| 	// Detach from the container's process. | ||||
| 	Detach bool | ||||
| 	// PidFile is the path to the file to write the process id to. | ||||
| 	PidFile string | ||||
| 	// ShimLog is the path to the log file for the launched shim process. | ||||
| 	ShimLog string | ||||
| } | ||||
|  | ||||
| func (opt *ExecOpts) args() ([]string, error) { | ||||
| 	var out []string | ||||
| 	if opt.Detach { | ||||
| 		out = append(out, "--detach") | ||||
| 	} | ||||
| 	if opt.PidFile != "" { | ||||
| 		abs, err := filepath.Abs(opt.PidFile) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		out = append(out, "--pid-file", abs) | ||||
| 	} | ||||
| 	if opt.ShimLog != "" { | ||||
| 		abs, err := filepath.Abs(opt.ShimLog) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		out = append(out, "--shim-log", abs) | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Exec executes an additional process inside the container based on the | ||||
| // oci.Process spec found at processFile. | ||||
| func (r *Runhcs) Exec(context context.Context, id, processFile string, opts *ExecOpts) error { | ||||
| 	args := []string{"exec", "--process", processFile} | ||||
| 	if opts != nil { | ||||
| 		oargs, err := opts.args() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		args = append(args, oargs...) | ||||
| 	} | ||||
| 	cmd := r.command(context, append(args, id)...) | ||||
| 	if opts != nil && opts.IO != nil { | ||||
| 		opts.Set(cmd) | ||||
| 	} | ||||
| 	if cmd.Stdout == nil && cmd.Stderr == nil { | ||||
| 		data, err := cmdOutput(cmd, true) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%s: %s", err, data) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	ec, err := runc.Monitor.Start(cmd) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if opts != nil && opts.IO != nil { | ||||
| 		if c, ok := opts.IO.(runc.StartCloser); ok { | ||||
| 			if err := c.CloseAfterStart(); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	status, err := runc.Monitor.Wait(cmd, ec) | ||||
| 	if err == nil && status != 0 { | ||||
| 		err = fmt.Errorf("%s did not terminate sucessfully", cmd.Args[0]) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_kill.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_kill.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
|  | ||||
| // Kill sends the specified signal (default: SIGTERM) to the container's init | ||||
| // process. | ||||
| func (r *Runhcs) Kill(context context.Context, id, signal string) error { | ||||
| 	return r.runOrError(r.command(context, "kill", id, signal)) | ||||
| } | ||||
							
								
								
									
										10
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_start.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/Microsoft/hcsshim/cmd/go-runhcs/runhcs_start.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| package runhcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| ) | ||||
|  | ||||
| // Start will start an already created container. | ||||
| func (r *Runhcs) Start(context context.Context, id string) error { | ||||
| 	return r.runOrError(r.command(context, "start", id)) | ||||
| } | ||||
							
								
								
									
										791
									
								
								vendor/github.com/Microsoft/hcsshim/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										791
									
								
								vendor/github.com/Microsoft/hcsshim/container.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,845 +1,192 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcs" | ||||
| 	"github.com/Microsoft/hcsshim/internal/mergemaps" | ||||
| 	"github.com/Microsoft/hcsshim/internal/schema1" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	defaultTimeout = time.Minute * 4 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	pendingUpdatesQuery    = `{ "PropertyTypes" : ["PendingUpdates"]}` | ||||
| 	statisticsQuery        = `{ "PropertyTypes" : ["Statistics"]}` | ||||
| 	processListQuery       = `{ "PropertyTypes" : ["ProcessList"]}` | ||||
| 	mappedVirtualDiskQuery = `{ "PropertyTypes" : ["MappedVirtualDisk"]}` | ||||
| ) | ||||
|  | ||||
| type container struct { | ||||
| 	handleLock     sync.RWMutex | ||||
| 	handle         hcsSystem | ||||
| 	id             string | ||||
| 	callbackNumber uintptr | ||||
| } | ||||
|  | ||||
| // ContainerProperties holds the properties for a container and the processes running in that container | ||||
| type ContainerProperties struct { | ||||
| 	ID                           string `json:"Id"` | ||||
| 	Name                         string | ||||
| 	SystemType                   string | ||||
| 	Owner                        string | ||||
| 	SiloGUID                     string                              `json:"SiloGuid,omitempty"` | ||||
| 	RuntimeID                    string                              `json:"RuntimeId,omitempty"` | ||||
| 	IsRuntimeTemplate            bool                                `json:",omitempty"` | ||||
| 	RuntimeImagePath             string                              `json:",omitempty"` | ||||
| 	Stopped                      bool                                `json:",omitempty"` | ||||
| 	ExitType                     string                              `json:",omitempty"` | ||||
| 	AreUpdatesPending            bool                                `json:",omitempty"` | ||||
| 	ObRoot                       string                              `json:",omitempty"` | ||||
| 	Statistics                   Statistics                          `json:",omitempty"` | ||||
| 	ProcessList                  []ProcessListItem                   `json:",omitempty"` | ||||
| 	MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"` | ||||
| } | ||||
| type ContainerProperties = schema1.ContainerProperties | ||||
|  | ||||
| // MemoryStats holds the memory statistics for a container | ||||
| type MemoryStats struct { | ||||
| 	UsageCommitBytes            uint64 `json:"MemoryUsageCommitBytes,omitempty"` | ||||
| 	UsageCommitPeakBytes        uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"` | ||||
| 	UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` | ||||
| } | ||||
| type MemoryStats = schema1.MemoryStats | ||||
|  | ||||
| // ProcessorStats holds the processor statistics for a container | ||||
| type ProcessorStats struct { | ||||
| 	TotalRuntime100ns  uint64 `json:",omitempty"` | ||||
| 	RuntimeUser100ns   uint64 `json:",omitempty"` | ||||
| 	RuntimeKernel100ns uint64 `json:",omitempty"` | ||||
| } | ||||
| type ProcessorStats = schema1.ProcessorStats | ||||
|  | ||||
| // StorageStats holds the storage statistics for a container | ||||
| type StorageStats struct { | ||||
| 	ReadCountNormalized  uint64 `json:",omitempty"` | ||||
| 	ReadSizeBytes        uint64 `json:",omitempty"` | ||||
| 	WriteCountNormalized uint64 `json:",omitempty"` | ||||
| 	WriteSizeBytes       uint64 `json:",omitempty"` | ||||
| } | ||||
| type StorageStats = schema1.StorageStats | ||||
|  | ||||
| // NetworkStats holds the network statistics for a container | ||||
| type NetworkStats struct { | ||||
| 	BytesReceived          uint64 `json:",omitempty"` | ||||
| 	BytesSent              uint64 `json:",omitempty"` | ||||
| 	PacketsReceived        uint64 `json:",omitempty"` | ||||
| 	PacketsSent            uint64 `json:",omitempty"` | ||||
| 	DroppedPacketsIncoming uint64 `json:",omitempty"` | ||||
| 	DroppedPacketsOutgoing uint64 `json:",omitempty"` | ||||
| 	EndpointId             string `json:",omitempty"` | ||||
| 	InstanceId             string `json:",omitempty"` | ||||
| } | ||||
| type NetworkStats = schema1.NetworkStats | ||||
|  | ||||
| // Statistics is the structure returned by a statistics call on a container | ||||
| type Statistics struct { | ||||
| 	Timestamp          time.Time      `json:",omitempty"` | ||||
| 	ContainerStartTime time.Time      `json:",omitempty"` | ||||
| 	Uptime100ns        uint64         `json:",omitempty"` | ||||
| 	Memory             MemoryStats    `json:",omitempty"` | ||||
| 	Processor          ProcessorStats `json:",omitempty"` | ||||
| 	Storage            StorageStats   `json:",omitempty"` | ||||
| 	Network            []NetworkStats `json:",omitempty"` | ||||
| } | ||||
| type Statistics = schema1.Statistics | ||||
|  | ||||
| // ProcessList is the structure of an item returned by a ProcessList call on a container | ||||
| type ProcessListItem struct { | ||||
| 	CreateTimestamp              time.Time `json:",omitempty"` | ||||
| 	ImageName                    string    `json:",omitempty"` | ||||
| 	KernelTime100ns              uint64    `json:",omitempty"` | ||||
| 	MemoryCommitBytes            uint64    `json:",omitempty"` | ||||
| 	MemoryWorkingSetPrivateBytes uint64    `json:",omitempty"` | ||||
| 	MemoryWorkingSetSharedBytes  uint64    `json:",omitempty"` | ||||
| 	ProcessId                    uint32    `json:",omitempty"` | ||||
| 	UserTime100ns                uint64    `json:",omitempty"` | ||||
| } | ||||
| type ProcessListItem = schema1.ProcessListItem | ||||
|  | ||||
| // MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container | ||||
| type MappedVirtualDiskController struct { | ||||
| 	MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"` | ||||
| } | ||||
| type MappedVirtualDiskController = schema1.MappedVirtualDiskController | ||||
|  | ||||
| // Type of Request Support in ModifySystem | ||||
| type RequestType string | ||||
| type RequestType = schema1.RequestType | ||||
|  | ||||
| // Type of Resource Support in ModifySystem | ||||
| type ResourceType string | ||||
| type ResourceType = schema1.ResourceType | ||||
|  | ||||
| // RequestType const | ||||
| const ( | ||||
| 	Add     RequestType  = "Add" | ||||
| 	Remove  RequestType  = "Remove" | ||||
| 	Network ResourceType = "Network" | ||||
| 	Add     = schema1.Add | ||||
| 	Remove  = schema1.Remove | ||||
| 	Network = schema1.Network | ||||
| ) | ||||
|  | ||||
| // ResourceModificationRequestResponse is the structure used to send request to the container to modify the system | ||||
| // Supported resource types are Network and Request Types are Add/Remove | ||||
| type ResourceModificationRequestResponse struct { | ||||
| 	Resource ResourceType `json:"ResourceType"` | ||||
| 	Data     interface{}  `json:"Settings"` | ||||
| 	Request  RequestType  `json:"RequestType,omitempty"` | ||||
| type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse | ||||
|  | ||||
| type container struct { | ||||
| 	system *hcs.System | ||||
| } | ||||
|  | ||||
| // createContainerAdditionalJSON is read from the environment at initialisation | ||||
| // createComputeSystemAdditionalJSON is read from the environment at initialisation | ||||
| // time. It allows an environment variable to define additional JSON which | ||||
| // is merged in the CreateContainer call to HCS. | ||||
| var createContainerAdditionalJSON string | ||||
|  | ||||
| // currentContainerStarts is used to limit the number of concurrent container | ||||
| // starts. | ||||
| var currentContainerStarts containerStarts | ||||
|  | ||||
| type containerStarts struct { | ||||
| 	maxParallel int | ||||
| 	inProgress  int | ||||
| 	sync.Mutex | ||||
| } | ||||
| // is merged in the CreateComputeSystem call to HCS. | ||||
| var createContainerAdditionalJSON []byte | ||||
|  | ||||
| func init() { | ||||
| 	createContainerAdditionalJSON = os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON") | ||||
| 	mpsS := os.Getenv("HCSSHIM_MAX_PARALLEL_START") | ||||
| 	if len(mpsS) > 0 { | ||||
| 		mpsI, err := strconv.Atoi(mpsS) | ||||
| 		if err != nil || mpsI < 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		currentContainerStarts.maxParallel = mpsI | ||||
| 	} | ||||
| 	createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON")) | ||||
| } | ||||
|  | ||||
| // CreateContainer creates a new container with the given configuration but does not start it. | ||||
| func CreateContainer(id string, c *ContainerConfig) (Container, error) { | ||||
| 	return createContainerWithJSON(id, c, "") | ||||
| 	fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err) | ||||
| 	} | ||||
|  | ||||
| // CreateContainerWithJSON creates a new container with the given configuration but does not start it. | ||||
| // It is identical to CreateContainer except that optional additional JSON can be merged before passing to HCS. | ||||
| func CreateContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) { | ||||
| 	return createContainerWithJSON(id, c, additionalJSON) | ||||
| } | ||||
|  | ||||
| func createContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) { | ||||
| 	operation := "CreateContainer" | ||||
| 	title := "HCSShim::" + operation | ||||
|  | ||||
| 	container := &container{ | ||||
| 		id: id, | ||||
| 	} | ||||
|  | ||||
| 	configurationb, err := json.Marshal(c) | ||||
| 	system, err := hcs.CreateComputeSystem(id, fullConfig) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	configuration := string(configurationb) | ||||
| 	logrus.Debugf(title+" id=%s config=%s", id, configuration) | ||||
|  | ||||
| 	// Merge any additional JSON. Priority is given to what is passed in explicitly, | ||||
| 	// falling back to what's set in the environment. | ||||
| 	if additionalJSON == "" && createContainerAdditionalJSON != "" { | ||||
| 		additionalJSON = createContainerAdditionalJSON | ||||
| 	} | ||||
| 	if additionalJSON != "" { | ||||
| 		configurationMap := map[string]interface{}{} | ||||
| 		if err := json.Unmarshal([]byte(configuration), &configurationMap); err != nil { | ||||
| 			return nil, fmt.Errorf("failed to unmarshal %s: %s", configuration, err) | ||||
| 		} | ||||
|  | ||||
| 		additionalMap := map[string]interface{}{} | ||||
| 		if err := json.Unmarshal([]byte(additionalJSON), &additionalMap); err != nil { | ||||
| 			return nil, fmt.Errorf("failed to unmarshal %s: %s", additionalJSON, err) | ||||
| 		} | ||||
|  | ||||
| 		mergedMap := mergeMaps(additionalMap, configurationMap) | ||||
| 		mergedJSON, err := json.Marshal(mergedMap) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to marshal merged configuration map %+v: %s", mergedMap, err) | ||||
| 		} | ||||
|  | ||||
| 		configuration = string(mergedJSON) | ||||
| 		logrus.Debugf(title+" id=%s merged config=%s", id, configuration) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		resultp  *uint16 | ||||
| 		identity syscall.Handle | ||||
| 	) | ||||
| 	createError := hcsCreateComputeSystem(id, configuration, identity, &container.handle, &resultp) | ||||
|  | ||||
| 	if createError == nil || IsPending(createError) { | ||||
| 		if err := container.registerCallback(); err != nil { | ||||
| 			// Terminate the container if it still exists. We're okay to ignore a failure here. | ||||
| 			container.Terminate() | ||||
| 			return nil, makeContainerError(container, operation, "", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) | ||||
| 	if err != nil { | ||||
| 		if err == ErrTimeout { | ||||
| 			// Terminate the container if it still exists. We're okay to ignore a failure here. | ||||
| 			container.Terminate() | ||||
| 		} | ||||
| 		return nil, makeContainerError(container, operation, configuration, err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle) | ||||
| 	return container, nil | ||||
| } | ||||
|  | ||||
| // mergeMaps recursively merges map `fromMap` into map `ToMap`. Any pre-existing values | ||||
| // in ToMap are overwritten. Values in fromMap are added to ToMap. | ||||
| // From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang | ||||
| func mergeMaps(fromMap, ToMap interface{}) interface{} { | ||||
| 	switch fromMap := fromMap.(type) { | ||||
| 	case map[string]interface{}: | ||||
| 		ToMap, ok := ToMap.(map[string]interface{}) | ||||
| 		if !ok { | ||||
| 			return fromMap | ||||
| 		} | ||||
| 		for keyToMap, valueToMap := range ToMap { | ||||
| 			if valueFromMap, ok := fromMap[keyToMap]; ok { | ||||
| 				fromMap[keyToMap] = mergeMaps(valueFromMap, valueToMap) | ||||
| 			} else { | ||||
| 				fromMap[keyToMap] = valueToMap | ||||
| 			} | ||||
| 		} | ||||
| 	case nil: | ||||
| 		// merge(nil, map[string]interface{...}) -> map[string]interface{...} | ||||
| 		ToMap, ok := ToMap.(map[string]interface{}) | ||||
| 		if ok { | ||||
| 			return ToMap | ||||
| 		} | ||||
| 	} | ||||
| 	return fromMap | ||||
| 	return &container{system}, err | ||||
| } | ||||
|  | ||||
| // OpenContainer opens an existing container by ID. | ||||
| func OpenContainer(id string) (Container, error) { | ||||
| 	operation := "OpenContainer" | ||||
| 	title := "HCSShim::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", id) | ||||
|  | ||||
| 	container := &container{ | ||||
| 		id: id, | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		handle  hcsSystem | ||||
| 		resultp *uint16 | ||||
| 	) | ||||
| 	err := hcsOpenComputeSystem(id, &handle, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	system, err := hcs.OpenComputeSystem(id) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	container.handle = handle | ||||
|  | ||||
| 	if err := container.registerCallback(); err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle) | ||||
| 	return container, nil | ||||
| 	return &container{system}, err | ||||
| } | ||||
|  | ||||
| // GetContainers gets a list of the containers on the system that match the query | ||||
| func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) { | ||||
| 	operation := "GetContainers" | ||||
| 	title := "HCSShim::" + operation | ||||
|  | ||||
| 	queryb, err := json.Marshal(q) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	query := string(queryb) | ||||
| 	logrus.Debugf(title+" query=%s", query) | ||||
|  | ||||
| 	var ( | ||||
| 		resultp         *uint16 | ||||
| 		computeSystemsp *uint16 | ||||
| 	) | ||||
| 	err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if computeSystemsp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	computeSystemsRaw := convertAndFreeCoTaskMemBytes(computeSystemsp) | ||||
| 	computeSystems := []ContainerProperties{} | ||||
| 	if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return computeSystems, nil | ||||
| 	return hcs.GetComputeSystems(q) | ||||
| } | ||||
|  | ||||
| // Start synchronously starts the container. | ||||
| func (container *container) Start() error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Start" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	return convertSystemError(container.system.Start(), container) | ||||
| } | ||||
|  | ||||
| 	// This is a very simple backoff-retry loop to limit the number | ||||
| 	// of parallel container starts if environment variable | ||||
| 	// HCSSHIM_MAX_PARALLEL_START is set to a positive integer. | ||||
| 	// It should generally only be used as a workaround to various | ||||
| 	// platform issues that exist between RS1 and RS4 as of Aug 2018. | ||||
| 	if currentContainerStarts.maxParallel > 0 { | ||||
| 		for { | ||||
| 			currentContainerStarts.Lock() | ||||
| 			if currentContainerStarts.inProgress < currentContainerStarts.maxParallel { | ||||
| 				currentContainerStarts.inProgress++ | ||||
| 				currentContainerStarts.Unlock() | ||||
| 				break | ||||
| 			} | ||||
| 			if currentContainerStarts.inProgress == currentContainerStarts.maxParallel { | ||||
| 				currentContainerStarts.Unlock() | ||||
| 				time.Sleep(100 * time.Millisecond) | ||||
| 			} | ||||
| 		} | ||||
| 		// Make sure we decrement the count when we are done. | ||||
| 		defer func() { | ||||
| 			currentContainerStarts.Lock() | ||||
| 			currentContainerStarts.inProgress-- | ||||
| 			currentContainerStarts.Unlock() | ||||
| 		}() | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsStartComputeSystem(container.handle, "", &resultp) | ||||
| 	err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Shutdown requests a container shutdown, if IsPending() on the error returned is true, | ||||
| // it may not actually be shut down until Wait() succeeds. | ||||
| // Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds. | ||||
| func (container *container) Shutdown() error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Shutdown" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	return convertSystemError(container.system.Shutdown(), container) | ||||
| } | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsShutdownComputeSystem(container.handle, "", &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Terminate requests a container terminate, if IsPending() on the error returned is true, | ||||
| // it may not actually be shut down until Wait() succeeds. | ||||
| // Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds. | ||||
| func (container *container) Terminate() error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Terminate" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	return convertSystemError(container.system.Terminate(), container) | ||||
| } | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsTerminateComputeSystem(container.handle, "", &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Wait synchronously waits for the container to shutdown or terminate. | ||||
| // Waits synchronously waits for the container to shutdown or terminate. | ||||
| func (container *container) Wait() error { | ||||
| 	operation := "Wait" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	return convertSystemError(container.system.Wait(), container) | ||||
| } | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| // WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It | ||||
| // returns false if timeout occurs. | ||||
| func (container *container) WaitTimeout(t time.Duration) error { | ||||
| 	return convertSystemError(container.system.WaitTimeout(t), container) | ||||
| } | ||||
|  | ||||
| // WaitTimeout synchronously waits for the container to terminate or the duration to elapse. | ||||
| // If the timeout expires, IsTimeout(err) == true | ||||
| func (container *container) WaitTimeout(timeout time.Duration) error { | ||||
| 	operation := "WaitTimeout" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| // Pause pauses the execution of a container. | ||||
| func (container *container) Pause() error { | ||||
| 	return convertSystemError(container.system.Pause(), container) | ||||
| } | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (container *container) properties(query string) (*ContainerProperties, error) { | ||||
| 	var ( | ||||
| 		resultp     *uint16 | ||||
| 		propertiesp *uint16 | ||||
| 	) | ||||
| 	err := hcsGetComputeSystemProperties(container.handle, query, &propertiesp, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if propertiesp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp) | ||||
| 	properties := &ContainerProperties{} | ||||
| 	if err := json.Unmarshal(propertiesRaw, properties); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return properties, nil | ||||
| // Resume resumes the execution of a container. | ||||
| func (container *container) Resume() error { | ||||
| 	return convertSystemError(container.system.Resume(), container) | ||||
| } | ||||
|  | ||||
| // HasPendingUpdates returns true if the container has updates pending to install | ||||
| func (container *container) HasPendingUpdates() (bool, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "HasPendingUpdates" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return false, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| 	properties, err := container.properties(pendingUpdatesQuery) | ||||
| 	if err != nil { | ||||
| 		return false, makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return properties.AreUpdatesPending, nil | ||||
| } | ||||
|  | ||||
| // Statistics returns statistics for the container | ||||
| // Statistics returns statistics for the container. This is a legacy v1 call | ||||
| func (container *container) Statistics() (Statistics, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Statistics" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return Statistics{}, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	properties, err := container.properties(statisticsQuery) | ||||
| 	properties, err := container.system.Properties(schema1.PropertyTypeStatistics) | ||||
| 	if err != nil { | ||||
| 		return Statistics{}, makeContainerError(container, operation, "", err) | ||||
| 		return Statistics{}, convertSystemError(err, container) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return properties.Statistics, nil | ||||
| } | ||||
|  | ||||
| // ProcessList returns an array of ProcessListItems for the container | ||||
| // ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call | ||||
| func (container *container) ProcessList() ([]ProcessListItem, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "ProcessList" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	properties, err := container.properties(processListQuery) | ||||
| 	properties, err := container.system.Properties(schema1.PropertyTypeProcessList) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 		return nil, convertSystemError(err, container) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return properties.ProcessList, nil | ||||
| } | ||||
|  | ||||
| // MappedVirtualDisks returns a map of the controllers and the disks mapped | ||||
| // to a container. | ||||
| // | ||||
| // Example of JSON returned by the query. | ||||
| //{ | ||||
| //   "Id":"1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3_svm", | ||||
| //   "SystemType":"Container", | ||||
| //   "RuntimeOsType":"Linux", | ||||
| //   "RuntimeId":"00000000-0000-0000-0000-000000000000", | ||||
| //   "State":"Running", | ||||
| //   "MappedVirtualDiskControllers":{ | ||||
| //      "0":{ | ||||
| //         "MappedVirtualDisks":{ | ||||
| //            "2":{ | ||||
| //               "HostPath":"C:\\lcow\\lcow\\scratch\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3.vhdx", | ||||
| //               "ContainerPath":"/mnt/gcs/LinuxServiceVM/scratch", | ||||
| //               "Lun":2, | ||||
| //               "CreateInUtilityVM":true | ||||
| //            }, | ||||
| //            "3":{ | ||||
| //               "HostPath":"C:\\lcow\\lcow\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3\\sandbox.vhdx", | ||||
| //               "Lun":3, | ||||
| //               "CreateInUtilityVM":true, | ||||
| //               "AttachOnly":true | ||||
| //            } | ||||
| //         } | ||||
| //      } | ||||
| //   } | ||||
| //} | ||||
| // This is a legacy v1 call | ||||
| func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "MappedVirtualDiskList" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	properties, err := container.properties(mappedVirtualDiskQuery) | ||||
| 	properties, err := container.system.Properties(schema1.PropertyTypeMappedVirtualDisk) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 		return nil, convertSystemError(err, container) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return properties.MappedVirtualDiskControllers, nil | ||||
| } | ||||
|  | ||||
| // Pause pauses the execution of the container. This feature is not enabled in TP5. | ||||
| func (container *container) Pause() error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Pause" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsPauseComputeSystem(container.handle, "", &resultp) | ||||
| 	err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Resume resumes the execution of the container. This feature is not enabled in TP5. | ||||
| func (container *container) Resume() error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Resume" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsResumeComputeSystem(container.handle, "", &resultp) | ||||
| 	err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CreateProcess launches a new process within the container. | ||||
| func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "CreateProcess" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	var ( | ||||
| 		processInfo   hcsProcessInformation | ||||
| 		processHandle hcsProcess | ||||
| 		resultp       *uint16 | ||||
| 	) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	// If we are not emulating a console, ignore any console size passed to us | ||||
| 	if !c.EmulateConsole { | ||||
| 		c.ConsoleSize[0] = 0 | ||||
| 		c.ConsoleSize[1] = 0 | ||||
| 	} | ||||
|  | ||||
| 	configurationb, err := json.Marshal(c) | ||||
| 	p, err := container.system.CreateProcess(c) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 		return nil, convertSystemError(err, container) | ||||
| 	} | ||||
|  | ||||
| 	configuration := string(configurationb) | ||||
| 	logrus.Debugf(title+" id=%s config=%s", container.id, configuration) | ||||
|  | ||||
| 	err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, configuration, err) | ||||
| 	} | ||||
|  | ||||
| 	process := &process{ | ||||
| 		handle:    processHandle, | ||||
| 		processID: int(processInfo.ProcessId), | ||||
| 		container: container, | ||||
| 		cachedPipes: &cachedPipes{ | ||||
| 			stdIn:  processInfo.StdInput, | ||||
| 			stdOut: processInfo.StdOutput, | ||||
| 			stdErr: processInfo.StdError, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	if err := process.registerCallback(); err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s processid=%d", container.id, process.processID) | ||||
| 	return process, nil | ||||
| 	return &process{p}, nil | ||||
| } | ||||
|  | ||||
| // OpenProcess gets an interface to an existing process within the container. | ||||
| func (container *container) OpenProcess(pid int) (Process, error) { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "OpenProcess" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, processid=%d", container.id, pid) | ||||
| 	var ( | ||||
| 		processHandle hcsProcess | ||||
| 		resultp       *uint16 | ||||
| 	) | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	p, err := container.system.OpenProcess(pid) | ||||
| 	if err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 		return nil, convertSystemError(err, container) | ||||
| 	} | ||||
|  | ||||
| 	process := &process{ | ||||
| 		handle:    processHandle, | ||||
| 		processID: pid, | ||||
| 		container: container, | ||||
| 	} | ||||
|  | ||||
| 	if err := process.registerCallback(); err != nil { | ||||
| 		return nil, makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID) | ||||
| 	return process, nil | ||||
| 	return &process{p}, nil | ||||
| } | ||||
|  | ||||
| // Close cleans up any state associated with the container but does not terminate or wait for it. | ||||
| func (container *container) Close() error { | ||||
| 	container.handleLock.Lock() | ||||
| 	defer container.handleLock.Unlock() | ||||
| 	operation := "Close" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", container.id) | ||||
|  | ||||
| 	// Don't double free this | ||||
| 	if container.handle == 0 { | ||||
| 		return nil | ||||
| 	return convertSystemError(container.system.Close(), container) | ||||
| } | ||||
|  | ||||
| 	if err := container.unregisterCallback(); err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := hcsCloseComputeSystem(container.handle); err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	container.handle = 0 | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (container *container) registerCallback() error { | ||||
| 	context := ¬ifcationWatcherContext{ | ||||
| 		channels: newChannels(), | ||||
| 	} | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackNumber := nextCallback | ||||
| 	nextCallback++ | ||||
| 	callbackMap[callbackNumber] = context | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	var callbackHandle hcsCallback | ||||
| 	err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	context.handle = callbackHandle | ||||
| 	container.callbackNumber = callbackNumber | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (container *container) unregisterCallback() error { | ||||
| 	callbackNumber := container.callbackNumber | ||||
|  | ||||
| 	callbackMapLock.RLock() | ||||
| 	context := callbackMap[callbackNumber] | ||||
| 	callbackMapLock.RUnlock() | ||||
|  | ||||
| 	if context == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	handle := context.handle | ||||
|  | ||||
| 	if handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// hcsUnregisterComputeSystemCallback has its own syncronization | ||||
| 	// to wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := hcsUnregisterComputeSystemCallback(handle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	closeChannels(context.channels) | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackMap[callbackNumber] = nil | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	handle = 0 | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Modifies the System by sending a request to HCS | ||||
| // Modify the System | ||||
| func (container *container) Modify(config *ResourceModificationRequestResponse) error { | ||||
| 	container.handleLock.RLock() | ||||
| 	defer container.handleLock.RUnlock() | ||||
| 	operation := "Modify" | ||||
| 	title := "HCSShim::Container::" + operation | ||||
|  | ||||
| 	if container.handle == 0 { | ||||
| 		return makeContainerError(container, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	requestJSON, err := json.Marshal(config) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	requestString := string(requestJSON) | ||||
| 	logrus.Debugf(title+" id=%s request=%s", container.id, requestString) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyComputeSystem(container.handle, requestString, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeContainerError(container, operation, "", err) | ||||
| 	} | ||||
| 	logrus.Debugf(title+" succeeded id=%s", container.id) | ||||
| 	return nil | ||||
| 	return convertSystemError(container.system.Modify(config), container) | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/createlayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/createlayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // CreateLayer creates a new, empty, read-only layer on the filesystem based on | ||||
| // the parent layer provided. | ||||
| func CreateLayer(info DriverInfo, id, parent string) error { | ||||
| 	title := "hcsshim::CreateLayer " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = createLayer(&infop, id, parent) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" - succeeded id=%s parent=%s flavour=%d", id, parent, info.Flavour) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										35
									
								
								vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,35 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // CreateSandboxLayer creates and populates new read-write layer for use by a container. | ||||
| // This requires both the id of the direct parent layer, as well as the full list | ||||
| // of paths to all parent layers up to the base (and including the direct parent | ||||
| // whose id was provided). | ||||
| func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { | ||||
| 	title := "hcsshim::CreateSandboxLayer " | ||||
| 	logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId) | ||||
|  | ||||
| 	// Generate layer descriptors | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = createSandboxLayer(&infop, layerId, parentId, layers) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"- succeeded layerId=%s parentId=%s", layerId, parentId) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/deactivatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/deactivatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // DeactivateLayer will dismount a layer that was mounted via ActivateLayer. | ||||
| func DeactivateLayer(info DriverInfo, id string) error { | ||||
| 	title := "hcsshim::DeactivateLayer " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = deactivateLayer(&infop, id) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/destroylayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/destroylayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // DestroyLayer will remove the on-disk files representing the layer with the given | ||||
| // id, including that layer's containing folder, if any. | ||||
| func DestroyLayer(info DriverInfo, id string) error { | ||||
| 	title := "hcsshim::DestroyLayer " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = destroyLayer(&infop, id) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										128
									
								
								vendor/github.com/Microsoft/hcsshim/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										128
									
								
								vendor/github.com/Microsoft/hcsshim/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,92 +1,83 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcs" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists | ||||
| 	ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e) | ||||
| 	// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist | ||||
| 	ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist | ||||
|  | ||||
| 	// ErrElementNotFound is an error encountered when the object being referenced does not exist | ||||
| 	ErrElementNotFound = syscall.Errno(0x490) | ||||
| 	ErrElementNotFound = hcs.ErrElementNotFound | ||||
|  | ||||
| 	// ErrElementNotFound is an error encountered when the object being referenced does not exist | ||||
| 	ErrNotSupported = syscall.Errno(0x32) | ||||
| 	ErrNotSupported = hcs.ErrNotSupported | ||||
|  | ||||
| 	// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported | ||||
| 	// decimal -2147024883 / hex 0x8007000d | ||||
| 	ErrInvalidData = syscall.Errno(0xd) | ||||
| 	ErrInvalidData = hcs.ErrInvalidData | ||||
|  | ||||
| 	// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed | ||||
| 	ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed") | ||||
| 	ErrHandleClose = hcs.ErrHandleClose | ||||
|  | ||||
| 	// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method | ||||
| 	ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed") | ||||
| 	ErrAlreadyClosed = hcs.ErrAlreadyClosed | ||||
|  | ||||
| 	// ErrInvalidNotificationType is an error encountered when an invalid notification type is used | ||||
| 	ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type") | ||||
| 	ErrInvalidNotificationType = hcs.ErrInvalidNotificationType | ||||
|  | ||||
| 	// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation | ||||
| 	ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") | ||||
| 	ErrInvalidProcessState = hcs.ErrInvalidProcessState | ||||
|  | ||||
| 	// ErrTimeout is an error encountered when waiting on a notification times out | ||||
| 	ErrTimeout = errors.New("hcsshim: timeout waiting for notification") | ||||
| 	ErrTimeout = hcs.ErrTimeout | ||||
|  | ||||
| 	// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for | ||||
| 	// a different expected notification | ||||
| 	ErrUnexpectedContainerExit = errors.New("unexpected container exit") | ||||
| 	ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit | ||||
|  | ||||
| 	// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service | ||||
| 	// is lost while waiting for a notification | ||||
| 	ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") | ||||
| 	ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort | ||||
|  | ||||
| 	// ErrUnexpectedValue is an error encountered when hcs returns an invalid value | ||||
| 	ErrUnexpectedValue = errors.New("unexpected value returned from hcs") | ||||
| 	ErrUnexpectedValue = hcs.ErrUnexpectedValue | ||||
|  | ||||
| 	// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container | ||||
| 	ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110) | ||||
| 	ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped | ||||
|  | ||||
| 	// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously | ||||
| 	ErrVmcomputeOperationPending = syscall.Errno(0xC0370103) | ||||
| 	ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending | ||||
|  | ||||
| 	// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation | ||||
| 	ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105) | ||||
| 	ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState | ||||
|  | ||||
| 	// ErrProcNotFound is an error encountered when the the process cannot be found | ||||
| 	ErrProcNotFound = syscall.Errno(0x7f) | ||||
| 	ErrProcNotFound = hcs.ErrProcNotFound | ||||
|  | ||||
| 	// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2 | ||||
| 	// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3. | ||||
| 	ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5) | ||||
| 	ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied | ||||
|  | ||||
| 	// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management | ||||
| 	ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d) | ||||
| 	ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON | ||||
|  | ||||
| 	// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message | ||||
| 	ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b) | ||||
| 	ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage | ||||
|  | ||||
| 	// ErrNotSupported is an error encountered when hcs doesn't support the request | ||||
| 	ErrPlatformNotSupported = errors.New("unsupported platform request") | ||||
| 	ErrPlatformNotSupported = hcs.ErrPlatformNotSupported | ||||
| ) | ||||
|  | ||||
| type EndpointNotFoundError struct { | ||||
| 	EndpointName string | ||||
| } | ||||
|  | ||||
| func (e EndpointNotFoundError) Error() string { | ||||
| 	return fmt.Sprintf("Endpoint %s not found", e.EndpointName) | ||||
| } | ||||
|  | ||||
| type NetworkNotFoundError struct { | ||||
| 	NetworkName string | ||||
| } | ||||
|  | ||||
| func (e NetworkNotFoundError) Error() string { | ||||
| 	return fmt.Sprintf("Network %s not found", e.NetworkName) | ||||
| } | ||||
| type EndpointNotFoundError = hns.EndpointNotFoundError | ||||
| type NetworkNotFoundError = hns.NetworkNotFoundError | ||||
|  | ||||
| // ProcessError is an error encountered in HCS during an operation on a Process object | ||||
| type ProcessError struct { | ||||
| @@ -94,6 +85,7 @@ type ProcessError struct { | ||||
| 	Operation string | ||||
| 	ExtraInfo string | ||||
| 	Err       error | ||||
| 	Events    []hcs.ErrorEvent | ||||
| } | ||||
|  | ||||
| // ContainerError is an error encountered in HCS during an operation on a Container object | ||||
| @@ -102,6 +94,7 @@ type ContainerError struct { | ||||
| 	Operation string | ||||
| 	ExtraInfo string | ||||
| 	Err       error | ||||
| 	Events    []hcs.ErrorEvent | ||||
| } | ||||
|  | ||||
| func (e *ContainerError) Error() string { | ||||
| @@ -113,7 +106,7 @@ func (e *ContainerError) Error() string { | ||||
| 		return "unexpected nil container for error: " + e.Err.Error() | ||||
| 	} | ||||
|  | ||||
| 	s := "container " + e.Container.id | ||||
| 	s := "container " + e.Container.system.ID() | ||||
|  | ||||
| 	if e.Operation != "" { | ||||
| 		s += " encountered an error during " + e.Operation | ||||
| @@ -123,11 +116,15 @@ func (e *ContainerError) Error() string { | ||||
| 	case nil: | ||||
| 		break | ||||
| 	case syscall.Errno: | ||||
| 		s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err)) | ||||
| 		s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) | ||||
| 	default: | ||||
| 		s += fmt.Sprintf(": %s", e.Err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	for _, ev := range e.Events { | ||||
| 		s += "\n" + ev.String() | ||||
| 	} | ||||
|  | ||||
| 	if e.ExtraInfo != "" { | ||||
| 		s += " extra info: " + e.ExtraInfo | ||||
| 	} | ||||
| @@ -153,12 +150,7 @@ func (e *ProcessError) Error() string { | ||||
| 		return "Unexpected nil process for error: " + e.Err.Error() | ||||
| 	} | ||||
|  | ||||
| 	s := fmt.Sprintf("process %d", e.Process.processID) | ||||
|  | ||||
| 	if e.Process.container != nil { | ||||
| 		s += " in container " + e.Process.container.id | ||||
| 	} | ||||
|  | ||||
| 	s := fmt.Sprintf("process %d in container %s", e.Process.p.Pid(), e.Process.p.SystemID()) | ||||
| 	if e.Operation != "" { | ||||
| 		s += " encountered an error during " + e.Operation | ||||
| 	} | ||||
| @@ -167,11 +159,15 @@ func (e *ProcessError) Error() string { | ||||
| 	case nil: | ||||
| 		break | ||||
| 	case syscall.Errno: | ||||
| 		s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err)) | ||||
| 		s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) | ||||
| 	default: | ||||
| 		s += fmt.Sprintf(": %s", e.Err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	for _, ev := range e.Events { | ||||
| 		s += "\n" + ev.String() | ||||
| 	} | ||||
|  | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| @@ -189,37 +185,31 @@ func makeProcessError(process *process, operation string, extraInfo string, err | ||||
| // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist | ||||
| // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. | ||||
| func IsNotExist(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	if _, ok := err.(EndpointNotFoundError); ok { | ||||
| 		return true | ||||
| 	} | ||||
| 	if _, ok := err.(NetworkNotFoundError); ok { | ||||
| 		return true | ||||
| 	} | ||||
| 	return err == ErrComputeSystemDoesNotExist || | ||||
| 		err == ErrElementNotFound || | ||||
| 		err == ErrProcNotFound | ||||
| 	return hcs.IsNotExist(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| // IsAlreadyClosed checks if an error is caused by the Container or Process having been | ||||
| // already closed by a call to the Close() method. | ||||
| func IsAlreadyClosed(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrAlreadyClosed | ||||
| 	return hcs.IsAlreadyClosed(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| // IsPending returns a boolean indicating whether the error is that | ||||
| // the requested operation is being completed in the background. | ||||
| func IsPending(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrVmcomputeOperationPending | ||||
| 	return hcs.IsPending(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| // IsTimeout returns a boolean indicating whether the error is caused by | ||||
| // a timeout waiting for the operation to complete. | ||||
| func IsTimeout(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrTimeout | ||||
| 	return hcs.IsTimeout(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| // IsAlreadyStopped returns a boolean indicating whether the error is caused by | ||||
| @@ -228,10 +218,7 @@ func IsTimeout(err error) bool { | ||||
| // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist | ||||
| // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. | ||||
| func IsAlreadyStopped(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrVmcomputeAlreadyStopped || | ||||
| 		err == ErrElementNotFound || | ||||
| 		err == ErrProcNotFound | ||||
| 	return hcs.IsAlreadyStopped(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| // IsNotSupported returns a boolean indicating whether the error is caused by | ||||
| @@ -240,12 +227,7 @@ func IsAlreadyStopped(err error) bool { | ||||
| // ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage | ||||
| // is thrown from the Platform | ||||
| func IsNotSupported(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	// If Platform doesn't recognize or support the request sent, below errors are seen | ||||
| 	return err == ErrVmcomputeInvalidJSON || | ||||
| 		err == ErrInvalidData || | ||||
| 		err == ErrNotSupported || | ||||
| 		err == ErrVmcomputeUnknownMessage | ||||
| 	return hcs.IsNotSupported(getInnerError(err)) | ||||
| } | ||||
|  | ||||
| func getInnerError(err error) error { | ||||
| @@ -259,3 +241,17 @@ func getInnerError(err error) error { | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func convertSystemError(err error, c *container) error { | ||||
| 	if serr, ok := err.(*hcs.SystemError); ok { | ||||
| 		return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func convertProcessError(err error, p *process) error { | ||||
| 	if perr, ok := err.(*hcs.ProcessError); ok { | ||||
| 		return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|   | ||||
							
								
								
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // ExpandSandboxSize expands the size of a layer to at least size bytes. | ||||
| func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error { | ||||
| 	title := "hcsshim::ExpandSandboxSize " | ||||
| 	logrus.Debugf(title+"layerId=%s size=%d", layerId, size) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = expandSandboxSize(&infop, layerId, size) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s  size=%d", layerId, size) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"- succeeded layerId=%s size=%d", layerId, size) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										19
									
								
								vendor/github.com/Microsoft/hcsshim/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/Microsoft/hcsshim/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,19 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"crypto/sha1" | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| type GUID [16]byte | ||||
|  | ||||
| func NewGUID(source string) *GUID { | ||||
| 	h := sha1.Sum([]byte(source)) | ||||
| 	var g GUID | ||||
| 	copy(g[0:], h[0:16]) | ||||
| 	return &g | ||||
| } | ||||
|  | ||||
| func (g *GUID) ToString() string { | ||||
| 	return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:]) | ||||
| } | ||||
							
								
								
									
										146
									
								
								vendor/github.com/Microsoft/hcsshim/hcsshim.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										146
									
								
								vendor/github.com/Microsoft/hcsshim/hcsshim.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,80 +4,20 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| ) | ||||
|  | ||||
| //go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go safeopen.go | ||||
| //go:generate go run mksyscall_windows.go -output zsyscall_windows.go hcsshim.go | ||||
|  | ||||
| //sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree | ||||
| //sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId | ||||
|  | ||||
| //sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? | ||||
| //sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? | ||||
| //sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? | ||||
| //sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? | ||||
| //sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize? | ||||
| //sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? | ||||
| //sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? | ||||
| //sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? | ||||
| //sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? | ||||
| //sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? | ||||
| //sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? | ||||
| //sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? | ||||
| //sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid? | ||||
| //sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? | ||||
| //sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? | ||||
| //sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage? | ||||
| //sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage? | ||||
|  | ||||
| //sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin? | ||||
| //sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext? | ||||
| //sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite? | ||||
| //sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd? | ||||
|  | ||||
| //sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin? | ||||
| //sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext? | ||||
| //sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead? | ||||
| //sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd? | ||||
|  | ||||
| //sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems? | ||||
| //sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem? | ||||
| //sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem? | ||||
| //sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem? | ||||
| //sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem? | ||||
| //sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem? | ||||
| //sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem? | ||||
| //sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem? | ||||
| //sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem? | ||||
| //sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties? | ||||
| //sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem? | ||||
| //sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback? | ||||
| //sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback? | ||||
|  | ||||
| //sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess? | ||||
| //sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess? | ||||
| //sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess? | ||||
| //sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess? | ||||
| //sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo? | ||||
| //sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties? | ||||
| //sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess? | ||||
| //sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties? | ||||
| //sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback? | ||||
| //sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback? | ||||
|  | ||||
| //sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings? | ||||
|  | ||||
| //sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? | ||||
|  | ||||
| const ( | ||||
| 	// Specific user-visible exit codes | ||||
| 	WaitErrExecFailed = 32767 | ||||
|  | ||||
| 	ERROR_GEN_FAILURE          = syscall.Errno(31) | ||||
| 	ERROR_GEN_FAILURE          = hcserror.ERROR_GEN_FAILURE | ||||
| 	ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115) | ||||
| 	WSAEINVAL                  = syscall.Errno(10022) | ||||
|  | ||||
| @@ -85,82 +25,4 @@ const ( | ||||
| 	TimeoutInfinite = 0xFFFFFFFF | ||||
| ) | ||||
|  | ||||
| type HcsError struct { | ||||
| 	title string | ||||
| 	rest  string | ||||
| 	Err   error | ||||
| } | ||||
|  | ||||
| type hcsSystem syscall.Handle | ||||
| type hcsProcess syscall.Handle | ||||
| type hcsCallback syscall.Handle | ||||
|  | ||||
| type hcsProcessInformation struct { | ||||
| 	ProcessId uint32 | ||||
| 	Reserved  uint32 | ||||
| 	StdInput  syscall.Handle | ||||
| 	StdOutput syscall.Handle | ||||
| 	StdError  syscall.Handle | ||||
| } | ||||
|  | ||||
| func makeError(err error, title, rest string) error { | ||||
| 	// Pass through DLL errors directly since they do not originate from HCS. | ||||
| 	if _, ok := err.(*syscall.DLLError); ok { | ||||
| 		return err | ||||
| 	} | ||||
| 	return &HcsError{title, rest, err} | ||||
| } | ||||
|  | ||||
| func makeErrorf(err error, title, format string, a ...interface{}) error { | ||||
| 	return makeError(err, title, fmt.Sprintf(format, a...)) | ||||
| } | ||||
|  | ||||
| func win32FromError(err error) uint32 { | ||||
| 	if herr, ok := err.(*HcsError); ok { | ||||
| 		return win32FromError(herr.Err) | ||||
| 	} | ||||
| 	if code, ok := err.(syscall.Errno); ok { | ||||
| 		return uint32(code) | ||||
| 	} | ||||
| 	return uint32(ERROR_GEN_FAILURE) | ||||
| } | ||||
|  | ||||
| func win32FromHresult(hr uintptr) uintptr { | ||||
| 	if hr&0x1fff0000 == 0x00070000 { | ||||
| 		return hr & 0xffff | ||||
| 	} | ||||
| 	return hr | ||||
| } | ||||
|  | ||||
| func (e *HcsError) Error() string { | ||||
| 	s := e.title | ||||
| 	if len(s) > 0 && s[len(s)-1] != ' ' { | ||||
| 		s += " " | ||||
| 	} | ||||
| 	s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err)) | ||||
| 	if e.rest != "" { | ||||
| 		if e.rest[0] != ' ' { | ||||
| 			s += " " | ||||
| 		} | ||||
| 		s += e.rest | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func convertAndFreeCoTaskMemString(buffer *uint16) string { | ||||
| 	str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:]) | ||||
| 	coTaskMemFree(unsafe.Pointer(buffer)) | ||||
| 	return str | ||||
| } | ||||
|  | ||||
| func convertAndFreeCoTaskMemBytes(buffer *uint16) []byte { | ||||
| 	return []byte(convertAndFreeCoTaskMemString(buffer)) | ||||
| } | ||||
|  | ||||
| func processHcsResult(err error, resultp *uint16) error { | ||||
| 	if resultp != nil { | ||||
| 		result := convertAndFreeCoTaskMemString(resultp) | ||||
| 		logrus.Debugf("Result: %s", result) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| type HcsError = hcserror.HcsError | ||||
|   | ||||
							
								
								
									
										248
									
								
								vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										248
									
								
								vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,29 +1,11 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| // HNSEndpoint represents a network endpoint in HNS | ||||
| type HNSEndpoint struct { | ||||
| 	Id                 string            `json:"ID,omitempty"` | ||||
| 	Name               string            `json:",omitempty"` | ||||
| 	VirtualNetwork     string            `json:",omitempty"` | ||||
| 	VirtualNetworkName string            `json:",omitempty"` | ||||
| 	Policies           []json.RawMessage `json:",omitempty"` | ||||
| 	MacAddress         string            `json:",omitempty"` | ||||
| 	IPAddress          net.IP            `json:",omitempty"` | ||||
| 	DNSSuffix          string            `json:",omitempty"` | ||||
| 	DNSServerList      string            `json:",omitempty"` | ||||
| 	GatewayAddress     string            `json:",omitempty"` | ||||
| 	EnableInternalDNS  bool              `json:",omitempty"` | ||||
| 	DisableICC         bool              `json:",omitempty"` | ||||
| 	PrefixLength       uint8             `json:",omitempty"` | ||||
| 	IsRemoteEndpoint   bool              `json:",omitempty"` | ||||
| } | ||||
| type HNSEndpoint = hns.HNSEndpoint | ||||
|  | ||||
| //SystemType represents the type of the system on which actions are done | ||||
| type SystemType string | ||||
| @@ -37,39 +19,19 @@ const ( | ||||
|  | ||||
| // EndpointAttachDetachRequest is the structure used to send request to the container to modify the system | ||||
| // Supported resource types are Network and Request Types are Add/Remove | ||||
| type EndpointAttachDetachRequest struct { | ||||
| 	ContainerID    string     `json:"ContainerId,omitempty"` | ||||
| 	SystemType     SystemType `json:"SystemType"` | ||||
| 	CompartmentID  uint16     `json:"CompartmentId,omitempty"` | ||||
| 	VirtualNICName string     `json:"VirtualNicName,omitempty"` | ||||
| } | ||||
| type EndpointAttachDetachRequest = hns.EndpointAttachDetachRequest | ||||
|  | ||||
| // EndpointResquestResponse is object to get the endpoint request response | ||||
| type EndpointResquestResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| } | ||||
| type EndpointResquestResponse = hns.EndpointResquestResponse | ||||
|  | ||||
| // HNSEndpointRequest makes a HNS call to modify/query a network endpoint | ||||
| func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { | ||||
| 	endpoint := &HNSEndpoint{} | ||||
| 	err := hnsCall(method, "/endpoints/"+path, request, &endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return endpoint, nil | ||||
| 	return hns.HNSEndpointRequest(method, path, request) | ||||
| } | ||||
|  | ||||
| // HNSListEndpointRequest makes a HNS call to query the list of available endpoints | ||||
| func HNSListEndpointRequest() ([]HNSEndpoint, error) { | ||||
| 	var endpoint []HNSEndpoint | ||||
| 	err := hnsCall("GET", "/endpoints/", "", &endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return endpoint, nil | ||||
| 	return hns.HNSListEndpointRequest() | ||||
| } | ||||
|  | ||||
| // HotAttachEndpoint makes a HCS Call to attach the endpoint to the container | ||||
| @@ -120,204 +82,10 @@ func modifyNetworkEndpoint(containerID string, endpointID string, request Reques | ||||
|  | ||||
| // GetHNSEndpointByID get the Endpoint by ID | ||||
| func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { | ||||
| 	return HNSEndpointRequest("GET", endpointID, "") | ||||
| 	return hns.GetHNSEndpointByID(endpointID) | ||||
| } | ||||
|  | ||||
| // GetHNSEndpointByName gets the endpoint filtered by Name | ||||
| func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { | ||||
| 	hnsResponse, err := HNSListEndpointRequest() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, hnsEndpoint := range hnsResponse { | ||||
| 		if hnsEndpoint.Name == endpointName { | ||||
| 			return &hnsEndpoint, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, EndpointNotFoundError{EndpointName: endpointName} | ||||
| } | ||||
|  | ||||
| // Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods | ||||
| func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	jsonString, err := json.Marshal(endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return HNSEndpointRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete Endpoint by sending EndpointRequest to HNS | ||||
| func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	return HNSEndpointRequest("DELETE", endpoint.Id, "") | ||||
| } | ||||
|  | ||||
| // Update Endpoint | ||||
| func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { | ||||
| 	operation := "Update" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	jsonString, err := json.Marshal(endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) | ||||
|  | ||||
| 	return endpoint, err | ||||
| } | ||||
|  | ||||
| // ContainerHotAttach attaches an endpoint to a running container | ||||
| func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { | ||||
| 	operation := "ContainerHotAttach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) | ||||
|  | ||||
| 	return modifyNetworkEndpoint(containerID, endpoint.Id, Add) | ||||
| } | ||||
|  | ||||
| // ContainerHotDetach detaches an endpoint from a running container | ||||
| func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { | ||||
| 	operation := "ContainerHotDetach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) | ||||
|  | ||||
| 	return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) | ||||
| } | ||||
|  | ||||
| // ApplyACLPolicy applies a set of ACL Policies on the Endpoint | ||||
| func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { | ||||
| 	operation := "ApplyACLPolicy" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	for _, policy := range policies { | ||||
| 		if policy == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		jsonString, err := json.Marshal(policy) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		endpoint.Policies = append(endpoint.Policies, jsonString) | ||||
| 	} | ||||
|  | ||||
| 	_, err := endpoint.Update() | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ContainerAttach attaches an endpoint to container | ||||
| func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { | ||||
| 	operation := "ContainerAttach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		ContainerID:   containerID, | ||||
| 		CompartmentID: compartmentID, | ||||
| 		SystemType:    ContainerType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // ContainerDetach detaches an endpoint from container | ||||
| func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { | ||||
| 	operation := "ContainerDetach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		ContainerID: containerID, | ||||
| 		SystemType:  ContainerType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // HostAttach attaches a nic on the host | ||||
| func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { | ||||
| 	operation := "HostAttach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		CompartmentID: compartmentID, | ||||
| 		SystemType:    HostType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
|  | ||||
| } | ||||
|  | ||||
| // HostDetach detaches a nic on the host | ||||
| func (endpoint *HNSEndpoint) HostDetach() error { | ||||
| 	operation := "HostDetach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		SystemType: HostType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // VirtualMachineNICAttach attaches a endpoint to a virtual machine | ||||
| func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { | ||||
| 	operation := "VirtualMachineNicAttach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		VirtualNICName: virtualMachineNICName, | ||||
| 		SystemType:     VirtualMachineType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // VirtualMachineNICDetach detaches a endpoint  from a virtual machine | ||||
| func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { | ||||
| 	operation := "VirtualMachineNicDetach" | ||||
| 	title := "HCSShim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		SystemType: VirtualMachineType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| 	return hns.GetHNSEndpointByName(endpointName) | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								vendor/github.com/Microsoft/hcsshim/hnsglobals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/Microsoft/hcsshim/hnsglobals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| type HNSGlobals = hns.HNSGlobals | ||||
| type HNSVersion = hns.HNSVersion | ||||
|  | ||||
| var ( | ||||
| 	HNSVersion1803 = hns.HNSVersion1803 | ||||
| ) | ||||
|  | ||||
| func GetHNSGlobals() (*HNSGlobals, error) { | ||||
| 	return hns.GetHNSGlobals() | ||||
| } | ||||
							
								
								
									
										121
									
								
								vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,141 +1,36 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| // Subnet is assoicated with a network and represents a list | ||||
| // of subnets available to the network | ||||
| type Subnet struct { | ||||
| 	AddressPrefix  string            `json:",omitempty"` | ||||
| 	GatewayAddress string            `json:",omitempty"` | ||||
| 	Policies       []json.RawMessage `json:",omitempty"` | ||||
| } | ||||
| type Subnet = hns.Subnet | ||||
|  | ||||
| // MacPool is assoicated with a network and represents a list | ||||
| // of macaddresses available to the network | ||||
| type MacPool struct { | ||||
| 	StartMacAddress string `json:",omitempty"` | ||||
| 	EndMacAddress   string `json:",omitempty"` | ||||
| } | ||||
| type MacPool = hns.MacPool | ||||
|  | ||||
| // HNSNetwork represents a network in HNS | ||||
| type HNSNetwork struct { | ||||
| 	Id                   string            `json:"ID,omitempty"` | ||||
| 	Name                 string            `json:",omitempty"` | ||||
| 	Type                 string            `json:",omitempty"` | ||||
| 	NetworkAdapterName   string            `json:",omitempty"` | ||||
| 	SourceMac            string            `json:",omitempty"` | ||||
| 	Policies             []json.RawMessage `json:",omitempty"` | ||||
| 	MacPools             []MacPool         `json:",omitempty"` | ||||
| 	Subnets              []Subnet          `json:",omitempty"` | ||||
| 	DNSSuffix            string            `json:",omitempty"` | ||||
| 	DNSServerList        string            `json:",omitempty"` | ||||
| 	DNSServerCompartment uint32            `json:",omitempty"` | ||||
| 	ManagementIP         string            `json:",omitempty"` | ||||
| 	AutomaticDNS         bool              `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type hnsNetworkResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| 	Output  HNSNetwork | ||||
| } | ||||
|  | ||||
| type hnsResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| 	Output  json.RawMessage | ||||
| } | ||||
| type HNSNetwork = hns.HNSNetwork | ||||
|  | ||||
| // HNSNetworkRequest makes a call into HNS to update/query a single network | ||||
| func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { | ||||
| 	var network HNSNetwork | ||||
| 	err := hnsCall(method, "/networks/"+path, request, &network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &network, nil | ||||
| 	return hns.HNSNetworkRequest(method, path, request) | ||||
| } | ||||
|  | ||||
| // HNSListNetworkRequest makes a HNS call to query the list of available networks | ||||
| func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { | ||||
| 	var network []HNSNetwork | ||||
| 	err := hnsCall(method, "/networks/"+path, request, &network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return network, nil | ||||
| 	return hns.HNSListNetworkRequest(method, path, request) | ||||
| } | ||||
|  | ||||
| // GetHNSNetworkByID | ||||
| func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { | ||||
| 	return HNSNetworkRequest("GET", networkID, "") | ||||
| 	return hns.GetHNSNetworkByID(networkID) | ||||
| } | ||||
|  | ||||
| // GetHNSNetworkName filtered by Name | ||||
| func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { | ||||
| 	hsnnetworks, err := HNSListNetworkRequest("GET", "", "") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, hnsnetwork := range hsnnetworks { | ||||
| 		if hnsnetwork.Name == networkName { | ||||
| 			return &hnsnetwork, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, NetworkNotFoundError{NetworkName: networkName} | ||||
| } | ||||
|  | ||||
| // Create Network by sending NetworkRequest to HNS. | ||||
| func (network *HNSNetwork) Create() (*HNSNetwork, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "HCSShim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
|  | ||||
| 	jsonString, err := json.Marshal(network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return HNSNetworkRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete Network by sending NetworkRequest to HNS | ||||
| func (network *HNSNetwork) Delete() (*HNSNetwork, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "HCSShim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
|  | ||||
| 	return HNSNetworkRequest("DELETE", network.Id, "") | ||||
| } | ||||
|  | ||||
| // Creates an endpoint on the Network. | ||||
| func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { | ||||
| 	return &HNSEndpoint{ | ||||
| 		VirtualNetwork: network.Id, | ||||
| 		IPAddress:      ipAddress, | ||||
| 		MacAddress:     string(macAddress), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { | ||||
| 	operation := "CreateEndpoint" | ||||
| 	title := "HCSShim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) | ||||
|  | ||||
| 	endpoint.VirtualNetwork = network.Id | ||||
| 	return endpoint.Create() | ||||
| } | ||||
|  | ||||
| func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { | ||||
| 	operation := "CreateRemoteEndpoint" | ||||
| 	title := "HCSShim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
| 	endpoint.IsRemoteEndpoint = true | ||||
| 	return network.CreateEndpoint(endpoint) | ||||
| 	return hns.GetHNSNetworkByName(networkName) | ||||
| } | ||||
|   | ||||
							
								
								
									
										107
									
								
								vendor/github.com/Microsoft/hcsshim/hnspolicy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/Microsoft/hcsshim/hnspolicy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,94 +1,57 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| // Type of Request Support in ModifySystem | ||||
| type PolicyType string | ||||
| type PolicyType = hns.PolicyType | ||||
|  | ||||
| // RequestType const | ||||
| const ( | ||||
| 	Nat                  PolicyType = "NAT" | ||||
| 	ACL                  PolicyType = "ACL" | ||||
| 	PA                   PolicyType = "PA" | ||||
| 	VLAN                 PolicyType = "VLAN" | ||||
| 	VSID                 PolicyType = "VSID" | ||||
| 	VNet                 PolicyType = "VNET" | ||||
| 	L2Driver             PolicyType = "L2Driver" | ||||
| 	Isolation            PolicyType = "Isolation" | ||||
| 	QOS                  PolicyType = "QOS" | ||||
| 	OutboundNat          PolicyType = "OutBoundNAT" | ||||
| 	ExternalLoadBalancer PolicyType = "ELB" | ||||
| 	Route                PolicyType = "ROUTE" | ||||
| 	Nat                  = hns.Nat | ||||
| 	ACL                  = hns.ACL | ||||
| 	PA                   = hns.PA | ||||
| 	VLAN                 = hns.VLAN | ||||
| 	VSID                 = hns.VSID | ||||
| 	VNet                 = hns.VNet | ||||
| 	L2Driver             = hns.L2Driver | ||||
| 	Isolation            = hns.Isolation | ||||
| 	QOS                  = hns.QOS | ||||
| 	OutboundNat          = hns.OutboundNat | ||||
| 	ExternalLoadBalancer = hns.ExternalLoadBalancer | ||||
| 	Route                = hns.Route | ||||
| ) | ||||
|  | ||||
| type NatPolicy struct { | ||||
| 	Type         PolicyType `json:"Type"` | ||||
| 	Protocol     string | ||||
| 	InternalPort uint16 | ||||
| 	ExternalPort uint16 | ||||
| } | ||||
| type NatPolicy = hns.NatPolicy | ||||
|  | ||||
| type QosPolicy struct { | ||||
| 	Type                            PolicyType `json:"Type"` | ||||
| 	MaximumOutgoingBandwidthInBytes uint64 | ||||
| } | ||||
| type QosPolicy = hns.QosPolicy | ||||
|  | ||||
| type IsolationPolicy struct { | ||||
| 	Type               PolicyType `json:"Type"` | ||||
| 	VLAN               uint | ||||
| 	VSID               uint | ||||
| 	InDefaultIsolation bool | ||||
| } | ||||
| type IsolationPolicy = hns.IsolationPolicy | ||||
|  | ||||
| type VlanPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	VLAN uint | ||||
| } | ||||
| type VlanPolicy = hns.VlanPolicy | ||||
|  | ||||
| type VsidPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	VSID uint | ||||
| } | ||||
| type VsidPolicy = hns.VsidPolicy | ||||
|  | ||||
| type PaPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	PA   string     `json:"PA"` | ||||
| } | ||||
| type PaPolicy = hns.PaPolicy | ||||
|  | ||||
| type OutboundNatPolicy struct { | ||||
| 	Policy | ||||
| 	VIP        string   `json:"VIP,omitempty"` | ||||
| 	Exceptions []string `json:"ExceptionList,omitempty"` | ||||
| } | ||||
| type OutboundNatPolicy = hns.OutboundNatPolicy | ||||
|  | ||||
| type ActionType string | ||||
| type DirectionType string | ||||
| type RuleType string | ||||
| type ActionType = hns.ActionType | ||||
| type DirectionType = hns.DirectionType | ||||
| type RuleType = hns.RuleType | ||||
|  | ||||
| const ( | ||||
| 	Allow ActionType = "Allow" | ||||
| 	Block ActionType = "Block" | ||||
| 	Allow = hns.Allow | ||||
| 	Block = hns.Block | ||||
|  | ||||
| 	In  DirectionType = "In" | ||||
| 	Out DirectionType = "Out" | ||||
| 	In  = hns.In | ||||
| 	Out = hns.Out | ||||
|  | ||||
| 	Host   RuleType = "Host" | ||||
| 	Switch RuleType = "Switch" | ||||
| 	Host   = hns.Host | ||||
| 	Switch = hns.Switch | ||||
| ) | ||||
|  | ||||
| type ACLPolicy struct { | ||||
| 	Type            PolicyType `json:"Type"` | ||||
| 	Protocol        uint16 | ||||
| 	InternalPort    uint16 | ||||
| 	Action          ActionType | ||||
| 	Direction       DirectionType | ||||
| 	LocalAddresses  string | ||||
| 	RemoteAddresses string | ||||
| 	LocalPort       uint16 | ||||
| 	RemotePort      uint16 | ||||
| 	RuleType        RuleType `json:"RuleType,omitempty"` | ||||
| 	Priority        uint16 | ||||
| 	ServiceName     string | ||||
| } | ||||
| type ACLPolicy = hns.ACLPolicy | ||||
|  | ||||
| type Policy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| } | ||||
| type Policy = hns.Policy | ||||
|   | ||||
							
								
								
									
										175
									
								
								vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										175
									
								
								vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,200 +1,47 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| // RoutePolicy is a structure defining schema for Route based Policy | ||||
| type RoutePolicy struct { | ||||
| 	Policy | ||||
| 	DestinationPrefix string `json:"DestinationPrefix,omitempty"` | ||||
| 	NextHop           string `json:"NextHop,omitempty"` | ||||
| 	EncapEnabled      bool   `json:"NeedEncap,omitempty"` | ||||
| } | ||||
| type RoutePolicy = hns.RoutePolicy | ||||
|  | ||||
| // ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy | ||||
| type ELBPolicy struct { | ||||
| 	LBPolicy | ||||
| 	SourceVIP string   `json:"SourceVIP,omitempty"` | ||||
| 	VIPs      []string `json:"VIPs,omitempty"` | ||||
| 	ILB       bool     `json:"ILB,omitempty"` | ||||
| } | ||||
| type ELBPolicy = hns.ELBPolicy | ||||
|  | ||||
| // LBPolicy is a structure defining schema for LoadBalancing based Policy | ||||
| type LBPolicy struct { | ||||
| 	Policy | ||||
| 	Protocol     uint16 `json:"Protocol,omitempty"` | ||||
| 	InternalPort uint16 | ||||
| 	ExternalPort uint16 | ||||
| } | ||||
| type LBPolicy = hns.LBPolicy | ||||
|  | ||||
| // PolicyList is a structure defining schema for Policy list request | ||||
| type PolicyList struct { | ||||
| 	ID                 string            `json:"ID,omitempty"` | ||||
| 	EndpointReferences []string          `json:"References,omitempty"` | ||||
| 	Policies           []json.RawMessage `json:"Policies,omitempty"` | ||||
| } | ||||
| type PolicyList = hns.PolicyList | ||||
|  | ||||
| // HNSPolicyListRequest makes a call into HNS to update/query a single network | ||||
| func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { | ||||
| 	var policy PolicyList | ||||
| 	err := hnsCall(method, "/policylists/"+path, request, &policy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &policy, nil | ||||
| 	return hns.HNSPolicyListRequest(method, path, request) | ||||
| } | ||||
|  | ||||
| // HNSListPolicyListRequest gets all the policy list | ||||
| func HNSListPolicyListRequest() ([]PolicyList, error) { | ||||
| 	var plist []PolicyList | ||||
| 	err := hnsCall("GET", "/policylists/", "", &plist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return plist, nil | ||||
| 	return hns.HNSListPolicyListRequest() | ||||
| } | ||||
|  | ||||
| // PolicyListRequest makes a HNS call to modify/query a network policy list | ||||
| func PolicyListRequest(method, path, request string) (*PolicyList, error) { | ||||
| 	policylist := &PolicyList{} | ||||
| 	err := hnsCall(method, "/policylists/"+path, request, &policylist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return policylist, nil | ||||
| 	return hns.PolicyListRequest(method, path, request) | ||||
| } | ||||
|  | ||||
| // GetPolicyListByID get the policy list by ID | ||||
| func GetPolicyListByID(policyListID string) (*PolicyList, error) { | ||||
| 	return PolicyListRequest("GET", policyListID, "") | ||||
| } | ||||
|  | ||||
| // Create PolicyList by sending PolicyListRequest to HNS. | ||||
| func (policylist *PolicyList) Create() (*PolicyList, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", policylist.ID) | ||||
| 	jsonString, err := json.Marshal(policylist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return PolicyListRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete deletes PolicyList | ||||
| func (policylist *PolicyList) Delete() (*PolicyList, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", policylist.ID) | ||||
|  | ||||
| 	return PolicyListRequest("DELETE", policylist.ID, "") | ||||
| } | ||||
|  | ||||
| // AddEndpoint add an endpoint to a Policy List | ||||
| func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { | ||||
| 	operation := "AddEndpoint" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) | ||||
|  | ||||
| 	_, err := policylist.Delete() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Add Endpoint to the Existing List | ||||
| 	policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
|  | ||||
| 	return policylist.Create() | ||||
| } | ||||
|  | ||||
| // RemoveEndpoint removes an endpoint from the Policy List | ||||
| func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { | ||||
| 	operation := "RemoveEndpoint" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) | ||||
|  | ||||
| 	_, err := policylist.Delete() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	elementToRemove := "/endpoints/" + endpoint.Id | ||||
|  | ||||
| 	var references []string | ||||
|  | ||||
| 	for _, endpointReference := range policylist.EndpointReferences { | ||||
| 		if endpointReference == elementToRemove { | ||||
| 			continue | ||||
| 		} | ||||
| 		references = append(references, endpointReference) | ||||
| 	} | ||||
| 	policylist.EndpointReferences = references | ||||
| 	return policylist.Create() | ||||
| 	return hns.GetPolicyListByID(policyListID) | ||||
| } | ||||
|  | ||||
| // AddLoadBalancer policy list for the specified endpoints | ||||
| func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { | ||||
| 	operation := "AddLoadBalancer" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) | ||||
|  | ||||
| 	policylist := &PolicyList{} | ||||
|  | ||||
| 	elbPolicy := &ELBPolicy{ | ||||
| 		SourceVIP: sourceVIP, | ||||
| 		ILB:       isILB, | ||||
| 	} | ||||
|  | ||||
| 	if len(vip) > 0 { | ||||
| 		elbPolicy.VIPs = []string{vip} | ||||
| 	} | ||||
| 	elbPolicy.Type = ExternalLoadBalancer | ||||
| 	elbPolicy.Protocol = protocol | ||||
| 	elbPolicy.InternalPort = internalPort | ||||
| 	elbPolicy.ExternalPort = externalPort | ||||
|  | ||||
| 	for _, endpoint := range endpoints { | ||||
| 		policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
| 	} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(elbPolicy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	policylist.Policies = append(policylist.Policies, jsonString) | ||||
| 	return policylist.Create() | ||||
| 	return hns.AddLoadBalancer(endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) | ||||
| } | ||||
|  | ||||
| // AddRoute adds route policy list for the specified endpoints | ||||
| func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { | ||||
| 	operation := "AddRoute" | ||||
| 	title := "HCSShim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) | ||||
|  | ||||
| 	policylist := &PolicyList{} | ||||
|  | ||||
| 	rPolicy := &RoutePolicy{ | ||||
| 		DestinationPrefix: destinationPrefix, | ||||
| 		NextHop:           nextHop, | ||||
| 		EncapEnabled:      encapEnabled, | ||||
| 	} | ||||
| 	rPolicy.Type = Route | ||||
|  | ||||
| 	for _, endpoint := range endpoints { | ||||
| 		policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
| 	} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(rPolicy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	policylist.Policies = append(policylist.Policies, jsonString) | ||||
| 	return policylist.Create() | ||||
| 	return hns.AddRoute(endpoints, destinationPrefix, nextHop, encapEnabled) | ||||
| } | ||||
|   | ||||
							
								
								
									
										13
									
								
								vendor/github.com/Microsoft/hcsshim/hnssupport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/Microsoft/hcsshim/hnssupport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hns" | ||||
| ) | ||||
|  | ||||
| type HNSSupportedFeatures = hns.HNSSupportedFeatures | ||||
|  | ||||
| type HNSAclFeatures = hns.HNSAclFeatures | ||||
|  | ||||
| func GetHNSSupportedFeatures() HNSSupportedFeatures { | ||||
| 	return hns.GetHNSSupportedFeatures() | ||||
| } | ||||
							
								
								
									
										135
									
								
								vendor/github.com/Microsoft/hcsshim/interface.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										135
									
								
								vendor/github.com/Microsoft/hcsshim/interface.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,142 +1,27 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/schema1" | ||||
| ) | ||||
|  | ||||
| // RegistryKey is used to specify registry key name | ||||
| type RegistryKey struct { | ||||
| 	Hive     string | ||||
| 	Name     string | ||||
| 	Volatile bool `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // RegistryKey is used to specify registry key name | ||||
| type RegistryValue struct { | ||||
| 	Key         RegistryKey | ||||
| 	Name        string | ||||
| 	Type        string | ||||
| 	StringValue string  `json:",omitempty"` | ||||
| 	BinaryValue []byte  `json:",omitempty"` | ||||
| 	DWordValue  *uint32 `json:",omitempty"` | ||||
| 	QWordValue  *uint64 `json:",omitempty"` | ||||
| 	CustomType  *uint32 `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type RegistryChanges struct { | ||||
| 	AddValues  []RegistryValue `json:",omitempty"` | ||||
| 	DeleteKeys []RegistryValue `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // ProcessConfig is used as both the input of Container.CreateProcess | ||||
| // and to convert the parameters to JSON for passing onto the HCS | ||||
| type ProcessConfig struct { | ||||
| 	ApplicationName   string            `json:",omitempty"` | ||||
| 	CommandLine       string            `json:",omitempty"` | ||||
| 	CommandArgs       []string          `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| 	User              string            `json:",omitempty"` | ||||
| 	WorkingDirectory  string            `json:",omitempty"` | ||||
| 	Environment       map[string]string `json:",omitempty"` | ||||
| 	EmulateConsole    bool              `json:",omitempty"` | ||||
| 	CreateStdInPipe   bool              `json:",omitempty"` | ||||
| 	CreateStdOutPipe  bool              `json:",omitempty"` | ||||
| 	CreateStdErrPipe  bool              `json:",omitempty"` | ||||
| 	ConsoleSize       [2]uint           `json:",omitempty"` | ||||
| 	CreateInUtilityVm bool              `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| 	OCISpecification  *json.RawMessage  `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| } | ||||
| type ProcessConfig = schema1.ProcessConfig | ||||
|  | ||||
| type Layer struct { | ||||
| 	ID   string | ||||
| 	Path string | ||||
| } | ||||
|  | ||||
| type MappedDir struct { | ||||
| 	HostPath          string | ||||
| 	ContainerPath     string | ||||
| 	ReadOnly          bool | ||||
| 	BandwidthMaximum  uint64 | ||||
| 	IOPSMaximum       uint64 | ||||
| 	CreateInUtilityVM bool | ||||
| 	// LinuxMetadata - Support added in 1803/RS4+. | ||||
| 	LinuxMetadata bool `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type MappedPipe struct { | ||||
| 	HostPath          string | ||||
| 	ContainerPipeName string | ||||
| } | ||||
|  | ||||
| type HvRuntime struct { | ||||
| 	ImagePath           string `json:",omitempty"` | ||||
| 	SkipTemplate        bool   `json:",omitempty"` | ||||
| 	LinuxInitrdFile     string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM | ||||
| 	LinuxKernelFile     string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM | ||||
| 	LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode | ||||
| 	BootSource          string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD | ||||
| 	WritableBootSource  bool   `json:",omitempty"` // Linux Utility VM booting from VHD | ||||
| } | ||||
|  | ||||
| type MappedVirtualDisk struct { | ||||
| 	HostPath          string `json:",omitempty"` // Path to VHD on the host | ||||
| 	ContainerPath     string // Platform-specific mount point path in the container | ||||
| 	CreateInUtilityVM bool   `json:",omitempty"` | ||||
| 	ReadOnly          bool   `json:",omitempty"` | ||||
| 	Cache             string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing" | ||||
| 	AttachOnly        bool   `json:",omitempty:` | ||||
| } | ||||
|  | ||||
| // AssignedDevice represents a device that has been directly assigned to a container | ||||
| // | ||||
| // NOTE: Support added in RS5 | ||||
| type AssignedDevice struct { | ||||
| 	//  InterfaceClassGUID of the device to assign to container. | ||||
| 	InterfaceClassGUID string `json:"InterfaceClassGuid,omitempty"` | ||||
| } | ||||
| type Layer = schema1.Layer | ||||
| type MappedDir = schema1.MappedDir | ||||
| type MappedPipe = schema1.MappedPipe | ||||
| type HvRuntime = schema1.HvRuntime | ||||
| type MappedVirtualDisk = schema1.MappedVirtualDisk | ||||
|  | ||||
| // ContainerConfig is used as both the input of CreateContainer | ||||
| // and to convert the parameters to JSON for passing onto the HCS | ||||
| type ContainerConfig struct { | ||||
| 	SystemType                  string              // HCS requires this to be hard-coded to "Container" | ||||
| 	Name                        string              // Name of the container. We use the docker ID. | ||||
| 	Owner                       string              `json:",omitempty"` // The management platform that created this container | ||||
| 	VolumePath                  string              `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID} | ||||
| 	IgnoreFlushesDuringBoot     bool                `json:",omitempty"` // Optimization hint for container startup in Windows | ||||
| 	LayerFolderPath             string              `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format  %root%\windowsfilter\containerID | ||||
| 	Layers                      []Layer             // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID | ||||
| 	Credentials                 string              `json:",omitempty"` // Credentials information | ||||
| 	ProcessorCount              uint32              `json:",omitempty"` // Number of processors to assign to the container. | ||||
| 	ProcessorWeight             uint64              `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares. | ||||
| 	ProcessorMaximum            int64               `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit. | ||||
| 	StorageIOPSMaximum          uint64              `json:",omitempty"` // Maximum Storage IOPS | ||||
| 	StorageBandwidthMaximum     uint64              `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second | ||||
| 	StorageSandboxSize          uint64              `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller | ||||
| 	MemoryMaximumInMB           int64               `json:",omitempty"` // Maximum memory available to the container in Megabytes | ||||
| 	HostName                    string              `json:",omitempty"` // Hostname | ||||
| 	MappedDirectories           []MappedDir         `json:",omitempty"` // List of mapped directories (volumes/mounts) | ||||
| 	MappedPipes                 []MappedPipe        `json:",omitempty"` // List of mapped Windows named pipes | ||||
| 	HvPartition                 bool                // True if it a Hyper-V Container | ||||
| 	NetworkSharedContainerName  string              `json:",omitempty"` // Name (ID) of the container that we will share the network stack with. | ||||
| 	EndpointList                []string            `json:",omitempty"` // List of networking endpoints to be attached to container | ||||
| 	HvRuntime                   *HvRuntime          `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM | ||||
| 	Servicing                   bool                `json:",omitempty"` // True if this container is for servicing | ||||
| 	AllowUnqualifiedDNSQuery    bool                `json:",omitempty"` // True to allow unqualified DNS name resolution | ||||
| 	DNSSearchList               string              `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution | ||||
| 	ContainerType               string              `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise. | ||||
| 	TerminateOnLastHandleClosed bool                `json:",omitempty"` // Should HCS terminate the container once all handles have been closed | ||||
| 	MappedVirtualDisks          []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start | ||||
| 	AssignedDevices             []AssignedDevice    `json:",omitempty"` // Array of devices to assign. NOTE: Support added in RS5 | ||||
| 	RegistryChanges             *RegistryChanges    `json:",omitempty"` // Registry changes to be applied to the container | ||||
| } | ||||
| type ContainerConfig = schema1.ContainerConfig | ||||
|  | ||||
| type ComputeSystemQuery struct { | ||||
| 	IDs    []string `json:"Ids,omitempty"` | ||||
| 	Types  []string `json:",omitempty"` | ||||
| 	Names  []string `json:",omitempty"` | ||||
| 	Owners []string `json:",omitempty"` | ||||
| } | ||||
| type ComputeSystemQuery = schema1.ComputeSystemQuery | ||||
|  | ||||
| // Container represents a created (but not necessarily running) container. | ||||
| type Container interface { | ||||
|   | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package guid | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| type GUID [16]byte | ||||
|  | ||||
| func New() GUID { | ||||
| 	g := GUID{} | ||||
| 	_, err := io.ReadFull(rand.Reader, g[:]) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return g | ||||
| } | ||||
|  | ||||
| func (g GUID) String() string { | ||||
| 	return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:]) | ||||
| } | ||||
| @@ -1,8 +1,10 @@ | ||||
| package hcsshim | ||||
| package hcs | ||||
| 
 | ||||
| import ( | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| @@ -62,7 +64,7 @@ func closeChannels(channels notificationChannels) { | ||||
| func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { | ||||
| 	var result error | ||||
| 	if int32(notificationStatus) < 0 { | ||||
| 		result = syscall.Errno(win32FromHresult(notificationStatus)) | ||||
| 		result = interop.Win32FromHresult(notificationStatus) | ||||
| 	} | ||||
| 
 | ||||
| 	callbackMapLock.RLock() | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package hcs | ||||
| 
 | ||||
| import "C" | ||||
| 
 | ||||
							
								
								
									
										279
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,279 @@ | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists | ||||
| 	ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e) | ||||
|  | ||||
| 	// ErrElementNotFound is an error encountered when the object being referenced does not exist | ||||
| 	ErrElementNotFound = syscall.Errno(0x490) | ||||
|  | ||||
| 	// ErrElementNotFound is an error encountered when the object being referenced does not exist | ||||
| 	ErrNotSupported = syscall.Errno(0x32) | ||||
|  | ||||
| 	// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported | ||||
| 	// decimal -2147024883 / hex 0x8007000d | ||||
| 	ErrInvalidData = syscall.Errno(0xd) | ||||
|  | ||||
| 	// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed | ||||
| 	ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed") | ||||
|  | ||||
| 	// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method | ||||
| 	ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed") | ||||
|  | ||||
| 	// ErrInvalidNotificationType is an error encountered when an invalid notification type is used | ||||
| 	ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type") | ||||
|  | ||||
| 	// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation | ||||
| 	ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") | ||||
|  | ||||
| 	// ErrTimeout is an error encountered when waiting on a notification times out | ||||
| 	ErrTimeout = errors.New("hcsshim: timeout waiting for notification") | ||||
|  | ||||
| 	// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for | ||||
| 	// a different expected notification | ||||
| 	ErrUnexpectedContainerExit = errors.New("unexpected container exit") | ||||
|  | ||||
| 	// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service | ||||
| 	// is lost while waiting for a notification | ||||
| 	ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") | ||||
|  | ||||
| 	// ErrUnexpectedValue is an error encountered when hcs returns an invalid value | ||||
| 	ErrUnexpectedValue = errors.New("unexpected value returned from hcs") | ||||
|  | ||||
| 	// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container | ||||
| 	ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110) | ||||
|  | ||||
| 	// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously | ||||
| 	ErrVmcomputeOperationPending = syscall.Errno(0xC0370103) | ||||
|  | ||||
| 	// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation | ||||
| 	ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105) | ||||
|  | ||||
| 	// ErrProcNotFound is an error encountered when the the process cannot be found | ||||
| 	ErrProcNotFound = syscall.Errno(0x7f) | ||||
|  | ||||
| 	// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2 | ||||
| 	// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3. | ||||
| 	ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5) | ||||
|  | ||||
| 	// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management | ||||
| 	ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d) | ||||
|  | ||||
| 	// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message | ||||
| 	ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b) | ||||
|  | ||||
| 	// ErrNotSupported is an error encountered when hcs doesn't support the request | ||||
| 	ErrPlatformNotSupported = errors.New("unsupported platform request") | ||||
| ) | ||||
|  | ||||
| type ErrorEvent struct { | ||||
| 	Message    string `json:"Message,omitempty"`    // Fully formated error message | ||||
| 	StackTrace string `json:"StackTrace,omitempty"` // Stack trace in string form | ||||
| 	Provider   string `json:"Provider,omitempty"` | ||||
| 	EventID    uint16 `json:"EventId,omitempty"` | ||||
| 	Flags      uint32 `json:"Flags,omitempty"` | ||||
| 	Source     string `json:"Source,omitempty"` | ||||
| 	//Data       []EventData `json:"Data,omitempty"`  // Omit this as HCS doesn't encode this well. It's more confusing to include. It is however logged in debug mode (see processHcsResult function) | ||||
| } | ||||
|  | ||||
| type hcsResult struct { | ||||
| 	Error        int32 | ||||
| 	ErrorMessage string | ||||
| 	ErrorEvents  []ErrorEvent `json:"ErrorEvents,omitempty"` | ||||
| } | ||||
|  | ||||
| func (ev *ErrorEvent) String() string { | ||||
| 	evs := "[Event Detail: " + ev.Message | ||||
| 	if ev.StackTrace != "" { | ||||
| 		evs += " Stack Trace: " + ev.StackTrace | ||||
| 	} | ||||
| 	if ev.Provider != "" { | ||||
| 		evs += " Provider: " + ev.Provider | ||||
| 	} | ||||
| 	if ev.EventID != 0 { | ||||
| 		evs = fmt.Sprintf("%s EventID: %d", evs, ev.EventID) | ||||
| 	} | ||||
| 	if ev.Flags != 0 { | ||||
| 		evs = fmt.Sprintf("%s flags: %d", evs, ev.Flags) | ||||
| 	} | ||||
| 	if ev.Source != "" { | ||||
| 		evs += " Source: " + ev.Source | ||||
| 	} | ||||
| 	evs += "]" | ||||
| 	return evs | ||||
| } | ||||
|  | ||||
| func processHcsResult(resultp *uint16) []ErrorEvent { | ||||
| 	if resultp != nil { | ||||
| 		resultj := interop.ConvertAndFreeCoTaskMemString(resultp) | ||||
| 		logrus.Debugf("Result: %s", resultj) | ||||
| 		result := &hcsResult{} | ||||
| 		if err := json.Unmarshal([]byte(resultj), result); err != nil { | ||||
| 			logrus.Warnf("Could not unmarshal HCS result %s: %s", resultj, err) | ||||
| 			return nil | ||||
| 		} | ||||
| 		return result.ErrorEvents | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type HcsError struct { | ||||
| 	Op     string | ||||
| 	Err    error | ||||
| 	Events []ErrorEvent | ||||
| } | ||||
|  | ||||
| func (e *HcsError) Error() string { | ||||
| 	s := e.Op + ": " + e.Err.Error() | ||||
| 	for _, ev := range e.Events { | ||||
| 		s += "\n" + ev.String() | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // ProcessError is an error encountered in HCS during an operation on a Process object | ||||
| type ProcessError struct { | ||||
| 	SystemID string | ||||
| 	Pid      int | ||||
| 	Op       string | ||||
| 	Err      error | ||||
| 	Events   []ErrorEvent | ||||
| } | ||||
|  | ||||
| // SystemError is an error encountered in HCS during an operation on a Container object | ||||
| type SystemError struct { | ||||
| 	ID     string | ||||
| 	Op     string | ||||
| 	Err    error | ||||
| 	Extra  string | ||||
| 	Events []ErrorEvent | ||||
| } | ||||
|  | ||||
| func (e *SystemError) Error() string { | ||||
| 	s := e.Op + " " + e.ID + ": " + e.Err.Error() | ||||
| 	for _, ev := range e.Events { | ||||
| 		s += "\n" + ev.String() | ||||
| 	} | ||||
| 	if e.Extra != "" { | ||||
| 		s += "\n(extra info: " + e.Extra + ")" | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error { | ||||
| 	// Don't double wrap errors | ||||
| 	if _, ok := err.(*SystemError); ok { | ||||
| 		return err | ||||
| 	} | ||||
| 	return &SystemError{ | ||||
| 		ID:     system.ID(), | ||||
| 		Op:     op, | ||||
| 		Extra:  extra, | ||||
| 		Err:    err, | ||||
| 		Events: events, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e *ProcessError) Error() string { | ||||
| 	s := fmt.Sprintf("%s %s:%d: %s", e.Op, e.SystemID, e.Pid, e.Err.Error()) | ||||
| 	for _, ev := range e.Events { | ||||
| 		s += "\n" + ev.String() | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error { | ||||
| 	// Don't double wrap errors | ||||
| 	if _, ok := err.(*ProcessError); ok { | ||||
| 		return err | ||||
| 	} | ||||
| 	return &ProcessError{ | ||||
| 		Pid:      process.Pid(), | ||||
| 		SystemID: process.SystemID(), | ||||
| 		Op:       op, | ||||
| 		Err:      err, | ||||
| 		Events:   events, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // IsNotExist checks if an error is caused by the Container or Process not existing. | ||||
| // Note: Currently, ErrElementNotFound can mean that a Process has either | ||||
| // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist | ||||
| // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. | ||||
| func IsNotExist(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrComputeSystemDoesNotExist || | ||||
| 		err == ErrElementNotFound || | ||||
| 		err == ErrProcNotFound | ||||
| } | ||||
|  | ||||
| // IsAlreadyClosed checks if an error is caused by the Container or Process having been | ||||
| // already closed by a call to the Close() method. | ||||
| func IsAlreadyClosed(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrAlreadyClosed | ||||
| } | ||||
|  | ||||
| // IsPending returns a boolean indicating whether the error is that | ||||
| // the requested operation is being completed in the background. | ||||
| func IsPending(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrVmcomputeOperationPending | ||||
| } | ||||
|  | ||||
| // IsTimeout returns a boolean indicating whether the error is caused by | ||||
| // a timeout waiting for the operation to complete. | ||||
| func IsTimeout(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrTimeout | ||||
| } | ||||
|  | ||||
| // IsAlreadyStopped returns a boolean indicating whether the error is caused by | ||||
| // a Container or Process being already stopped. | ||||
| // Note: Currently, ErrElementNotFound can mean that a Process has either | ||||
| // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist | ||||
| // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. | ||||
| func IsAlreadyStopped(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	return err == ErrVmcomputeAlreadyStopped || | ||||
| 		err == ErrElementNotFound || | ||||
| 		err == ErrProcNotFound | ||||
| } | ||||
|  | ||||
| // IsNotSupported returns a boolean indicating whether the error is caused by | ||||
| // unsupported platform requests | ||||
| // Note: Currently Unsupported platform requests can be mean either | ||||
| // ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage | ||||
| // is thrown from the Platform | ||||
| func IsNotSupported(err error) bool { | ||||
| 	err = getInnerError(err) | ||||
| 	// If Platform doesn't recognize or support the request sent, below errors are seen | ||||
| 	return err == ErrVmcomputeInvalidJSON || | ||||
| 		err == ErrInvalidData || | ||||
| 		err == ErrNotSupported || | ||||
| 		err == ErrVmcomputeUnknownMessage | ||||
| } | ||||
|  | ||||
| func getInnerError(err error) error { | ||||
| 	switch pe := err.(type) { | ||||
| 	case nil: | ||||
| 		return nil | ||||
| 	case *HcsError: | ||||
| 		err = pe.Err | ||||
| 	case *SystemError: | ||||
| 		err = pe.Err | ||||
| 	case *ProcessError: | ||||
| 		err = pe.Err | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										47
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/hcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/hcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| // Shim for the Host Compute Service (HCS) to manage Windows Server | ||||
| // containers and Hyper-V containers. | ||||
|  | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| //go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hcs.go | ||||
|  | ||||
| //sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems? | ||||
| //sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem? | ||||
| //sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem? | ||||
| //sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem? | ||||
| //sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem? | ||||
| //sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem? | ||||
| //sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem? | ||||
| //sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem? | ||||
| //sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem? | ||||
| //sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties? | ||||
| //sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem? | ||||
| //sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback? | ||||
| //sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback? | ||||
|  | ||||
| //sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess? | ||||
| //sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess? | ||||
| //sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess? | ||||
| //sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess? | ||||
| //sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo? | ||||
| //sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties? | ||||
| //sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess? | ||||
| //sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties? | ||||
| //sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback? | ||||
| //sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback? | ||||
|  | ||||
| type hcsSystem syscall.Handle | ||||
| type hcsProcess syscall.Handle | ||||
| type hcsCallback syscall.Handle | ||||
|  | ||||
| type hcsProcessInformation struct { | ||||
| 	ProcessId uint32 | ||||
| 	Reserved  uint32 | ||||
| 	StdInput  syscall.Handle | ||||
| 	StdOutput syscall.Handle | ||||
| 	StdError  syscall.Handle | ||||
| } | ||||
							
								
								
									
										386
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,386 @@ | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // ContainerError is an error encountered in HCS | ||||
| type Process struct { | ||||
| 	handleLock     sync.RWMutex | ||||
| 	handle         hcsProcess | ||||
| 	processID      int | ||||
| 	system         *System | ||||
| 	cachedPipes    *cachedPipes | ||||
| 	callbackNumber uintptr | ||||
| } | ||||
|  | ||||
| type cachedPipes struct { | ||||
| 	stdIn  syscall.Handle | ||||
| 	stdOut syscall.Handle | ||||
| 	stdErr syscall.Handle | ||||
| } | ||||
|  | ||||
| type processModifyRequest struct { | ||||
| 	Operation   string | ||||
| 	ConsoleSize *consoleSize `json:",omitempty"` | ||||
| 	CloseHandle *closeHandle `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type consoleSize struct { | ||||
| 	Height uint16 | ||||
| 	Width  uint16 | ||||
| } | ||||
|  | ||||
| type closeHandle struct { | ||||
| 	Handle string | ||||
| } | ||||
|  | ||||
| type ProcessStatus struct { | ||||
| 	ProcessID      uint32 | ||||
| 	Exited         bool | ||||
| 	ExitCode       uint32 | ||||
| 	LastWaitResult int32 | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	stdIn  string = "StdIn" | ||||
| 	stdOut string = "StdOut" | ||||
| 	stdErr string = "StdErr" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	modifyConsoleSize string = "ConsoleSize" | ||||
| 	modifyCloseHandle string = "CloseHandle" | ||||
| ) | ||||
|  | ||||
| // Pid returns the process ID of the process within the container. | ||||
| func (process *Process) Pid() int { | ||||
| 	return process.processID | ||||
| } | ||||
|  | ||||
| // SystemID returns the ID of the process's compute system. | ||||
| func (process *Process) SystemID() string { | ||||
| 	return process.system.ID() | ||||
| } | ||||
|  | ||||
| // Kill signals the process to terminate but does not wait for it to finish terminating. | ||||
| func (process *Process) Kill() error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "Kill" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsTerminateProcess(process.handle, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Wait waits for the process to exit. | ||||
| func (process *Process) Wait() error { | ||||
| 	operation := "Wait" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // WaitTimeout waits for the process to exit or the duration to elapse. It returns | ||||
| // false if timeout occurs. | ||||
| func (process *Process) WaitTimeout(timeout time.Duration) error { | ||||
| 	operation := "WaitTimeout" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ResizeConsole resizes the console of the process. | ||||
| func (process *Process) ResizeConsole(width, height uint16) error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "ResizeConsole" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	modifyRequest := processModifyRequest{ | ||||
| 		Operation: modifyConsoleSize, | ||||
| 		ConsoleSize: &consoleSize{ | ||||
| 			Height: height, | ||||
| 			Width:  width, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestb, err := json.Marshal(modifyRequest) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) Properties() (*ProcessStatus, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "Properties" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		resultp     *uint16 | ||||
| 		propertiesp *uint16 | ||||
| 	) | ||||
| 	err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	if propertiesp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp) | ||||
|  | ||||
| 	properties := &ProcessStatus{} | ||||
| 	if err := json.Unmarshal(propertiesRaw, properties); err != nil { | ||||
| 		return nil, makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw) | ||||
| 	return properties, nil | ||||
| } | ||||
|  | ||||
| // ExitCode returns the exit code of the process. The process must have | ||||
| // already terminated. | ||||
| func (process *Process) ExitCode() (int, error) { | ||||
| 	operation := "ExitCode" | ||||
| 	properties, err := process.Properties() | ||||
| 	if err != nil { | ||||
| 		return 0, makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	if properties.Exited == false { | ||||
| 		return 0, makeProcessError(process, operation, ErrInvalidProcessState, nil) | ||||
| 	} | ||||
|  | ||||
| 	if properties.LastWaitResult != 0 { | ||||
| 		return 0, makeProcessError(process, operation, syscall.Errno(properties.LastWaitResult), nil) | ||||
| 	} | ||||
|  | ||||
| 	return int(properties.ExitCode), nil | ||||
| } | ||||
|  | ||||
| // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing | ||||
| // these pipes does not close the underlying pipes; it should be possible to | ||||
| // call this multiple times to get multiple interfaces. | ||||
| func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "Stdio" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var stdIn, stdOut, stdErr syscall.Handle | ||||
|  | ||||
| 	if process.cachedPipes == nil { | ||||
| 		var ( | ||||
| 			processInfo hcsProcessInformation | ||||
| 			resultp     *uint16 | ||||
| 		) | ||||
| 		err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) | ||||
| 		events := processHcsResult(resultp) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, makeProcessError(process, operation, err, events) | ||||
| 		} | ||||
|  | ||||
| 		stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError | ||||
| 	} else { | ||||
| 		// Use cached pipes | ||||
| 		stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr | ||||
|  | ||||
| 		// Invalidate the cache | ||||
| 		process.cachedPipes = nil | ||||
| 	} | ||||
|  | ||||
| 	pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return pipes[0], pipes[1], pipes[2], nil | ||||
| } | ||||
|  | ||||
| // CloseStdin closes the write side of the stdin pipe so that the process is | ||||
| // notified on the read side that there is no more data in stdin. | ||||
| func (process *Process) CloseStdin() error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "CloseStdin" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	modifyRequest := processModifyRequest{ | ||||
| 		Operation: modifyCloseHandle, | ||||
| 		CloseHandle: &closeHandle{ | ||||
| 			Handle: stdIn, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestb, err := json.Marshal(modifyRequest) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Close cleans up any state associated with the process but does not kill | ||||
| // or wait on it. | ||||
| func (process *Process) Close() error { | ||||
| 	process.handleLock.Lock() | ||||
| 	defer process.handleLock.Unlock() | ||||
| 	operation := "Close" | ||||
| 	title := "hcsshim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	// Don't double free this | ||||
| 	if process.handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if err := process.unregisterCallback(); err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	if err := hcsCloseProcess(process.handle); err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	process.handle = 0 | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) registerCallback() error { | ||||
| 	context := ¬ifcationWatcherContext{ | ||||
| 		channels: newChannels(), | ||||
| 	} | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackNumber := nextCallback | ||||
| 	nextCallback++ | ||||
| 	callbackMap[callbackNumber] = context | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	var callbackHandle hcsCallback | ||||
| 	err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	context.handle = callbackHandle | ||||
| 	process.callbackNumber = callbackNumber | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) unregisterCallback() error { | ||||
| 	callbackNumber := process.callbackNumber | ||||
|  | ||||
| 	callbackMapLock.RLock() | ||||
| 	context := callbackMap[callbackNumber] | ||||
| 	callbackMapLock.RUnlock() | ||||
|  | ||||
| 	if context == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	handle := context.handle | ||||
|  | ||||
| 	if handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// hcsUnregisterProcessCallback has its own syncronization | ||||
| 	// to wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := hcsUnregisterProcessCallback(handle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	closeChannels(context.channels) | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackMap[callbackNumber] = nil | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	handle = 0 | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										547
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										547
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,547 @@ | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/Microsoft/hcsshim/internal/schema1" | ||||
| 	"github.com/Microsoft/hcsshim/internal/timeout" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // currentContainerStarts is used to limit the number of concurrent container | ||||
| // starts. | ||||
| var currentContainerStarts containerStarts | ||||
|  | ||||
| type containerStarts struct { | ||||
| 	maxParallel int | ||||
| 	inProgress  int | ||||
| 	sync.Mutex | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	mpsS := os.Getenv("HCSSHIM_MAX_PARALLEL_START") | ||||
| 	if len(mpsS) > 0 { | ||||
| 		mpsI, err := strconv.Atoi(mpsS) | ||||
| 		if err != nil || mpsI < 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		currentContainerStarts.maxParallel = mpsI | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type System struct { | ||||
| 	handleLock     sync.RWMutex | ||||
| 	handle         hcsSystem | ||||
| 	id             string | ||||
| 	callbackNumber uintptr | ||||
| } | ||||
|  | ||||
| // CreateComputeSystem creates a new compute system with the given configuration but does not start it. | ||||
| func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System, error) { | ||||
| 	operation := "CreateComputeSystem" | ||||
| 	title := "hcsshim::" + operation | ||||
|  | ||||
| 	computeSystem := &System{ | ||||
| 		id: id, | ||||
| 	} | ||||
|  | ||||
| 	hcsDocumentB, err := json.Marshal(hcsDocumentInterface) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	hcsDocument := string(hcsDocumentB) | ||||
| 	logrus.Debugf(title+" ID=%s config=%s", id, hcsDocument) | ||||
|  | ||||
| 	var ( | ||||
| 		resultp  *uint16 | ||||
| 		identity syscall.Handle | ||||
| 	) | ||||
| 	createError := hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp) | ||||
|  | ||||
| 	if createError == nil || IsPending(createError) { | ||||
| 		if err := computeSystem.registerCallback(); err != nil { | ||||
| 			// Terminate the compute system if it still exists. We're okay to | ||||
| 			// ignore a failure here. | ||||
| 			computeSystem.Terminate() | ||||
| 			return nil, makeSystemError(computeSystem, operation, "", err, nil) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.Duration) | ||||
| 	if err != nil { | ||||
| 		if err == ErrTimeout { | ||||
| 			// Terminate the compute system if it still exists. We're okay to | ||||
| 			// ignore a failure here. | ||||
| 			computeSystem.Terminate() | ||||
| 		} | ||||
| 		return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s handle=%d", id, computeSystem.handle) | ||||
| 	return computeSystem, nil | ||||
| } | ||||
|  | ||||
| // OpenComputeSystem opens an existing compute system by ID. | ||||
| func OpenComputeSystem(id string) (*System, error) { | ||||
| 	operation := "OpenComputeSystem" | ||||
| 	title := "hcsshim::" + operation | ||||
| 	logrus.Debugf(title+" ID=%s", id) | ||||
|  | ||||
| 	computeSystem := &System{ | ||||
| 		id: id, | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		handle  hcsSystem | ||||
| 		resultp *uint16 | ||||
| 	) | ||||
| 	err := hcsOpenComputeSystem(id, &handle, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, operation, "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	computeSystem.handle = handle | ||||
|  | ||||
| 	if err := computeSystem.registerCallback(); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, operation, "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle) | ||||
| 	return computeSystem, nil | ||||
| } | ||||
|  | ||||
| // GetComputeSystems gets a list of the compute systems on the system that match the query | ||||
| func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerProperties, error) { | ||||
| 	operation := "GetComputeSystems" | ||||
| 	title := "hcsshim::" + operation | ||||
|  | ||||
| 	queryb, err := json.Marshal(q) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	query := string(queryb) | ||||
| 	logrus.Debugf(title+" query=%s", query) | ||||
|  | ||||
| 	var ( | ||||
| 		resultp         *uint16 | ||||
| 		computeSystemsp *uint16 | ||||
| 	) | ||||
| 	err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, &HcsError{Op: operation, Err: err, Events: events} | ||||
| 	} | ||||
|  | ||||
| 	if computeSystemsp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	computeSystemsRaw := interop.ConvertAndFreeCoTaskMemBytes(computeSystemsp) | ||||
| 	computeSystems := []schema1.ContainerProperties{} | ||||
| 	if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return computeSystems, nil | ||||
| } | ||||
|  | ||||
| // Start synchronously starts the computeSystem. | ||||
| func (computeSystem *System) Start() error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::Start ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Start", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	// This is a very simple backoff-retry loop to limit the number | ||||
| 	// of parallel container starts if environment variable | ||||
| 	// HCSSHIM_MAX_PARALLEL_START is set to a positive integer. | ||||
| 	// It should generally only be used as a workaround to various | ||||
| 	// platform issues that exist between RS1 and RS4 as of Aug 2018 | ||||
| 	if currentContainerStarts.maxParallel > 0 { | ||||
| 		for { | ||||
| 			currentContainerStarts.Lock() | ||||
| 			if currentContainerStarts.inProgress < currentContainerStarts.maxParallel { | ||||
| 				currentContainerStarts.inProgress++ | ||||
| 				currentContainerStarts.Unlock() | ||||
| 				break | ||||
| 			} | ||||
| 			if currentContainerStarts.inProgress == currentContainerStarts.maxParallel { | ||||
| 				currentContainerStarts.Unlock() | ||||
| 				time.Sleep(100 * time.Millisecond) | ||||
| 			} | ||||
| 		} | ||||
| 		// Make sure we decrement the count when we are done. | ||||
| 		defer func() { | ||||
| 			currentContainerStarts.Lock() | ||||
| 			currentContainerStarts.inProgress-- | ||||
| 			currentContainerStarts.Unlock() | ||||
| 		}() | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsStartComputeSystem(computeSystem.handle, "", &resultp) | ||||
| 	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.Duration) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Start", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ID returns the compute system's identifier. | ||||
| func (computeSystem *System) ID() string { | ||||
| 	return computeSystem.id | ||||
| } | ||||
|  | ||||
| // Shutdown requests a compute system shutdown, if IsPending() on the error returned is true, | ||||
| // it may not actually be shut down until Wait() succeeds. | ||||
| func (computeSystem *System) Shutdown() error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::Shutdown" | ||||
| 	logrus.Debugf(title) | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Shutdown", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Shutdown", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Terminate requests a compute system terminate, if IsPending() on the error returned is true, | ||||
| // it may not actually be shut down until Wait() succeeds. | ||||
| func (computeSystem *System) Terminate() error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::Terminate ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Terminate", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Terminate", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Wait synchronously waits for the compute system to shutdown or terminate. | ||||
| func (computeSystem *System) Wait() error { | ||||
| 	title := "hcsshim::ComputeSystem::Wait ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Wait", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // WaitTimeout synchronously waits for the compute system to terminate or the duration to elapse. | ||||
| // If the timeout expires, IsTimeout(err) == true | ||||
| func (computeSystem *System) WaitTimeout(timeout time.Duration) error { | ||||
| 	title := "hcsshim::ComputeSystem::WaitTimeout ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "WaitTimeout", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (computeSystem *System) Properties(types ...schema1.PropertyType) (*schema1.ContainerProperties, error) { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
|  | ||||
| 	queryj, err := json.Marshal(schema1.PropertyQuery{types}) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "Properties", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp, propertiesp *uint16 | ||||
| 	err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "Properties", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	if propertiesp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp) | ||||
| 	properties := &schema1.ContainerProperties{} | ||||
| 	if err := json.Unmarshal(propertiesRaw, properties); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "Properties", "", err, nil) | ||||
| 	} | ||||
| 	return properties, nil | ||||
| } | ||||
|  | ||||
| // Pause pauses the execution of the computeSystem. This feature is not enabled in TP5. | ||||
| func (computeSystem *System) Pause() error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::Pause ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Pause", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp) | ||||
| 	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.Duration) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Pause", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Resume resumes the execution of the computeSystem. This feature is not enabled in TP5. | ||||
| func (computeSystem *System) Resume() error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::Resume ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Resume", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp) | ||||
| 	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.Duration) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Resume", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CreateProcess launches a new process within the computeSystem. | ||||
| func (computeSystem *System) CreateProcess(c interface{}) (*Process, error) { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::CreateProcess ID=" + computeSystem.ID() | ||||
| 	var ( | ||||
| 		processInfo   hcsProcessInformation | ||||
| 		processHandle hcsProcess | ||||
| 		resultp       *uint16 | ||||
| 	) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return nil, makeSystemError(computeSystem, "CreateProcess", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	configurationb, err := json.Marshal(c) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	configuration := string(configurationb) | ||||
| 	logrus.Debugf(title+" config=%s", configuration) | ||||
|  | ||||
| 	err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events) | ||||
| 	} | ||||
|  | ||||
| 	process := &Process{ | ||||
| 		handle:    processHandle, | ||||
| 		processID: int(processInfo.ProcessId), | ||||
| 		system:    computeSystem, | ||||
| 		cachedPipes: &cachedPipes{ | ||||
| 			stdIn:  processInfo.StdInput, | ||||
| 			stdOut: processInfo.StdOutput, | ||||
| 			stdErr: processInfo.StdError, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	if err := process.registerCallback(); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return process, nil | ||||
| } | ||||
|  | ||||
| // OpenProcess gets an interface to an existing process within the computeSystem. | ||||
| func (computeSystem *System) OpenProcess(pid int) (*Process, error) { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::ComputeSystem::OpenProcess ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title+" processid=%d", pid) | ||||
| 	var ( | ||||
| 		processHandle hcsProcess | ||||
| 		resultp       *uint16 | ||||
| 	) | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events) | ||||
| 	} | ||||
|  | ||||
| 	process := &Process{ | ||||
| 		handle:    processHandle, | ||||
| 		processID: pid, | ||||
| 		system:    computeSystem, | ||||
| 	} | ||||
|  | ||||
| 	if err := process.registerCallback(); err != nil { | ||||
| 		return nil, makeSystemError(computeSystem, "OpenProcess", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%s", process.processID) | ||||
| 	return process, nil | ||||
| } | ||||
|  | ||||
| // Close cleans up any state associated with the compute system but does not terminate or wait for it. | ||||
| func (computeSystem *System) Close() error { | ||||
| 	computeSystem.handleLock.Lock() | ||||
| 	defer computeSystem.handleLock.Unlock() | ||||
| 	title := "hcsshim::ComputeSystem::Close ID=" + computeSystem.ID() | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	// Don't double free this | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if err := computeSystem.unregisterCallback(); err != nil { | ||||
| 		return makeSystemError(computeSystem, "Close", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	if err := hcsCloseComputeSystem(computeSystem.handle); err != nil { | ||||
| 		return makeSystemError(computeSystem, "Close", "", err, nil) | ||||
| 	} | ||||
|  | ||||
| 	computeSystem.handle = 0 | ||||
|  | ||||
| 	logrus.Debugf(title + " succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (computeSystem *System) registerCallback() error { | ||||
| 	context := ¬ifcationWatcherContext{ | ||||
| 		channels: newChannels(), | ||||
| 	} | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackNumber := nextCallback | ||||
| 	nextCallback++ | ||||
| 	callbackMap[callbackNumber] = context | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	var callbackHandle hcsCallback | ||||
| 	err := hcsRegisterComputeSystemCallback(computeSystem.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	context.handle = callbackHandle | ||||
| 	computeSystem.callbackNumber = callbackNumber | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (computeSystem *System) unregisterCallback() error { | ||||
| 	callbackNumber := computeSystem.callbackNumber | ||||
|  | ||||
| 	callbackMapLock.RLock() | ||||
| 	context := callbackMap[callbackNumber] | ||||
| 	callbackMapLock.RUnlock() | ||||
|  | ||||
| 	if context == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	handle := context.handle | ||||
|  | ||||
| 	if handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// hcsUnregisterComputeSystemCallback has its own syncronization | ||||
| 	// to wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := hcsUnregisterComputeSystemCallback(handle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	closeChannels(context.channels) | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackMap[callbackNumber] = nil | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	handle = 0 | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Modifies the System by sending a request to HCS | ||||
| func (computeSystem *System) Modify(config interface{}) error { | ||||
| 	computeSystem.handleLock.RLock() | ||||
| 	defer computeSystem.handleLock.RUnlock() | ||||
| 	title := "hcsshim::Modify ID=" + computeSystem.id | ||||
|  | ||||
| 	if computeSystem.handle == 0 { | ||||
| 		return makeSystemError(computeSystem, "Modify", "", ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	requestJSON, err := json.Marshal(config) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	requestString := string(requestJSON) | ||||
| 	logrus.Debugf(title + " " + requestString) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeSystemError(computeSystem, "Modify", requestString, err, events) | ||||
| 	} | ||||
| 	logrus.Debugf(title + " succeeded ") | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package hcs | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package hcs | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| @@ -6,13 +6,13 @@ import ( | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { | ||||
| 	err = processHcsResult(err, resultp) | ||||
| func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) ([]ErrorEvent, error) { | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if IsPending(err) { | ||||
| 		return waitForNotification(callbackNumber, expectedNotification, timeout) | ||||
| 		return nil, waitForNotification(callbackNumber, expectedNotification, timeout) | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| 	return events, err | ||||
| } | ||||
| 
 | ||||
| func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { | ||||
							
								
								
									
										441
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,441 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") | ||||
|  | ||||
| 	procHcsEnumerateComputeSystems         = modvmcompute.NewProc("HcsEnumerateComputeSystems") | ||||
| 	procHcsCreateComputeSystem             = modvmcompute.NewProc("HcsCreateComputeSystem") | ||||
| 	procHcsOpenComputeSystem               = modvmcompute.NewProc("HcsOpenComputeSystem") | ||||
| 	procHcsCloseComputeSystem              = modvmcompute.NewProc("HcsCloseComputeSystem") | ||||
| 	procHcsStartComputeSystem              = modvmcompute.NewProc("HcsStartComputeSystem") | ||||
| 	procHcsShutdownComputeSystem           = modvmcompute.NewProc("HcsShutdownComputeSystem") | ||||
| 	procHcsTerminateComputeSystem          = modvmcompute.NewProc("HcsTerminateComputeSystem") | ||||
| 	procHcsPauseComputeSystem              = modvmcompute.NewProc("HcsPauseComputeSystem") | ||||
| 	procHcsResumeComputeSystem             = modvmcompute.NewProc("HcsResumeComputeSystem") | ||||
| 	procHcsGetComputeSystemProperties      = modvmcompute.NewProc("HcsGetComputeSystemProperties") | ||||
| 	procHcsModifyComputeSystem             = modvmcompute.NewProc("HcsModifyComputeSystem") | ||||
| 	procHcsRegisterComputeSystemCallback   = modvmcompute.NewProc("HcsRegisterComputeSystemCallback") | ||||
| 	procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback") | ||||
| 	procHcsCreateProcess                   = modvmcompute.NewProc("HcsCreateProcess") | ||||
| 	procHcsOpenProcess                     = modvmcompute.NewProc("HcsOpenProcess") | ||||
| 	procHcsCloseProcess                    = modvmcompute.NewProc("HcsCloseProcess") | ||||
| 	procHcsTerminateProcess                = modvmcompute.NewProc("HcsTerminateProcess") | ||||
| 	procHcsGetProcessInfo                  = modvmcompute.NewProc("HcsGetProcessInfo") | ||||
| 	procHcsGetProcessProperties            = modvmcompute.NewProc("HcsGetProcessProperties") | ||||
| 	procHcsModifyProcess                   = modvmcompute.NewProc("HcsModifyProcess") | ||||
| 	procHcsGetServiceProperties            = modvmcompute.NewProc("HcsGetServiceProperties") | ||||
| 	procHcsRegisterProcessCallback         = modvmcompute.NewProc("HcsRegisterProcessCallback") | ||||
| 	procHcsUnregisterProcessCallback       = modvmcompute.NewProc("HcsUnregisterProcessCallback") | ||||
| ) | ||||
|  | ||||
| func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(query) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsEnumerateComputeSystems(_p0, computeSystems, result) | ||||
| } | ||||
|  | ||||
| func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsEnumerateComputeSystems.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(configuration) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsCreateComputeSystem(_p0, _p1, identity, computeSystem, result) | ||||
| } | ||||
|  | ||||
| func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { | ||||
| 	if hr = procHcsCreateComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsOpenComputeSystem(_p0, computeSystem, result) | ||||
| } | ||||
|  | ||||
| func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16) (hr error) { | ||||
| 	if hr = procHcsOpenComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) { | ||||
| 	if hr = procHcsCloseComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(options) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsStartComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsStartComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(options) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsShutdownComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsShutdownComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(options) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsTerminateComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsTerminateComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(options) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsPauseComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsPauseComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(options) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsResumeComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsResumeComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(propertyQuery) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsGetComputeSystemProperties(computeSystem, _p0, properties, result) | ||||
| } | ||||
|  | ||||
| func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsGetComputeSystemProperties.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(configuration) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsModifyComputeSystem(computeSystem, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsModifyComputeSystem.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { | ||||
| 	if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) { | ||||
| 	if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(processParameters) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsCreateProcess(computeSystem, _p0, processInformation, process, result) | ||||
| } | ||||
|  | ||||
| func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { | ||||
| 	if hr = procHcsCreateProcess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) { | ||||
| 	if hr = procHcsOpenProcess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsCloseProcess(process hcsProcess) (hr error) { | ||||
| 	if hr = procHcsCloseProcess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) { | ||||
| 	if hr = procHcsTerminateProcess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) { | ||||
| 	if hr = procHcsGetProcessInfo.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsGetProcessProperties.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(settings) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsModifyProcess(process, _p0, result) | ||||
| } | ||||
|  | ||||
| func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsModifyProcess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(propertyQuery) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _hcsGetServiceProperties(_p0, properties, result) | ||||
| } | ||||
|  | ||||
| func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { | ||||
| 	if hr = procHcsGetServiceProperties.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { | ||||
| 	if hr = procHcsRegisterProcessCallback.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) { | ||||
| 	if hr = procHcsUnregisterProcessCallback.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										51
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package hcserror | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| const ERROR_GEN_FAILURE = syscall.Errno(31) | ||||
|  | ||||
| type HcsError struct { | ||||
| 	title string | ||||
| 	rest  string | ||||
| 	Err   error | ||||
| } | ||||
|  | ||||
| func (e *HcsError) Error() string { | ||||
| 	s := e.title | ||||
| 	if len(s) > 0 && s[len(s)-1] != ' ' { | ||||
| 		s += " " | ||||
| 	} | ||||
| 	s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, Win32FromError(e.Err)) | ||||
| 	if e.rest != "" { | ||||
| 		if e.rest[0] != ' ' { | ||||
| 			s += " " | ||||
| 		} | ||||
| 		s += e.rest | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func New(err error, title, rest string) error { | ||||
| 	// Pass through DLL errors directly since they do not originate from HCS. | ||||
| 	if _, ok := err.(*syscall.DLLError); ok { | ||||
| 		return err | ||||
| 	} | ||||
| 	return &HcsError{title, rest, err} | ||||
| } | ||||
|  | ||||
| func Errorf(err error, title, format string, a ...interface{}) error { | ||||
| 	return New(err, title, fmt.Sprintf(format, a...)) | ||||
| } | ||||
|  | ||||
| func Win32FromError(err error) uint32 { | ||||
| 	if herr, ok := err.(*HcsError); ok { | ||||
| 		return Win32FromError(herr.Err) | ||||
| 	} | ||||
| 	if code, ok := err.(syscall.Errno); ok { | ||||
| 		return uint32(code) | ||||
| 	} | ||||
| 	return uint32(ERROR_GEN_FAILURE) | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hns.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hns.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package hns | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| //go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hns.go | ||||
|  | ||||
| //sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? | ||||
|  | ||||
| type EndpointNotFoundError struct { | ||||
| 	EndpointName string | ||||
| } | ||||
|  | ||||
| func (e EndpointNotFoundError) Error() string { | ||||
| 	return fmt.Sprintf("Endpoint %s not found", e.EndpointName) | ||||
| } | ||||
|  | ||||
| type NetworkNotFoundError struct { | ||||
| 	NetworkName string | ||||
| } | ||||
|  | ||||
| func (e NetworkNotFoundError) Error() string { | ||||
| 	return fmt.Sprintf("Network %s not found", e.NetworkName) | ||||
| } | ||||
							
								
								
									
										260
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,260 @@ | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // HNSEndpoint represents a network endpoint in HNS | ||||
| type HNSEndpoint struct { | ||||
| 	Id                 string            `json:"ID,omitempty"` | ||||
| 	Name               string            `json:",omitempty"` | ||||
| 	VirtualNetwork     string            `json:",omitempty"` | ||||
| 	VirtualNetworkName string            `json:",omitempty"` | ||||
| 	Policies           []json.RawMessage `json:",omitempty"` | ||||
| 	MacAddress         string            `json:",omitempty"` | ||||
| 	IPAddress          net.IP            `json:",omitempty"` | ||||
| 	DNSSuffix          string            `json:",omitempty"` | ||||
| 	DNSServerList      string            `json:",omitempty"` | ||||
| 	GatewayAddress     string            `json:",omitempty"` | ||||
| 	EnableInternalDNS  bool              `json:",omitempty"` | ||||
| 	DisableICC         bool              `json:",omitempty"` | ||||
| 	PrefixLength       uint8             `json:",omitempty"` | ||||
| 	IsRemoteEndpoint   bool              `json:",omitempty"` | ||||
| 	Namespace          *Namespace        `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| //SystemType represents the type of the system on which actions are done | ||||
| type SystemType string | ||||
|  | ||||
| // SystemType const | ||||
| const ( | ||||
| 	ContainerType      SystemType = "Container" | ||||
| 	VirtualMachineType SystemType = "VirtualMachine" | ||||
| 	HostType           SystemType = "Host" | ||||
| ) | ||||
|  | ||||
| // EndpointAttachDetachRequest is the structure used to send request to the container to modify the system | ||||
| // Supported resource types are Network and Request Types are Add/Remove | ||||
| type EndpointAttachDetachRequest struct { | ||||
| 	ContainerID    string     `json:"ContainerId,omitempty"` | ||||
| 	SystemType     SystemType `json:"SystemType"` | ||||
| 	CompartmentID  uint16     `json:"CompartmentId,omitempty"` | ||||
| 	VirtualNICName string     `json:"VirtualNicName,omitempty"` | ||||
| } | ||||
|  | ||||
| // EndpointResquestResponse is object to get the endpoint request response | ||||
| type EndpointResquestResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| } | ||||
|  | ||||
| // HNSEndpointRequest makes a HNS call to modify/query a network endpoint | ||||
| func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { | ||||
| 	endpoint := &HNSEndpoint{} | ||||
| 	err := hnsCall(method, "/endpoints/"+path, request, &endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return endpoint, nil | ||||
| } | ||||
|  | ||||
| // HNSListEndpointRequest makes a HNS call to query the list of available endpoints | ||||
| func HNSListEndpointRequest() ([]HNSEndpoint, error) { | ||||
| 	var endpoint []HNSEndpoint | ||||
| 	err := hnsCall("GET", "/endpoints/", "", &endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return endpoint, nil | ||||
| } | ||||
|  | ||||
| // GetHNSEndpointByID get the Endpoint by ID | ||||
| func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { | ||||
| 	return HNSEndpointRequest("GET", endpointID, "") | ||||
| } | ||||
|  | ||||
| // GetHNSEndpointByName gets the endpoint filtered by Name | ||||
| func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { | ||||
| 	hnsResponse, err := HNSListEndpointRequest() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, hnsEndpoint := range hnsResponse { | ||||
| 		if hnsEndpoint.Name == endpointName { | ||||
| 			return &hnsEndpoint, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, EndpointNotFoundError{EndpointName: endpointName} | ||||
| } | ||||
|  | ||||
| // Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods | ||||
| func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	jsonString, err := json.Marshal(endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return HNSEndpointRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete Endpoint by sending EndpointRequest to HNS | ||||
| func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	return HNSEndpointRequest("DELETE", endpoint.Id, "") | ||||
| } | ||||
|  | ||||
| // Update Endpoint | ||||
| func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { | ||||
| 	operation := "Update" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	jsonString, err := json.Marshal(endpoint) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) | ||||
|  | ||||
| 	return endpoint, err | ||||
| } | ||||
|  | ||||
| // ApplyACLPolicy applies a set of ACL Policies on the Endpoint | ||||
| func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { | ||||
| 	operation := "ApplyACLPolicy" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	for _, policy := range policies { | ||||
| 		if policy == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		jsonString, err := json.Marshal(policy) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		endpoint.Policies = append(endpoint.Policies, jsonString) | ||||
| 	} | ||||
|  | ||||
| 	_, err := endpoint.Update() | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ContainerAttach attaches an endpoint to container | ||||
| func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { | ||||
| 	operation := "ContainerAttach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		ContainerID:   containerID, | ||||
| 		CompartmentID: compartmentID, | ||||
| 		SystemType:    ContainerType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // ContainerDetach detaches an endpoint from container | ||||
| func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { | ||||
| 	operation := "ContainerDetach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		ContainerID: containerID, | ||||
| 		SystemType:  ContainerType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // HostAttach attaches a nic on the host | ||||
| func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { | ||||
| 	operation := "HostAttach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		CompartmentID: compartmentID, | ||||
| 		SystemType:    HostType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
|  | ||||
| } | ||||
|  | ||||
| // HostDetach detaches a nic on the host | ||||
| func (endpoint *HNSEndpoint) HostDetach() error { | ||||
| 	operation := "HostDetach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		SystemType: HostType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // VirtualMachineNICAttach attaches a endpoint to a virtual machine | ||||
| func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { | ||||
| 	operation := "VirtualMachineNicAttach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		VirtualNICName: virtualMachineNICName, | ||||
| 		SystemType:     VirtualMachineType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) | ||||
| } | ||||
|  | ||||
| // VirtualMachineNICDetach detaches a endpoint  from a virtual machine | ||||
| func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { | ||||
| 	operation := "VirtualMachineNicDetach" | ||||
| 	title := "hcsshim::HNSEndpoint::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", endpoint.Id) | ||||
|  | ||||
| 	requestMessage := &EndpointAttachDetachRequest{ | ||||
| 		SystemType: VirtualMachineType, | ||||
| 	} | ||||
| 	response := &EndpointResquestResponse{} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(requestMessage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) | ||||
| } | ||||
| @@ -1,9 +1,11 @@ | ||||
| package hcsshim | ||||
| package hns | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| @@ -13,9 +15,9 @@ func hnsCall(method, path, request string, returnResponse interface{}) error { | ||||
| 
 | ||||
| 	err := _hnsCall(method, path, request, &responseBuffer) | ||||
| 	if err != nil { | ||||
| 		return makeError(err, "hnsCall ", "") | ||||
| 		return hcserror.New(err, "hnsCall ", "") | ||||
| 	} | ||||
| 	response := convertAndFreeCoTaskMemString(responseBuffer) | ||||
| 	response := interop.ConvertAndFreeCoTaskMemString(responseBuffer) | ||||
| 
 | ||||
| 	hnsresponse := &hnsResponse{} | ||||
| 	if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil { | ||||
							
								
								
									
										28
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsglobals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsglobals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package hns | ||||
|  | ||||
| type HNSGlobals struct { | ||||
| 	Version HNSVersion `json:"Version"` | ||||
| } | ||||
|  | ||||
| type HNSVersion struct { | ||||
| 	Major int `json:"Major"` | ||||
| 	Minor int `json:"Minor"` | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	HNSVersion1803 = HNSVersion{Major: 7, Minor: 2} | ||||
| ) | ||||
|  | ||||
| func GetHNSGlobals() (*HNSGlobals, error) { | ||||
| 	var version HNSVersion | ||||
| 	err := hnsCall("GET", "/globals/version", "", &version) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	globals := &HNSGlobals{ | ||||
| 		Version: version, | ||||
| 	} | ||||
|  | ||||
| 	return globals, nil | ||||
| } | ||||
							
								
								
									
										141
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsnetwork.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnsnetwork.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // Subnet is assoicated with a network and represents a list | ||||
| // of subnets available to the network | ||||
| type Subnet struct { | ||||
| 	AddressPrefix  string            `json:",omitempty"` | ||||
| 	GatewayAddress string            `json:",omitempty"` | ||||
| 	Policies       []json.RawMessage `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // MacPool is assoicated with a network and represents a list | ||||
| // of macaddresses available to the network | ||||
| type MacPool struct { | ||||
| 	StartMacAddress string `json:",omitempty"` | ||||
| 	EndMacAddress   string `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // HNSNetwork represents a network in HNS | ||||
| type HNSNetwork struct { | ||||
| 	Id                   string            `json:"ID,omitempty"` | ||||
| 	Name                 string            `json:",omitempty"` | ||||
| 	Type                 string            `json:",omitempty"` | ||||
| 	NetworkAdapterName   string            `json:",omitempty"` | ||||
| 	SourceMac            string            `json:",omitempty"` | ||||
| 	Policies             []json.RawMessage `json:",omitempty"` | ||||
| 	MacPools             []MacPool         `json:",omitempty"` | ||||
| 	Subnets              []Subnet          `json:",omitempty"` | ||||
| 	DNSSuffix            string            `json:",omitempty"` | ||||
| 	DNSServerList        string            `json:",omitempty"` | ||||
| 	DNSServerCompartment uint32            `json:",omitempty"` | ||||
| 	ManagementIP         string            `json:",omitempty"` | ||||
| 	AutomaticDNS         bool              `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type hnsNetworkResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| 	Output  HNSNetwork | ||||
| } | ||||
|  | ||||
| type hnsResponse struct { | ||||
| 	Success bool | ||||
| 	Error   string | ||||
| 	Output  json.RawMessage | ||||
| } | ||||
|  | ||||
| // HNSNetworkRequest makes a call into HNS to update/query a single network | ||||
| func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { | ||||
| 	var network HNSNetwork | ||||
| 	err := hnsCall(method, "/networks/"+path, request, &network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &network, nil | ||||
| } | ||||
|  | ||||
| // HNSListNetworkRequest makes a HNS call to query the list of available networks | ||||
| func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { | ||||
| 	var network []HNSNetwork | ||||
| 	err := hnsCall(method, "/networks/"+path, request, &network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return network, nil | ||||
| } | ||||
|  | ||||
| // GetHNSNetworkByID | ||||
| func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { | ||||
| 	return HNSNetworkRequest("GET", networkID, "") | ||||
| } | ||||
|  | ||||
| // GetHNSNetworkName filtered by Name | ||||
| func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { | ||||
| 	hsnnetworks, err := HNSListNetworkRequest("GET", "", "") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, hnsnetwork := range hsnnetworks { | ||||
| 		if hnsnetwork.Name == networkName { | ||||
| 			return &hnsnetwork, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, NetworkNotFoundError{NetworkName: networkName} | ||||
| } | ||||
|  | ||||
| // Create Network by sending NetworkRequest to HNS. | ||||
| func (network *HNSNetwork) Create() (*HNSNetwork, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "hcsshim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
|  | ||||
| 	jsonString, err := json.Marshal(network) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return HNSNetworkRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete Network by sending NetworkRequest to HNS | ||||
| func (network *HNSNetwork) Delete() (*HNSNetwork, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "hcsshim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
|  | ||||
| 	return HNSNetworkRequest("DELETE", network.Id, "") | ||||
| } | ||||
|  | ||||
| // Creates an endpoint on the Network. | ||||
| func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { | ||||
| 	return &HNSEndpoint{ | ||||
| 		VirtualNetwork: network.Id, | ||||
| 		IPAddress:      ipAddress, | ||||
| 		MacAddress:     string(macAddress), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { | ||||
| 	operation := "CreateEndpoint" | ||||
| 	title := "hcsshim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) | ||||
|  | ||||
| 	endpoint.VirtualNetwork = network.Id | ||||
| 	return endpoint.Create() | ||||
| } | ||||
|  | ||||
| func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { | ||||
| 	operation := "CreateRemoteEndpoint" | ||||
| 	title := "hcsshim::HNSNetwork::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", network.Id) | ||||
| 	endpoint.IsRemoteEndpoint = true | ||||
| 	return network.CreateEndpoint(endpoint) | ||||
| } | ||||
							
								
								
									
										98
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| package hns | ||||
|  | ||||
| // Type of Request Support in ModifySystem | ||||
| type PolicyType string | ||||
|  | ||||
| // RequestType const | ||||
| const ( | ||||
| 	Nat                  PolicyType = "NAT" | ||||
| 	ACL                  PolicyType = "ACL" | ||||
| 	PA                   PolicyType = "PA" | ||||
| 	VLAN                 PolicyType = "VLAN" | ||||
| 	VSID                 PolicyType = "VSID" | ||||
| 	VNet                 PolicyType = "VNET" | ||||
| 	L2Driver             PolicyType = "L2Driver" | ||||
| 	Isolation            PolicyType = "Isolation" | ||||
| 	QOS                  PolicyType = "QOS" | ||||
| 	OutboundNat          PolicyType = "OutBoundNAT" | ||||
| 	ExternalLoadBalancer PolicyType = "ELB" | ||||
| 	Route                PolicyType = "ROUTE" | ||||
| ) | ||||
|  | ||||
| type NatPolicy struct { | ||||
| 	Type         PolicyType `json:"Type"` | ||||
| 	Protocol     string | ||||
| 	InternalPort uint16 | ||||
| 	ExternalPort uint16 | ||||
| } | ||||
|  | ||||
| type QosPolicy struct { | ||||
| 	Type                            PolicyType `json:"Type"` | ||||
| 	MaximumOutgoingBandwidthInBytes uint64 | ||||
| } | ||||
|  | ||||
| type IsolationPolicy struct { | ||||
| 	Type               PolicyType `json:"Type"` | ||||
| 	VLAN               uint | ||||
| 	VSID               uint | ||||
| 	InDefaultIsolation bool | ||||
| } | ||||
|  | ||||
| type VlanPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	VLAN uint | ||||
| } | ||||
|  | ||||
| type VsidPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	VSID uint | ||||
| } | ||||
|  | ||||
| type PaPolicy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| 	PA   string     `json:"PA"` | ||||
| } | ||||
|  | ||||
| type OutboundNatPolicy struct { | ||||
| 	Policy | ||||
| 	VIP        string   `json:"VIP,omitempty"` | ||||
| 	Exceptions []string `json:"ExceptionList,omitempty"` | ||||
| } | ||||
|  | ||||
| type ActionType string | ||||
| type DirectionType string | ||||
| type RuleType string | ||||
|  | ||||
| const ( | ||||
| 	Allow ActionType = "Allow" | ||||
| 	Block ActionType = "Block" | ||||
|  | ||||
| 	In  DirectionType = "In" | ||||
| 	Out DirectionType = "Out" | ||||
|  | ||||
| 	Host   RuleType = "Host" | ||||
| 	Switch RuleType = "Switch" | ||||
| ) | ||||
|  | ||||
| type ACLPolicy struct { | ||||
| 	Type            PolicyType `json:"Type"` | ||||
| 	Id              string     `json:"Id,omitempty"` | ||||
| 	Protocol        uint16 | ||||
| 	Protocols       string `json:"Protocols,omitempty"` | ||||
| 	InternalPort    uint16 | ||||
| 	Action          ActionType | ||||
| 	Direction       DirectionType | ||||
| 	LocalAddresses  string | ||||
| 	RemoteAddresses string | ||||
| 	LocalPorts      string `json:"LocalPorts,omitempty"` | ||||
| 	LocalPort       uint16 | ||||
| 	RemotePorts     string `json:"RemotePorts,omitempty"` | ||||
| 	RemotePort      uint16 | ||||
| 	RuleType        RuleType `json:"RuleType,omitempty"` | ||||
| 	Priority        uint16 | ||||
| 	ServiceName     string | ||||
| } | ||||
|  | ||||
| type Policy struct { | ||||
| 	Type PolicyType `json:"Type"` | ||||
| } | ||||
							
								
								
									
										200
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,200 @@ | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // RoutePolicy is a structure defining schema for Route based Policy | ||||
| type RoutePolicy struct { | ||||
| 	Policy | ||||
| 	DestinationPrefix string `json:"DestinationPrefix,omitempty"` | ||||
| 	NextHop           string `json:"NextHop,omitempty"` | ||||
| 	EncapEnabled      bool   `json:"NeedEncap,omitempty"` | ||||
| } | ||||
|  | ||||
| // ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy | ||||
| type ELBPolicy struct { | ||||
| 	LBPolicy | ||||
| 	SourceVIP string   `json:"SourceVIP,omitempty"` | ||||
| 	VIPs      []string `json:"VIPs,omitempty"` | ||||
| 	ILB       bool     `json:"ILB,omitempty"` | ||||
| } | ||||
|  | ||||
| // LBPolicy is a structure defining schema for LoadBalancing based Policy | ||||
| type LBPolicy struct { | ||||
| 	Policy | ||||
| 	Protocol     uint16 `json:"Protocol,omitempty"` | ||||
| 	InternalPort uint16 | ||||
| 	ExternalPort uint16 | ||||
| } | ||||
|  | ||||
| // PolicyList is a structure defining schema for Policy list request | ||||
| type PolicyList struct { | ||||
| 	ID                 string            `json:"ID,omitempty"` | ||||
| 	EndpointReferences []string          `json:"References,omitempty"` | ||||
| 	Policies           []json.RawMessage `json:"Policies,omitempty"` | ||||
| } | ||||
|  | ||||
| // HNSPolicyListRequest makes a call into HNS to update/query a single network | ||||
| func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { | ||||
| 	var policy PolicyList | ||||
| 	err := hnsCall(method, "/policylists/"+path, request, &policy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &policy, nil | ||||
| } | ||||
|  | ||||
| // HNSListPolicyListRequest gets all the policy list | ||||
| func HNSListPolicyListRequest() ([]PolicyList, error) { | ||||
| 	var plist []PolicyList | ||||
| 	err := hnsCall("GET", "/policylists/", "", &plist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return plist, nil | ||||
| } | ||||
|  | ||||
| // PolicyListRequest makes a HNS call to modify/query a network policy list | ||||
| func PolicyListRequest(method, path, request string) (*PolicyList, error) { | ||||
| 	policylist := &PolicyList{} | ||||
| 	err := hnsCall(method, "/policylists/"+path, request, &policylist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return policylist, nil | ||||
| } | ||||
|  | ||||
| // GetPolicyListByID get the policy list by ID | ||||
| func GetPolicyListByID(policyListID string) (*PolicyList, error) { | ||||
| 	return PolicyListRequest("GET", policyListID, "") | ||||
| } | ||||
|  | ||||
| // Create PolicyList by sending PolicyListRequest to HNS. | ||||
| func (policylist *PolicyList) Create() (*PolicyList, error) { | ||||
| 	operation := "Create" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", policylist.ID) | ||||
| 	jsonString, err := json.Marshal(policylist) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return PolicyListRequest("POST", "", string(jsonString)) | ||||
| } | ||||
|  | ||||
| // Delete deletes PolicyList | ||||
| func (policylist *PolicyList) Delete() (*PolicyList, error) { | ||||
| 	operation := "Delete" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s", policylist.ID) | ||||
|  | ||||
| 	return PolicyListRequest("DELETE", policylist.ID, "") | ||||
| } | ||||
|  | ||||
| // AddEndpoint add an endpoint to a Policy List | ||||
| func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { | ||||
| 	operation := "AddEndpoint" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) | ||||
|  | ||||
| 	_, err := policylist.Delete() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Add Endpoint to the Existing List | ||||
| 	policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
|  | ||||
| 	return policylist.Create() | ||||
| } | ||||
|  | ||||
| // RemoveEndpoint removes an endpoint from the Policy List | ||||
| func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { | ||||
| 	operation := "RemoveEndpoint" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) | ||||
|  | ||||
| 	_, err := policylist.Delete() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	elementToRemove := "/endpoints/" + endpoint.Id | ||||
|  | ||||
| 	var references []string | ||||
|  | ||||
| 	for _, endpointReference := range policylist.EndpointReferences { | ||||
| 		if endpointReference == elementToRemove { | ||||
| 			continue | ||||
| 		} | ||||
| 		references = append(references, endpointReference) | ||||
| 	} | ||||
| 	policylist.EndpointReferences = references | ||||
| 	return policylist.Create() | ||||
| } | ||||
|  | ||||
| // AddLoadBalancer policy list for the specified endpoints | ||||
| func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { | ||||
| 	operation := "AddLoadBalancer" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) | ||||
|  | ||||
| 	policylist := &PolicyList{} | ||||
|  | ||||
| 	elbPolicy := &ELBPolicy{ | ||||
| 		SourceVIP: sourceVIP, | ||||
| 		ILB:       isILB, | ||||
| 	} | ||||
|  | ||||
| 	if len(vip) > 0 { | ||||
| 		elbPolicy.VIPs = []string{vip} | ||||
| 	} | ||||
| 	elbPolicy.Type = ExternalLoadBalancer | ||||
| 	elbPolicy.Protocol = protocol | ||||
| 	elbPolicy.InternalPort = internalPort | ||||
| 	elbPolicy.ExternalPort = externalPort | ||||
|  | ||||
| 	for _, endpoint := range endpoints { | ||||
| 		policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
| 	} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(elbPolicy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	policylist.Policies = append(policylist.Policies, jsonString) | ||||
| 	return policylist.Create() | ||||
| } | ||||
|  | ||||
| // AddRoute adds route policy list for the specified endpoints | ||||
| func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { | ||||
| 	operation := "AddRoute" | ||||
| 	title := "hcsshim::PolicyList::" + operation | ||||
| 	logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) | ||||
|  | ||||
| 	policylist := &PolicyList{} | ||||
|  | ||||
| 	rPolicy := &RoutePolicy{ | ||||
| 		DestinationPrefix: destinationPrefix, | ||||
| 		NextHop:           nextHop, | ||||
| 		EncapEnabled:      encapEnabled, | ||||
| 	} | ||||
| 	rPolicy.Type = Route | ||||
|  | ||||
| 	for _, endpoint := range endpoints { | ||||
| 		policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) | ||||
| 	} | ||||
|  | ||||
| 	jsonString, err := json.Marshal(rPolicy) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	policylist.Policies = append(policylist.Policies, jsonString) | ||||
| 	return policylist.Create() | ||||
| } | ||||
							
								
								
									
										49
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnssupport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/hnssupport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| type HNSSupportedFeatures struct { | ||||
| 	Acl HNSAclFeatures `json:"ACL"` | ||||
| } | ||||
|  | ||||
| type HNSAclFeatures struct { | ||||
| 	AclAddressLists       bool `json:"AclAddressLists"` | ||||
| 	AclNoHostRulePriority bool `json:"AclHostRulePriority"` | ||||
| 	AclPortRanges         bool `json:"AclPortRanges"` | ||||
| 	AclRuleId             bool `json:"AclRuleId"` | ||||
| } | ||||
|  | ||||
| func GetHNSSupportedFeatures() HNSSupportedFeatures { | ||||
| 	var hnsFeatures HNSSupportedFeatures | ||||
|  | ||||
| 	globals, err := GetHNSGlobals() | ||||
| 	if err != nil { | ||||
| 		// Expected on pre-1803 builds, all features will be false/unsupported | ||||
| 		logrus.Debugf("Unable to obtain HNS globals: %s", err) | ||||
| 		return hnsFeatures | ||||
| 	} | ||||
|  | ||||
| 	hnsFeatures.Acl = HNSAclFeatures{ | ||||
| 		AclAddressLists:       isHNSFeatureSupported(globals.Version, HNSVersion1803), | ||||
| 		AclNoHostRulePriority: isHNSFeatureSupported(globals.Version, HNSVersion1803), | ||||
| 		AclPortRanges:         isHNSFeatureSupported(globals.Version, HNSVersion1803), | ||||
| 		AclRuleId:             isHNSFeatureSupported(globals.Version, HNSVersion1803), | ||||
| 	} | ||||
|  | ||||
| 	return hnsFeatures | ||||
| } | ||||
|  | ||||
| func isHNSFeatureSupported(currentVersion HNSVersion, minVersionSupported HNSVersion) bool { | ||||
| 	if currentVersion.Major < minVersionSupported.Major { | ||||
| 		return false | ||||
| 	} | ||||
| 	if currentVersion.Major > minVersionSupported.Major { | ||||
| 		return true | ||||
| 	} | ||||
| 	if currentVersion.Minor < minVersionSupported.Minor { | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										110
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/namespace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/namespace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type namespaceRequest struct { | ||||
| 	IsDefault bool `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type namespaceEndpointRequest struct { | ||||
| 	ID string `json:"Id"` | ||||
| } | ||||
|  | ||||
| type NamespaceResource struct { | ||||
| 	Type string | ||||
| 	Data json.RawMessage | ||||
| } | ||||
|  | ||||
| type namespaceResourceRequest struct { | ||||
| 	Type string | ||||
| 	Data interface{} | ||||
| } | ||||
|  | ||||
| type Namespace struct { | ||||
| 	ID           string | ||||
| 	IsDefault    bool                `json:",omitempty"` | ||||
| 	ResourceList []NamespaceResource `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| func issueNamespaceRequest(id *string, method, subpath string, request interface{}) (*Namespace, error) { | ||||
| 	var err error | ||||
| 	hnspath := "/namespaces/" | ||||
| 	if id != nil { | ||||
| 		hnspath = path.Join(hnspath, *id) | ||||
| 	} | ||||
| 	if subpath != "" { | ||||
| 		hnspath = path.Join(hnspath, subpath) | ||||
| 	} | ||||
| 	var reqJSON []byte | ||||
| 	if request != nil { | ||||
| 		if reqJSON, err = json.Marshal(request); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	var ns Namespace | ||||
| 	err = hnsCall(method, hnspath, string(reqJSON), &ns) | ||||
| 	if err != nil { | ||||
| 		if strings.Contains(err.Error(), "Element not found.") { | ||||
| 			return nil, os.ErrNotExist | ||||
| 		} | ||||
| 		return nil, fmt.Errorf("%s %s: %s", method, hnspath, err) | ||||
| 	} | ||||
| 	return &ns, err | ||||
| } | ||||
|  | ||||
| func CreateNamespace() (string, error) { | ||||
| 	req := namespaceRequest{} | ||||
| 	ns, err := issueNamespaceRequest(nil, "POST", "", &req) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return ns.ID, nil | ||||
| } | ||||
|  | ||||
| func RemoveNamespace(id string) error { | ||||
| 	_, err := issueNamespaceRequest(&id, "DELETE", "", nil) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func GetNamespaceEndpoints(id string) ([]string, error) { | ||||
| 	ns, err := issueNamespaceRequest(&id, "GET", "", nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var endpoints []string | ||||
| 	for _, rsrc := range ns.ResourceList { | ||||
| 		if rsrc.Type == "Endpoint" { | ||||
| 			var endpoint namespaceEndpointRequest | ||||
| 			err = json.Unmarshal(rsrc.Data, &endpoint) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("unmarshal endpoint: %s", err) | ||||
| 			} | ||||
| 			endpoints = append(endpoints, endpoint.ID) | ||||
| 		} | ||||
| 	} | ||||
| 	return endpoints, nil | ||||
| } | ||||
|  | ||||
| func AddNamespaceEndpoint(id string, endpointID string) error { | ||||
| 	resource := namespaceResourceRequest{ | ||||
| 		Type: "Endpoint", | ||||
| 		Data: namespaceEndpointRequest{endpointID}, | ||||
| 	} | ||||
| 	_, err := issueNamespaceRequest(&id, "POST", "addresource", &resource) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func RemoveNamespaceEndpoint(id string, endpointID string) error { | ||||
| 	resource := namespaceResourceRequest{ | ||||
| 		Type: "Endpoint", | ||||
| 		Data: namespaceEndpointRequest{endpointID}, | ||||
| 	} | ||||
| 	_, err := issueNamespaceRequest(&id, "POST", "removeresource", &resource) | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										74
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package hns | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") | ||||
|  | ||||
| 	procHNSCall = modvmcompute.NewProc("HNSCall") | ||||
| ) | ||||
|  | ||||
| func _hnsCall(method string, path string, object string, response **uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(method) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(path) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p2 *uint16 | ||||
| 	_p2, hr = syscall.UTF16PtrFromString(object) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return __hnsCall(_p0, _p1, _p2, response) | ||||
| } | ||||
|  | ||||
| func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) { | ||||
| 	if hr = procHNSCall.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package interop | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go interop.go | ||||
|  | ||||
| //sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree | ||||
|  | ||||
| func ConvertAndFreeCoTaskMemString(buffer *uint16) string { | ||||
| 	str := syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(buffer))[:]) | ||||
| 	coTaskMemFree(unsafe.Pointer(buffer)) | ||||
| 	return str | ||||
| } | ||||
|  | ||||
| func ConvertAndFreeCoTaskMemBytes(buffer *uint16) []byte { | ||||
| 	return []byte(ConvertAndFreeCoTaskMemString(buffer)) | ||||
| } | ||||
|  | ||||
| func Win32FromHresult(hr uintptr) syscall.Errno { | ||||
| 	if hr&0x1fff0000 == 0x00070000 { | ||||
| 		return syscall.Errno(hr & 0xffff) | ||||
| 	} | ||||
| 	return syscall.Errno(hr) | ||||
| } | ||||
							
								
								
									
										48
									
								
								vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package interop | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modole32 = windows.NewLazySystemDLL("ole32.dll") | ||||
|  | ||||
| 	procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") | ||||
| ) | ||||
|  | ||||
| func coTaskMemFree(buffer unsafe.Pointer) { | ||||
| 	syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/longpath/longpath.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/longpath/longpath.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package longpath | ||||
|  | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // LongAbs makes a path absolute and returns it in NT long path form. | ||||
| func LongAbs(path string) (string, error) { | ||||
| 	if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) { | ||||
| 		return path, nil | ||||
| 	} | ||||
| 	if !filepath.IsAbs(path) { | ||||
| 		absPath, err := filepath.Abs(path) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		path = absPath | ||||
| 	} | ||||
| 	if strings.HasPrefix(path, `\\`) { | ||||
| 		return `\\?\UNC\` + path[2:], nil | ||||
| 	} | ||||
| 	return `\\?\` + path, nil | ||||
| } | ||||
							
								
								
									
										52
									
								
								vendor/github.com/Microsoft/hcsshim/internal/mergemaps/merge.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/Microsoft/hcsshim/internal/mergemaps/merge.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package mergemaps | ||||
|  | ||||
| import "encoding/json" | ||||
|  | ||||
| // Merge recursively merges map `fromMap` into map `ToMap`. Any pre-existing values | ||||
| // in ToMap are overwritten. Values in fromMap are added to ToMap. | ||||
| // From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang | ||||
| func Merge(fromMap, ToMap interface{}) interface{} { | ||||
| 	switch fromMap := fromMap.(type) { | ||||
| 	case map[string]interface{}: | ||||
| 		ToMap, ok := ToMap.(map[string]interface{}) | ||||
| 		if !ok { | ||||
| 			return fromMap | ||||
| 		} | ||||
| 		for keyToMap, valueToMap := range ToMap { | ||||
| 			if valueFromMap, ok := fromMap[keyToMap]; ok { | ||||
| 				fromMap[keyToMap] = Merge(valueFromMap, valueToMap) | ||||
| 			} else { | ||||
| 				fromMap[keyToMap] = valueToMap | ||||
| 			} | ||||
| 		} | ||||
| 	case nil: | ||||
| 		// merge(nil, map[string]interface{...}) -> map[string]interface{...} | ||||
| 		ToMap, ok := ToMap.(map[string]interface{}) | ||||
| 		if ok { | ||||
| 			return ToMap | ||||
| 		} | ||||
| 	} | ||||
| 	return fromMap | ||||
| } | ||||
|  | ||||
| // MergeJSON merges the contents of a JSON string into an object representation, | ||||
| // returning a new object suitable for translating to JSON. | ||||
| func MergeJSON(object interface{}, additionalJSON []byte) (interface{}, error) { | ||||
| 	if len(additionalJSON) == 0 { | ||||
| 		return object, nil | ||||
| 	} | ||||
| 	objectJSON, err := json.Marshal(object) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var objectMap, newMap map[string]interface{} | ||||
| 	err = json.Unmarshal(objectJSON, &objectMap) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = json.Unmarshal(additionalJSON, &newMap) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return Merge(newMap, objectMap), nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package safefile | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| @@ -10,9 +10,13 @@ import ( | ||||
| 	"unicode/utf16" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/longpath" | ||||
| 
 | ||||
| 	winio "github.com/Microsoft/go-winio" | ||||
| ) | ||||
| 
 | ||||
| //go:generate go run $GOROOT\src\syscall\mksyscall_windows.go -output zsyscall_windows.go safeopen.go | ||||
| 
 | ||||
| //sys ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) = ntdll.NtCreateFile | ||||
| //sys ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) = ntdll.NtSetInformationFile | ||||
| //sys rtlNtStatusToDosError(status uint32) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb | ||||
| @@ -53,28 +57,28 @@ const ( | ||||
| 	_FileLinkInformation          = 11 | ||||
| 	_FileDispositionInformationEx = 64 | ||||
| 
 | ||||
| 	_FILE_READ_ATTRIBUTES  = 0x0080 | ||||
| 	_FILE_WRITE_ATTRIBUTES = 0x0100 | ||||
| 	_DELETE                = 0x10000 | ||||
| 	FILE_READ_ATTRIBUTES  = 0x0080 | ||||
| 	FILE_WRITE_ATTRIBUTES = 0x0100 | ||||
| 	DELETE                = 0x10000 | ||||
| 
 | ||||
| 	_FILE_OPEN   = 1 | ||||
| 	_FILE_CREATE = 2 | ||||
| 	FILE_OPEN   = 1 | ||||
| 	FILE_CREATE = 2 | ||||
| 
 | ||||
| 	_FILE_DIRECTORY_FILE          = 0x00000001 | ||||
| 	_FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020 | ||||
| 	_FILE_DELETE_ON_CLOSE         = 0x00001000 | ||||
| 	_FILE_OPEN_FOR_BACKUP_INTENT  = 0x00004000 | ||||
| 	_FILE_OPEN_REPARSE_POINT      = 0x00200000 | ||||
| 	FILE_DIRECTORY_FILE          = 0x00000001 | ||||
| 	FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020 | ||||
| 	FILE_DELETE_ON_CLOSE         = 0x00001000 | ||||
| 	FILE_OPEN_FOR_BACKUP_INTENT  = 0x00004000 | ||||
| 	FILE_OPEN_REPARSE_POINT      = 0x00200000 | ||||
| 
 | ||||
| 	_FILE_DISPOSITION_DELETE = 0x00000001 | ||||
| 	FILE_DISPOSITION_DELETE = 0x00000001 | ||||
| 
 | ||||
| 	_OBJ_DONT_REPARSE = 0x1000 | ||||
| 
 | ||||
| 	_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B | ||||
| ) | ||||
| 
 | ||||
| func openRoot(path string) (*os.File, error) { | ||||
| 	longpath, err := makeLongAbsPath(path) | ||||
| func OpenRoot(path string) (*os.File, error) { | ||||
| 	longpath, err := longpath.LongAbs(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -141,7 +145,7 @@ func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFl | ||||
| 		0, | ||||
| 		shareFlags, | ||||
| 		createDisposition, | ||||
| 		_FILE_OPEN_FOR_BACKUP_INTENT|_FILE_SYNCHRONOUS_IO_NONALERT|flags, | ||||
| 		FILE_OPEN_FOR_BACKUP_INTENT|FILE_SYNCHRONOUS_IO_NONALERT|flags, | ||||
| 		nil, | ||||
| 		0, | ||||
| 	) | ||||
| @@ -149,7 +153,7 @@ func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFl | ||||
| 		return nil, rtlNtStatusToDosError(status) | ||||
| 	} | ||||
| 
 | ||||
| 	fullPath, err := makeLongAbsPath(filepath.Join(root.Name(), path)) | ||||
| 	fullPath, err := longpath.LongAbs(filepath.Join(root.Name(), path)) | ||||
| 	if err != nil { | ||||
| 		syscall.Close(syscall.Handle(h)) | ||||
| 		return nil, err | ||||
| @@ -158,9 +162,9 @@ func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFl | ||||
| 	return os.NewFile(h, fullPath), nil | ||||
| } | ||||
| 
 | ||||
| // openRelative opens a relative path from the given root, failing if | ||||
| // OpenRelative opens a relative path from the given root, failing if | ||||
| // any of the intermediate path components are reparse points. | ||||
| func openRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { | ||||
| func OpenRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { | ||||
| 	f, err := openRelativeInternal(path, root, accessMask, shareFlags, createDisposition, flags) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "open", Path: filepath.Join(root.Name(), path), Err: err} | ||||
| @@ -168,17 +172,17 @@ func openRelative(path string, root *os.File, accessMask uint32, shareFlags uint | ||||
| 	return f, err | ||||
| } | ||||
| 
 | ||||
| // linkRelative creates a hard link from oldname to newname (relative to oldroot | ||||
| // LinkRelative creates a hard link from oldname to newname (relative to oldroot | ||||
| // and newroot), failing if any of the intermediate path components are reparse | ||||
| // points. | ||||
| func linkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error { | ||||
| func LinkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error { | ||||
| 	// Open the old file. | ||||
| 	oldf, err := openRelativeInternal( | ||||
| 		oldname, | ||||
| 		oldroot, | ||||
| 		syscall.FILE_WRITE_ATTRIBUTES, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 		_FILE_OPEN, | ||||
| 		FILE_OPEN, | ||||
| 		0, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| @@ -195,8 +199,8 @@ func linkRelative(oldname string, oldroot *os.File, newname string, newroot *os. | ||||
| 			newroot, | ||||
| 			syscall.GENERIC_READ, | ||||
| 			syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 			_FILE_OPEN, | ||||
| 			_FILE_DIRECTORY_FILE) | ||||
| 			FILE_OPEN, | ||||
| 			FILE_DIRECTORY_FILE) | ||||
| 		if err != nil { | ||||
| 			return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err} | ||||
| 		} | ||||
| @@ -248,7 +252,7 @@ func linkRelative(oldname string, oldroot *os.File, newname string, newroot *os. | ||||
| 
 | ||||
| // deleteOnClose marks a file to be deleted when the handle is closed. | ||||
| func deleteOnClose(f *os.File) error { | ||||
| 	disposition := fileDispositionInformationEx{Flags: _FILE_DISPOSITION_DELETE} | ||||
| 	disposition := fileDispositionInformationEx{Flags: FILE_DISPOSITION_DELETE} | ||||
| 	var iosb ioStatusBlock | ||||
| 	status := ntSetInformationFile( | ||||
| 		f.Fd(), | ||||
| @@ -281,16 +285,16 @@ func clearReadOnly(f *os.File) error { | ||||
| 	return winio.SetFileBasicInfo(f, &sbi) | ||||
| } | ||||
| 
 | ||||
| // removeRelative removes a file or directory relative to a root, failing if any | ||||
| // RemoveRelative removes a file or directory relative to a root, failing if any | ||||
| // intermediate path components are reparse points. | ||||
| func removeRelative(path string, root *os.File) error { | ||||
| func RemoveRelative(path string, root *os.File) error { | ||||
| 	f, err := openRelativeInternal( | ||||
| 		path, | ||||
| 		root, | ||||
| 		_FILE_READ_ATTRIBUTES|_FILE_WRITE_ATTRIBUTES|_DELETE, | ||||
| 		FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|DELETE, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 		_FILE_OPEN, | ||||
| 		_FILE_OPEN_REPARSE_POINT) | ||||
| 		FILE_OPEN, | ||||
| 		FILE_OPEN_REPARSE_POINT) | ||||
| 	if err == nil { | ||||
| 		defer f.Close() | ||||
| 		err = deleteOnClose(f) | ||||
| @@ -306,10 +310,10 @@ func removeRelative(path string, root *os.File) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // removeAllRelative removes a directory tree relative to a root, failing if any | ||||
| // RemoveAllRelative removes a directory tree relative to a root, failing if any | ||||
| // intermediate path components are reparse points. | ||||
| func removeAllRelative(path string, root *os.File) error { | ||||
| 	fi, err := lstatRelative(path, root) | ||||
| func RemoveAllRelative(path string, root *os.File) error { | ||||
| 	fi, err := LstatRelative(path, root) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return nil | ||||
| @@ -319,7 +323,7 @@ func removeAllRelative(path string, root *os.File) error { | ||||
| 	fileAttributes := fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes | ||||
| 	if fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 || fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { | ||||
| 		// If this is a reparse point, it can't have children. Simple remove will do. | ||||
| 		err := removeRelative(path, root) | ||||
| 		err := RemoveRelative(path, root) | ||||
| 		if err == nil || os.IsNotExist(err) { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -327,7 +331,7 @@ func removeAllRelative(path string, root *os.File) error { | ||||
| 	} | ||||
| 
 | ||||
| 	// It is necessary to use os.Open as Readdirnames does not work with | ||||
| 	// openRelative. This is safe because the above lstatrelative fails | ||||
| 	// OpenRelative. This is safe because the above lstatrelative fails | ||||
| 	// if the target is outside the root, and we know this is not a | ||||
| 	// symlink from the above FILE_ATTRIBUTE_REPARSE_POINT check. | ||||
| 	fd, err := os.Open(filepath.Join(root.Name(), path)) | ||||
| @@ -344,7 +348,7 @@ func removeAllRelative(path string, root *os.File) error { | ||||
| 	for { | ||||
| 		names, err1 := fd.Readdirnames(100) | ||||
| 		for _, name := range names { | ||||
| 			err1 := removeAllRelative(path+string(os.PathSeparator)+name, root) | ||||
| 			err1 := RemoveAllRelative(path+string(os.PathSeparator)+name, root) | ||||
| 			if err == nil { | ||||
| 				err = err1 | ||||
| 			} | ||||
| @@ -363,7 +367,7 @@ func removeAllRelative(path string, root *os.File) error { | ||||
| 	fd.Close() | ||||
| 
 | ||||
| 	// Remove directory. | ||||
| 	err1 := removeRelative(path, root) | ||||
| 	err1 := RemoveRelative(path, root) | ||||
| 	if err1 == nil || os.IsNotExist(err1) { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -373,16 +377,16 @@ func removeAllRelative(path string, root *os.File) error { | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // mkdirRelative creates a directory relative to a root, failing if any | ||||
| // MkdirRelative creates a directory relative to a root, failing if any | ||||
| // intermediate path components are reparse points. | ||||
| func mkdirRelative(path string, root *os.File) error { | ||||
| func MkdirRelative(path string, root *os.File) error { | ||||
| 	f, err := openRelativeInternal( | ||||
| 		path, | ||||
| 		root, | ||||
| 		0, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 		_FILE_CREATE, | ||||
| 		_FILE_DIRECTORY_FILE) | ||||
| 		FILE_CREATE, | ||||
| 		FILE_DIRECTORY_FILE) | ||||
| 	if err == nil { | ||||
| 		f.Close() | ||||
| 	} else { | ||||
| @@ -391,16 +395,16 @@ func mkdirRelative(path string, root *os.File) error { | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // lstatRelative performs a stat operation on a file relative to a root, failing | ||||
| // LstatRelative performs a stat operation on a file relative to a root, failing | ||||
| // if any intermediate path components are reparse points. | ||||
| func lstatRelative(path string, root *os.File) (os.FileInfo, error) { | ||||
| func LstatRelative(path string, root *os.File) (os.FileInfo, error) { | ||||
| 	f, err := openRelativeInternal( | ||||
| 		path, | ||||
| 		root, | ||||
| 		_FILE_READ_ATTRIBUTES, | ||||
| 		FILE_READ_ATTRIBUTES, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 		_FILE_OPEN, | ||||
| 		_FILE_OPEN_REPARSE_POINT) | ||||
| 		FILE_OPEN, | ||||
| 		FILE_OPEN_REPARSE_POINT) | ||||
| 	if err != nil { | ||||
| 		return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err} | ||||
| 	} | ||||
| @@ -408,16 +412,16 @@ func lstatRelative(path string, root *os.File) (os.FileInfo, error) { | ||||
| 	return f.Stat() | ||||
| } | ||||
| 
 | ||||
| // ensureNotReparsePointRelative validates that a given file (relative to a | ||||
| // EnsureNotReparsePointRelative validates that a given file (relative to a | ||||
| // root) and all intermediate path components are not a reparse points. | ||||
| func ensureNotReparsePointRelative(path string, root *os.File) error { | ||||
| func EnsureNotReparsePointRelative(path string, root *os.File) error { | ||||
| 	// Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT. | ||||
| 	f, err := openRelative( | ||||
| 	f, err := OpenRelative( | ||||
| 		path, | ||||
| 		root, | ||||
| 		0, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, | ||||
| 		_FILE_OPEN, | ||||
| 		FILE_OPEN, | ||||
| 		0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
							
								
								
									
										79
									
								
								vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package safefile | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modntdll    = windows.NewLazySystemDLL("ntdll.dll") | ||||
| 	modkernel32 = windows.NewLazySystemDLL("kernel32.dll") | ||||
|  | ||||
| 	procNtCreateFile               = modntdll.NewProc("NtCreateFile") | ||||
| 	procNtSetInformationFile       = modntdll.NewProc("NtSetInformationFile") | ||||
| 	procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") | ||||
| 	procLocalAlloc                 = modkernel32.NewProc("LocalAlloc") | ||||
| 	procLocalFree                  = modkernel32.NewProc("LocalFree") | ||||
| ) | ||||
|  | ||||
| func ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) { | ||||
| 	r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(accessMask), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(fileAttributes), uintptr(shareAccess), uintptr(createDisposition), uintptr(createOptions), uintptr(unsafe.Pointer(eaBuffer)), uintptr(eaLength), 0) | ||||
| 	status = uint32(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) { | ||||
| 	r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(information), uintptr(length), uintptr(class), 0) | ||||
| 	status = uint32(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func rtlNtStatusToDosError(status uint32) (winerr error) { | ||||
| 	r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		winerr = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func localAlloc(flags uint32, size int) (ptr uintptr) { | ||||
| 	r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(size), 0) | ||||
| 	ptr = uintptr(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func localFree(ptr uintptr) { | ||||
| 	syscall.Syscall(procLocalFree.Addr(), 1, uintptr(ptr), 0, 0) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										228
									
								
								vendor/github.com/Microsoft/hcsshim/internal/schema1/schema1.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								vendor/github.com/Microsoft/hcsshim/internal/schema1/schema1.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,228 @@ | ||||
| package schema1 | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // ProcessConfig is used as both the input of Container.CreateProcess | ||||
| // and to convert the parameters to JSON for passing onto the HCS | ||||
| type ProcessConfig struct { | ||||
| 	ApplicationName   string            `json:",omitempty"` | ||||
| 	CommandLine       string            `json:",omitempty"` | ||||
| 	CommandArgs       []string          `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| 	User              string            `json:",omitempty"` | ||||
| 	WorkingDirectory  string            `json:",omitempty"` | ||||
| 	Environment       map[string]string `json:",omitempty"` | ||||
| 	EmulateConsole    bool              `json:",omitempty"` | ||||
| 	CreateStdInPipe   bool              `json:",omitempty"` | ||||
| 	CreateStdOutPipe  bool              `json:",omitempty"` | ||||
| 	CreateStdErrPipe  bool              `json:",omitempty"` | ||||
| 	ConsoleSize       [2]uint           `json:",omitempty"` | ||||
| 	CreateInUtilityVm bool              `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| 	OCISpecification  *json.RawMessage  `json:",omitempty"` // Used by Linux Containers on Windows | ||||
| } | ||||
|  | ||||
| type Layer struct { | ||||
| 	ID   string | ||||
| 	Path string | ||||
| } | ||||
|  | ||||
| type MappedDir struct { | ||||
| 	HostPath          string | ||||
| 	ContainerPath     string | ||||
| 	ReadOnly          bool | ||||
| 	BandwidthMaximum  uint64 | ||||
| 	IOPSMaximum       uint64 | ||||
| 	CreateInUtilityVM bool | ||||
| 	// LinuxMetadata - Support added in 1803/RS4+. | ||||
| 	LinuxMetadata bool `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type MappedPipe struct { | ||||
| 	HostPath          string | ||||
| 	ContainerPipeName string | ||||
| } | ||||
|  | ||||
| type HvRuntime struct { | ||||
| 	ImagePath           string `json:",omitempty"` | ||||
| 	SkipTemplate        bool   `json:",omitempty"` | ||||
| 	LinuxInitrdFile     string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM | ||||
| 	LinuxKernelFile     string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM | ||||
| 	LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode | ||||
| 	BootSource          string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD | ||||
| 	WritableBootSource  bool   `json:",omitempty"` // Linux Utility VM booting from VHD | ||||
| } | ||||
|  | ||||
| type MappedVirtualDisk struct { | ||||
| 	HostPath          string `json:",omitempty"` // Path to VHD on the host | ||||
| 	ContainerPath     string // Platform-specific mount point path in the container | ||||
| 	CreateInUtilityVM bool   `json:",omitempty"` | ||||
| 	ReadOnly          bool   `json:",omitempty"` | ||||
| 	Cache             string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing" | ||||
| 	AttachOnly        bool   `json:",omitempty:` | ||||
| } | ||||
|  | ||||
| // AssignedDevice represents a device that has been directly assigned to a container | ||||
| // | ||||
| // NOTE: Support added in RS5 | ||||
| type AssignedDevice struct { | ||||
| 	//  InterfaceClassGUID of the device to assign to container. | ||||
| 	InterfaceClassGUID string `json:"InterfaceClassGuid,omitempty"` | ||||
| } | ||||
|  | ||||
| // ContainerConfig is used as both the input of CreateContainer | ||||
| // and to convert the parameters to JSON for passing onto the HCS | ||||
| type ContainerConfig struct { | ||||
| 	SystemType                  string              // HCS requires this to be hard-coded to "Container" | ||||
| 	Name                        string              // Name of the container. We use the docker ID. | ||||
| 	Owner                       string              `json:",omitempty"` // The management platform that created this container | ||||
| 	VolumePath                  string              `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID} | ||||
| 	IgnoreFlushesDuringBoot     bool                `json:",omitempty"` // Optimization hint for container startup in Windows | ||||
| 	LayerFolderPath             string              `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format  %root%\windowsfilter\containerID | ||||
| 	Layers                      []Layer             // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID | ||||
| 	Credentials                 string              `json:",omitempty"` // Credentials information | ||||
| 	ProcessorCount              uint32              `json:",omitempty"` // Number of processors to assign to the container. | ||||
| 	ProcessorWeight             uint64              `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares. | ||||
| 	ProcessorMaximum            int64               `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit. | ||||
| 	StorageIOPSMaximum          uint64              `json:",omitempty"` // Maximum Storage IOPS | ||||
| 	StorageBandwidthMaximum     uint64              `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second | ||||
| 	StorageSandboxSize          uint64              `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller | ||||
| 	MemoryMaximumInMB           int64               `json:",omitempty"` // Maximum memory available to the container in Megabytes | ||||
| 	HostName                    string              `json:",omitempty"` // Hostname | ||||
| 	MappedDirectories           []MappedDir         `json:",omitempty"` // List of mapped directories (volumes/mounts) | ||||
| 	MappedPipes                 []MappedPipe        `json:",omitempty"` // List of mapped Windows named pipes | ||||
| 	HvPartition                 bool                // True if it a Hyper-V Container | ||||
| 	NetworkSharedContainerName  string              `json:",omitempty"` // Name (ID) of the container that we will share the network stack with. | ||||
| 	EndpointList                []string            `json:",omitempty"` // List of networking endpoints to be attached to container | ||||
| 	HvRuntime                   *HvRuntime          `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM | ||||
| 	Servicing                   bool                `json:",omitempty"` // True if this container is for servicing | ||||
| 	AllowUnqualifiedDNSQuery    bool                `json:",omitempty"` // True to allow unqualified DNS name resolution | ||||
| 	DNSSearchList               string              `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution | ||||
| 	ContainerType               string              `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise. | ||||
| 	TerminateOnLastHandleClosed bool                `json:",omitempty"` // Should HCS terminate the container once all handles have been closed | ||||
| 	MappedVirtualDisks          []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start | ||||
| 	AssignedDevices             []AssignedDevice    `json:",omitempty"` // Array of devices to assign. NOTE: Support added in RS5 | ||||
| } | ||||
|  | ||||
| type ComputeSystemQuery struct { | ||||
| 	IDs    []string `json:"Ids,omitempty"` | ||||
| 	Types  []string `json:",omitempty"` | ||||
| 	Names  []string `json:",omitempty"` | ||||
| 	Owners []string `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type PropertyType string | ||||
|  | ||||
| const ( | ||||
| 	PropertyTypeStatistics        PropertyType = "Statistics" | ||||
| 	PropertyTypeProcessList                    = "ProcessList" | ||||
| 	PropertyTypeMappedVirtualDisk              = "MappedVirtualDisk" | ||||
| ) | ||||
|  | ||||
| type PropertyQuery struct { | ||||
| 	PropertyTypes []PropertyType `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // ContainerProperties holds the properties for a container and the processes running in that container | ||||
| type ContainerProperties struct { | ||||
| 	ID                           string `json:"Id"` | ||||
| 	State                        string | ||||
| 	Name                         string | ||||
| 	SystemType                   string | ||||
| 	Owner                        string | ||||
| 	SiloGUID                     string                              `json:"SiloGuid,omitempty"` | ||||
| 	RuntimeID                    string                              `json:"RuntimeId,omitempty"` | ||||
| 	IsRuntimeTemplate            bool                                `json:",omitempty"` | ||||
| 	RuntimeImagePath             string                              `json:",omitempty"` | ||||
| 	Stopped                      bool                                `json:",omitempty"` | ||||
| 	ExitType                     string                              `json:",omitempty"` | ||||
| 	AreUpdatesPending            bool                                `json:",omitempty"` | ||||
| 	ObRoot                       string                              `json:",omitempty"` | ||||
| 	Statistics                   Statistics                          `json:",omitempty"` | ||||
| 	ProcessList                  []ProcessListItem                   `json:",omitempty"` | ||||
| 	MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // MemoryStats holds the memory statistics for a container | ||||
| type MemoryStats struct { | ||||
| 	UsageCommitBytes            uint64 `json:"MemoryUsageCommitBytes,omitempty"` | ||||
| 	UsageCommitPeakBytes        uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"` | ||||
| 	UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` | ||||
| } | ||||
|  | ||||
| // ProcessorStats holds the processor statistics for a container | ||||
| type ProcessorStats struct { | ||||
| 	TotalRuntime100ns  uint64 `json:",omitempty"` | ||||
| 	RuntimeUser100ns   uint64 `json:",omitempty"` | ||||
| 	RuntimeKernel100ns uint64 `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // StorageStats holds the storage statistics for a container | ||||
| type StorageStats struct { | ||||
| 	ReadCountNormalized  uint64 `json:",omitempty"` | ||||
| 	ReadSizeBytes        uint64 `json:",omitempty"` | ||||
| 	WriteCountNormalized uint64 `json:",omitempty"` | ||||
| 	WriteSizeBytes       uint64 `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // NetworkStats holds the network statistics for a container | ||||
| type NetworkStats struct { | ||||
| 	BytesReceived          uint64 `json:",omitempty"` | ||||
| 	BytesSent              uint64 `json:",omitempty"` | ||||
| 	PacketsReceived        uint64 `json:",omitempty"` | ||||
| 	PacketsSent            uint64 `json:",omitempty"` | ||||
| 	DroppedPacketsIncoming uint64 `json:",omitempty"` | ||||
| 	DroppedPacketsOutgoing uint64 `json:",omitempty"` | ||||
| 	EndpointId             string `json:",omitempty"` | ||||
| 	InstanceId             string `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // Statistics is the structure returned by a statistics call on a container | ||||
| type Statistics struct { | ||||
| 	Timestamp          time.Time      `json:",omitempty"` | ||||
| 	ContainerStartTime time.Time      `json:",omitempty"` | ||||
| 	Uptime100ns        uint64         `json:",omitempty"` | ||||
| 	Memory             MemoryStats    `json:",omitempty"` | ||||
| 	Processor          ProcessorStats `json:",omitempty"` | ||||
| 	Storage            StorageStats   `json:",omitempty"` | ||||
| 	Network            []NetworkStats `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // ProcessList is the structure of an item returned by a ProcessList call on a container | ||||
| type ProcessListItem struct { | ||||
| 	CreateTimestamp              time.Time `json:",omitempty"` | ||||
| 	ImageName                    string    `json:",omitempty"` | ||||
| 	KernelTime100ns              uint64    `json:",omitempty"` | ||||
| 	MemoryCommitBytes            uint64    `json:",omitempty"` | ||||
| 	MemoryWorkingSetPrivateBytes uint64    `json:",omitempty"` | ||||
| 	MemoryWorkingSetSharedBytes  uint64    `json:",omitempty"` | ||||
| 	ProcessId                    uint32    `json:",omitempty"` | ||||
| 	UserTime100ns                uint64    `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container | ||||
| type MappedVirtualDiskController struct { | ||||
| 	MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| // Type of Request Support in ModifySystem | ||||
| type RequestType string | ||||
|  | ||||
| // Type of Resource Support in ModifySystem | ||||
| type ResourceType string | ||||
|  | ||||
| // RequestType const | ||||
| const ( | ||||
| 	Add     RequestType  = "Add" | ||||
| 	Remove  RequestType  = "Remove" | ||||
| 	Network ResourceType = "Network" | ||||
| ) | ||||
|  | ||||
| // ResourceModificationRequestResponse is the structure used to send request to the container to modify the system | ||||
| // Supported resource types are Network and Request Types are Add/Remove | ||||
| type ResourceModificationRequestResponse struct { | ||||
| 	Resource ResourceType `json:"ResourceType"` | ||||
| 	Data     interface{}  `json:"Settings"` | ||||
| 	Request  RequestType  `json:"RequestType,omitempty"` | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package timeout | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // Duration is the default time to wait for various operations. | ||||
| // - Waiting for async notifications from HCS | ||||
| // - Waiting for processes to launch through | ||||
| // - Waiting to copy data to/from a launched processes stdio pipes. | ||||
| // | ||||
| // This can be overridden through environment variable `HCS_TIMEOUT_SECONDS` | ||||
|  | ||||
| var Duration = 4 * time.Minute | ||||
|  | ||||
| func init() { | ||||
| 	envTimeout := os.Getenv("HCSSHIM_TIMEOUT_SECONDS") | ||||
| 	if len(envTimeout) > 0 { | ||||
| 		e, err := strconv.Atoi(envTimeout) | ||||
| 		if err == nil && e > 0 { | ||||
| 			Duration = time.Second * time.Duration(e) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // ActivateLayer will find the layer with the given id and mount it's filesystem. | ||||
| // For a read/write layer, the mounted filesystem will appear as a volume on the | ||||
| // host, while a read-only layer is generally expected to be a no-op. | ||||
| // An activated layer must later be deactivated via DeactivateLayer. | ||||
| func ActivateLayer(path string) error { | ||||
| 	title := "hcsshim::ActivateLayer " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	err := activateLayer(&stdDriverInfo, path) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" - succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| @@ -7,6 +7,8 @@ import ( | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/safefile" | ||||
| ) | ||||
| 
 | ||||
| type baseLayerWriter struct { | ||||
| @@ -29,7 +31,7 @@ type dirInfo struct { | ||||
| func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error { | ||||
| 	for i := range dis { | ||||
| 		di := &dis[len(dis)-i-1] // reverse order: process child directories first | ||||
| 		f, err := openRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_OPEN, _FILE_DIRECTORY_FILE) | ||||
| 		f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_OPEN, safefile.FILE_DIRECTORY_FILE) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -84,21 +86,21 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e | ||||
| 
 | ||||
| 	extraFlags := uint32(0) | ||||
| 	if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { | ||||
| 		extraFlags |= _FILE_DIRECTORY_FILE | ||||
| 		extraFlags |= safefile.FILE_DIRECTORY_FILE | ||||
| 		if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { | ||||
| 			w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo}) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY) | ||||
| 	f, err = openRelative(name, w.root, mode, syscall.FILE_SHARE_READ, _FILE_CREATE, extraFlags) | ||||
| 	f, err = safefile.OpenRelative(name, w.root, mode, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, extraFlags) | ||||
| 	if err != nil { | ||||
| 		return makeError(err, "Failed to openRelative", name) | ||||
| 		return hcserror.New(err, "Failed to safefile.OpenRelative", name) | ||||
| 	} | ||||
| 
 | ||||
| 	err = winio.SetFileBasicInfo(f, fileInfo) | ||||
| 	if err != nil { | ||||
| 		return makeError(err, "Failed to SetFileBasicInfo", name) | ||||
| 		return hcserror.New(err, "Failed to SetFileBasicInfo", name) | ||||
| 	} | ||||
| 
 | ||||
| 	w.f = f | ||||
| @@ -119,7 +121,7 @@ func (w *baseLayerWriter) AddLink(name string, target string) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return linkRelative(target, w.root, name, w.root) | ||||
| 	return safefile.LinkRelative(target, w.root, name, w.root) | ||||
| } | ||||
| 
 | ||||
| func (w *baseLayerWriter) Remove(name string) error { | ||||
| @@ -157,7 +159,7 @@ func (w *baseLayerWriter) Close() error { | ||||
| 		} | ||||
| 
 | ||||
| 		if w.hasUtilityVM { | ||||
| 			err := ensureNotReparsePointRelative("UtilityVM", w.root) | ||||
| 			err := safefile.EnsureNotReparsePointRelative("UtilityVM", w.root) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
							
								
								
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // CreateLayer creates a new, empty, read-only layer on the filesystem based on | ||||
| // the parent layer provided. | ||||
| func CreateLayer(path, parent string) error { | ||||
| 	title := "hcsshim::CreateLayer " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s parent %s", path, parent) | ||||
|  | ||||
| 	err := createLayer(&stdDriverInfo, path, parent) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s parent=%s flavour=%d", path, parent) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" - succeeded path=%s parent=%s flavour=%d", path, parent) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // CreateScratchLayer creates and populates new read-write layer for use by a container. | ||||
| // This requires both the id of the direct parent layer, as well as the full list | ||||
| // of paths to all parent layers up to the base (and including the direct parent | ||||
| // whose id was provided). | ||||
| func CreateScratchLayer(path string, parentLayerPaths []string) error { | ||||
| 	title := "hcsshim::CreateScratchLayer " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	// Generate layer descriptors | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = createSandboxLayer(&stdDriverInfo, path, 0, layers) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"- succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // DeactivateLayer will dismount a layer that was mounted via ActivateLayer. | ||||
| func DeactivateLayer(path string) error { | ||||
| 	title := "hcsshim::DeactivateLayer " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	err := deactivateLayer(&stdDriverInfo, path) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // DestroyLayer will remove the on-disk files representing the layer with the given | ||||
| // path, including that layer's containing folder, if any. | ||||
| func DestroyLayer(path string) error { | ||||
| 	title := "hcsshim::DestroyLayer " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	err := destroyLayer(&stdDriverInfo, path) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // ExpandScratchSize expands the size of a layer to at least size bytes. | ||||
| func ExpandScratchSize(path string, size uint64) error { | ||||
| 	title := "hcsshim::ExpandScratchSize " | ||||
| 	logrus.Debugf(title+"path=%s size=%d", path, size) | ||||
|  | ||||
| 	err := expandSandboxSize(&stdDriverInfo, path, size) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s size=%d", path, size) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"- succeeded path=%s size=%d", path, size) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| @@ -7,6 +7,8 @@ import ( | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| @@ -15,9 +17,9 @@ import ( | ||||
| // format includes any metadata required for later importing the layer (using | ||||
| // ImportLayer), and requires the full list of parent layer paths in order to | ||||
| // perform the export. | ||||
| func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error { | ||||
| func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string) error { | ||||
| 	title := "hcsshim::ExportLayer " | ||||
| 	logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath) | ||||
| 	logrus.Debugf(title+"path %s folder %s", path, exportFolderPath) | ||||
| 
 | ||||
| 	// Generate layer descriptors | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| @@ -25,21 +27,14 @@ func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, paren | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	err = exportLayer(&stdDriverInfo, path, exportFolderPath, layers) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s folder=%s", path, exportFolderPath) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = exportLayer(&infop, layerId, exportFolderPath, layers) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath) | ||||
| 	logrus.Debugf(title+"succeeded path=%s folder=%s", path, exportFolderPath) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -69,11 +64,11 @@ func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) | ||||
| 		if err == syscall.ERROR_NO_MORE_FILES { | ||||
| 			err = io.EOF | ||||
| 		} else { | ||||
| 			err = makeError(err, "ExportLayerNext", "") | ||||
| 			err = hcserror.New(err, "ExportLayerNext", "") | ||||
| 		} | ||||
| 		return "", 0, nil, err | ||||
| 	} | ||||
| 	fileName := convertAndFreeCoTaskMemString(fileNamep) | ||||
| 	fileName := interop.ConvertAndFreeCoTaskMemString(fileNamep) | ||||
| 	if deleted != 0 { | ||||
| 		fileInfo = nil | ||||
| 	} | ||||
| @@ -88,7 +83,7 @@ func (r *FilterLayerReader) Read(b []byte) (int, error) { | ||||
| 	var bytesRead uint32 | ||||
| 	err := exportLayerRead(r.context, b, &bytesRead) | ||||
| 	if err != nil { | ||||
| 		return 0, makeError(err, "ExportLayerRead", "") | ||||
| 		return 0, hcserror.New(err, "ExportLayerRead", "") | ||||
| 	} | ||||
| 	if bytesRead == 0 { | ||||
| 		return 0, io.EOF | ||||
| @@ -103,7 +98,7 @@ func (r *FilterLayerReader) Close() (err error) { | ||||
| 	if r.context != 0 { | ||||
| 		err = exportLayerEnd(r.context) | ||||
| 		if err != nil { | ||||
| 			err = makeError(err, "ExportLayerEnd", "") | ||||
| 			err = hcserror.New(err, "ExportLayerEnd", "") | ||||
| 		} | ||||
| 		r.context = 0 | ||||
| 	} | ||||
| @@ -113,34 +108,30 @@ func (r *FilterLayerReader) Close() (err error) { | ||||
| // NewLayerReader returns a new layer reader for reading the contents of an on-disk layer. | ||||
| // The caller must have taken the SeBackupPrivilege privilege | ||||
| // to call this and any methods on the resulting LayerReader. | ||||
| func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) { | ||||
| func NewLayerReader(path string, parentLayerPaths []string) (LayerReader, error) { | ||||
| 	if procExportLayerBegin.Find() != nil { | ||||
| 		// The new layer reader is not available on this Windows build. Fall back to the | ||||
| 		// legacy export code path. | ||||
| 		path, err := ioutil.TempDir("", "hcs") | ||||
| 		exportPath, err := ioutil.TempDir("", "hcs") | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		err = ExportLayer(info, layerID, path, parentLayerPaths) | ||||
| 		err = ExportLayer(path, exportPath, parentLayerPaths) | ||||
| 		if err != nil { | ||||
| 			os.RemoveAll(path) | ||||
| 			os.RemoveAll(exportPath) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return &legacyLayerReaderWrapper{newLegacyLayerReader(path)}, nil | ||||
| 		return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r := &FilterLayerReader{} | ||||
| 	err = exportLayerBegin(&infop, layerID, layers, &r.context) | ||||
| 	err = exportLayerBegin(&stdDriverInfo, path, layers, &r.context) | ||||
| 	if err != nil { | ||||
| 		return nil, makeError(err, "ExportLayerBegin", "") | ||||
| 		return nil, hcserror.New(err, "ExportLayerBegin", "") | ||||
| 	} | ||||
| 	return r, err | ||||
| } | ||||
| @@ -1,34 +1,28 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| // GetLayerMountPath will look for a mounted layer with the given id and return | ||||
| // GetLayerMountPath will look for a mounted layer with the given path and return | ||||
| // the path at which that layer can be accessed.  This path may be a volume path | ||||
| // if the layer is a mounted read-write layer, otherwise it is expected to be the | ||||
| // folder path at which the layer is stored. | ||||
| func GetLayerMountPath(info DriverInfo, id string) (string, error) { | ||||
| func GetLayerMountPath(path string) (string, error) { | ||||
| 	title := "hcsshim::GetLayerMountPath " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) | ||||
| 
 | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return "", err | ||||
| 	} | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
| 
 | ||||
| 	var mountPathLength uintptr | ||||
| 	mountPathLength = 0 | ||||
| 
 | ||||
| 	// Call the procedure itself. | ||||
| 	logrus.Debugf("Calling proc (1)") | ||||
| 	err = getLayerMountPath(&infop, id, &mountPathLength, nil) | ||||
| 	err := getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour) | ||||
| 		err = hcserror.Errorf(err, title, "(first call) path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -42,14 +36,14 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) { | ||||
| 
 | ||||
| 	// Call the procedure again | ||||
| 	logrus.Debugf("Calling proc (2)") | ||||
| 	err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0]) | ||||
| 	err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, &mountPathp[0]) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour) | ||||
| 		err = hcserror.Errorf(err, title, "(second call) path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	path := syscall.UTF16ToString(mountPathp[0:]) | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path) | ||||
| 	return path, nil | ||||
| 	mountPath := syscall.UTF16ToString(mountPathp[0:]) | ||||
| 	logrus.Debugf(title+"succeeded path=%s mountPath=%s", path, mountPath) | ||||
| 	return mountPath, nil | ||||
| } | ||||
| @@ -1,6 +1,10 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import "github.com/sirupsen/logrus" | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| // GetSharedBaseImages will enumerate the images stored in the common central | ||||
| // image store and return descriptive info about those images for the purpose | ||||
| @@ -12,11 +16,11 @@ func GetSharedBaseImages() (imageData string, err error) { | ||||
| 	var buffer *uint16 | ||||
| 	err = getBaseImages(&buffer) | ||||
| 	if err != nil { | ||||
| 		err = makeError(err, title, "") | ||||
| 		err = hcserror.New(err, title, "") | ||||
| 		logrus.Error(err) | ||||
| 		return | ||||
| 	} | ||||
| 	imageData = convertAndFreeCoTaskMemString(buffer) | ||||
| 	imageData = interop.ConvertAndFreeCoTaskMemString(buffer) | ||||
| 	logrus.Debugf(title+" - succeeded output=%s", imageData) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // GrantVmAccess adds access to a file for a given VM | ||||
| func GrantVmAccess(vmid string, filepath string) error { | ||||
| 	title := fmt.Sprintf("hcsshim::GrantVmAccess id:%s path:%s ", vmid, filepath) | ||||
| 	logrus.Debugf(title) | ||||
|  | ||||
| 	err := grantVmAccess(vmid, filepath) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", filepath) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title + " - succeeded") | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| @@ -7,6 +7,8 @@ import ( | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/Microsoft/hcsshim/internal/safefile" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| @@ -14,9 +16,9 @@ import ( | ||||
| // that into a layer with the id layerId.  Note that in order to correctly populate | ||||
| // the layer and interperet the transport format, all parent layers must already | ||||
| // be present on the system at the paths provided in parentLayerPaths. | ||||
| func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error { | ||||
| func ImportLayer(path string, importFolderPath string, parentLayerPaths []string) error { | ||||
| 	title := "hcsshim::ImportLayer " | ||||
| 	logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerID, importFolderPath) | ||||
| 	logrus.Debugf(title+"path %s folder %s", path, importFolderPath) | ||||
| 
 | ||||
| 	// Generate layer descriptors | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| @@ -24,21 +26,14 @@ func ImportLayer(info DriverInfo, layerID string, importFolderPath string, paren | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	err = importLayer(&stdDriverInfo, path, importFolderPath, layers) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s folder=%s", path, importFolderPath) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = importLayer(&infop, layerID, importFolderPath, layers) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerID, info.Flavour, importFolderPath) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerID, importFolderPath) | ||||
| 	logrus.Debugf(title+"succeeded path=%s folder=%s", path, importFolderPath) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -73,7 +68,7 @@ func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 	} | ||||
| 	err := importLayerNext(w.context, name, fileInfo) | ||||
| 	if err != nil { | ||||
| 		return makeError(err, "ImportLayerNext", "") | ||||
| 		return hcserror.New(err, "ImportLayerNext", "") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -92,7 +87,7 @@ func (w *FilterLayerWriter) Remove(name string) error { | ||||
| 	} | ||||
| 	err := importLayerNext(w.context, name, nil) | ||||
| 	if err != nil { | ||||
| 		return makeError(err, "ImportLayerNext", "") | ||||
| 		return hcserror.New(err, "ImportLayerNext", "") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -101,7 +96,7 @@ func (w *FilterLayerWriter) Remove(name string) error { | ||||
| func (w *FilterLayerWriter) Write(b []byte) (int, error) { | ||||
| 	err := importLayerWrite(w.context, b) | ||||
| 	if err != nil { | ||||
| 		err = makeError(err, "ImportLayerWrite", "") | ||||
| 		err = hcserror.New(err, "ImportLayerWrite", "") | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return len(b), err | ||||
| @@ -113,7 +108,7 @@ func (w *FilterLayerWriter) Close() (err error) { | ||||
| 	if w.context != 0 { | ||||
| 		err = importLayerEnd(w.context) | ||||
| 		if err != nil { | ||||
| 			err = makeError(err, "ImportLayerEnd", "") | ||||
| 			err = hcserror.New(err, "ImportLayerEnd", "") | ||||
| 		} | ||||
| 		w.context = 0 | ||||
| 	} | ||||
| @@ -122,8 +117,6 @@ func (w *FilterLayerWriter) Close() (err error) { | ||||
| 
 | ||||
| type legacyLayerWriterWrapper struct { | ||||
| 	*legacyLayerWriter | ||||
| 	info             DriverInfo | ||||
| 	layerID          string | ||||
| 	path             string | ||||
| 	parentLayerPaths []string | ||||
| } | ||||
| @@ -136,28 +129,26 @@ func (r *legacyLayerWriterWrapper) Close() error { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	info := r.info | ||||
| 	info.HomeDir = "" | ||||
| 	if err = ImportLayer(info, r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil { | ||||
| 	if err = ImportLayer(r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, name := range r.Tombstones { | ||||
| 		if err = removeRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) { | ||||
| 		if err = safefile.RemoveRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	// Add any hard links that were collected. | ||||
| 	for _, lnk := range r.PendingLinks { | ||||
| 		if err = removeRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) { | ||||
| 		if err = safefile.RemoveRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err = linkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil { | ||||
| 		if err = safefile.LinkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	// Prepare the utility VM for use if one is present in the layer. | ||||
| 	if r.HasUtilityVM { | ||||
| 		err := ensureNotReparsePointRelative("UtilityVM", r.destRoot) | ||||
| 		err := safefile.EnsureNotReparsePointRelative("UtilityVM", r.destRoot) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -172,10 +163,10 @@ func (r *legacyLayerWriterWrapper) Close() error { | ||||
| // NewLayerWriter returns a new layer writer for creating a layer on disk. | ||||
| // The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges | ||||
| // to call this and any methods on the resulting LayerWriter. | ||||
| func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) { | ||||
| func NewLayerWriter(path string, parentLayerPaths []string) (LayerWriter, error) { | ||||
| 	if len(parentLayerPaths) == 0 { | ||||
| 		// This is a base layer. It gets imported differently. | ||||
| 		f, err := openRoot(filepath.Join(info.HomeDir, layerID)) | ||||
| 		f, err := safefile.OpenRoot(path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -187,19 +178,17 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) | ||||
| 	if procImportLayerBegin.Find() != nil { | ||||
| 		// The new layer reader is not available on this Windows build. Fall back to the | ||||
| 		// legacy export code path. | ||||
| 		path, err := ioutil.TempDir("", "hcs") | ||||
| 		importPath, err := ioutil.TempDir("", "hcs") | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		w, err := newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)) | ||||
| 		w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return &legacyLayerWriterWrapper{ | ||||
| 			legacyLayerWriter: w, | ||||
| 			info:              info, | ||||
| 			layerID:           layerID, | ||||
| 			path:              path, | ||||
| 			path:              importPath, | ||||
| 			parentLayerPaths:  parentLayerPaths, | ||||
| 		}, nil | ||||
| 	} | ||||
| @@ -208,15 +197,10 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	w := &FilterLayerWriter{} | ||||
| 	err = importLayerBegin(&infop, layerID, layers, &w.context) | ||||
| 	err = importLayerBegin(&stdDriverInfo, path, layers, &w.context) | ||||
| 	if err != nil { | ||||
| 		return nil, makeError(err, "ImportLayerStart", "") | ||||
| 		return nil, hcserror.New(err, "ImportLayerStart", "") | ||||
| 	} | ||||
| 	return w, nil | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // LayerExists will return true if a layer with the given id exists and is known | ||||
| // to the system. | ||||
| func LayerExists(path string) (bool, error) { | ||||
| 	title := "hcsshim::LayerExists " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	// Call the procedure itself. | ||||
| 	var exists uint32 | ||||
| 	err := layerExists(&stdDriverInfo, path, &exists) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded path=%s exists=%d", path, exists) | ||||
| 	return exists != 0, nil | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/guid" | ||||
| ) | ||||
|  | ||||
| // LayerID returns the layer ID of a layer on disk. | ||||
| func LayerID(path string) (guid.GUID, error) { | ||||
| 	_, file := filepath.Split(path) | ||||
| 	return NameToGuid(file) | ||||
| } | ||||
| @@ -1,12 +1,12 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| // This file contains utility functions to support storage (graph) related | ||||
| // functionality. | ||||
| 
 | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/guid" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| @@ -22,28 +22,16 @@ struct DriverInfo { | ||||
|     LPCWSTR HomeDir; | ||||
| }; | ||||
| */ | ||||
| type DriverInfo struct { | ||||
| 	Flavour int | ||||
| 	HomeDir string | ||||
| } | ||||
| 
 | ||||
| type driverInfo struct { | ||||
| 	Flavour  int | ||||
| 	HomeDirp *uint16 | ||||
| } | ||||
| 
 | ||||
| func convertDriverInfo(info DriverInfo) (driverInfo, error) { | ||||
| 	homedirp, err := syscall.UTF16PtrFromString(info.HomeDir) | ||||
| 	if err != nil { | ||||
| 		logrus.Debugf("Failed conversion of home to pointer for driver info: %s", err.Error()) | ||||
| 		return driverInfo{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	return driverInfo{ | ||||
| 		Flavour:  info.Flavour, | ||||
| 		HomeDirp: homedirp, | ||||
| 	}, nil | ||||
| } | ||||
| var ( | ||||
| 	utf16EmptyString uint16 | ||||
| 	stdDriverInfo    = driverInfo{1, &utf16EmptyString} | ||||
| ) | ||||
| 
 | ||||
| /* To pass into syscall, we need a struct matching the following: | ||||
| typedef struct _WC_LAYER_DESCRIPTOR { | ||||
| @@ -75,7 +63,7 @@ typedef struct _WC_LAYER_DESCRIPTOR { | ||||
| } WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR; | ||||
| */ | ||||
| type WC_LAYER_DESCRIPTOR struct { | ||||
| 	LayerId GUID | ||||
| 	LayerId guid.GUID | ||||
| 	Flags   uint32 | ||||
| 	Pathp   *uint16 | ||||
| } | ||||
| @@ -85,10 +73,7 @@ func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, | ||||
| 	var layers []WC_LAYER_DESCRIPTOR | ||||
| 
 | ||||
| 	for i := 0; i < len(parentLayerPaths); i++ { | ||||
| 		// Create a layer descriptor, using the folder name | ||||
| 		// as the source for a GUID LayerId | ||||
| 		_, folderName := filepath.Split(parentLayerPaths[i]) | ||||
| 		g, err := NameToGuid(folderName) | ||||
| 		g, err := LayerID(parentLayerPaths[i]) | ||||
| 		if err != nil { | ||||
| 			logrus.Debugf("Failed to convert name to guid %s", err) | ||||
| 			return nil, err | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| @@ -6,12 +6,15 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/Microsoft/hcsshim/internal/longpath" | ||||
| 	"github.com/Microsoft/hcsshim/internal/safefile" | ||||
| ) | ||||
| 
 | ||||
| var errorIterationCanceled = errors.New("") | ||||
| @@ -34,23 +37,6 @@ func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os | ||||
| 	return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition) | ||||
| } | ||||
| 
 | ||||
| func makeLongAbsPath(path string) (string, error) { | ||||
| 	if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) { | ||||
| 		return path, nil | ||||
| 	} | ||||
| 	if !filepath.IsAbs(path) { | ||||
| 		absPath, err := filepath.Abs(path) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		path = absPath | ||||
| 	} | ||||
| 	if strings.HasPrefix(path, `\\`) { | ||||
| 		return `\\?\UNC\` + path[2:], nil | ||||
| 	} | ||||
| 	return `\\?\` + path, nil | ||||
| } | ||||
| 
 | ||||
| func hasPathPrefix(p, prefix string) bool { | ||||
| 	return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\' | ||||
| } | ||||
| @@ -106,7 +92,7 @@ func readTombstones(path string) (map[string]([]string), error) { | ||||
| } | ||||
| 
 | ||||
| func (r *legacyLayerReader) walkUntilCancelled() error { | ||||
| 	root, err := makeLongAbsPath(r.root) | ||||
| 	root, err := longpath.LongAbs(r.root) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -349,6 +335,7 @@ type legacyLayerWriter struct { | ||||
| 	destRoot        *os.File | ||||
| 	parentRoots     []*os.File | ||||
| 	currentFile     *os.File | ||||
| 	bufWriter       *bufio.Writer | ||||
| 	currentFileName string | ||||
| 	currentFileRoot *os.File | ||||
| 	backupWriter    *winio.BackupFileWriter | ||||
| @@ -373,21 +360,22 @@ func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w | ||||
| 			w = nil | ||||
| 		} | ||||
| 	}() | ||||
| 	w.root, err = openRoot(root) | ||||
| 	w.root, err = safefile.OpenRoot(root) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	w.destRoot, err = openRoot(destRoot) | ||||
| 	w.destRoot, err = safefile.OpenRoot(destRoot) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	for _, r := range parentRoots { | ||||
| 		f, err := openRoot(r) | ||||
| 		f, err := safefile.OpenRoot(r) | ||||
| 		if err != nil { | ||||
| 			return w, err | ||||
| 		} | ||||
| 		w.parentRoots = append(w.parentRoots, f) | ||||
| 	} | ||||
| 	w.bufWriter = bufio.NewWriterSize(ioutil.Discard, 65536) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| @@ -408,7 +396,7 @@ func (w *legacyLayerWriter) CloseRoots() { | ||||
| 
 | ||||
| func (w *legacyLayerWriter) initUtilityVM() error { | ||||
| 	if !w.HasUtilityVM { | ||||
| 		err := mkdirRelative(utilityVMPath, w.destRoot) | ||||
| 		err := safefile.MkdirRelative(utilityVMPath, w.destRoot) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -426,6 +414,11 @@ func (w *legacyLayerWriter) initUtilityVM() error { | ||||
| } | ||||
| 
 | ||||
| func (w *legacyLayerWriter) reset() error { | ||||
| 	err := w.bufWriter.Flush() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	w.bufWriter.Reset(ioutil.Discard) | ||||
| 	if w.currentIsDir { | ||||
| 		r := w.currentFile | ||||
| 		br := winio.NewBackupStreamReader(r) | ||||
| @@ -449,7 +442,7 @@ func (w *legacyLayerWriter) reset() error { | ||||
| 				// describes a directory reparse point. Delete the placeholder | ||||
| 				// directory to prevent future files being added into the | ||||
| 				// destination of the reparse point during the ImportLayer call | ||||
| 				if err := removeRelative(w.currentFileName, w.currentFileRoot); err != nil { | ||||
| 				if err := safefile.RemoveRelative(w.currentFileName, w.currentFileRoot); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				w.pendingDirs = append(w.pendingDirs, pendingDir{Path: w.currentFileName, Root: w.currentFileRoot}) | ||||
| @@ -474,13 +467,13 @@ func (w *legacyLayerWriter) reset() error { | ||||
| 
 | ||||
| // copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata | ||||
| func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) { | ||||
| 	src, err := openRelative( | ||||
| 	src, err := safefile.OpenRelative( | ||||
| 		subPath, | ||||
| 		srcRoot, | ||||
| 		syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, | ||||
| 		syscall.FILE_SHARE_READ, | ||||
| 		_FILE_OPEN, | ||||
| 		_FILE_OPEN_REPARSE_POINT) | ||||
| 		safefile.FILE_OPEN, | ||||
| 		safefile.FILE_OPEN_REPARSE_POINT) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -495,14 +488,14 @@ func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool | ||||
| 
 | ||||
| 	extraFlags := uint32(0) | ||||
| 	if isDir { | ||||
| 		extraFlags |= _FILE_DIRECTORY_FILE | ||||
| 		extraFlags |= safefile.FILE_DIRECTORY_FILE | ||||
| 	} | ||||
| 	dest, err := openRelative( | ||||
| 	dest, err := safefile.OpenRelative( | ||||
| 		subPath, | ||||
| 		destRoot, | ||||
| 		syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, | ||||
| 		syscall.FILE_SHARE_READ, | ||||
| 		_FILE_CREATE, | ||||
| 		safefile.FILE_CREATE, | ||||
| 		extraFlags) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -534,7 +527,7 @@ func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool | ||||
| // the file names in the provided map and just copies those files. | ||||
| func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error { | ||||
| 	var di []dirInfo | ||||
| 	err := ensureNotReparsePointRelative(subPath, srcRoot) | ||||
| 	err := safefile.EnsureNotReparsePointRelative(subPath, srcRoot) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -566,18 +559,12 @@ func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles | ||||
| 				di = append(di, dirInfo{path: relPath, fileInfo: *fi}) | ||||
| 			} | ||||
| 		} else { | ||||
| 			err = linkRelative(relPath, srcRoot, relPath, destRoot) | ||||
| 			err = safefile.LinkRelative(relPath, srcRoot, relPath, destRoot) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Don't recurse on reparse points in go1.8 and older. Filepath.Walk | ||||
| 		// handles this in go1.9 and newer. | ||||
| 		if isDir && isReparsePoint && shouldSkipDirectoryReparse { | ||||
| 			return filepath.SkipDir | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| @@ -604,9 +591,9 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 		if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath { | ||||
| 			return errors.New("invalid UtilityVM layer") | ||||
| 		} | ||||
| 		createDisposition := uint32(_FILE_OPEN) | ||||
| 		createDisposition := uint32(safefile.FILE_OPEN) | ||||
| 		if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { | ||||
| 			st, err := lstatRelative(name, w.destRoot) | ||||
| 			st, err := safefile.LstatRelative(name, w.destRoot) | ||||
| 			if err != nil && !os.IsNotExist(err) { | ||||
| 				return err | ||||
| 			} | ||||
| @@ -614,14 +601,14 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 				// Delete the existing file/directory if it is not the same type as this directory. | ||||
| 				existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes | ||||
| 				if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { | ||||
| 					if err = removeAllRelative(name, w.destRoot); err != nil { | ||||
| 					if err = safefile.RemoveAllRelative(name, w.destRoot); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					st = nil | ||||
| 				} | ||||
| 			} | ||||
| 			if st == nil { | ||||
| 				if err = mkdirRelative(name, w.destRoot); err != nil { | ||||
| 				if err = safefile.MkdirRelative(name, w.destRoot); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| @@ -630,20 +617,20 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Overwrite any existing hard link. | ||||
| 			err := removeRelative(name, w.destRoot) | ||||
| 			err := safefile.RemoveRelative(name, w.destRoot) | ||||
| 			if err != nil && !os.IsNotExist(err) { | ||||
| 				return err | ||||
| 			} | ||||
| 			createDisposition = _FILE_CREATE | ||||
| 			createDisposition = safefile.FILE_CREATE | ||||
| 		} | ||||
| 
 | ||||
| 		f, err := openRelative( | ||||
| 		f, err := safefile.OpenRelative( | ||||
| 			name, | ||||
| 			w.destRoot, | ||||
| 			syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, | ||||
| 			syscall.FILE_SHARE_READ, | ||||
| 			createDisposition, | ||||
| 			_FILE_OPEN_REPARSE_POINT, | ||||
| 			safefile.FILE_OPEN_REPARSE_POINT, | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -651,7 +638,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 		defer func() { | ||||
| 			if f != nil { | ||||
| 				f.Close() | ||||
| 				removeRelative(name, w.destRoot) | ||||
| 				safefile.RemoveRelative(name, w.destRoot) | ||||
| 			} | ||||
| 		}() | ||||
| 
 | ||||
| @@ -661,6 +648,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 		} | ||||
| 
 | ||||
| 		w.backupWriter = winio.NewBackupFileWriter(f, true) | ||||
| 		w.bufWriter.Reset(w.backupWriter) | ||||
| 		w.currentFile = f | ||||
| 		w.currentFileName = name | ||||
| 		w.currentFileRoot = w.destRoot | ||||
| @@ -671,7 +659,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 
 | ||||
| 	fname := name | ||||
| 	if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { | ||||
| 		err := mkdirRelative(name, w.root) | ||||
| 		err := safefile.MkdirRelative(name, w.root) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -679,14 +667,14 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 		w.currentIsDir = true | ||||
| 	} | ||||
| 
 | ||||
| 	f, err := openRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_CREATE, 0) | ||||
| 	f, err := safefile.OpenRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if f != nil { | ||||
| 			f.Close() | ||||
| 			removeRelative(fname, w.root) | ||||
| 			safefile.RemoveRelative(fname, w.root) | ||||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| @@ -699,10 +687,13 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro | ||||
| 
 | ||||
| 	if hasPathPrefix(name, hivesPath) { | ||||
| 		w.backupWriter = winio.NewBackupFileWriter(f, false) | ||||
| 		w.bufWriter.Reset(w.backupWriter) | ||||
| 	} else { | ||||
| 		w.bufWriter.Reset(f) | ||||
| 		// The file attributes are written before the stream. | ||||
| 		err = binary.Write(f, binary.LittleEndian, uint32(fileInfo.FileAttributes)) | ||||
| 		err = binary.Write(w.bufWriter, binary.LittleEndian, uint32(fileInfo.FileAttributes)) | ||||
| 		if err != nil { | ||||
| 			w.bufWriter.Reset(ioutil.Discard) | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| @@ -744,7 +735,7 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error { | ||||
| 		selectedRoot = w.destRoot | ||||
| 	} else { | ||||
| 		for _, r := range roots { | ||||
| 			if _, err := lstatRelative(target, r); err != nil { | ||||
| 			if _, err := safefile.LstatRelative(target, r); err != nil { | ||||
| 				if !os.IsNotExist(err) { | ||||
| 					return err | ||||
| 				} | ||||
| @@ -780,10 +771,10 @@ func (w *legacyLayerWriter) Remove(name string) error { | ||||
| 		// Make sure the path exists; os.RemoveAll will not fail if the file is | ||||
| 		// already gone, and this needs to be a fatal error for diagnostics | ||||
| 		// purposes. | ||||
| 		if _, err := lstatRelative(name, w.destRoot); err != nil { | ||||
| 		if _, err := safefile.LstatRelative(name, w.destRoot); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		err = removeAllRelative(name, w.destRoot) | ||||
| 		err = safefile.RemoveAllRelative(name, w.destRoot) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -795,24 +786,21 @@ func (w *legacyLayerWriter) Remove(name string) error { | ||||
| } | ||||
| 
 | ||||
| func (w *legacyLayerWriter) Write(b []byte) (int, error) { | ||||
| 	if w.backupWriter == nil { | ||||
| 		if w.currentFile == nil { | ||||
| 	if w.backupWriter == nil && w.currentFile == nil { | ||||
| 		return 0, errors.New("closed") | ||||
| 	} | ||||
| 		return w.currentFile.Write(b) | ||||
| 	} | ||||
| 	return w.backupWriter.Write(b) | ||||
| 	return w.bufWriter.Write(b) | ||||
| } | ||||
| 
 | ||||
| func (w *legacyLayerWriter) Close() error { | ||||
| 	if err := w.reset(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := removeRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) { | ||||
| 	if err := safefile.RemoveRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, pd := range w.pendingDirs { | ||||
| 		err := mkdirRelative(pd.Path, pd.Root) | ||||
| 		err := safefile.MkdirRelative(pd.Path, pd.Root) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
							
								
								
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/guid" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // NameToGuid converts the given string into a GUID using the algorithm in the | ||||
| // Host Compute Service, ensuring GUIDs generated with the same string are common | ||||
| // across all clients. | ||||
| func NameToGuid(name string) (id guid.GUID, err error) { | ||||
| 	title := "hcsshim::NameToGuid " | ||||
|  | ||||
| 	err = nameToGuid(name, &id) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "name=%s", name) | ||||
| 		logrus.Error(err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"name:%s guid:%s", name, id.String()) | ||||
| 	return | ||||
| } | ||||
| @@ -1,21 +1,22 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import ( | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| var prepareLayerLock sync.Mutex | ||||
| 
 | ||||
| // PrepareLayer finds a mounted read-write layer matching layerId and enables the | ||||
| // PrepareLayer finds a mounted read-write layer matching path and enables the | ||||
| // the filesystem filter for use on that layer.  This requires the paths to all | ||||
| // parent layers, and is necessary in order to view or interact with the layer | ||||
| // as an actual filesystem (reading and writing files, creating directories, etc). | ||||
| // Disabling the filter must be done via UnprepareLayer. | ||||
| func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error { | ||||
| func PrepareLayer(path string, parentLayerPaths []string) error { | ||||
| 	title := "hcsshim::PrepareLayer " | ||||
| 	logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
| 
 | ||||
| 	// Generate layer descriptors | ||||
| 	layers, err := layerPathsToDescriptors(parentLayerPaths) | ||||
| @@ -23,24 +24,17 @@ func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) er | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// This lock is a temporary workaround for a Windows bug. Only allowing one | ||||
| 	// call to prepareLayer at a time vastly reduces the chance of a timeout. | ||||
| 	prepareLayerLock.Lock() | ||||
| 	defer prepareLayerLock.Unlock() | ||||
| 	err = prepareLayer(&infop, layerId, layers) | ||||
| 	err = prepareLayer(&stdDriverInfo, path, layers) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d layerId=%s", info.Flavour, layerId) | ||||
| 	logrus.Debugf(title+"succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package hcsshim | ||||
| package wclayer | ||||
| 
 | ||||
| import "os" | ||||
| 
 | ||||
							
								
								
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcserror" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // UnprepareLayer disables the filesystem filter for the read-write layer with | ||||
| // the given id. | ||||
| func UnprepareLayer(path string) error { | ||||
| 	title := "hcsshim::UnprepareLayer " | ||||
| 	logrus.Debugf(title+"path %s", path) | ||||
|  | ||||
| 	err := unprepareLayer(&stdDriverInfo, path) | ||||
| 	if err != nil { | ||||
| 		err = hcserror.Errorf(err, title, "path=%s", path) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded path=%s", path) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										37
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| package wclayer | ||||
|  | ||||
| import "github.com/Microsoft/hcsshim/internal/guid" | ||||
|  | ||||
| //go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go -winio wclayer.go | ||||
|  | ||||
| //sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? | ||||
| //sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? | ||||
| //sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? | ||||
| //sys createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? | ||||
| //sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize? | ||||
| //sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? | ||||
| //sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? | ||||
| //sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? | ||||
| //sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? | ||||
| //sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? | ||||
| //sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? | ||||
| //sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? | ||||
| //sys nameToGuid(name string, guid *_guid) (hr error) = vmcompute.NameToGuid? | ||||
| //sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? | ||||
| //sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? | ||||
| //sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage? | ||||
| //sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage? | ||||
|  | ||||
| //sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin? | ||||
| //sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext? | ||||
| //sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite? | ||||
| //sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd? | ||||
|  | ||||
| //sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin? | ||||
| //sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext? | ||||
| //sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead? | ||||
| //sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd? | ||||
|  | ||||
| //sys grantVmAccess(vmid string, filepath string) (hr error) = vmcompute.GrantVmAccess? | ||||
|  | ||||
| type _guid = guid.GUID | ||||
							
								
								
									
										597
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										597
									
								
								vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,597 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package wclayer | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/Microsoft/go-winio" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") | ||||
|  | ||||
| 	procActivateLayer       = modvmcompute.NewProc("ActivateLayer") | ||||
| 	procCopyLayer           = modvmcompute.NewProc("CopyLayer") | ||||
| 	procCreateLayer         = modvmcompute.NewProc("CreateLayer") | ||||
| 	procCreateSandboxLayer  = modvmcompute.NewProc("CreateSandboxLayer") | ||||
| 	procExpandSandboxSize   = modvmcompute.NewProc("ExpandSandboxSize") | ||||
| 	procDeactivateLayer     = modvmcompute.NewProc("DeactivateLayer") | ||||
| 	procDestroyLayer        = modvmcompute.NewProc("DestroyLayer") | ||||
| 	procExportLayer         = modvmcompute.NewProc("ExportLayer") | ||||
| 	procGetLayerMountPath   = modvmcompute.NewProc("GetLayerMountPath") | ||||
| 	procGetBaseImages       = modvmcompute.NewProc("GetBaseImages") | ||||
| 	procImportLayer         = modvmcompute.NewProc("ImportLayer") | ||||
| 	procLayerExists         = modvmcompute.NewProc("LayerExists") | ||||
| 	procNameToGuid          = modvmcompute.NewProc("NameToGuid") | ||||
| 	procPrepareLayer        = modvmcompute.NewProc("PrepareLayer") | ||||
| 	procUnprepareLayer      = modvmcompute.NewProc("UnprepareLayer") | ||||
| 	procProcessBaseImage    = modvmcompute.NewProc("ProcessBaseImage") | ||||
| 	procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage") | ||||
| 	procImportLayerBegin    = modvmcompute.NewProc("ImportLayerBegin") | ||||
| 	procImportLayerNext     = modvmcompute.NewProc("ImportLayerNext") | ||||
| 	procImportLayerWrite    = modvmcompute.NewProc("ImportLayerWrite") | ||||
| 	procImportLayerEnd      = modvmcompute.NewProc("ImportLayerEnd") | ||||
| 	procExportLayerBegin    = modvmcompute.NewProc("ExportLayerBegin") | ||||
| 	procExportLayerNext     = modvmcompute.NewProc("ExportLayerNext") | ||||
| 	procExportLayerRead     = modvmcompute.NewProc("ExportLayerRead") | ||||
| 	procExportLayerEnd      = modvmcompute.NewProc("ExportLayerEnd") | ||||
| 	procGrantVmAccess       = modvmcompute.NewProc("GrantVmAccess") | ||||
| ) | ||||
|  | ||||
| func activateLayer(info *driverInfo, id string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _activateLayer(info, _p0) | ||||
| } | ||||
|  | ||||
| func _activateLayer(info *driverInfo, id *uint16) (hr error) { | ||||
| 	if hr = procActivateLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(srcId) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(dstId) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _copyLayer(info, _p0, _p1, descriptors) | ||||
| } | ||||
|  | ||||
| func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p2 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p2 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procCopyLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func createLayer(info *driverInfo, id string, parent string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(parent) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _createLayer(info, _p0, _p1) | ||||
| } | ||||
|  | ||||
| func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) { | ||||
| 	if hr = procCreateLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _createSandboxLayer(info, _p0, parent, descriptors) | ||||
| } | ||||
|  | ||||
| func _createSandboxLayer(info *driverInfo, id *uint16, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p1 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p1 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procCreateSandboxLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(parent), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _expandSandboxSize(info, _p0, size) | ||||
| } | ||||
|  | ||||
| func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) { | ||||
| 	if hr = procExpandSandboxSize.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size)) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func deactivateLayer(info *driverInfo, id string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _deactivateLayer(info, _p0) | ||||
| } | ||||
|  | ||||
| func _deactivateLayer(info *driverInfo, id *uint16) (hr error) { | ||||
| 	if hr = procDeactivateLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func destroyLayer(info *driverInfo, id string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _destroyLayer(info, _p0) | ||||
| } | ||||
|  | ||||
| func _destroyLayer(info *driverInfo, id *uint16) (hr error) { | ||||
| 	if hr = procDestroyLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(path) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _exportLayer(info, _p0, _p1, descriptors) | ||||
| } | ||||
|  | ||||
| func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p2 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p2 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procExportLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _getLayerMountPath(info, _p0, length, buffer) | ||||
| } | ||||
|  | ||||
| func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) { | ||||
| 	if hr = procGetLayerMountPath.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getBaseImages(buffer **uint16) (hr error) { | ||||
| 	if hr = procGetBaseImages.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(path) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _importLayer(info, _p0, _p1, descriptors) | ||||
| } | ||||
|  | ||||
| func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p2 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p2 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procImportLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func layerExists(info *driverInfo, id string, exists *uint32) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _layerExists(info, _p0, exists) | ||||
| } | ||||
|  | ||||
| func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) { | ||||
| 	if hr = procLayerExists.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func nameToGuid(name string, guid *_guid) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(name) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _nameToGuid(_p0, guid) | ||||
| } | ||||
|  | ||||
| func _nameToGuid(name *uint16, guid *_guid) (hr error) { | ||||
| 	if hr = procNameToGuid.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _prepareLayer(info, _p0, descriptors) | ||||
| } | ||||
|  | ||||
| func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { | ||||
| 	var _p1 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p1 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procPrepareLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func unprepareLayer(info *driverInfo, id string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _unprepareLayer(info, _p0) | ||||
| } | ||||
|  | ||||
| func _unprepareLayer(info *driverInfo, id *uint16) (hr error) { | ||||
| 	if hr = procUnprepareLayer.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func processBaseImage(path string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(path) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _processBaseImage(_p0) | ||||
| } | ||||
|  | ||||
| func _processBaseImage(path *uint16) (hr error) { | ||||
| 	if hr = procProcessBaseImage.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func processUtilityImage(path string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(path) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _processUtilityImage(_p0) | ||||
| } | ||||
|  | ||||
| func _processUtilityImage(path *uint16) (hr error) { | ||||
| 	if hr = procProcessUtilityImage.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _importLayerBegin(info, _p0, descriptors, context) | ||||
| } | ||||
|  | ||||
| func _importLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { | ||||
| 	var _p1 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p1 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procImportLayerBegin.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procImportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(fileName) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _importLayerNext(context, _p0, fileInfo) | ||||
| } | ||||
|  | ||||
| func _importLayerNext(context uintptr, fileName *uint16, fileInfo *winio.FileBasicInfo) (hr error) { | ||||
| 	if hr = procImportLayerNext.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procImportLayerNext.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func importLayerWrite(context uintptr, buffer []byte) (hr error) { | ||||
| 	var _p0 *byte | ||||
| 	if len(buffer) > 0 { | ||||
| 		_p0 = &buffer[0] | ||||
| 	} | ||||
| 	if hr = procImportLayerWrite.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procImportLayerWrite.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer))) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func importLayerEnd(context uintptr) (hr error) { | ||||
| 	if hr = procImportLayerEnd.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procImportLayerEnd.Addr(), 1, uintptr(context), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(id) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _exportLayerBegin(info, _p0, descriptors, context) | ||||
| } | ||||
|  | ||||
| func _exportLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { | ||||
| 	var _p1 *WC_LAYER_DESCRIPTOR | ||||
| 	if len(descriptors) > 0 { | ||||
| 		_p1 = &descriptors[0] | ||||
| 	} | ||||
| 	if hr = procExportLayerBegin.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procExportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) { | ||||
| 	if hr = procExportLayerNext.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procExportLayerNext.Addr(), 5, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo)), uintptr(unsafe.Pointer(fileSize)), uintptr(unsafe.Pointer(deleted)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) { | ||||
| 	var _p0 *byte | ||||
| 	if len(buffer) > 0 { | ||||
| 		_p0 = &buffer[0] | ||||
| 	} | ||||
| 	if hr = procExportLayerRead.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall6(procExportLayerRead.Addr(), 4, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer)), uintptr(unsafe.Pointer(bytesRead)), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func exportLayerEnd(context uintptr) (hr error) { | ||||
| 	if hr = procExportLayerEnd.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procExportLayerEnd.Addr(), 1, uintptr(context), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func grantVmAccess(vmid string, filepath string) (hr error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, hr = syscall.UTF16PtrFromString(vmid) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *uint16 | ||||
| 	_p1, hr = syscall.UTF16PtrFromString(filepath) | ||||
| 	if hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _grantVmAccess(_p0, _p1) | ||||
| } | ||||
|  | ||||
| func _grantVmAccess(vmid *uint16, filepath *uint16) (hr error) { | ||||
| 	if hr = procGrantVmAccess.Find(); hr != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, _ := syscall.Syscall(procGrantVmAccess.Addr(), 2, uintptr(unsafe.Pointer(vmid)), uintptr(unsafe.Pointer(filepath)), 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										108
									
								
								vendor/github.com/Microsoft/hcsshim/layer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								vendor/github.com/Microsoft/hcsshim/layer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"crypto/sha1" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/guid" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/wclayer" | ||||
| ) | ||||
|  | ||||
| func layerPath(info *DriverInfo, id string) string { | ||||
| 	return filepath.Join(info.HomeDir, id) | ||||
| } | ||||
|  | ||||
| func ActivateLayer(info DriverInfo, id string) error { | ||||
| 	return wclayer.ActivateLayer(layerPath(&info, id)) | ||||
| } | ||||
| func CreateLayer(info DriverInfo, id, parent string) error { | ||||
| 	return wclayer.CreateLayer(layerPath(&info, id), parent) | ||||
| } | ||||
| // New clients should use CreateScratchLayer instead. Kept in to preserve API compatibility. | ||||
| func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { | ||||
| 	return wclayer.CreateScratchLayer(layerPath(&info, layerId), parentLayerPaths) | ||||
| } | ||||
| func CreateScratchLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { | ||||
| 	return wclayer.CreateScratchLayer(layerPath(&info, layerId), parentLayerPaths) | ||||
| } | ||||
| func DeactivateLayer(info DriverInfo, id string) error { | ||||
| 	return wclayer.DeactivateLayer(layerPath(&info, id)) | ||||
| } | ||||
| func DestroyLayer(info DriverInfo, id string) error { | ||||
| 	return wclayer.DestroyLayer(layerPath(&info, id)) | ||||
| } | ||||
| // New clients should use ExpandScratchSize instead. Kept in to preserve API compatibility. | ||||
| func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error { | ||||
| 	return wclayer.ExpandScratchSize(layerPath(&info, layerId), size) | ||||
| } | ||||
| func ExpandScratchSize(info DriverInfo, layerId string, size uint64) error { | ||||
| 	return wclayer.ExpandScratchSize(layerPath(&info, layerId), size) | ||||
| } | ||||
| func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error { | ||||
| 	return wclayer.ExportLayer(layerPath(&info, layerId), exportFolderPath, parentLayerPaths) | ||||
| } | ||||
| func GetLayerMountPath(info DriverInfo, id string) (string, error) { | ||||
| 	return wclayer.GetLayerMountPath(layerPath(&info, id)) | ||||
| } | ||||
| func GetSharedBaseImages() (imageData string, err error) { | ||||
| 	return wclayer.GetSharedBaseImages() | ||||
| } | ||||
| func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error { | ||||
| 	return wclayer.ImportLayer(layerPath(&info, layerID), importFolderPath, parentLayerPaths) | ||||
| } | ||||
| func LayerExists(info DriverInfo, id string) (bool, error) { | ||||
| 	return wclayer.LayerExists(layerPath(&info, id)) | ||||
| } | ||||
| func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error { | ||||
| 	return wclayer.PrepareLayer(layerPath(&info, layerId), parentLayerPaths) | ||||
| } | ||||
| func ProcessBaseLayer(path string) error { | ||||
| 	return wclayer.ProcessBaseLayer(path) | ||||
| } | ||||
| func ProcessUtilityVMImage(path string) error { | ||||
| 	return wclayer.ProcessUtilityVMImage(path) | ||||
| } | ||||
| func UnprepareLayer(info DriverInfo, layerId string) error { | ||||
| 	return wclayer.UnprepareLayer(layerPath(&info, layerId)) | ||||
| } | ||||
|  | ||||
| type DriverInfo struct { | ||||
| 	Flavour int | ||||
| 	HomeDir string | ||||
| } | ||||
|  | ||||
| type FilterLayerReader = wclayer.FilterLayerReader | ||||
| type FilterLayerWriter = wclayer.FilterLayerWriter | ||||
|  | ||||
| type GUID [16]byte | ||||
|  | ||||
| func NameToGuid(name string) (id GUID, err error) { | ||||
| 	g, err := wclayer.NameToGuid(name) | ||||
| 	return GUID(g), err | ||||
| } | ||||
|  | ||||
| func NewGUID(source string) *GUID { | ||||
| 	h := sha1.Sum([]byte(source)) | ||||
| 	var g GUID | ||||
| 	copy(g[0:], h[0:16]) | ||||
| 	return &g | ||||
| } | ||||
|  | ||||
| func (g *GUID) ToString() string { | ||||
| 	return (guid.GUID)(*g).String() | ||||
| } | ||||
|  | ||||
| type LayerReader = wclayer.LayerReader | ||||
|  | ||||
| func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) { | ||||
| 	return wclayer.NewLayerReader(layerPath(&info, layerID), parentLayerPaths) | ||||
| } | ||||
|  | ||||
| type LayerWriter = wclayer.LayerWriter | ||||
|  | ||||
| func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) { | ||||
| 	return wclayer.NewLayerWriter(layerPath(&info, layerID), parentLayerPaths) | ||||
| } | ||||
|  | ||||
| type WC_LAYER_DESCRIPTOR = wclayer.WC_LAYER_DESCRIPTOR | ||||
							
								
								
									
										30
									
								
								vendor/github.com/Microsoft/hcsshim/layerexists.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/Microsoft/hcsshim/layerexists.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,30 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // LayerExists will return true if a layer with the given id exists and is known | ||||
| // to the system. | ||||
| func LayerExists(info DriverInfo, id string) (bool, error) { | ||||
| 	title := "hcsshim::LayerExists " | ||||
| 	logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	// Call the procedure itself. | ||||
| 	var exists uint32 | ||||
|  | ||||
| 	err = layerExists(&infop, id, &exists) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists) | ||||
| 	return exists != 0, nil | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/github.com/Microsoft/hcsshim/legacy18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/Microsoft/hcsshim/legacy18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,7 +0,0 @@ | ||||
| // +build !go1.9 | ||||
|  | ||||
| package hcsshim | ||||
|  | ||||
| // Due to a bug in go1.8 and before, directory reparse points need to be skipped | ||||
| // during filepath.Walk. This is fixed in go1.9 | ||||
| var shouldSkipDirectoryReparse = true | ||||
							
								
								
									
										7
									
								
								vendor/github.com/Microsoft/hcsshim/legacy19.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/Microsoft/hcsshim/legacy19.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,7 +0,0 @@ | ||||
| // +build go1.9 | ||||
|  | ||||
| package hcsshim | ||||
|  | ||||
| // Due to a bug in go1.8 and before, directory reparse points need to be skipped | ||||
| // during filepath.Walk. This is fixed in go1.9 | ||||
| var shouldSkipDirectoryReparse = false | ||||
							
								
								
									
										20
									
								
								vendor/github.com/Microsoft/hcsshim/nametoguid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/Microsoft/hcsshim/nametoguid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,20 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // NameToGuid converts the given string into a GUID using the algorithm in the | ||||
| // Host Compute Service, ensuring GUIDs generated with the same string are common | ||||
| // across all clients. | ||||
| func NameToGuid(name string) (id GUID, err error) { | ||||
| 	title := "hcsshim::NameToGuid " | ||||
| 	logrus.Debugf(title+"Name %s", name) | ||||
|  | ||||
| 	err = nameToGuid(name, &id) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "name=%s", name) | ||||
| 		logrus.Error(err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										342
									
								
								vendor/github.com/Microsoft/hcsshim/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										342
									
								
								vendor/github.com/Microsoft/hcsshim/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,384 +1,72 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/hcs" | ||||
| ) | ||||
|  | ||||
| // ContainerError is an error encountered in HCS | ||||
| type process struct { | ||||
| 	handleLock     sync.RWMutex | ||||
| 	handle         hcsProcess | ||||
| 	processID      int | ||||
| 	container      *container | ||||
| 	cachedPipes    *cachedPipes | ||||
| 	callbackNumber uintptr | ||||
| 	p *hcs.Process | ||||
| } | ||||
|  | ||||
| type cachedPipes struct { | ||||
| 	stdIn  syscall.Handle | ||||
| 	stdOut syscall.Handle | ||||
| 	stdErr syscall.Handle | ||||
| } | ||||
|  | ||||
| type processModifyRequest struct { | ||||
| 	Operation   string | ||||
| 	ConsoleSize *consoleSize `json:",omitempty"` | ||||
| 	CloseHandle *closeHandle `json:",omitempty"` | ||||
| } | ||||
|  | ||||
| type consoleSize struct { | ||||
| 	Height uint16 | ||||
| 	Width  uint16 | ||||
| } | ||||
|  | ||||
| type closeHandle struct { | ||||
| 	Handle string | ||||
| } | ||||
|  | ||||
| type processStatus struct { | ||||
| 	ProcessID      uint32 | ||||
| 	Exited         bool | ||||
| 	ExitCode       uint32 | ||||
| 	LastWaitResult int32 | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	stdIn  string = "StdIn" | ||||
| 	stdOut string = "StdOut" | ||||
| 	stdErr string = "StdErr" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	modifyConsoleSize string = "ConsoleSize" | ||||
| 	modifyCloseHandle string = "CloseHandle" | ||||
| ) | ||||
|  | ||||
| // Pid returns the process ID of the process within the container. | ||||
| func (process *process) Pid() int { | ||||
| 	return process.processID | ||||
| 	return process.p.Pid() | ||||
| } | ||||
|  | ||||
| // Kill signals the process to terminate but does not wait for it to finish terminating. | ||||
| func (process *process) Kill() error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "Kill" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err := hcsTerminateProcess(process.handle, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| 	return convertProcessError(process.p.Kill(), process) | ||||
| } | ||||
|  | ||||
| // Wait waits for the process to exit. | ||||
| func (process *process) Wait() error { | ||||
| 	operation := "Wait" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| 	return convertProcessError(process.p.Wait(), process) | ||||
| } | ||||
|  | ||||
| // WaitTimeout waits for the process to exit or the duration to elapse. It returns | ||||
| // false if timeout occurs. | ||||
| func (process *process) WaitTimeout(timeout time.Duration) error { | ||||
| 	operation := "WaitTimeout" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| 	return convertProcessError(process.p.WaitTimeout(timeout), process) | ||||
| } | ||||
|  | ||||
| // ExitCode returns the exit code of the process. The process must have | ||||
| // already terminated. | ||||
| func (process *process) ExitCode() (int, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "ExitCode" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return 0, makeProcessError(process, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	properties, err := process.properties() | ||||
| 	code, err := process.p.ExitCode() | ||||
| 	if err != nil { | ||||
| 		return 0, makeProcessError(process, operation, "", err) | ||||
| 		err = convertProcessError(err, process) | ||||
| 	} | ||||
|  | ||||
| 	if properties.Exited == false { | ||||
| 		return 0, makeProcessError(process, operation, "", ErrInvalidProcessState) | ||||
| 	} | ||||
|  | ||||
| 	if properties.LastWaitResult != 0 { | ||||
| 		return 0, makeProcessError(process, operation, "", syscall.Errno(properties.LastWaitResult)) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d exitCode=%d", process.processID, properties.ExitCode) | ||||
| 	return int(properties.ExitCode), nil | ||||
| 	return code, err | ||||
| } | ||||
|  | ||||
| // ResizeConsole resizes the console of the process. | ||||
| func (process *process) ResizeConsole(width, height uint16) error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "ResizeConsole" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	modifyRequest := processModifyRequest{ | ||||
| 		Operation: modifyConsoleSize, | ||||
| 		ConsoleSize: &consoleSize{ | ||||
| 			Height: height, | ||||
| 			Width:  width, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestb, err := json.Marshal(modifyRequest) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *process) properties() (*processStatus, error) { | ||||
| 	operation := "properties" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	var ( | ||||
| 		resultp     *uint16 | ||||
| 		propertiesp *uint16 | ||||
| 	) | ||||
| 	err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if propertiesp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp) | ||||
|  | ||||
| 	properties := &processStatus{} | ||||
| 	if err := json.Unmarshal(propertiesRaw, properties); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw) | ||||
| 	return properties, nil | ||||
| 	return convertProcessError(process.p.ResizeConsole(width, height), process) | ||||
| } | ||||
|  | ||||
| // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing | ||||
| // these pipes does not close the underlying pipes; it should be possible to | ||||
| // call this multiple times to get multiple interfaces. | ||||
| func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "Stdio" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	var stdIn, stdOut, stdErr syscall.Handle | ||||
|  | ||||
| 	if process.cachedPipes == nil { | ||||
| 		var ( | ||||
| 			processInfo hcsProcessInformation | ||||
| 			resultp     *uint16 | ||||
| 		) | ||||
| 		err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) | ||||
| 		err = processHcsResult(err, resultp) | ||||
| 	stdin, stdout, stderr, err := process.p.Stdio() | ||||
| 	if err != nil { | ||||
| 			return nil, nil, nil, makeProcessError(process, operation, "", err) | ||||
| 		err = convertProcessError(err, process) | ||||
| 	} | ||||
|  | ||||
| 		stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError | ||||
| 	} else { | ||||
| 		// Use cached pipes | ||||
| 		stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr | ||||
|  | ||||
| 		// Invalidate the cache | ||||
| 		process.cachedPipes = nil | ||||
| 	} | ||||
|  | ||||
| 	pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return pipes[0], pipes[1], pipes[2], nil | ||||
| 	return stdin, stdout, stderr, err | ||||
| } | ||||
|  | ||||
| // CloseStdin closes the write side of the stdin pipe so that the process is | ||||
| // notified on the read side that there is no more data in stdin. | ||||
| func (process *process) CloseStdin() error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
| 	operation := "CloseStdin" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, "", ErrAlreadyClosed) | ||||
| 	} | ||||
|  | ||||
| 	modifyRequest := processModifyRequest{ | ||||
| 		Operation: modifyCloseHandle, | ||||
| 		CloseHandle: &closeHandle{ | ||||
| 			Handle: stdIn, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestb, err := json.Marshal(modifyRequest) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	err = processHcsResult(err, resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| 	return convertProcessError(process.p.CloseStdin(), process) | ||||
| } | ||||
|  | ||||
| // Close cleans up any state associated with the process but does not kill | ||||
| // or wait on it. | ||||
| func (process *process) Close() error { | ||||
| 	process.handleLock.Lock() | ||||
| 	defer process.handleLock.Unlock() | ||||
| 	operation := "Close" | ||||
| 	title := "HCSShim::Process::" + operation | ||||
| 	logrus.Debugf(title+" processid=%d", process.processID) | ||||
|  | ||||
| 	// Don't double free this | ||||
| 	if process.handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if err := process.unregisterCallback(); err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := hcsCloseProcess(process.handle); err != nil { | ||||
| 		return makeProcessError(process, operation, "", err) | ||||
| 	} | ||||
|  | ||||
| 	process.handle = 0 | ||||
|  | ||||
| 	logrus.Debugf(title+" succeeded processid=%d", process.processID) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *process) registerCallback() error { | ||||
| 	context := ¬ifcationWatcherContext{ | ||||
| 		channels: newChannels(), | ||||
| 	} | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackNumber := nextCallback | ||||
| 	nextCallback++ | ||||
| 	callbackMap[callbackNumber] = context | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	var callbackHandle hcsCallback | ||||
| 	err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	context.handle = callbackHandle | ||||
| 	process.callbackNumber = callbackNumber | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *process) unregisterCallback() error { | ||||
| 	callbackNumber := process.callbackNumber | ||||
|  | ||||
| 	callbackMapLock.RLock() | ||||
| 	context := callbackMap[callbackNumber] | ||||
| 	callbackMapLock.RUnlock() | ||||
|  | ||||
| 	if context == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	handle := context.handle | ||||
|  | ||||
| 	if handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// hcsUnregisterProcessCallback has its own syncronization | ||||
| 	// to wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := hcsUnregisterProcessCallback(handle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	closeChannels(context.channels) | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackMap[callbackNumber] = nil | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	handle = 0 | ||||
|  | ||||
| 	return nil | ||||
| 	return convertProcessError(process.p.Close(), process) | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/unpreparelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/hcsshim/unpreparelayer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| package hcsshim | ||||
|  | ||||
| import "github.com/sirupsen/logrus" | ||||
|  | ||||
| // UnprepareLayer disables the filesystem filter for the read-write layer with | ||||
| // the given id. | ||||
| func UnprepareLayer(info DriverInfo, layerId string) error { | ||||
| 	title := "hcsshim::UnprepareLayer " | ||||
| 	logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId) | ||||
|  | ||||
| 	// Convert info to API calling convention | ||||
| 	infop, err := convertDriverInfo(info) | ||||
| 	if err != nil { | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = unprepareLayer(&infop, layerId) | ||||
| 	if err != nil { | ||||
| 		err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour) | ||||
| 		logrus.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf(title+"succeeded flavour %d layerId=%s", info.Flavour, layerId) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										3
									
								
								vendor/github.com/Microsoft/hcsshim/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/Microsoft/hcsshim/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,6 +2,5 @@ package hcsshim | ||||
|  | ||||
| // IsTP4 returns whether the currently running Windows build is at least TP4. | ||||
| func IsTP4() bool { | ||||
| 	// HNSCall was not present in TP4 | ||||
| 	return procHNSCall.Find() != nil | ||||
| 	return false | ||||
| } | ||||
|   | ||||
							
								
								
									
										1080
									
								
								vendor/github.com/Microsoft/hcsshim/zhcsshim.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1080
									
								
								vendor/github.com/Microsoft/hcsshim/zhcsshim.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										52
									
								
								vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT | ||||
|  | ||||
| package hcsshim | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") | ||||
|  | ||||
| 	procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId") | ||||
| ) | ||||
|  | ||||
| func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) { | ||||
| 	r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0) | ||||
| 	if int32(r0) < 0 { | ||||
| 		hr = interop.Win32FromHresult(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										2
									
								
								vendor/github.com/containerd/go-runc/console.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/containerd/go-runc/console.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,5 @@ | ||||
| // +build !windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|   | ||||
							
								
								
									
										48
									
								
								vendor/github.com/containerd/go-runc/io.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/containerd/go-runc/io.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -20,9 +20,6 @@ import ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type IO interface { | ||||
| @@ -37,51 +34,6 @@ type StartCloser interface { | ||||
| 	CloseAfterStart() error | ||||
| } | ||||
|  | ||||
| // NewPipeIO creates pipe pairs to be used with runc | ||||
| func NewPipeIO(uid, gid int) (i IO, err error) { | ||||
| 	var pipes []*pipe | ||||
| 	// cleanup in case of an error | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			for _, p := range pipes { | ||||
| 				p.Close() | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	stdin, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stdin) | ||||
| 	if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stdin") | ||||
| 	} | ||||
|  | ||||
| 	stdout, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stdout) | ||||
| 	if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stdout") | ||||
| 	} | ||||
|  | ||||
| 	stderr, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stderr) | ||||
| 	if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stderr") | ||||
| 	} | ||||
|  | ||||
| 	return &pipeIO{ | ||||
| 		in:  stdin, | ||||
| 		out: stdout, | ||||
| 		err: stderr, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func newPipe() (*pipe, error) { | ||||
| 	r, w, err := os.Pipe() | ||||
| 	if err != nil { | ||||
|   | ||||
							
								
								
									
										69
									
								
								vendor/github.com/containerd/go-runc/io_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/containerd/go-runc/io_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| // +build !windows | ||||
|  | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package runc | ||||
|  | ||||
| import ( | ||||
| 	"github.com/pkg/errors" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // NewPipeIO creates pipe pairs to be used with runc | ||||
| func NewPipeIO(uid, gid int) (i IO, err error) { | ||||
| 	var pipes []*pipe | ||||
| 	// cleanup in case of an error | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			for _, p := range pipes { | ||||
| 				p.Close() | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	stdin, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stdin) | ||||
| 	if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stdin") | ||||
| 	} | ||||
|  | ||||
| 	stdout, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stdout) | ||||
| 	if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stdout") | ||||
| 	} | ||||
|  | ||||
| 	stderr, err := newPipe() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	pipes = append(pipes, stderr) | ||||
| 	if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to chown stderr") | ||||
| 	} | ||||
|  | ||||
| 	return &pipeIO{ | ||||
| 		in:  stdin, | ||||
| 		out: stdout, | ||||
| 		err: stderr, | ||||
| 	}, nil | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Justin Terry (VM)
					Justin Terry (VM)