Update Vendor
(*) github.com/Microsoft/hcsshim (*) golang.org/x/sys (*) github.com/x/cyrpto (*) github.com/sirupsen/logrus (*) github.com/Microsoft/go-winio (*) github.com/juju/errors (*) github.com/buger/jsonparser
This commit is contained in:
1
vendor/github.com/Microsoft/hcsshim/.gitignore
generated
vendored
Normal file
1
vendor/github.com/Microsoft/hcsshim/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.exe
|
21
vendor/github.com/Microsoft/hcsshim/LICENSE
generated
vendored
Normal file
21
vendor/github.com/Microsoft/hcsshim/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
41
vendor/github.com/Microsoft/hcsshim/README.md
generated
vendored
Normal file
41
vendor/github.com/Microsoft/hcsshim/README.md
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# hcsshim
|
||||
|
||||
[](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.
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
|
||||
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
|
||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
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
|
||||
|
||||
Security issues and bugs should be reported privately, via email, to the Microsoft Security
|
||||
Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should
|
||||
receive a response within 24 hours. If for some reason you do not, please follow up via
|
||||
email to ensure we received your original message. Further information, including the
|
||||
[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.
|
19
vendor/github.com/Microsoft/hcsshim/appveyor.yml
generated
vendored
Normal file
19
vendor/github.com/Microsoft/hcsshim/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
version: 0.1.{build}
|
||||
|
||||
image: Visual Studio 2017
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\Microsoft\hcsshim
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%PATH%
|
||||
|
||||
build_script:
|
||||
- go get -v -t ./...
|
||||
- go build ./cmd/wclayer
|
||||
- go build ./cmd/runhcs
|
||||
- go test -v ./... -tags admin
|
||||
|
||||
artifacts:
|
||||
- path: 'wclayer.exe'
|
||||
- path: 'runhcs.exe'
|
192
vendor/github.com/Microsoft/hcsshim/container.go
generated
vendored
Normal file
192
vendor/github.com/Microsoft/hcsshim/container.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hcs"
|
||||
"github.com/Microsoft/hcsshim/internal/mergemaps"
|
||||
"github.com/Microsoft/hcsshim/internal/schema1"
|
||||
)
|
||||
|
||||
// ContainerProperties holds the properties for a container and the processes running in that container
|
||||
type ContainerProperties = schema1.ContainerProperties
|
||||
|
||||
// MemoryStats holds the memory statistics for a container
|
||||
type MemoryStats = schema1.MemoryStats
|
||||
|
||||
// ProcessorStats holds the processor statistics for a container
|
||||
type ProcessorStats = schema1.ProcessorStats
|
||||
|
||||
// StorageStats holds the storage statistics for a container
|
||||
type StorageStats = schema1.StorageStats
|
||||
|
||||
// NetworkStats holds the network statistics for a container
|
||||
type NetworkStats = schema1.NetworkStats
|
||||
|
||||
// Statistics is the structure returned by a statistics call on a container
|
||||
type Statistics = schema1.Statistics
|
||||
|
||||
// ProcessList is the structure of an item returned by a ProcessList call on a container
|
||||
type ProcessListItem = schema1.ProcessListItem
|
||||
|
||||
// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container
|
||||
type MappedVirtualDiskController = schema1.MappedVirtualDiskController
|
||||
|
||||
// Type of Request Support in ModifySystem
|
||||
type RequestType = schema1.RequestType
|
||||
|
||||
// Type of Resource Support in ModifySystem
|
||||
type ResourceType = schema1.ResourceType
|
||||
|
||||
// RequestType const
|
||||
const (
|
||||
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 = schema1.ResourceModificationRequestResponse
|
||||
|
||||
type container struct {
|
||||
system *hcs.System
|
||||
}
|
||||
|
||||
// createComputeSystemAdditionalJSON is read from the environment at initialisation
|
||||
// time. It allows an environment variable to define additional JSON which
|
||||
// is merged in the CreateComputeSystem call to HCS.
|
||||
var createContainerAdditionalJSON []byte
|
||||
|
||||
func init() {
|
||||
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) {
|
||||
fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err)
|
||||
}
|
||||
|
||||
system, err := hcs.CreateComputeSystem(id, fullConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &container{system}, err
|
||||
}
|
||||
|
||||
// OpenContainer opens an existing container by ID.
|
||||
func OpenContainer(id string) (Container, error) {
|
||||
system, err := hcs.OpenComputeSystem(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &container{system}, err
|
||||
}
|
||||
|
||||
// GetContainers gets a list of the containers on the system that match the query
|
||||
func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
|
||||
return hcs.GetComputeSystems(q)
|
||||
}
|
||||
|
||||
// Start synchronously starts the container.
|
||||
func (container *container) Start() error {
|
||||
return convertSystemError(container.system.Start(), container)
|
||||
}
|
||||
|
||||
// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
|
||||
func (container *container) Shutdown() error {
|
||||
return convertSystemError(container.system.Shutdown(), container)
|
||||
}
|
||||
|
||||
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
|
||||
func (container *container) Terminate() error {
|
||||
return convertSystemError(container.system.Terminate(), container)
|
||||
}
|
||||
|
||||
// Waits synchronously waits for the container to shutdown or terminate.
|
||||
func (container *container) Wait() error {
|
||||
return convertSystemError(container.system.Wait(), container)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Pause pauses the execution of a container.
|
||||
func (container *container) Pause() error {
|
||||
return convertSystemError(container.system.Pause(), container)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Statistics returns statistics for the container. This is a legacy v1 call
|
||||
func (container *container) Statistics() (Statistics, error) {
|
||||
properties, err := container.system.Properties(schema1.PropertyTypeStatistics)
|
||||
if err != nil {
|
||||
return Statistics{}, convertSystemError(err, container)
|
||||
}
|
||||
|
||||
return properties.Statistics, nil
|
||||
}
|
||||
|
||||
// ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call
|
||||
func (container *container) ProcessList() ([]ProcessListItem, error) {
|
||||
properties, err := container.system.Properties(schema1.PropertyTypeProcessList)
|
||||
if err != nil {
|
||||
return nil, convertSystemError(err, container)
|
||||
}
|
||||
|
||||
return properties.ProcessList, nil
|
||||
}
|
||||
|
||||
// This is a legacy v1 call
|
||||
func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
|
||||
properties, err := container.system.Properties(schema1.PropertyTypeMappedVirtualDisk)
|
||||
if err != nil {
|
||||
return nil, convertSystemError(err, container)
|
||||
}
|
||||
|
||||
return properties.MappedVirtualDiskControllers, nil
|
||||
}
|
||||
|
||||
// CreateProcess launches a new process within the container.
|
||||
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
|
||||
p, err := container.system.CreateProcess(c)
|
||||
if err != nil {
|
||||
return nil, convertSystemError(err, container)
|
||||
}
|
||||
return &process{p}, nil
|
||||
}
|
||||
|
||||
// OpenProcess gets an interface to an existing process within the container.
|
||||
func (container *container) OpenProcess(pid int) (Process, error) {
|
||||
p, err := container.system.OpenProcess(pid)
|
||||
if err != nil {
|
||||
return nil, convertSystemError(err, container)
|
||||
}
|
||||
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 {
|
||||
return convertSystemError(container.system.Close(), container)
|
||||
}
|
||||
|
||||
// Modify the System
|
||||
func (container *container) Modify(config *ResourceModificationRequestResponse) error {
|
||||
return convertSystemError(container.system.Modify(config), container)
|
||||
}
|
257
vendor/github.com/Microsoft/hcsshim/errors.go
generated
vendored
Normal file
257
vendor/github.com/Microsoft/hcsshim/errors.go
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"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 = hcs.exist
|
||||
ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist
|
||||
|
||||
// ErrElementNotFound is an error encountered when the object being referenced does not exist
|
||||
ErrElementNotFound = hcs.ErrElementNotFound
|
||||
|
||||
// ErrElementNotFound is an error encountered when the object being referenced does not exist
|
||||
ErrNotSupported = hcs.ErrNotSupported
|
||||
|
||||
// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
|
||||
// decimal -2147024883 / hex 0x8007000d
|
||||
ErrInvalidData = hcs.ErrInvalidData
|
||||
|
||||
// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
|
||||
ErrHandleClose = hcs.ErrHandleClose
|
||||
|
||||
// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
|
||||
ErrAlreadyClosed = hcs.ErrAlreadyClosed
|
||||
|
||||
// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
|
||||
ErrInvalidNotificationType = hcs.ErrInvalidNotificationType
|
||||
|
||||
// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
|
||||
ErrInvalidProcessState = hcs.ErrInvalidProcessState
|
||||
|
||||
// ErrTimeout is an error encountered when waiting on a notification times out
|
||||
ErrTimeout = hcs.ErrTimeout
|
||||
|
||||
// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
|
||||
// a different expected notification
|
||||
ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit
|
||||
|
||||
// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
|
||||
// is lost while waiting for a notification
|
||||
ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort
|
||||
|
||||
// ErrUnexpectedValue is an error encountered when hcs returns an invalid value
|
||||
ErrUnexpectedValue = hcs.ErrUnexpectedValue
|
||||
|
||||
// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
|
||||
ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped
|
||||
|
||||
// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
|
||||
ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending
|
||||
|
||||
// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
|
||||
ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState
|
||||
|
||||
// ErrProcNotFound is an error encountered when the the process cannot be found
|
||||
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 = hcs.ErrVmcomputeOperationAccessIsDenied
|
||||
|
||||
// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
|
||||
ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON
|
||||
|
||||
// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
|
||||
ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage
|
||||
|
||||
// ErrNotSupported is an error encountered when hcs doesn't support the request
|
||||
ErrPlatformNotSupported = hcs.ErrPlatformNotSupported
|
||||
)
|
||||
|
||||
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 {
|
||||
Process *process
|
||||
Operation string
|
||||
ExtraInfo string
|
||||
Err error
|
||||
Events []hcs.ErrorEvent
|
||||
}
|
||||
|
||||
// ContainerError is an error encountered in HCS during an operation on a Container object
|
||||
type ContainerError struct {
|
||||
Container *container
|
||||
Operation string
|
||||
ExtraInfo string
|
||||
Err error
|
||||
Events []hcs.ErrorEvent
|
||||
}
|
||||
|
||||
func (e *ContainerError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
if e.Container == nil {
|
||||
return "unexpected nil container for error: " + e.Err.Error()
|
||||
}
|
||||
|
||||
s := "container " + e.Container.system.ID()
|
||||
|
||||
if e.Operation != "" {
|
||||
s += " encountered an error during " + e.Operation
|
||||
}
|
||||
|
||||
switch e.Err.(type) {
|
||||
case nil:
|
||||
break
|
||||
case syscall.Errno:
|
||||
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
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func makeContainerError(container *container, operation string, extraInfo string, err error) error {
|
||||
// Don't double wrap errors
|
||||
if _, ok := err.(*ContainerError); ok {
|
||||
return err
|
||||
}
|
||||
containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
|
||||
return containerError
|
||||
}
|
||||
|
||||
func (e *ProcessError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
if e.Process == nil {
|
||||
return "Unexpected nil process for error: " + e.Err.Error()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
switch e.Err.(type) {
|
||||
case nil:
|
||||
break
|
||||
case syscall.Errno:
|
||||
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
|
||||
}
|
||||
|
||||
func makeProcessError(process *process, operation string, extraInfo string, err error) error {
|
||||
// Don't double wrap errors
|
||||
if _, ok := err.(*ProcessError); ok {
|
||||
return err
|
||||
}
|
||||
processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
|
||||
return processError
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if _, ok := err.(EndpointNotFoundError); ok {
|
||||
return true
|
||||
}
|
||||
if _, ok := err.(NetworkNotFoundError); ok {
|
||||
return true
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
return hcs.IsTimeout(getInnerError(err))
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return hcs.IsAlreadyStopped(getInnerError(err))
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return hcs.IsNotSupported(getInnerError(err))
|
||||
}
|
||||
|
||||
func getInnerError(err error) error {
|
||||
switch pe := err.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
case *ContainerError:
|
||||
err = pe.Err
|
||||
case *ProcessError:
|
||||
err = pe.Err
|
||||
}
|
||||
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
|
||||
}
|
12
vendor/github.com/Microsoft/hcsshim/functional_tests.ps1
generated
vendored
Normal file
12
vendor/github.com/Microsoft/hcsshim/functional_tests.ps1
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Requirements so far:
|
||||
# dockerd running
|
||||
# - image microsoft/nanoserver (matching host base image) docker load -i c:\baseimages\nanoserver.tar
|
||||
# - image alpine (linux) docker pull --platform=linux alpine
|
||||
|
||||
|
||||
# TODO: Add this a parameter for debugging. ie "functional-tests -debug=$true"
|
||||
#$env:HCSSHIM_FUNCTIONAL_TESTS_DEBUG="yes please"
|
||||
|
||||
#pushd uvm
|
||||
go test -v -tags "functional uvmcreate uvmscratch uvmscsi uvmvpmem uvmvsmb uvmp9" ./...
|
||||
#popd
|
28
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
Normal file
28
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Shim for the Host Compute Service (HCS) to manage Windows Server
|
||||
// containers and Hyper-V containers.
|
||||
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
)
|
||||
|
||||
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go hcsshim.go
|
||||
|
||||
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
||||
|
||||
const (
|
||||
// Specific user-visible exit codes
|
||||
WaitErrExecFailed = 32767
|
||||
|
||||
ERROR_GEN_FAILURE = hcserror.ERROR_GEN_FAILURE
|
||||
ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
|
||||
WSAEINVAL = syscall.Errno(10022)
|
||||
|
||||
// Timeout on wait calls
|
||||
TimeoutInfinite = 0xFFFFFFFF
|
||||
)
|
||||
|
||||
type HcsError = hcserror.HcsError
|
91
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
Normal file
91
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim/internal/hns"
|
||||
)
|
||||
|
||||
// HNSEndpoint represents a network endpoint in HNS
|
||||
type HNSEndpoint = hns.HNSEndpoint
|
||||
|
||||
//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 = hns.EndpointAttachDetachRequest
|
||||
|
||||
// EndpointResquestResponse is object to get the endpoint request response
|
||||
type EndpointResquestResponse = hns.EndpointResquestResponse
|
||||
|
||||
// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
|
||||
func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
|
||||
return hns.HNSEndpointRequest(method, path, request)
|
||||
}
|
||||
|
||||
// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
|
||||
func HNSListEndpointRequest() ([]HNSEndpoint, error) {
|
||||
return hns.HNSListEndpointRequest()
|
||||
}
|
||||
|
||||
// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
|
||||
func HotAttachEndpoint(containerID string, endpointID string) error {
|
||||
return modifyNetworkEndpoint(containerID, endpointID, Add)
|
||||
}
|
||||
|
||||
// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container
|
||||
func HotDetachEndpoint(containerID string, endpointID string) error {
|
||||
return modifyNetworkEndpoint(containerID, endpointID, Remove)
|
||||
}
|
||||
|
||||
// ModifyContainer corresponding to the container id, by sending a request
|
||||
func modifyContainer(id string, request *ResourceModificationRequestResponse) error {
|
||||
container, err := OpenContainer(id)
|
||||
if err != nil {
|
||||
if IsNotExist(err) {
|
||||
return ErrComputeSystemDoesNotExist
|
||||
}
|
||||
return getInnerError(err)
|
||||
}
|
||||
defer container.Close()
|
||||
err = container.Modify(request)
|
||||
if err != nil {
|
||||
if IsNotSupported(err) {
|
||||
return ErrPlatformNotSupported
|
||||
}
|
||||
return getInnerError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error {
|
||||
requestMessage := &ResourceModificationRequestResponse{
|
||||
Resource: Network,
|
||||
Request: request,
|
||||
Data: endpointID,
|
||||
}
|
||||
err := modifyContainer(containerID, requestMessage)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHNSEndpointByID get the Endpoint by ID
|
||||
func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
|
||||
return hns.GetHNSEndpointByID(endpointID)
|
||||
}
|
||||
|
||||
// GetHNSEndpointByName gets the endpoint filtered by Name
|
||||
func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
|
||||
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()
|
||||
}
|
36
vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
generated
vendored
Normal file
36
vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim/internal/hns"
|
||||
)
|
||||
|
||||
// Subnet is assoicated with a network and represents a list
|
||||
// of subnets available to the network
|
||||
type Subnet = hns.Subnet
|
||||
|
||||
// MacPool is assoicated with a network and represents a list
|
||||
// of macaddresses available to the network
|
||||
type MacPool = hns.MacPool
|
||||
|
||||
// HNSNetwork represents a network in HNS
|
||||
type HNSNetwork = hns.HNSNetwork
|
||||
|
||||
// HNSNetworkRequest makes a call into HNS to update/query a single network
|
||||
func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
|
||||
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) {
|
||||
return hns.HNSListNetworkRequest(method, path, request)
|
||||
}
|
||||
|
||||
// GetHNSNetworkByID
|
||||
func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
|
||||
return hns.GetHNSNetworkByID(networkID)
|
||||
}
|
||||
|
||||
// GetHNSNetworkName filtered by Name
|
||||
func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
|
||||
return hns.GetHNSNetworkByName(networkName)
|
||||
}
|
57
vendor/github.com/Microsoft/hcsshim/hnspolicy.go
generated
vendored
Normal file
57
vendor/github.com/Microsoft/hcsshim/hnspolicy.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim/internal/hns"
|
||||
)
|
||||
|
||||
// Type of Request Support in ModifySystem
|
||||
type PolicyType = hns.PolicyType
|
||||
|
||||
// RequestType const
|
||||
const (
|
||||
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 = hns.NatPolicy
|
||||
|
||||
type QosPolicy = hns.QosPolicy
|
||||
|
||||
type IsolationPolicy = hns.IsolationPolicy
|
||||
|
||||
type VlanPolicy = hns.VlanPolicy
|
||||
|
||||
type VsidPolicy = hns.VsidPolicy
|
||||
|
||||
type PaPolicy = hns.PaPolicy
|
||||
|
||||
type OutboundNatPolicy = hns.OutboundNatPolicy
|
||||
|
||||
type ActionType = hns.ActionType
|
||||
type DirectionType = hns.DirectionType
|
||||
type RuleType = hns.RuleType
|
||||
|
||||
const (
|
||||
Allow = hns.Allow
|
||||
Block = hns.Block
|
||||
|
||||
In = hns.In
|
||||
Out = hns.Out
|
||||
|
||||
Host = hns.Host
|
||||
Switch = hns.Switch
|
||||
)
|
||||
|
||||
type ACLPolicy = hns.ACLPolicy
|
||||
|
||||
type Policy = hns.Policy
|
47
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
Normal file
47
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim/internal/hns"
|
||||
)
|
||||
|
||||
// RoutePolicy is a structure defining schema for Route based Policy
|
||||
type RoutePolicy = hns.RoutePolicy
|
||||
|
||||
// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
|
||||
type ELBPolicy = hns.ELBPolicy
|
||||
|
||||
// LBPolicy is a structure defining schema for LoadBalancing based Policy
|
||||
type LBPolicy = hns.LBPolicy
|
||||
|
||||
// PolicyList is a structure defining schema for Policy list request
|
||||
type PolicyList = hns.PolicyList
|
||||
|
||||
// HNSPolicyListRequest makes a call into HNS to update/query a single network
|
||||
func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
|
||||
return hns.HNSPolicyListRequest(method, path, request)
|
||||
}
|
||||
|
||||
// HNSListPolicyListRequest gets all the policy list
|
||||
func HNSListPolicyListRequest() ([]PolicyList, error) {
|
||||
return hns.HNSListPolicyListRequest()
|
||||
}
|
||||
|
||||
// PolicyListRequest makes a HNS call to modify/query a network policy list
|
||||
func PolicyListRequest(method, path, request string) (*PolicyList, error) {
|
||||
return hns.PolicyListRequest(method, path, request)
|
||||
}
|
||||
|
||||
// GetPolicyListByID get the policy list by ID
|
||||
func GetPolicyListByID(policyListID string) (*PolicyList, error) {
|
||||
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) {
|
||||
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) {
|
||||
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()
|
||||
}
|
109
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
Normal file
109
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/schema1"
|
||||
)
|
||||
|
||||
// ProcessConfig is used as both the input of Container.CreateProcess
|
||||
// and to convert the parameters to JSON for passing onto the HCS
|
||||
type ProcessConfig = schema1.ProcessConfig
|
||||
|
||||
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 = schema1.ContainerConfig
|
||||
|
||||
type ComputeSystemQuery = schema1.ComputeSystemQuery
|
||||
|
||||
// Container represents a created (but not necessarily running) container.
|
||||
type Container interface {
|
||||
// Start synchronously starts the container.
|
||||
Start() error
|
||||
|
||||
// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
|
||||
Shutdown() error
|
||||
|
||||
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
|
||||
Terminate() error
|
||||
|
||||
// Waits synchronously waits for the container to shutdown or terminate.
|
||||
Wait() error
|
||||
|
||||
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
|
||||
// returns false if timeout occurs.
|
||||
WaitTimeout(time.Duration) error
|
||||
|
||||
// Pause pauses the execution of a container.
|
||||
Pause() error
|
||||
|
||||
// Resume resumes the execution of a container.
|
||||
Resume() error
|
||||
|
||||
// HasPendingUpdates returns true if the container has updates pending to install.
|
||||
HasPendingUpdates() (bool, error)
|
||||
|
||||
// Statistics returns statistics for a container.
|
||||
Statistics() (Statistics, error)
|
||||
|
||||
// ProcessList returns details for the processes in a container.
|
||||
ProcessList() ([]ProcessListItem, error)
|
||||
|
||||
// MappedVirtualDisks returns virtual disks mapped to a utility VM, indexed by controller
|
||||
MappedVirtualDisks() (map[int]MappedVirtualDiskController, error)
|
||||
|
||||
// CreateProcess launches a new process within the container.
|
||||
CreateProcess(c *ProcessConfig) (Process, error)
|
||||
|
||||
// OpenProcess gets an interface to an existing process within the container.
|
||||
OpenProcess(pid int) (Process, error)
|
||||
|
||||
// Close cleans up any state associated with the container but does not terminate or wait for it.
|
||||
Close() error
|
||||
|
||||
// Modify the System
|
||||
Modify(config *ResourceModificationRequestResponse) error
|
||||
}
|
||||
|
||||
// Process represents a running or exited process.
|
||||
type Process interface {
|
||||
// Pid returns the process ID of the process within the container.
|
||||
Pid() int
|
||||
|
||||
// Kill signals the process to terminate but does not wait for it to finish terminating.
|
||||
Kill() error
|
||||
|
||||
// Wait waits for the process to exit.
|
||||
Wait() error
|
||||
|
||||
// WaitTimeout waits for the process to exit or the duration to elapse. It returns
|
||||
// false if timeout occurs.
|
||||
WaitTimeout(time.Duration) error
|
||||
|
||||
// ExitCode returns the exit code of the process. The process must have
|
||||
// already terminated.
|
||||
ExitCode() (int, error)
|
||||
|
||||
// ResizeConsole resizes the console of the process.
|
||||
ResizeConsole(width, height uint16) error
|
||||
|
||||
// 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.
|
||||
Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error)
|
||||
|
||||
// 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.
|
||||
CloseStdin() error
|
||||
|
||||
// Close cleans up any state associated with the process but does not kill
|
||||
// or wait on it.
|
||||
Close() error
|
||||
}
|
69
vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
generated
vendored
Normal file
69
vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = (json.Marshaler)(&GUID{})
|
||||
var _ = (json.Unmarshaler)(&GUID{})
|
||||
|
||||
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:])
|
||||
}
|
||||
|
||||
func FromString(s string) GUID {
|
||||
if len(s) != 36 {
|
||||
panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
|
||||
}
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
panic("invalid GUID format")
|
||||
}
|
||||
indexOrder := [16]int{
|
||||
0, 2, 4, 6,
|
||||
9, 11,
|
||||
14, 16,
|
||||
19, 21,
|
||||
24, 26, 28, 30, 32, 34,
|
||||
}
|
||||
byteOrder := [16]int{
|
||||
3, 2, 1, 0,
|
||||
5, 4,
|
||||
7, 6,
|
||||
8, 9,
|
||||
10, 11, 12, 13, 14, 15,
|
||||
}
|
||||
var g GUID
|
||||
for i, x := range indexOrder {
|
||||
b, err := strconv.ParseInt(s[x:x+2], 16, 16)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
g[byteOrder[i]] = byte(b)
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func (g GUID) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(g.String())
|
||||
}
|
||||
|
||||
func (g *GUID) UnmarshalJSON(data []byte) error {
|
||||
*g = FromString(strings.Trim(string(data), "\""))
|
||||
return nil
|
||||
}
|
81
vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go
generated
vendored
Normal file
81
vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/interop"
|
||||
)
|
||||
|
||||
var (
|
||||
nextCallback uintptr
|
||||
callbackMap = map[uintptr]*notifcationWatcherContext{}
|
||||
callbackMapLock = sync.RWMutex{}
|
||||
|
||||
notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
|
||||
|
||||
// Notifications for HCS_SYSTEM handles
|
||||
hcsNotificationSystemExited hcsNotification = 0x00000001
|
||||
hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
|
||||
hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
|
||||
hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
|
||||
hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
|
||||
|
||||
// Notifications for HCS_PROCESS handles
|
||||
hcsNotificationProcessExited hcsNotification = 0x00010000
|
||||
|
||||
// Common notifications
|
||||
hcsNotificationInvalid hcsNotification = 0x00000000
|
||||
hcsNotificationServiceDisconnect hcsNotification = 0x01000000
|
||||
)
|
||||
|
||||
type hcsNotification uint32
|
||||
type notificationChannel chan error
|
||||
|
||||
type notifcationWatcherContext struct {
|
||||
channels notificationChannels
|
||||
handle hcsCallback
|
||||
}
|
||||
|
||||
type notificationChannels map[hcsNotification]notificationChannel
|
||||
|
||||
func newChannels() notificationChannels {
|
||||
channels := make(notificationChannels)
|
||||
|
||||
channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
|
||||
return channels
|
||||
}
|
||||
func closeChannels(channels notificationChannels) {
|
||||
close(channels[hcsNotificationSystemExited])
|
||||
close(channels[hcsNotificationSystemCreateCompleted])
|
||||
close(channels[hcsNotificationSystemStartCompleted])
|
||||
close(channels[hcsNotificationSystemPauseCompleted])
|
||||
close(channels[hcsNotificationSystemResumeCompleted])
|
||||
close(channels[hcsNotificationProcessExited])
|
||||
close(channels[hcsNotificationServiceDisconnect])
|
||||
}
|
||||
|
||||
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
|
||||
var result error
|
||||
if int32(notificationStatus) < 0 {
|
||||
result = interop.Win32FromHresult(notificationStatus)
|
||||
}
|
||||
|
||||
callbackMapLock.RLock()
|
||||
context := callbackMap[callbackNumber]
|
||||
callbackMapLock.RUnlock()
|
||||
|
||||
if context == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
context.channels[notificationType] <- result
|
||||
|
||||
return 0
|
||||
}
|
7
vendor/github.com/Microsoft/hcsshim/internal/hcs/cgo.go
generated
vendored
Normal file
7
vendor/github.com/Microsoft/hcsshim/internal/hcs/cgo.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package hcs
|
||||
|
||||
import "C"
|
||||
|
||||
// This import is needed to make the library compile as CGO because HCSSHIM
|
||||
// only works with CGO due to callbacks from HCS comming back from a C thread
|
||||
// which is not supported without CGO. See https://github.com/golang/go/issues/10973
|
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
|
||||
}
|
393
vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
generated
vendored
Normal file
393
vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
generated
vendored
Normal file
@ -0,0 +1,393 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("TerminateProcess %s: %d", process.SystemID(), process.Pid()), &completed)
|
||||
err := hcsTerminateProcess(process.handle, &resultp)
|
||||
completed = true
|
||||
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
|
||||
)
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("GetProcessProperties %s: %d", process.SystemID(), process.Pid()), &completed)
|
||||
err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp)
|
||||
completed = true
|
||||
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
|
||||
}
|
585
vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
generated
vendored
Normal file
585
vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
generated
vendored
Normal file
@ -0,0 +1,585 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"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
|
||||
)
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("CreateCompleteSystem %s: %s", id, hcsDocument), &completed)
|
||||
createError := hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp)
|
||||
completed = true
|
||||
|
||||
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.SystemCreate)
|
||||
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
|
||||
)
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("GetComputeSystems %s:", query), &completed)
|
||||
err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
|
||||
completed = true
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("StartComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsStartComputeSystem(computeSystem.handle, "", &resultp)
|
||||
completed = true
|
||||
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart)
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("ShutdownComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp)
|
||||
completed = true
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("TerminateComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp)
|
||||
completed = true
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("GetComputeSystemProperties %s:", computeSystem.ID()), &completed)
|
||||
err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
|
||||
completed = true
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("PauseComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp)
|
||||
completed = true
|
||||
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause)
|
||||
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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("ResumeComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp)
|
||||
completed = true
|
||||
events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume)
|
||||
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)
|
||||
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("CreateProcess %s: %s", computeSystem.ID(), configuration), &completed)
|
||||
err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp)
|
||||
completed = true
|
||||
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)
|
||||
}
|
||||
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("OpenProcess %s: %d", computeSystem.ID(), pid), &completed)
|
||||
err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp)
|
||||
completed = true
|
||||
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)
|
||||
}
|
||||
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("CloseComputeSystem %s:", computeSystem.ID()), &completed)
|
||||
err := hcsCloseComputeSystem(computeSystem.handle)
|
||||
completed = true
|
||||
if 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
|
||||
completed := false
|
||||
go syscallWatcher(fmt.Sprintf("ModifyComputeSystem %s: %s", computeSystem.ID(), requestString), &completed)
|
||||
err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp)
|
||||
completed = true
|
||||
events := processHcsResult(resultp)
|
||||
if err != nil {
|
||||
return makeSystemError(computeSystem, "Modify", requestString, err, events)
|
||||
}
|
||||
logrus.Debugf(title + " succeeded ")
|
||||
return nil
|
||||
}
|
33
vendor/github.com/Microsoft/hcsshim/internal/hcs/utils.go
generated
vendored
Normal file
33
vendor/github.com/Microsoft/hcsshim/internal/hcs/utils.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles
|
||||
// if there is an error.
|
||||
func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) {
|
||||
fs := make([]io.ReadWriteCloser, len(hs))
|
||||
for i, h := range hs {
|
||||
if h != syscall.Handle(0) {
|
||||
if err == nil {
|
||||
fs[i], err = winio.MakeOpenFile(h)
|
||||
}
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
for _, f := range fs {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return fs, nil
|
||||
}
|
63
vendor/github.com/Microsoft/hcsshim/internal/hcs/waithelper.go
generated
vendored
Normal file
63
vendor/github.com/Microsoft/hcsshim/internal/hcs/waithelper.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) ([]ErrorEvent, error) {
|
||||
events := processHcsResult(resultp)
|
||||
if IsPending(err) {
|
||||
return nil, waitForNotification(callbackNumber, expectedNotification, timeout)
|
||||
}
|
||||
|
||||
return events, err
|
||||
}
|
||||
|
||||
func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {
|
||||
callbackMapLock.RLock()
|
||||
channels := callbackMap[callbackNumber].channels
|
||||
callbackMapLock.RUnlock()
|
||||
|
||||
expectedChannel := channels[expectedNotification]
|
||||
if expectedChannel == nil {
|
||||
logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification)
|
||||
return ErrInvalidNotificationType
|
||||
}
|
||||
|
||||
var c <-chan time.Time
|
||||
if timeout != nil {
|
||||
timer := time.NewTimer(*timeout)
|
||||
c = timer.C
|
||||
defer timer.Stop()
|
||||
}
|
||||
|
||||
select {
|
||||
case err, ok := <-expectedChannel:
|
||||
if !ok {
|
||||
return ErrHandleClose
|
||||
}
|
||||
return err
|
||||
case err, ok := <-channels[hcsNotificationSystemExited]:
|
||||
if !ok {
|
||||
return ErrHandleClose
|
||||
}
|
||||
// If the expected notification is hcsNotificationSystemExited which of the two selects
|
||||
// chosen is random. Return the raw error if hcsNotificationSystemExited is expected
|
||||
if channels[hcsNotificationSystemExited] == expectedChannel {
|
||||
return err
|
||||
}
|
||||
return ErrUnexpectedContainerExit
|
||||
case _, ok := <-channels[hcsNotificationServiceDisconnect]:
|
||||
if !ok {
|
||||
return ErrHandleClose
|
||||
}
|
||||
// hcsNotificationServiceDisconnect should never be an expected notification
|
||||
// it does not need the same handling as hcsNotificationSystemExited
|
||||
return ErrUnexpectedProcessAbort
|
||||
case <-c:
|
||||
return ErrTimeout
|
||||
}
|
||||
return nil
|
||||
}
|
30
vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go
generated
vendored
Normal file
30
vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package hcs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/timeout"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// syscallWatcher is used as a very simple goroutine around calls into
|
||||
// the platform. In some cases, we have seen HCS APIs not returning due to
|
||||
// various bugs, and the goroutine making the syscall ends up not returning,
|
||||
// prior to its async callback. By spinning up a syscallWatcher, it allows
|
||||
// us to at least log a warning if a syscall doesn't complete in a reasonable
|
||||
// amount of time.
|
||||
//
|
||||
// Usage is:
|
||||
//
|
||||
// completed := false
|
||||
// go syscallWatcher("some description", &completed)
|
||||
// <syscall>
|
||||
// completed = true
|
||||
//
|
||||
func syscallWatcher(description string, syscallCompleted *bool) {
|
||||
time.Sleep(timeout.SyscallWatcher)
|
||||
if *syscallCompleted {
|
||||
return
|
||||
}
|
||||
logrus.Warnf("%s: Did not complete within %s. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see is there is a syscall stuck in the platform API for a significant length of time.", description, timeout.SyscallWatcher)
|
||||
}
|
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)
|
||||
}
|
42
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsfuncs.go
generated
vendored
Normal file
42
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsfuncs.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
package hns
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
"github.com/Microsoft/hcsshim/internal/interop"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func hnsCall(method, path, request string, returnResponse interface{}) error {
|
||||
var responseBuffer *uint16
|
||||
logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request)
|
||||
|
||||
err := _hnsCall(method, path, request, &responseBuffer)
|
||||
if err != nil {
|
||||
return hcserror.New(err, "hnsCall ", "")
|
||||
}
|
||||
response := interop.ConvertAndFreeCoTaskMemString(responseBuffer)
|
||||
|
||||
hnsresponse := &hnsResponse{}
|
||||
if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !hnsresponse.Success {
|
||||
return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error)
|
||||
}
|
||||
|
||||
if len(hnsresponse.Output) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
logrus.Debugf("Network Response : %s", hnsresponse.Output)
|
||||
err = json.Unmarshal(hnsresponse.Output, returnResponse)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return 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 @@
|
||||
// Code generated by 'go generate'; 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
|
||||
}
|
431
vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go
generated
vendored
Normal file
431
vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go
generated
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
package safefile
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"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
|
||||
//sys localAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc
|
||||
//sys localFree(ptr uintptr) = kernel32.LocalFree
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
ObjectName uintptr
|
||||
Attributes uintptr
|
||||
SecurityDescriptor uintptr
|
||||
SecurityQoS uintptr
|
||||
}
|
||||
|
||||
type unicodeString struct {
|
||||
Length uint16
|
||||
MaximumLength uint16
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
type fileLinkInformation struct {
|
||||
ReplaceIfExists bool
|
||||
RootDirectory uintptr
|
||||
FileNameLength uint32
|
||||
FileName [1]uint16
|
||||
}
|
||||
|
||||
type fileDispositionInformationEx struct {
|
||||
Flags uintptr
|
||||
}
|
||||
|
||||
const (
|
||||
_FileLinkInformation = 11
|
||||
_FileDispositionInformationEx = 64
|
||||
|
||||
FILE_READ_ATTRIBUTES = 0x0080
|
||||
FILE_WRITE_ATTRIBUTES = 0x0100
|
||||
DELETE = 0x10000
|
||||
|
||||
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_DISPOSITION_DELETE = 0x00000001
|
||||
|
||||
_OBJ_DONT_REPARSE = 0x1000
|
||||
|
||||
_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B
|
||||
)
|
||||
|
||||
func OpenRoot(path string) (*os.File, error) {
|
||||
longpath, err := longpath.LongAbs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return winio.OpenForBackup(longpath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.OPEN_EXISTING)
|
||||
}
|
||||
|
||||
func ntRelativePath(path string) ([]uint16, error) {
|
||||
path = filepath.Clean(path)
|
||||
if strings.Contains(":", path) {
|
||||
// Since alternate data streams must follow the file they
|
||||
// are attached to, finding one here (out of order) is invalid.
|
||||
return nil, errors.New("path contains invalid character `:`")
|
||||
}
|
||||
fspath := filepath.FromSlash(path)
|
||||
if len(fspath) > 0 && fspath[0] == '\\' {
|
||||
return nil, errors.New("expected relative path")
|
||||
}
|
||||
|
||||
path16 := utf16.Encode(([]rune)(fspath))
|
||||
if len(path16) > 32767 {
|
||||
return nil, syscall.ENAMETOOLONG
|
||||
}
|
||||
|
||||
return path16, nil
|
||||
}
|
||||
|
||||
// openRelativeInternal opens a relative path from the given root, failing if
|
||||
// any of the intermediate path components are reparse points.
|
||||
func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) {
|
||||
var (
|
||||
h uintptr
|
||||
iosb ioStatusBlock
|
||||
oa objectAttributes
|
||||
)
|
||||
|
||||
path16, err := ntRelativePath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if root == nil || root.Fd() == 0 {
|
||||
return nil, errors.New("missing root directory")
|
||||
}
|
||||
|
||||
upathBuffer := localAlloc(0, int(unsafe.Sizeof(unicodeString{}))+len(path16)*2)
|
||||
defer localFree(upathBuffer)
|
||||
|
||||
upath := (*unicodeString)(unsafe.Pointer(upathBuffer))
|
||||
upath.Length = uint16(len(path16) * 2)
|
||||
upath.MaximumLength = upath.Length
|
||||
upath.Buffer = upathBuffer + unsafe.Sizeof(*upath)
|
||||
copy((*[32768]uint16)(unsafe.Pointer(upath.Buffer))[:], path16)
|
||||
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
oa.ObjectName = upathBuffer
|
||||
oa.RootDirectory = uintptr(root.Fd())
|
||||
oa.Attributes = _OBJ_DONT_REPARSE
|
||||
status := ntCreateFile(
|
||||
&h,
|
||||
accessMask|syscall.SYNCHRONIZE,
|
||||
&oa,
|
||||
&iosb,
|
||||
nil,
|
||||
0,
|
||||
shareFlags,
|
||||
createDisposition,
|
||||
FILE_OPEN_FOR_BACKUP_INTENT|FILE_SYNCHRONOUS_IO_NONALERT|flags,
|
||||
nil,
|
||||
0,
|
||||
)
|
||||
if status != 0 {
|
||||
return nil, rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
fullPath, err := longpath.LongAbs(filepath.Join(root.Name(), path))
|
||||
if err != nil {
|
||||
syscall.Close(syscall.Handle(h))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return os.NewFile(h, fullPath), nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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}
|
||||
}
|
||||
return f, err
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return &os.LinkError{Op: "link", Old: filepath.Join(oldroot.Name(), oldname), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||
}
|
||||
defer oldf.Close()
|
||||
|
||||
// Open the parent of the new file.
|
||||
var parent *os.File
|
||||
parentPath := filepath.Dir(newname)
|
||||
if parentPath != "." {
|
||||
parent, err = openRelativeInternal(
|
||||
parentPath,
|
||||
newroot,
|
||||
syscall.GENERIC_READ,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_DIRECTORY_FILE)
|
||||
if err != nil {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||
}
|
||||
defer parent.Close()
|
||||
|
||||
fi, err := winio.GetFileBasicInfo(parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (fi.FileAttributes & syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: rtlNtStatusToDosError(_STATUS_REPARSE_POINT_ENCOUNTERED)}
|
||||
}
|
||||
|
||||
} else {
|
||||
parent = newroot
|
||||
}
|
||||
|
||||
// Issue an NT call to create the link. This will be safe because NT will
|
||||
// not open any more directories to create the link, so it cannot walk any
|
||||
// more reparse points.
|
||||
newbase := filepath.Base(newname)
|
||||
newbase16, err := ntRelativePath(newbase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
size := int(unsafe.Offsetof(fileLinkInformation{}.FileName)) + len(newbase16)*2
|
||||
linkinfoBuffer := localAlloc(0, size)
|
||||
defer localFree(linkinfoBuffer)
|
||||
linkinfo := (*fileLinkInformation)(unsafe.Pointer(linkinfoBuffer))
|
||||
linkinfo.RootDirectory = parent.Fd()
|
||||
linkinfo.FileNameLength = uint32(len(newbase16) * 2)
|
||||
copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16)
|
||||
|
||||
var iosb ioStatusBlock
|
||||
status := ntSetInformationFile(
|
||||
oldf.Fd(),
|
||||
&iosb,
|
||||
linkinfoBuffer,
|
||||
uint32(size),
|
||||
_FileLinkInformation,
|
||||
)
|
||||
if status != 0 {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(parent.Name(), newbase), Err: rtlNtStatusToDosError(status)}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteOnClose marks a file to be deleted when the handle is closed.
|
||||
func deleteOnClose(f *os.File) error {
|
||||
disposition := fileDispositionInformationEx{Flags: FILE_DISPOSITION_DELETE}
|
||||
var iosb ioStatusBlock
|
||||
status := ntSetInformationFile(
|
||||
f.Fd(),
|
||||
&iosb,
|
||||
uintptr(unsafe.Pointer(&disposition)),
|
||||
uint32(unsafe.Sizeof(disposition)),
|
||||
_FileDispositionInformationEx,
|
||||
)
|
||||
if status != 0 {
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// clearReadOnly clears the readonly attribute on a file.
|
||||
func clearReadOnly(f *os.File) error {
|
||||
bi, err := winio.GetFileBasicInfo(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY == 0 {
|
||||
return nil
|
||||
}
|
||||
sbi := winio.FileBasicInfo{
|
||||
FileAttributes: bi.FileAttributes &^ syscall.FILE_ATTRIBUTE_READONLY,
|
||||
}
|
||||
if sbi.FileAttributes == 0 {
|
||||
sbi.FileAttributes = syscall.FILE_ATTRIBUTE_NORMAL
|
||||
}
|
||||
return winio.SetFileBasicInfo(f, &sbi)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
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)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
err = deleteOnClose(f)
|
||||
if err == syscall.ERROR_ACCESS_DENIED {
|
||||
// Maybe the file is marked readonly. Clear the bit and retry.
|
||||
clearReadOnly(f)
|
||||
err = deleteOnClose(f)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "remove", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
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)
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// It is necessary to use os.Open as Readdirnames does not work with
|
||||
// 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))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Race. It was deleted between the Lstat and Open.
|
||||
// Return nil per RemoveAll's docs.
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove contents & return first error.
|
||||
for {
|
||||
names, err1 := fd.Readdirnames(100)
|
||||
for _, name := range names {
|
||||
err1 := RemoveAllRelative(path+string(os.PathSeparator)+name, root)
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
}
|
||||
if err1 == io.EOF {
|
||||
break
|
||||
}
|
||||
// If Readdirnames returned an error, use it.
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
if len(names) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fd.Close()
|
||||
|
||||
// Remove directory.
|
||||
err1 := RemoveRelative(path, root)
|
||||
if err1 == nil || os.IsNotExist(err1) {
|
||||
return nil
|
||||
}
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 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 {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
0,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_CREATE,
|
||||
FILE_DIRECTORY_FILE)
|
||||
if err == nil {
|
||||
f.Close()
|
||||
} else {
|
||||
err = &os.PathError{Op: "mkdir", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 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) {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_OPEN_REPARSE_POINT)
|
||||
if err != nil {
|
||||
return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
defer f.Close()
|
||||
return f.Stat()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT.
|
||||
f, err := OpenRelative(
|
||||
path,
|
||||
root,
|
||||
0,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
return nil
|
||||
}
|
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 @@
|
||||
// Code generated by 'go generate'; 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"`
|
||||
}
|
70
vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
generated
vendored
Normal file
70
vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
package timeout
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// defaultTimeout is the timeout for most operations that is not overridden.
|
||||
defaultTimeout = 4 * time.Minute
|
||||
|
||||
// defaultTimeoutTestdRetry is the retry loop timeout for testd to respond
|
||||
// for a disk to come online in LCOW.
|
||||
defaultTimeoutTestdRetry = 5 * time.Second
|
||||
)
|
||||
|
||||
// External variables for HCSShim consumers to use.
|
||||
var (
|
||||
// SystemCreate is the timeout for creating a compute system
|
||||
SystemCreate time.Duration = defaultTimeout
|
||||
|
||||
// SystemStart is the timeout for starting a compute system
|
||||
SystemStart time.Duration = defaultTimeout
|
||||
|
||||
// SystemPause is the timeout for pausing a compute system
|
||||
SystemPause time.Duration = defaultTimeout
|
||||
|
||||
// SystemResume is the timeout for resuming a compute system
|
||||
SystemResume time.Duration = defaultTimeout
|
||||
|
||||
// SyscallWatcher is the timeout before warning of a potential stuck platform syscall.
|
||||
SyscallWatcher time.Duration = defaultTimeout
|
||||
|
||||
// Tar2VHD is the timeout for the tar2vhd operation to complete
|
||||
Tar2VHD time.Duration = defaultTimeout
|
||||
|
||||
// ExternalCommandToStart is the timeout for external commands to start
|
||||
ExternalCommandToStart = defaultTimeout
|
||||
|
||||
// ExternalCommandToComplete is the timeout for external commands to complete.
|
||||
// Generally this means copying data from their stdio pipes.
|
||||
ExternalCommandToComplete = defaultTimeout
|
||||
|
||||
// TestDRetryLoop is the timeout for testd retry loop when onlining a SCSI disk in LCOW
|
||||
TestDRetryLoop = defaultTimeoutTestdRetry
|
||||
)
|
||||
|
||||
func init() {
|
||||
SystemCreate = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMCREATE", SystemCreate)
|
||||
SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart)
|
||||
SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause)
|
||||
SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume)
|
||||
SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher)
|
||||
Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD)
|
||||
ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart)
|
||||
ExternalCommandToComplete = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDCOMPLETE", ExternalCommandToComplete)
|
||||
TestDRetryLoop = durationFromEnvironment("HCSSHIM_TIMEOUT_TESTDRETRYLOOP", TestDRetryLoop)
|
||||
}
|
||||
|
||||
func durationFromEnvironment(env string, defaultValue time.Duration) time.Duration {
|
||||
envTimeout := os.Getenv(env)
|
||||
if len(envTimeout) > 0 {
|
||||
e, err := strconv.Atoi(envTimeout)
|
||||
if err == nil && e > 0 {
|
||||
return time.Second * time.Duration(e)
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
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
|
||||
}
|
173
vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go
generated
vendored
Normal file
173
vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
package wclayer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
"github.com/Microsoft/hcsshim/internal/safefile"
|
||||
)
|
||||
|
||||
type baseLayerWriter struct {
|
||||
root *os.File
|
||||
f *os.File
|
||||
bw *winio.BackupFileWriter
|
||||
err error
|
||||
hasUtilityVM bool
|
||||
dirInfo []dirInfo
|
||||
}
|
||||
|
||||
type dirInfo struct {
|
||||
path string
|
||||
fileInfo winio.FileBasicInfo
|
||||
}
|
||||
|
||||
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
||||
// after processing of the directory tree has completed. The times are expected
|
||||
// to be ordered such that parent directories come before child directories.
|
||||
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 := 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
|
||||
}
|
||||
|
||||
err = winio.SetFileBasicInfo(f, &di.fileInfo)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) closeCurrentFile() error {
|
||||
if w.f != nil {
|
||||
err := w.bw.Close()
|
||||
err2 := w.f.Close()
|
||||
w.f = nil
|
||||
w.bw = nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
}()
|
||||
|
||||
err = w.closeCurrentFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if filepath.ToSlash(name) == `UtilityVM/Files` {
|
||||
w.hasUtilityVM = true
|
||||
}
|
||||
|
||||
var f *os.File
|
||||
defer func() {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
extraFlags := uint32(0)
|
||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
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 = safefile.OpenRelative(name, w.root, mode, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, extraFlags)
|
||||
if err != nil {
|
||||
return hcserror.New(err, "Failed to safefile.OpenRelative", name)
|
||||
}
|
||||
|
||||
err = winio.SetFileBasicInfo(f, fileInfo)
|
||||
if err != nil {
|
||||
return hcserror.New(err, "Failed to SetFileBasicInfo", name)
|
||||
}
|
||||
|
||||
w.f = f
|
||||
w.bw = winio.NewBackupFileWriter(f, true)
|
||||
f = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
}()
|
||||
|
||||
err = w.closeCurrentFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return safefile.LinkRelative(target, w.root, name, w.root)
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) Remove(name string) error {
|
||||
return errors.New("base layer cannot have tombstones")
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) Write(b []byte) (int, error) {
|
||||
n, err := w.bw.Write(b)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) Close() error {
|
||||
defer func() {
|
||||
w.root.Close()
|
||||
w.root = nil
|
||||
}()
|
||||
err := w.closeCurrentFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if w.err == nil {
|
||||
// Restore the file times of all the directories, since they may have
|
||||
// been modified by creating child directories.
|
||||
err = reapplyDirectoryTimes(w.root, w.dirInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ProcessBaseLayer(w.root.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if w.hasUtilityVM {
|
||||
err := safefile.EnsureNotReparsePointRelative("UtilityVM", w.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return w.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+"ID %s parent %s", path, parent)
|
||||
|
||||
err := createLayer(&stdDriverInfo, path, parent)
|
||||
if err != nil {
|
||||
err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+"- succeeded path=%s parent=%s", 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
|
||||
}
|
147
vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go
generated
vendored
Normal file
147
vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
package wclayer
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
"github.com/Microsoft/hcsshim/internal/interop"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ExportLayer will create a folder at exportFolderPath and fill that folder with
|
||||
// the transport format version of the layer identified by layerId. This transport
|
||||
// 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(path string, exportFolderPath string, parentLayerPaths []string) error {
|
||||
title := "hcsshim::ExportLayer "
|
||||
logrus.Debugf(title+"path %s folder %s", path, exportFolderPath)
|
||||
|
||||
// Generate layer descriptors
|
||||
layers, err := layerPathsToDescriptors(parentLayerPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
logrus.Debugf(title+"succeeded path=%s folder=%s", path, exportFolderPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
type LayerReader interface {
|
||||
Next() (string, int64, *winio.FileBasicInfo, error)
|
||||
Read(b []byte) (int, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
// FilterLayerReader provides an interface for extracting the contents of an on-disk layer.
|
||||
type FilterLayerReader struct {
|
||||
context uintptr
|
||||
}
|
||||
|
||||
// Next reads the next available file from a layer, ensuring that parent directories are always read
|
||||
// before child files and directories.
|
||||
//
|
||||
// Next returns the file's relative path, size, and basic file metadata. Read() should be used to
|
||||
// extract a Win32 backup stream with the remainder of the metadata and the data.
|
||||
func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) {
|
||||
var fileNamep *uint16
|
||||
fileInfo := &winio.FileBasicInfo{}
|
||||
var deleted uint32
|
||||
var fileSize int64
|
||||
err := exportLayerNext(r.context, &fileNamep, fileInfo, &fileSize, &deleted)
|
||||
if err != nil {
|
||||
if err == syscall.ERROR_NO_MORE_FILES {
|
||||
err = io.EOF
|
||||
} else {
|
||||
err = hcserror.New(err, "ExportLayerNext", "")
|
||||
}
|
||||
return "", 0, nil, err
|
||||
}
|
||||
fileName := interop.ConvertAndFreeCoTaskMemString(fileNamep)
|
||||
if deleted != 0 {
|
||||
fileInfo = nil
|
||||
}
|
||||
if fileName[0] == '\\' {
|
||||
fileName = fileName[1:]
|
||||
}
|
||||
return fileName, fileSize, fileInfo, nil
|
||||
}
|
||||
|
||||
// Read reads from the current file's Win32 backup stream.
|
||||
func (r *FilterLayerReader) Read(b []byte) (int, error) {
|
||||
var bytesRead uint32
|
||||
err := exportLayerRead(r.context, b, &bytesRead)
|
||||
if err != nil {
|
||||
return 0, hcserror.New(err, "ExportLayerRead", "")
|
||||
}
|
||||
if bytesRead == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return int(bytesRead), nil
|
||||
}
|
||||
|
||||
// Close frees resources associated with the layer reader. It will return an
|
||||
// error if there was an error while reading the layer or of the layer was not
|
||||
// completely read.
|
||||
func (r *FilterLayerReader) Close() (err error) {
|
||||
if r.context != 0 {
|
||||
err = exportLayerEnd(r.context)
|
||||
if err != nil {
|
||||
err = hcserror.New(err, "ExportLayerEnd", "")
|
||||
}
|
||||
r.context = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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(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.
|
||||
exportPath, err := ioutil.TempDir("", "hcs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = ExportLayer(path, exportPath, parentLayerPaths)
|
||||
if err != nil {
|
||||
os.RemoveAll(exportPath)
|
||||
return nil, err
|
||||
}
|
||||
return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil
|
||||
}
|
||||
|
||||
layers, err := layerPathsToDescriptors(parentLayerPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := &FilterLayerReader{}
|
||||
err = exportLayerBegin(&stdDriverInfo, path, layers, &r.context)
|
||||
if err != nil {
|
||||
return nil, hcserror.New(err, "ExportLayerBegin", "")
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
type legacyLayerReaderWrapper struct {
|
||||
*legacyLayerReader
|
||||
}
|
||||
|
||||
func (r *legacyLayerReaderWrapper) Close() error {
|
||||
err := r.legacyLayerReader.Close()
|
||||
os.RemoveAll(r.root)
|
||||
return err
|
||||
}
|
49
vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go
generated
vendored
Normal file
49
vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package wclayer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 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(path string) (string, error) {
|
||||
title := "hcsshim::GetLayerMountPath "
|
||||
logrus.Debugf(title+"path %s", path)
|
||||
|
||||
var mountPathLength uintptr
|
||||
mountPathLength = 0
|
||||
|
||||
// Call the procedure itself.
|
||||
logrus.Debugf("Calling proc (1)")
|
||||
err := getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil)
|
||||
if err != nil {
|
||||
err = hcserror.Errorf(err, title, "(first call) path=%s", path)
|
||||
logrus.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Allocate a mount path of the returned length.
|
||||
if mountPathLength == 0 {
|
||||
return "", nil
|
||||
}
|
||||
mountPathp := make([]uint16, mountPathLength)
|
||||
mountPathp[0] = 0
|
||||
|
||||
// Call the procedure again
|
||||
logrus.Debugf("Calling proc (2)")
|
||||
err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, &mountPathp[0])
|
||||
if err != nil {
|
||||
err = hcserror.Errorf(err, title, "(second call) path=%s", path)
|
||||
logrus.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
mountPath := syscall.UTF16ToString(mountPathp[0:])
|
||||
logrus.Debugf(title+"succeeded path=%s mountPath=%s", path, mountPath)
|
||||
return mountPath, nil
|
||||
}
|
26
vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go
generated
vendored
Normal file
26
vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
package wclayer
|
||||
|
||||
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
|
||||
// of registering them with the graphdriver, graph, and tagstore.
|
||||
func GetSharedBaseImages() (imageData string, err error) {
|
||||
title := "hcsshim::GetSharedBaseImages "
|
||||
|
||||
logrus.Debugf("Calling proc")
|
||||
var buffer *uint16
|
||||
err = getBaseImages(&buffer)
|
||||
if err != nil {
|
||||
err = hcserror.New(err, title, "")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
206
vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go
generated
vendored
Normal file
206
vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
package wclayer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||
"github.com/Microsoft/hcsshim/internal/safefile"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ImportLayer will take the contents of the folder at importFolderPath and 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(path string, importFolderPath string, parentLayerPaths []string) error {
|
||||
title := "hcsshim::ImportLayer "
|
||||
logrus.Debugf(title+"path %s folder %s", path, importFolderPath)
|
||||
|
||||
// Generate layer descriptors
|
||||
layers, err := layerPathsToDescriptors(parentLayerPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
logrus.Debugf(title+"succeeded path=%s folder=%s", path, importFolderPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LayerWriter is an interface that supports writing a new container image layer.
|
||||
type LayerWriter interface {
|
||||
// Add adds a file to the layer with given metadata.
|
||||
Add(name string, fileInfo *winio.FileBasicInfo) error
|
||||
// AddLink adds a hard link to the layer. The target must already have been added.
|
||||
AddLink(name string, target string) error
|
||||
// Remove removes a file that was present in a parent layer from the layer.
|
||||
Remove(name string) error
|
||||
// Write writes data to the current file. The data must be in the format of a Win32
|
||||
// backup stream.
|
||||
Write(b []byte) (int, error)
|
||||
// Close finishes the layer writing process and releases any resources.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// FilterLayerWriter provides an interface to write the contents of a layer to the file system.
|
||||
type FilterLayerWriter struct {
|
||||
context uintptr
|
||||
}
|
||||
|
||||
// Add adds a file or directory to the layer. The file's parent directory must have already been added.
|
||||
//
|
||||
// name contains the file's relative path. fileInfo contains file times and file attributes; the rest
|
||||
// of the file metadata and the file data must be written as a Win32 backup stream to the Write() method.
|
||||
// winio.BackupStreamWriter can be used to facilitate this.
|
||||
func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
||||
if name[0] != '\\' {
|
||||
name = `\` + name
|
||||
}
|
||||
err := importLayerNext(w.context, name, fileInfo)
|
||||
if err != nil {
|
||||
return hcserror.New(err, "ImportLayerNext", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLink adds a hard link to the layer. The target of the link must have already been added.
|
||||
func (w *FilterLayerWriter) AddLink(name string, target string) error {
|
||||
return errors.New("hard links not yet supported")
|
||||
}
|
||||
|
||||
// Remove removes a file from the layer. The file must have been present in the parent layer.
|
||||
//
|
||||
// name contains the file's relative path.
|
||||
func (w *FilterLayerWriter) Remove(name string) error {
|
||||
if name[0] != '\\' {
|
||||
name = `\` + name
|
||||
}
|
||||
err := importLayerNext(w.context, name, nil)
|
||||
if err != nil {
|
||||
return hcserror.New(err, "ImportLayerNext", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes more backup stream data to the current file.
|
||||
func (w *FilterLayerWriter) Write(b []byte) (int, error) {
|
||||
err := importLayerWrite(w.context, b)
|
||||
if err != nil {
|
||||
err = hcserror.New(err, "ImportLayerWrite", "")
|
||||
return 0, err
|
||||
}
|
||||
return len(b), err
|
||||
}
|
||||
|
||||
// Close completes the layer write operation. The error must be checked to ensure that the
|
||||
// operation was successful.
|
||||
func (w *FilterLayerWriter) Close() (err error) {
|
||||
if w.context != 0 {
|
||||
err = importLayerEnd(w.context)
|
||||
if err != nil {
|
||||
err = hcserror.New(err, "ImportLayerEnd", "")
|
||||
}
|
||||
w.context = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type legacyLayerWriterWrapper struct {
|
||||
*legacyLayerWriter
|
||||
path string
|
||||
parentLayerPaths []string
|
||||
}
|
||||
|
||||
func (r *legacyLayerWriterWrapper) Close() error {
|
||||
defer os.RemoveAll(r.root.Name())
|
||||
defer r.legacyLayerWriter.CloseRoots()
|
||||
err := r.legacyLayerWriter.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ImportLayer(r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range r.Tombstones {
|
||||
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 = safefile.RemoveRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
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 := safefile.EnsureNotReparsePointRelative("UtilityVM", r.destRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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(path string, parentLayerPaths []string) (LayerWriter, error) {
|
||||
if len(parentLayerPaths) == 0 {
|
||||
// This is a base layer. It gets imported differently.
|
||||
f, err := safefile.OpenRoot(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &baseLayerWriter{
|
||||
root: f,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if procImportLayerBegin.Find() != nil {
|
||||
// The new layer reader is not available on this Windows build. Fall back to the
|
||||
// legacy export code path.
|
||||
importPath, err := ioutil.TempDir("", "hcs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &legacyLayerWriterWrapper{
|
||||
legacyLayerWriter: w,
|
||||
path: importPath,
|
||||
parentLayerPaths: parentLayerPaths,
|
||||
}, nil
|
||||
}
|
||||
layers, err := layerPathsToDescriptors(parentLayerPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
w := &FilterLayerWriter{}
|
||||
err = importLayerBegin(&stdDriverInfo, path, layers, &w.context)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
96
vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go
generated
vendored
Normal file
96
vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
package wclayer
|
||||
|
||||
// This file contains utility functions to support storage (graph) related
|
||||
// functionality.
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/guid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/* To pass into syscall, we need a struct matching the following:
|
||||
enum GraphDriverType
|
||||
{
|
||||
DiffDriver,
|
||||
FilterDriver
|
||||
};
|
||||
|
||||
struct DriverInfo {
|
||||
GraphDriverType Flavour;
|
||||
LPCWSTR HomeDir;
|
||||
};
|
||||
*/
|
||||
|
||||
type driverInfo struct {
|
||||
Flavour int
|
||||
HomeDirp *uint16
|
||||
}
|
||||
|
||||
var (
|
||||
utf16EmptyString uint16
|
||||
stdDriverInfo = driverInfo{1, &utf16EmptyString}
|
||||
)
|
||||
|
||||
/* To pass into syscall, we need a struct matching the following:
|
||||
typedef struct _WC_LAYER_DESCRIPTOR {
|
||||
|
||||
//
|
||||
// The ID of the layer
|
||||
//
|
||||
|
||||
GUID LayerId;
|
||||
|
||||
//
|
||||
// Additional flags
|
||||
//
|
||||
|
||||
union {
|
||||
struct {
|
||||
ULONG Reserved : 31;
|
||||
ULONG Dirty : 1; // Created from sandbox as a result of snapshot
|
||||
};
|
||||
ULONG Value;
|
||||
} Flags;
|
||||
|
||||
//
|
||||
// Path to the layer root directory, null-terminated
|
||||
//
|
||||
|
||||
PCWSTR Path;
|
||||
|
||||
} WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR;
|
||||
*/
|
||||
type WC_LAYER_DESCRIPTOR struct {
|
||||
LayerId guid.GUID
|
||||
Flags uint32
|
||||
Pathp *uint16
|
||||
}
|
||||
|
||||
func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, error) {
|
||||
// Array of descriptors that gets constructed.
|
||||
var layers []WC_LAYER_DESCRIPTOR
|
||||
|
||||
for i := 0; i < len(parentLayerPaths); i++ {
|
||||
g, err := LayerID(parentLayerPaths[i])
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to convert name to guid %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, err := syscall.UTF16PtrFromString(parentLayerPaths[i])
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed conversion of parentLayerPath to pointer %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
layers = append(layers, WC_LAYER_DESCRIPTOR{
|
||||
LayerId: g,
|
||||
Flags: 0,
|
||||
Pathp: p,
|
||||
})
|
||||
}
|
||||
|
||||
return layers, nil
|
||||
}
|
815
vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go
generated
vendored
Normal file
815
vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go
generated
vendored
Normal file
@ -0,0 +1,815 @@
|
||||
package wclayer
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"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("")
|
||||
|
||||
var mutatedUtilityVMFiles = map[string]bool{
|
||||
`EFI\Microsoft\Boot\BCD`: true,
|
||||
`EFI\Microsoft\Boot\BCD.LOG`: true,
|
||||
`EFI\Microsoft\Boot\BCD.LOG1`: true,
|
||||
`EFI\Microsoft\Boot\BCD.LOG2`: true,
|
||||
}
|
||||
|
||||
const (
|
||||
filesPath = `Files`
|
||||
hivesPath = `Hives`
|
||||
utilityVMPath = `UtilityVM`
|
||||
utilityVMFilesPath = `UtilityVM\Files`
|
||||
)
|
||||
|
||||
func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) {
|
||||
return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition)
|
||||
}
|
||||
|
||||
func hasPathPrefix(p, prefix string) bool {
|
||||
return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\'
|
||||
}
|
||||
|
||||
type fileEntry struct {
|
||||
path string
|
||||
fi os.FileInfo
|
||||
err error
|
||||
}
|
||||
|
||||
type legacyLayerReader struct {
|
||||
root string
|
||||
result chan *fileEntry
|
||||
proceed chan bool
|
||||
currentFile *os.File
|
||||
backupReader *winio.BackupFileReader
|
||||
}
|
||||
|
||||
// newLegacyLayerReader returns a new LayerReader that can read the Windows
|
||||
// container layer transport format from disk.
|
||||
func newLegacyLayerReader(root string) *legacyLayerReader {
|
||||
r := &legacyLayerReader{
|
||||
root: root,
|
||||
result: make(chan *fileEntry),
|
||||
proceed: make(chan bool),
|
||||
}
|
||||
go r.walk()
|
||||
return r
|
||||
}
|
||||
|
||||
func readTombstones(path string) (map[string]([]string), error) {
|
||||
tf, err := os.Open(filepath.Join(path, "tombstones.txt"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tf.Close()
|
||||
s := bufio.NewScanner(tf)
|
||||
if !s.Scan() || s.Text() != "\xef\xbb\xbfVersion 1.0" {
|
||||
return nil, errors.New("Invalid tombstones file")
|
||||
}
|
||||
|
||||
ts := make(map[string]([]string))
|
||||
for s.Scan() {
|
||||
t := filepath.Join(filesPath, s.Text()[1:]) // skip leading `\`
|
||||
dir := filepath.Dir(t)
|
||||
ts[dir] = append(ts[dir], t)
|
||||
}
|
||||
if err = s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) walkUntilCancelled() error {
|
||||
root, err := longpath.LongAbs(r.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.root = root
|
||||
ts, err := readTombstones(r.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048.
|
||||
// Handle failure from what may be a golang bug in the conversion of
|
||||
// UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat
|
||||
// which is called by filepath.Walk will fail when a filename contains
|
||||
// unicode characters. Skip the recycle bin regardless which is goodness.
|
||||
if strings.EqualFold(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) && info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") {
|
||||
return nil
|
||||
}
|
||||
|
||||
r.result <- &fileEntry{path, info, nil}
|
||||
if !<-r.proceed {
|
||||
return errorIterationCanceled
|
||||
}
|
||||
|
||||
// List all the tombstones.
|
||||
if info.IsDir() {
|
||||
relPath, err := filepath.Rel(r.root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dts, ok := ts[relPath]; ok {
|
||||
for _, t := range dts {
|
||||
r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil}
|
||||
if !<-r.proceed {
|
||||
return errorIterationCanceled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == errorIterationCanceled {
|
||||
return nil
|
||||
}
|
||||
if err == nil {
|
||||
return io.EOF
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) walk() {
|
||||
defer close(r.result)
|
||||
if !<-r.proceed {
|
||||
return
|
||||
}
|
||||
|
||||
err := r.walkUntilCancelled()
|
||||
if err != nil {
|
||||
for {
|
||||
r.result <- &fileEntry{err: err}
|
||||
if !<-r.proceed {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) reset() {
|
||||
if r.backupReader != nil {
|
||||
r.backupReader.Close()
|
||||
r.backupReader = nil
|
||||
}
|
||||
if r.currentFile != nil {
|
||||
r.currentFile.Close()
|
||||
r.currentFile = nil
|
||||
}
|
||||
}
|
||||
|
||||
func findBackupStreamSize(r io.Reader) (int64, error) {
|
||||
br := winio.NewBackupStreamReader(r)
|
||||
for {
|
||||
hdr, err := br.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
if hdr.Id == winio.BackupData {
|
||||
return hdr.Size, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) {
|
||||
r.reset()
|
||||
r.proceed <- true
|
||||
fe := <-r.result
|
||||
if fe == nil {
|
||||
err = errors.New("LegacyLayerReader closed")
|
||||
return
|
||||
}
|
||||
if fe.err != nil {
|
||||
err = fe.err
|
||||
return
|
||||
}
|
||||
|
||||
path, err = filepath.Rel(r.root, fe.path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if fe.fi == nil {
|
||||
// This is a tombstone. Return a nil fileInfo.
|
||||
return
|
||||
}
|
||||
|
||||
if fe.fi.IsDir() && hasPathPrefix(path, filesPath) {
|
||||
fe.path += ".$wcidirs$"
|
||||
}
|
||||
|
||||
f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
fileInfo, err = winio.GetFileBasicInfo(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !hasPathPrefix(path, filesPath) {
|
||||
size = fe.fi.Size()
|
||||
r.backupReader = winio.NewBackupFileReader(f, false)
|
||||
if path == hivesPath || path == filesPath {
|
||||
// The Hives directory has a non-deterministic file time because of the
|
||||
// nature of the import process. Use the times from System_Delta.
|
||||
var g *os.File
|
||||
g, err = os.Open(filepath.Join(r.root, hivesPath, `System_Delta`))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attr := fileInfo.FileAttributes
|
||||
fileInfo, err = winio.GetFileBasicInfo(g)
|
||||
g.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fileInfo.FileAttributes = attr
|
||||
}
|
||||
|
||||
// The creation time and access time get reset for files outside of the Files path.
|
||||
fileInfo.CreationTime = fileInfo.LastWriteTime
|
||||
fileInfo.LastAccessTime = fileInfo.LastWriteTime
|
||||
|
||||
} else {
|
||||
// The file attributes are written before the backup stream.
|
||||
var attr uint32
|
||||
err = binary.Read(f, binary.LittleEndian, &attr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fileInfo.FileAttributes = attr
|
||||
beginning := int64(4)
|
||||
|
||||
// Find the accurate file size.
|
||||
if !fe.fi.IsDir() {
|
||||
size, err = findBackupStreamSize(f)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "findBackupStreamSize", Path: fe.path, Err: err}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Return back to the beginning of the backup stream.
|
||||
_, err = f.Seek(beginning, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
r.currentFile = f
|
||||
f = nil
|
||||
return
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) Read(b []byte) (int, error) {
|
||||
if r.backupReader == nil {
|
||||
if r.currentFile == nil {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return r.currentFile.Read(b)
|
||||
}
|
||||
return r.backupReader.Read(b)
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) Seek(offset int64, whence int) (int64, error) {
|
||||
if r.backupReader == nil {
|
||||
if r.currentFile == nil {
|
||||
return 0, errors.New("no current file")
|
||||
}
|
||||
return r.currentFile.Seek(offset, whence)
|
||||
}
|
||||
return 0, errors.New("seek not supported on this stream")
|
||||
}
|
||||
|
||||
func (r *legacyLayerReader) Close() error {
|
||||
r.proceed <- false
|
||||
<-r.result
|
||||
r.reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
type pendingLink struct {
|
||||
Path, Target string
|
||||
TargetRoot *os.File
|
||||
}
|
||||
|
||||
type pendingDir struct {
|
||||
Path string
|
||||
Root *os.File
|
||||
}
|
||||
|
||||
type legacyLayerWriter struct {
|
||||
root *os.File
|
||||
destRoot *os.File
|
||||
parentRoots []*os.File
|
||||
currentFile *os.File
|
||||
bufWriter *bufio.Writer
|
||||
currentFileName string
|
||||
currentFileRoot *os.File
|
||||
backupWriter *winio.BackupFileWriter
|
||||
Tombstones []string
|
||||
HasUtilityVM bool
|
||||
uvmDi []dirInfo
|
||||
addedFiles map[string]bool
|
||||
PendingLinks []pendingLink
|
||||
pendingDirs []pendingDir
|
||||
currentIsDir bool
|
||||
}
|
||||
|
||||
// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
|
||||
// transport format to disk.
|
||||
func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) {
|
||||
w = &legacyLayerWriter{
|
||||
addedFiles: make(map[string]bool),
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
w.CloseRoots()
|
||||
w = nil
|
||||
}
|
||||
}()
|
||||
w.root, err = safefile.OpenRoot(root)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
w.destRoot, err = safefile.OpenRoot(destRoot)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, r := range parentRoots {
|
||||
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
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) CloseRoots() {
|
||||
if w.root != nil {
|
||||
w.root.Close()
|
||||
w.root = nil
|
||||
}
|
||||
if w.destRoot != nil {
|
||||
w.destRoot.Close()
|
||||
w.destRoot = nil
|
||||
}
|
||||
for i := range w.parentRoots {
|
||||
w.parentRoots[i].Close()
|
||||
}
|
||||
w.parentRoots = nil
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) initUtilityVM() error {
|
||||
if !w.HasUtilityVM {
|
||||
err := safefile.MkdirRelative(utilityVMPath, w.destRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Server 2016 does not support multiple layers for the utility VM, so
|
||||
// clone the utility VM from the parent layer into this layer. Use hard
|
||||
// links to avoid unnecessary copying, since most of the files are
|
||||
// immutable.
|
||||
err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
|
||||
}
|
||||
w.HasUtilityVM = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
// Seek to the beginning of the backup stream, skipping the fileattrs
|
||||
if _, err := r.Seek(4, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
bhdr, err := br.Next()
|
||||
if err == io.EOF {
|
||||
// end of backupstream data
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch bhdr.Id {
|
||||
case winio.BackupReparseData:
|
||||
// The current file is a `.$wcidirs$` metadata file that
|
||||
// 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 := safefile.RemoveRelative(w.currentFileName, w.currentFileRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
w.pendingDirs = append(w.pendingDirs, pendingDir{Path: w.currentFileName, Root: w.currentFileRoot})
|
||||
default:
|
||||
// ignore all other stream types, as we only care about directory reparse points
|
||||
}
|
||||
}
|
||||
w.currentIsDir = false
|
||||
}
|
||||
if w.backupWriter != nil {
|
||||
w.backupWriter.Close()
|
||||
w.backupWriter = nil
|
||||
}
|
||||
if w.currentFile != nil {
|
||||
w.currentFile.Close()
|
||||
w.currentFile = nil
|
||||
w.currentFileName = ""
|
||||
w.currentFileRoot = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 := safefile.OpenRelative(
|
||||
subPath,
|
||||
srcRoot,
|
||||
syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY,
|
||||
syscall.FILE_SHARE_READ,
|
||||
safefile.FILE_OPEN,
|
||||
safefile.FILE_OPEN_REPARSE_POINT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer src.Close()
|
||||
srcr := winio.NewBackupFileReader(src, true)
|
||||
defer srcr.Close()
|
||||
|
||||
fileInfo, err = winio.GetFileBasicInfo(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extraFlags := uint32(0)
|
||||
if isDir {
|
||||
extraFlags |= safefile.FILE_DIRECTORY_FILE
|
||||
}
|
||||
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,
|
||||
safefile.FILE_CREATE,
|
||||
extraFlags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
err = winio.SetFileBasicInfo(dest, fileInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
destw := winio.NewBackupFileWriter(dest, true)
|
||||
defer func() {
|
||||
cerr := destw.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(destw, srcr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fileInfo, nil
|
||||
}
|
||||
|
||||
// cloneTree clones a directory tree using hard links. It skips hard links for
|
||||
// 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 := safefile.EnsureNotReparsePointRelative(subPath, srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = filepath.Walk(filepath.Join(srcRoot.Name(), subPath), func(srcFilePath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||
// Directories, reparse points, and files that will be mutated during
|
||||
// utility VM import must be copied. All other files can be hard linked.
|
||||
isReparsePoint := fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0
|
||||
// In go1.9, FileInfo.IsDir() returns false if the directory is also a symlink.
|
||||
// See: https://github.com/golang/go/commit/1989921aef60c83e6f9127a8448fb5ede10e9acc
|
||||
// Fixes the problem by checking syscall.FILE_ATTRIBUTE_DIRECTORY directly
|
||||
isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
|
||||
|
||||
if isDir || isReparsePoint || mutatedFiles[relPath] {
|
||||
fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isDir && !isReparsePoint {
|
||||
di = append(di, dirInfo{path: relPath, fileInfo: *fi})
|
||||
}
|
||||
} else {
|
||||
err = safefile.LinkRelative(relPath, srcRoot, relPath, destRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return reapplyDirectoryTimes(destRoot, di)
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
||||
if err := w.reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if name == utilityVMPath {
|
||||
return w.initUtilityVM()
|
||||
}
|
||||
|
||||
name = filepath.Clean(name)
|
||||
if hasPathPrefix(name, utilityVMPath) {
|
||||
if !w.HasUtilityVM {
|
||||
return errors.New("missing UtilityVM directory")
|
||||
}
|
||||
if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
|
||||
return errors.New("invalid UtilityVM layer")
|
||||
}
|
||||
createDisposition := uint32(safefile.FILE_OPEN)
|
||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||
st, err := safefile.LstatRelative(name, w.destRoot)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if st != nil {
|
||||
// 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 = safefile.RemoveAllRelative(name, w.destRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
st = nil
|
||||
}
|
||||
}
|
||||
if st == nil {
|
||||
if err = safefile.MkdirRelative(name, w.destRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||
w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo})
|
||||
}
|
||||
} else {
|
||||
// Overwrite any existing hard link.
|
||||
err := safefile.RemoveRelative(name, w.destRoot)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
createDisposition = safefile.FILE_CREATE
|
||||
}
|
||||
|
||||
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,
|
||||
safefile.FILE_OPEN_REPARSE_POINT,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
safefile.RemoveRelative(name, w.destRoot)
|
||||
}
|
||||
}()
|
||||
|
||||
err = winio.SetFileBasicInfo(f, fileInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.backupWriter = winio.NewBackupFileWriter(f, true)
|
||||
w.bufWriter.Reset(w.backupWriter)
|
||||
w.currentFile = f
|
||||
w.currentFileName = name
|
||||
w.currentFileRoot = w.destRoot
|
||||
w.addedFiles[name] = true
|
||||
f = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
fname := name
|
||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||
err := safefile.MkdirRelative(name, w.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fname += ".$wcidirs$"
|
||||
w.currentIsDir = true
|
||||
}
|
||||
|
||||
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()
|
||||
safefile.RemoveRelative(fname, w.root)
|
||||
}
|
||||
}()
|
||||
|
||||
strippedFi := *fileInfo
|
||||
strippedFi.FileAttributes = 0
|
||||
err = winio.SetFileBasicInfo(f, &strippedFi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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(w.bufWriter, binary.LittleEndian, uint32(fileInfo.FileAttributes))
|
||||
if err != nil {
|
||||
w.bufWriter.Reset(ioutil.Discard)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
w.currentFile = f
|
||||
w.currentFileName = name
|
||||
w.currentFileRoot = w.root
|
||||
w.addedFiles[name] = true
|
||||
f = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
||||
if err := w.reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target = filepath.Clean(target)
|
||||
var roots []*os.File
|
||||
if hasPathPrefix(target, filesPath) {
|
||||
// Look for cross-layer hard link targets in the parent layers, since
|
||||
// nothing is in the destination path yet.
|
||||
roots = w.parentRoots
|
||||
} else if hasPathPrefix(target, utilityVMFilesPath) {
|
||||
// Since the utility VM is fully cloned into the destination path
|
||||
// already, look for cross-layer hard link targets directly in the
|
||||
// destination path.
|
||||
roots = []*os.File{w.destRoot}
|
||||
}
|
||||
|
||||
if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
|
||||
return errors.New("invalid hard link in layer")
|
||||
}
|
||||
|
||||
// Find to try the target of the link in a previously added file. If that
|
||||
// fails, search in parent layers.
|
||||
var selectedRoot *os.File
|
||||
if _, ok := w.addedFiles[target]; ok {
|
||||
selectedRoot = w.destRoot
|
||||
} else {
|
||||
for _, r := range roots {
|
||||
if _, err := safefile.LstatRelative(target, r); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
selectedRoot = r
|
||||
break
|
||||
}
|
||||
}
|
||||
if selectedRoot == nil {
|
||||
return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
|
||||
}
|
||||
}
|
||||
|
||||
// The link can't be written until after the ImportLayer call.
|
||||
w.PendingLinks = append(w.PendingLinks, pendingLink{
|
||||
Path: name,
|
||||
Target: target,
|
||||
TargetRoot: selectedRoot,
|
||||
})
|
||||
w.addedFiles[name] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) Remove(name string) error {
|
||||
name = filepath.Clean(name)
|
||||
if hasPathPrefix(name, filesPath) {
|
||||
w.Tombstones = append(w.Tombstones, name)
|
||||
} else if hasPathPrefix(name, utilityVMFilesPath) {
|
||||
err := w.initUtilityVM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 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 := safefile.LstatRelative(name, w.destRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
err = safefile.RemoveAllRelative(name, w.destRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("invalid tombstone %s", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) Write(b []byte) (int, error) {
|
||||
if w.backupWriter == nil && w.currentFile == nil {
|
||||
return 0, errors.New("closed")
|
||||
}
|
||||
return w.bufWriter.Write(b)
|
||||
}
|
||||
|
||||
func (w *legacyLayerWriter) Close() error {
|
||||
if err := w.reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := safefile.RemoveRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
for _, pd := range w.pendingDirs {
|
||||
err := safefile.MkdirRelative(pd.Path, pd.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if w.HasUtilityVM {
|
||||
err := reapplyDirectoryTimes(w.destRoot, w.uvmDi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
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
|
||||
}
|
40
vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go
generated
vendored
Normal file
40
vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
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 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(path string, parentLayerPaths []string) error {
|
||||
title := "hcsshim::PrepareLayer "
|
||||
logrus.Debugf(title+"path %s", path)
|
||||
|
||||
// Generate layer descriptors
|
||||
layers, err := layerPathsToDescriptors(parentLayerPaths)
|
||||
if err != nil {
|
||||
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(&stdDriverInfo, path, 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
|
||||
}
|
23
vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go
generated
vendored
Normal file
23
vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
package wclayer
|
||||
|
||||
import "os"
|
||||
|
||||
// ProcessBaseLayer post-processes a base layer that has had its files extracted.
|
||||
// The files should have been extracted to <path>\Files.
|
||||
func ProcessBaseLayer(path string) error {
|
||||
err := processBaseImage(path)
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "ProcessBaseLayer", Path: path, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProcessUtilityVMImage post-processes a utility VM image that has had its files extracted.
|
||||
// The files should have been extracted to <path>\Files.
|
||||
func ProcessUtilityVMImage(path string) error {
|
||||
err := processUtilityImage(path)
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "ProcessUtilityVMImage", Path: path, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
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
|
938
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
Normal file
938
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,938 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
mksyscall_windows generates windows system call bodies
|
||||
|
||||
It parses all files specified on command line containing function
|
||||
prototypes (like syscall_windows.go) and prints system call bodies
|
||||
to standard output.
|
||||
|
||||
The prototypes are marked by lines beginning with "//sys" and read
|
||||
like func declarations if //sys is replaced by func, but:
|
||||
|
||||
* The parameter lists must give a name for each argument. This
|
||||
includes return parameters.
|
||||
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
|
||||
* If go func name needs to be different from it's winapi dll name,
|
||||
the winapi name could be specified at the end, after "=" sign, like
|
||||
//sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA
|
||||
|
||||
* Each function that returns err needs to supply a condition, that
|
||||
return value of winapi will be tested against to detect failure.
|
||||
This would set err to windows "last-error", otherwise it will be nil.
|
||||
The value can be provided at end of //sys declaration, like
|
||||
//sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA
|
||||
and is [failretval==0] by default.
|
||||
|
||||
Usage:
|
||||
mksyscall_windows [flags] [path ...]
|
||||
|
||||
The flags are:
|
||||
-output
|
||||
Specify output file name (outputs to console if blank).
|
||||
-trace
|
||||
Generate print statement after every syscall.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
||||
printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
|
||||
systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory")
|
||||
winio = flag.Bool("winio", false, "import go-winio")
|
||||
)
|
||||
|
||||
func trim(s string) string {
|
||||
return strings.Trim(s, " \t")
|
||||
}
|
||||
|
||||
var packageName string
|
||||
|
||||
func packagename() string {
|
||||
return packageName
|
||||
}
|
||||
|
||||
func syscalldot() string {
|
||||
if packageName == "syscall" {
|
||||
return ""
|
||||
}
|
||||
return "syscall."
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
fn *Fn
|
||||
tmpVarIdx int
|
||||
}
|
||||
|
||||
// tmpVar returns temp variable name that will be used to represent p during syscall.
|
||||
func (p *Param) tmpVar() string {
|
||||
if p.tmpVarIdx < 0 {
|
||||
p.tmpVarIdx = p.fn.curTmpVarIdx
|
||||
p.fn.curTmpVarIdx++
|
||||
}
|
||||
return fmt.Sprintf("_p%d", p.tmpVarIdx)
|
||||
}
|
||||
|
||||
// BoolTmpVarCode returns source code for bool temp variable.
|
||||
func (p *Param) BoolTmpVarCode() string {
|
||||
const code = `var %s uint32
|
||||
if %s {
|
||||
%s = 1
|
||||
} else {
|
||||
%s = 0
|
||||
}`
|
||||
tmp := p.tmpVar()
|
||||
return fmt.Sprintf(code, tmp, p.Name, tmp, tmp)
|
||||
}
|
||||
|
||||
// SliceTmpVarCode returns source code for slice temp variable.
|
||||
func (p *Param) SliceTmpVarCode() string {
|
||||
const code = `var %s *%s
|
||||
if len(%s) > 0 {
|
||||
%s = &%s[0]
|
||||
}`
|
||||
tmp := p.tmpVar()
|
||||
return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name)
|
||||
}
|
||||
|
||||
// StringTmpVarCode returns source code for string temp variable.
|
||||
func (p *Param) StringTmpVarCode() string {
|
||||
errvar := p.fn.Rets.ErrorVarName()
|
||||
if errvar == "" {
|
||||
errvar = "_"
|
||||
}
|
||||
tmp := p.tmpVar()
|
||||
const code = `var %s %s
|
||||
%s, %s = %s(%s)`
|
||||
s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name)
|
||||
if errvar == "-" {
|
||||
return s
|
||||
}
|
||||
const morecode = `
|
||||
if %s != nil {
|
||||
return
|
||||
}`
|
||||
return s + fmt.Sprintf(morecode, errvar)
|
||||
}
|
||||
|
||||
// TmpVarCode returns source code for temp variable.
|
||||
func (p *Param) TmpVarCode() string {
|
||||
switch {
|
||||
case p.Type == "bool":
|
||||
return p.BoolTmpVarCode()
|
||||
case strings.HasPrefix(p.Type, "[]"):
|
||||
return p.SliceTmpVarCode()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// TmpVarHelperCode returns source code for helper's temp variable.
|
||||
func (p *Param) TmpVarHelperCode() string {
|
||||
if p.Type != "string" {
|
||||
return ""
|
||||
}
|
||||
return p.StringTmpVarCode()
|
||||
}
|
||||
|
||||
// SyscallArgList returns source code fragments representing p parameter
|
||||
// in syscall. Slices are translated into 2 syscall parameters: pointer to
|
||||
// the first element and length.
|
||||
func (p *Param) SyscallArgList() []string {
|
||||
t := p.HelperType()
|
||||
var s string
|
||||
switch {
|
||||
case t[0] == '*':
|
||||
s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
|
||||
case t == "bool":
|
||||
s = p.tmpVar()
|
||||
case strings.HasPrefix(t, "[]"):
|
||||
return []string{
|
||||
fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
|
||||
fmt.Sprintf("uintptr(len(%s))", p.Name),
|
||||
}
|
||||
default:
|
||||
s = p.Name
|
||||
}
|
||||
return []string{fmt.Sprintf("uintptr(%s)", s)}
|
||||
}
|
||||
|
||||
// IsError determines if p parameter is used to return error.
|
||||
func (p *Param) IsError() bool {
|
||||
return p.Name == "err" && p.Type == "error"
|
||||
}
|
||||
|
||||
// HelperType returns type of parameter p used in helper function.
|
||||
func (p *Param) HelperType() string {
|
||||
if p.Type == "string" {
|
||||
return p.fn.StrconvType()
|
||||
}
|
||||
return p.Type
|
||||
}
|
||||
|
||||
// join concatenates parameters ps into a string with sep separator.
|
||||
// Each parameter is converted into string by applying fn to it
|
||||
// before conversion.
|
||||
func join(ps []*Param, fn func(*Param) string, sep string) string {
|
||||
if len(ps) == 0 {
|
||||
return ""
|
||||
}
|
||||
a := make([]string, 0)
|
||||
for _, p := range ps {
|
||||
a = append(a, fn(p))
|
||||
}
|
||||
return strings.Join(a, sep)
|
||||
}
|
||||
|
||||
// Rets describes function return parameters.
|
||||
type Rets struct {
|
||||
Name string
|
||||
Type string
|
||||
ReturnsError bool
|
||||
FailCond string
|
||||
}
|
||||
|
||||
// ErrorVarName returns error variable name for r.
|
||||
func (r *Rets) ErrorVarName() string {
|
||||
if r.ReturnsError {
|
||||
return "err"
|
||||
}
|
||||
if r.Type == "error" {
|
||||
return r.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ToParams converts r into slice of *Param.
|
||||
func (r *Rets) ToParams() []*Param {
|
||||
ps := make([]*Param, 0)
|
||||
if len(r.Name) > 0 {
|
||||
ps = append(ps, &Param{Name: r.Name, Type: r.Type})
|
||||
}
|
||||
if r.ReturnsError {
|
||||
ps = append(ps, &Param{Name: "err", Type: "error"})
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
// List returns source code of syscall return parameters.
|
||||
func (r *Rets) List() string {
|
||||
s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
||||
if len(s) > 0 {
|
||||
s = "(" + s + ")"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// PrintList returns source code of trace printing part correspondent
|
||||
// to syscall return values.
|
||||
func (r *Rets) PrintList() string {
|
||||
return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
||||
}
|
||||
|
||||
// SetReturnValuesCode returns source code that accepts syscall return values.
|
||||
func (r *Rets) SetReturnValuesCode() string {
|
||||
if r.Name == "" && !r.ReturnsError {
|
||||
return ""
|
||||
}
|
||||
retvar := "r0"
|
||||
if r.Name == "" {
|
||||
retvar = "r1"
|
||||
}
|
||||
errvar := "_"
|
||||
if r.ReturnsError {
|
||||
errvar = "e1"
|
||||
}
|
||||
return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
|
||||
}
|
||||
|
||||
func (r *Rets) useLongHandleErrorCode(retvar string) string {
|
||||
const code = `if %s {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = %sEINVAL
|
||||
}
|
||||
}`
|
||||
cond := retvar + " == 0"
|
||||
if r.FailCond != "" {
|
||||
cond = strings.Replace(r.FailCond, "failretval", retvar, 1)
|
||||
}
|
||||
return fmt.Sprintf(code, cond, syscalldot())
|
||||
}
|
||||
|
||||
// SetErrorCode returns source code that sets return parameters.
|
||||
func (r *Rets) SetErrorCode() string {
|
||||
const code = `if r0 != 0 {
|
||||
%s = %sErrno(r0)
|
||||
}`
|
||||
const hrCode = `if int32(r0) < 0 {
|
||||
%s = interop.Win32FromHresult(r0)
|
||||
}`
|
||||
if r.Name == "" && !r.ReturnsError {
|
||||
return ""
|
||||
}
|
||||
if r.Name == "" {
|
||||
return r.useLongHandleErrorCode("r1")
|
||||
}
|
||||
if r.Type == "error" {
|
||||
if r.Name == "hr" {
|
||||
return fmt.Sprintf(hrCode, r.Name)
|
||||
} else {
|
||||
return fmt.Sprintf(code, r.Name, syscalldot())
|
||||
}
|
||||
}
|
||||
s := ""
|
||||
switch {
|
||||
case r.Type[0] == '*':
|
||||
s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
|
||||
case r.Type == "bool":
|
||||
s = fmt.Sprintf("%s = r0 != 0", r.Name)
|
||||
default:
|
||||
s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
|
||||
}
|
||||
if !r.ReturnsError {
|
||||
return s
|
||||
}
|
||||
return s + "\n\t" + r.useLongHandleErrorCode(r.Name)
|
||||
}
|
||||
|
||||
// Fn describes syscall function.
|
||||
type Fn struct {
|
||||
Name string
|
||||
Params []*Param
|
||||
Rets *Rets
|
||||
PrintTrace bool
|
||||
confirmproc bool
|
||||
dllname string
|
||||
dllfuncname string
|
||||
src string
|
||||
// TODO: get rid of this field and just use parameter index instead
|
||||
curTmpVarIdx int // insure tmp variables have uniq names
|
||||
}
|
||||
|
||||
// extractParams parses s to extract function parameters.
|
||||
func extractParams(s string, f *Fn) ([]*Param, error) {
|
||||
s = trim(s)
|
||||
if s == "" {
|
||||
return nil, nil
|
||||
}
|
||||
a := strings.Split(s, ",")
|
||||
ps := make([]*Param, len(a))
|
||||
for i := range ps {
|
||||
s2 := trim(a[i])
|
||||
b := strings.Split(s2, " ")
|
||||
if len(b) != 2 {
|
||||
b = strings.Split(s2, "\t")
|
||||
if len(b) != 2 {
|
||||
return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
|
||||
}
|
||||
}
|
||||
ps[i] = &Param{
|
||||
Name: trim(b[0]),
|
||||
Type: trim(b[1]),
|
||||
fn: f,
|
||||
tmpVarIdx: -1,
|
||||
}
|
||||
}
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
// extractSection extracts text out of string s starting after start
|
||||
// and ending just before end. found return value will indicate success,
|
||||
// and prefix, body and suffix will contain correspondent parts of string s.
|
||||
func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
|
||||
s = trim(s)
|
||||
if strings.HasPrefix(s, string(start)) {
|
||||
// no prefix
|
||||
body = s[1:]
|
||||
} else {
|
||||
a := strings.SplitN(s, string(start), 2)
|
||||
if len(a) != 2 {
|
||||
return "", "", s, false
|
||||
}
|
||||
prefix = a[0]
|
||||
body = a[1]
|
||||
}
|
||||
a := strings.SplitN(body, string(end), 2)
|
||||
if len(a) != 2 {
|
||||
return "", "", "", false
|
||||
}
|
||||
return prefix, a[0], a[1], true
|
||||
}
|
||||
|
||||
// newFn parses string s and return created function Fn.
|
||||
func newFn(s string) (*Fn, error) {
|
||||
s = trim(s)
|
||||
f := &Fn{
|
||||
Rets: &Rets{},
|
||||
src: s,
|
||||
PrintTrace: *printTraceFlag,
|
||||
}
|
||||
// function name and args
|
||||
prefix, body, s, found := extractSection(s, '(', ')')
|
||||
if !found || prefix == "" {
|
||||
return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
|
||||
}
|
||||
f.Name = prefix
|
||||
var err error
|
||||
f.Params, err = extractParams(body, f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// return values
|
||||
_, body, s, found = extractSection(s, '(', ')')
|
||||
if found {
|
||||
r, err := extractParams(body, f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(r) {
|
||||
case 0:
|
||||
case 1:
|
||||
if r[0].IsError() {
|
||||
f.Rets.ReturnsError = true
|
||||
} else {
|
||||
f.Rets.Name = r[0].Name
|
||||
f.Rets.Type = r[0].Type
|
||||
}
|
||||
case 2:
|
||||
if !r[1].IsError() {
|
||||
return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
|
||||
}
|
||||
f.Rets.ReturnsError = true
|
||||
f.Rets.Name = r[0].Name
|
||||
f.Rets.Type = r[0].Type
|
||||
default:
|
||||
return nil, errors.New("Too many return values in \"" + f.src + "\"")
|
||||
}
|
||||
}
|
||||
// fail condition
|
||||
_, body, s, found = extractSection(s, '[', ']')
|
||||
if found {
|
||||
f.Rets.FailCond = body
|
||||
}
|
||||
// dll and dll function names
|
||||
s = trim(s)
|
||||
if s == "" {
|
||||
return f, nil
|
||||
}
|
||||
if !strings.HasPrefix(s, "=") {
|
||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
||||
}
|
||||
s = trim(s[1:])
|
||||
a := strings.Split(s, ".")
|
||||
switch len(a) {
|
||||
case 1:
|
||||
f.dllfuncname = a[0]
|
||||
case 2:
|
||||
f.dllname = a[0]
|
||||
f.dllfuncname = a[1]
|
||||
default:
|
||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
||||
}
|
||||
if f.dllfuncname[len(f.dllfuncname)-1] == '?' {
|
||||
f.confirmproc = true
|
||||
f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1]
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// DLLName returns DLL name for function f.
|
||||
func (f *Fn) DLLName() string {
|
||||
if f.dllname == "" {
|
||||
return "kernel32"
|
||||
}
|
||||
return f.dllname
|
||||
}
|
||||
|
||||
// DLLName returns DLL function name for function f.
|
||||
func (f *Fn) DLLFuncName() string {
|
||||
if f.dllfuncname == "" {
|
||||
return f.Name
|
||||
}
|
||||
return f.dllfuncname
|
||||
}
|
||||
|
||||
func (f *Fn) ConfirmProc() bool {
|
||||
return f.confirmproc
|
||||
}
|
||||
|
||||
// ParamList returns source code for function f parameters.
|
||||
func (f *Fn) ParamList() string {
|
||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
||||
}
|
||||
|
||||
// HelperParamList returns source code for helper function f parameters.
|
||||
func (f *Fn) HelperParamList() string {
|
||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
|
||||
}
|
||||
|
||||
// ParamPrintList returns source code of trace printing part correspondent
|
||||
// to syscall input parameters.
|
||||
func (f *Fn) ParamPrintList() string {
|
||||
return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
||||
}
|
||||
|
||||
// ParamCount return number of syscall parameters for function f.
|
||||
func (f *Fn) ParamCount() int {
|
||||
n := 0
|
||||
for _, p := range f.Params {
|
||||
n += len(p.SyscallArgList())
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/...
|
||||
// to use. It returns parameter count for correspondent SyscallX function.
|
||||
func (f *Fn) SyscallParamCount() int {
|
||||
n := f.ParamCount()
|
||||
switch {
|
||||
case n <= 3:
|
||||
return 3
|
||||
case n <= 6:
|
||||
return 6
|
||||
case n <= 9:
|
||||
return 9
|
||||
case n <= 12:
|
||||
return 12
|
||||
case n <= 15:
|
||||
return 15
|
||||
default:
|
||||
panic("too many arguments to system call")
|
||||
}
|
||||
}
|
||||
|
||||
// Syscall determines which SyscallX function to use for function f.
|
||||
func (f *Fn) Syscall() string {
|
||||
c := f.SyscallParamCount()
|
||||
if c == 3 {
|
||||
return syscalldot() + "Syscall"
|
||||
}
|
||||
return syscalldot() + "Syscall" + strconv.Itoa(c)
|
||||
}
|
||||
|
||||
// SyscallParamList returns source code for SyscallX parameters for function f.
|
||||
func (f *Fn) SyscallParamList() string {
|
||||
a := make([]string, 0)
|
||||
for _, p := range f.Params {
|
||||
a = append(a, p.SyscallArgList()...)
|
||||
}
|
||||
for len(a) < f.SyscallParamCount() {
|
||||
a = append(a, "0")
|
||||
}
|
||||
return strings.Join(a, ", ")
|
||||
}
|
||||
|
||||
// HelperCallParamList returns source code of call into function f helper.
|
||||
func (f *Fn) HelperCallParamList() string {
|
||||
a := make([]string, 0, len(f.Params))
|
||||
for _, p := range f.Params {
|
||||
s := p.Name
|
||||
if p.Type == "string" {
|
||||
s = p.tmpVar()
|
||||
}
|
||||
a = append(a, s)
|
||||
}
|
||||
return strings.Join(a, ", ")
|
||||
}
|
||||
|
||||
// IsUTF16 is true, if f is W (utf16) function. It is false
|
||||
// for all A (ascii) functions.
|
||||
func (_ *Fn) IsUTF16() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// StrconvFunc returns name of Go string to OS string function for f.
|
||||
func (f *Fn) StrconvFunc() string {
|
||||
if f.IsUTF16() {
|
||||
return syscalldot() + "UTF16PtrFromString"
|
||||
}
|
||||
return syscalldot() + "BytePtrFromString"
|
||||
}
|
||||
|
||||
// StrconvType returns Go type name used for OS string for f.
|
||||
func (f *Fn) StrconvType() string {
|
||||
if f.IsUTF16() {
|
||||
return "*uint16"
|
||||
}
|
||||
return "*byte"
|
||||
}
|
||||
|
||||
// HasStringParam is true, if f has at least one string parameter.
|
||||
// Otherwise it is false.
|
||||
func (f *Fn) HasStringParam() bool {
|
||||
for _, p := range f.Params {
|
||||
if p.Type == "string" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var uniqDllFuncName = make(map[string]bool)
|
||||
|
||||
// IsNotDuplicate is true if f is not a duplicated function
|
||||
func (f *Fn) IsNotDuplicate() bool {
|
||||
funcName := f.DLLFuncName()
|
||||
if uniqDllFuncName[funcName] == false {
|
||||
uniqDllFuncName[funcName] = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HelperName returns name of function f helper.
|
||||
func (f *Fn) HelperName() string {
|
||||
if !f.HasStringParam() {
|
||||
return f.Name
|
||||
}
|
||||
return "_" + f.Name
|
||||
}
|
||||
|
||||
// Source files and functions.
|
||||
type Source struct {
|
||||
Funcs []*Fn
|
||||
Files []string
|
||||
StdLibImports []string
|
||||
ExternalImports []string
|
||||
}
|
||||
|
||||
func (src *Source) Import(pkg string) {
|
||||
src.StdLibImports = append(src.StdLibImports, pkg)
|
||||
sort.Strings(src.StdLibImports)
|
||||
}
|
||||
|
||||
func (src *Source) ExternalImport(pkg string) {
|
||||
src.ExternalImports = append(src.ExternalImports, pkg)
|
||||
sort.Strings(src.ExternalImports)
|
||||
}
|
||||
|
||||
// ParseFiles parses files listed in fs and extracts all syscall
|
||||
// functions listed in sys comments. It returns source files
|
||||
// and functions collection *Source if successful.
|
||||
func ParseFiles(fs []string) (*Source, error) {
|
||||
src := &Source{
|
||||
Funcs: make([]*Fn, 0),
|
||||
Files: make([]string, 0),
|
||||
StdLibImports: []string{
|
||||
"unsafe",
|
||||
},
|
||||
ExternalImports: make([]string, 0),
|
||||
}
|
||||
for _, file := range fs {
|
||||
if err := src.ParseFile(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return src, nil
|
||||
}
|
||||
|
||||
// DLLs return dll names for a source set src.
|
||||
func (src *Source) DLLs() []string {
|
||||
uniq := make(map[string]bool)
|
||||
r := make([]string, 0)
|
||||
for _, f := range src.Funcs {
|
||||
name := f.DLLName()
|
||||
if _, found := uniq[name]; !found {
|
||||
uniq[name] = true
|
||||
r = append(r, name)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// ParseFile adds additional file path to a source set src.
|
||||
func (src *Source) ParseFile(path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := trim(s.Text())
|
||||
if len(t) < 7 {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(t, "//sys") {
|
||||
continue
|
||||
}
|
||||
t = t[5:]
|
||||
if !(t[0] == ' ' || t[0] == '\t') {
|
||||
continue
|
||||
}
|
||||
f, err := newFn(t[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src.Funcs = append(src.Funcs, f)
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
src.Files = append(src.Files, path)
|
||||
|
||||
// get package name
|
||||
fset := token.NewFileSet()
|
||||
_, err = file.Seek(0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageName = pkg.Name.Name
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsStdRepo returns true if src is part of standard library.
|
||||
func (src *Source) IsStdRepo() (bool, error) {
|
||||
if len(src.Files) == 0 {
|
||||
return false, errors.New("no input files provided")
|
||||
}
|
||||
abspath, err := filepath.Abs(src.Files[0])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
goroot := runtime.GOROOT()
|
||||
if runtime.GOOS == "windows" {
|
||||
abspath = strings.ToLower(abspath)
|
||||
goroot = strings.ToLower(goroot)
|
||||
}
|
||||
sep := string(os.PathSeparator)
|
||||
if !strings.HasSuffix(goroot, sep) {
|
||||
goroot += sep
|
||||
}
|
||||
return strings.HasPrefix(abspath, goroot), nil
|
||||
}
|
||||
|
||||
// Generate output source file from a source set src.
|
||||
func (src *Source) Generate(w io.Writer) error {
|
||||
const (
|
||||
pkgStd = iota // any package in std library
|
||||
pkgXSysWindows // x/sys/windows package
|
||||
pkgOther
|
||||
)
|
||||
isStdRepo, err := src.IsStdRepo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var pkgtype int
|
||||
switch {
|
||||
case isStdRepo:
|
||||
pkgtype = pkgStd
|
||||
case packageName == "windows":
|
||||
// TODO: this needs better logic than just using package name
|
||||
pkgtype = pkgXSysWindows
|
||||
default:
|
||||
pkgtype = pkgOther
|
||||
}
|
||||
if *systemDLL {
|
||||
switch pkgtype {
|
||||
case pkgStd:
|
||||
src.Import("internal/syscall/windows/sysdll")
|
||||
case pkgXSysWindows:
|
||||
default:
|
||||
src.ExternalImport("golang.org/x/sys/windows")
|
||||
}
|
||||
}
|
||||
src.ExternalImport("github.com/Microsoft/hcsshim/internal/interop")
|
||||
if *winio {
|
||||
src.ExternalImport("github.com/Microsoft/go-winio")
|
||||
}
|
||||
if packageName != "syscall" {
|
||||
src.Import("syscall")
|
||||
}
|
||||
funcMap := template.FuncMap{
|
||||
"packagename": packagename,
|
||||
"syscalldot": syscalldot,
|
||||
"newlazydll": func(dll string) string {
|
||||
arg := "\"" + dll + ".dll\""
|
||||
if !*systemDLL {
|
||||
return syscalldot() + "NewLazyDLL(" + arg + ")"
|
||||
}
|
||||
switch pkgtype {
|
||||
case pkgStd:
|
||||
return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))"
|
||||
case pkgXSysWindows:
|
||||
return "NewLazySystemDLL(" + arg + ")"
|
||||
default:
|
||||
return "windows.NewLazySystemDLL(" + arg + ")"
|
||||
}
|
||||
},
|
||||
}
|
||||
t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
|
||||
err = t.Execute(w, src)
|
||||
if err != nil {
|
||||
return errors.New("Failed to execute template: " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
src, err := ParseFiles(flag.Args())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := src.Generate(&buf); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
data, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if *filename == "" {
|
||||
_, err = os.Stdout.Write(data)
|
||||
} else {
|
||||
err = ioutil.WriteFile(*filename, data, 0644)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use println instead to print in the following template
|
||||
const srcTemplate = `
|
||||
|
||||
{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
|
||||
package {{packagename}}
|
||||
|
||||
import (
|
||||
{{range .StdLibImports}}"{{.}}"
|
||||
{{end}}
|
||||
|
||||
{{range .ExternalImports}}"{{.}}"
|
||||
{{end}}
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING)
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e {{syscalldot}}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 (
|
||||
{{template "dlls" .}}
|
||||
{{template "funcnames" .}})
|
||||
{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
|
||||
{{end}}
|
||||
|
||||
{{/* help functions */}}
|
||||
|
||||
{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "helperbody"}}
|
||||
func {{.Name}}({{.ParamList}}) {{template "results" .}}{
|
||||
{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{define "funcbody"}}
|
||||
func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
|
||||
{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}}
|
||||
{{template "seterror" .}}{{template "printtrace" .}} return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
|
||||
|
||||
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
|
||||
|
||||
{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil {
|
||||
return
|
||||
}
|
||||
{{end}}{{end}}
|
||||
|
||||
|
||||
{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
||||
{{end}}{{end}}
|
||||
|
||||
`
|
72
vendor/github.com/Microsoft/hcsshim/process.go
generated
vendored
Normal file
72
vendor/github.com/Microsoft/hcsshim/process.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hcs"
|
||||
)
|
||||
|
||||
// ContainerError is an error encountered in HCS
|
||||
type process struct {
|
||||
p *hcs.Process
|
||||
}
|
||||
|
||||
// Pid returns the process ID of the process within the container.
|
||||
func (process *process) Pid() int {
|
||||
return process.p.Pid()
|
||||
}
|
||||
|
||||
// Kill signals the process to terminate but does not wait for it to finish terminating.
|
||||
func (process *process) Kill() error {
|
||||
return convertProcessError(process.p.Kill(), process)
|
||||
}
|
||||
|
||||
// Wait waits for the process to exit.
|
||||
func (process *process) Wait() error {
|
||||
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 {
|
||||
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) {
|
||||
code, err := process.p.ExitCode()
|
||||
if err != nil {
|
||||
err = convertProcessError(err, process)
|
||||
}
|
||||
return code, err
|
||||
}
|
||||
|
||||
// ResizeConsole resizes the console of the process.
|
||||
func (process *process) ResizeConsole(width, height uint16) error {
|
||||
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) {
|
||||
stdin, stdout, stderr, err := process.p.Stdio()
|
||||
if err != nil {
|
||||
err = convertProcessError(err, process)
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
return convertProcessError(process.p.Close(), process)
|
||||
}
|
6
vendor/github.com/Microsoft/hcsshim/version.go
generated
vendored
Normal file
6
vendor/github.com/Microsoft/hcsshim/version.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
package hcsshim
|
||||
|
||||
// IsTP4 returns whether the currently running Windows build is at least TP4.
|
||||
func IsTP4() bool {
|
||||
return false
|
||||
}
|
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
|
||||
}
|
Reference in New Issue
Block a user