Merge pull request #2322 from darrenstahlmsft/revendorHcsshim
Update hcsshim to v0.6.10
This commit is contained in:
commit
40c3acd36c
@ -34,7 +34,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
|||||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||||
github.com/Microsoft/go-winio v0.4.5
|
github.com/Microsoft/go-winio v0.4.5
|
||||||
github.com/Microsoft/hcsshim v0.6.7
|
github.com/Microsoft/hcsshim v0.6.10
|
||||||
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
|
54
vendor/github.com/Microsoft/hcsshim/baselayer.go
generated
vendored
54
vendor/github.com/Microsoft/hcsshim/baselayer.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type baseLayerWriter struct {
|
type baseLayerWriter struct {
|
||||||
root string
|
root *os.File
|
||||||
f *os.File
|
f *os.File
|
||||||
bw *winio.BackupFileWriter
|
bw *winio.BackupFileWriter
|
||||||
err error
|
err error
|
||||||
@ -26,10 +26,10 @@ type dirInfo struct {
|
|||||||
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
||||||
// after processing of the directory tree has completed. The times are expected
|
// after processing of the directory tree has completed. The times are expected
|
||||||
// to be ordered such that parent directories come before child directories.
|
// to be ordered such that parent directories come before child directories.
|
||||||
func reapplyDirectoryTimes(dis []dirInfo) error {
|
func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
|
||||||
for i := range dis {
|
for i := range dis {
|
||||||
di := &dis[len(dis)-i-1] // reverse order: process child directories first
|
di := &dis[len(dis)-i-1] // reverse order: process child directories first
|
||||||
f, err := winio.OpenForBackup(di.path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING)
|
f, err := openRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_OPEN, _FILE_DIRECTORY_FILE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -75,12 +75,6 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
|
|||||||
w.hasUtilityVM = true
|
w.hasUtilityVM = true
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(w.root, name)
|
|
||||||
path, err = makeLongAbsPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var f *os.File
|
var f *os.File
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
@ -88,27 +82,23 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
createmode := uint32(syscall.CREATE_NEW)
|
extraFlags := uint32(0)
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||||
err := os.Mkdir(path, 0)
|
extraFlags |= _FILE_DIRECTORY_FILE
|
||||||
if err != nil && !os.IsExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
createmode = syscall.OPEN_EXISTING
|
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||||
w.dirInfo = append(w.dirInfo, dirInfo{path, *fileInfo})
|
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)
|
mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
|
||||||
f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode)
|
f, err = openRelative(name, w.root, mode, syscall.FILE_SHARE_READ, _FILE_CREATE, extraFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return makeError(err, "Failed to OpenForBackup", path)
|
return makeError(err, "Failed to openRelative", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = winio.SetFileBasicInfo(f, fileInfo)
|
err = winio.SetFileBasicInfo(f, fileInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return makeError(err, "Failed to SetFileBasicInfo", path)
|
return makeError(err, "Failed to SetFileBasicInfo", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.f = f
|
w.f = f
|
||||||
@ -129,17 +119,7 @@ func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
linkpath, err := makeLongAbsPath(filepath.Join(w.root, name))
|
return linkRelative(target, w.root, name, w.root)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
linktarget, err := makeLongAbsPath(filepath.Join(w.root, target))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.Link(linktarget, linkpath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *baseLayerWriter) Remove(name string) error {
|
func (w *baseLayerWriter) Remove(name string) error {
|
||||||
@ -155,6 +135,10 @@ func (w *baseLayerWriter) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *baseLayerWriter) Close() error {
|
func (w *baseLayerWriter) Close() error {
|
||||||
|
defer func() {
|
||||||
|
w.root.Close()
|
||||||
|
w.root = nil
|
||||||
|
}()
|
||||||
err := w.closeCurrentFile()
|
err := w.closeCurrentFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -162,18 +146,22 @@ func (w *baseLayerWriter) Close() error {
|
|||||||
if w.err == nil {
|
if w.err == nil {
|
||||||
// Restore the file times of all the directories, since they may have
|
// Restore the file times of all the directories, since they may have
|
||||||
// been modified by creating child directories.
|
// been modified by creating child directories.
|
||||||
err = reapplyDirectoryTimes(w.dirInfo)
|
err = reapplyDirectoryTimes(w.root, w.dirInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ProcessBaseLayer(w.root)
|
err = ProcessBaseLayer(w.root.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.hasUtilityVM {
|
if w.hasUtilityVM {
|
||||||
err = ProcessUtilityVMImage(filepath.Join(w.root, "UtilityVM"))
|
err := ensureNotReparsePointRelative("UtilityVM", w.root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go
|
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go safeopen.go
|
||||||
|
|
||||||
//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
|
//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
|
||||||
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
||||||
|
646
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
646
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
generated
vendored
@ -1,323 +1,323 @@
|
|||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HNSEndpoint represents a network endpoint in HNS
|
// HNSEndpoint represents a network endpoint in HNS
|
||||||
type HNSEndpoint struct {
|
type HNSEndpoint struct {
|
||||||
Id string `json:"ID,omitempty"`
|
Id string `json:"ID,omitempty"`
|
||||||
Name string `json:",omitempty"`
|
Name string `json:",omitempty"`
|
||||||
VirtualNetwork string `json:",omitempty"`
|
VirtualNetwork string `json:",omitempty"`
|
||||||
VirtualNetworkName string `json:",omitempty"`
|
VirtualNetworkName string `json:",omitempty"`
|
||||||
Policies []json.RawMessage `json:",omitempty"`
|
Policies []json.RawMessage `json:",omitempty"`
|
||||||
MacAddress string `json:",omitempty"`
|
MacAddress string `json:",omitempty"`
|
||||||
IPAddress net.IP `json:",omitempty"`
|
IPAddress net.IP `json:",omitempty"`
|
||||||
DNSSuffix string `json:",omitempty"`
|
DNSSuffix string `json:",omitempty"`
|
||||||
DNSServerList string `json:",omitempty"`
|
DNSServerList string `json:",omitempty"`
|
||||||
GatewayAddress string `json:",omitempty"`
|
GatewayAddress string `json:",omitempty"`
|
||||||
EnableInternalDNS bool `json:",omitempty"`
|
EnableInternalDNS bool `json:",omitempty"`
|
||||||
DisableICC bool `json:",omitempty"`
|
DisableICC bool `json:",omitempty"`
|
||||||
PrefixLength uint8 `json:",omitempty"`
|
PrefixLength uint8 `json:",omitempty"`
|
||||||
IsRemoteEndpoint bool `json:",omitempty"`
|
IsRemoteEndpoint bool `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//SystemType represents the type of the system on which actions are done
|
//SystemType represents the type of the system on which actions are done
|
||||||
type SystemType string
|
type SystemType string
|
||||||
|
|
||||||
// SystemType const
|
// SystemType const
|
||||||
const (
|
const (
|
||||||
ContainerType SystemType = "Container"
|
ContainerType SystemType = "Container"
|
||||||
VirtualMachineType SystemType = "VirtualMachine"
|
VirtualMachineType SystemType = "VirtualMachine"
|
||||||
HostType SystemType = "Host"
|
HostType SystemType = "Host"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system
|
// 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
|
// Supported resource types are Network and Request Types are Add/Remove
|
||||||
type EndpointAttachDetachRequest struct {
|
type EndpointAttachDetachRequest struct {
|
||||||
ContainerID string `json:"ContainerId,omitempty"`
|
ContainerID string `json:"ContainerId,omitempty"`
|
||||||
SystemType SystemType `json:"SystemType"`
|
SystemType SystemType `json:"SystemType"`
|
||||||
CompartmentID uint16 `json:"CompartmentId,omitempty"`
|
CompartmentID uint16 `json:"CompartmentId,omitempty"`
|
||||||
VirtualNICName string `json:"VirtualNicName,omitempty"`
|
VirtualNICName string `json:"VirtualNicName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointResquestResponse is object to get the endpoint request response
|
// EndpointResquestResponse is object to get the endpoint request response
|
||||||
type EndpointResquestResponse struct {
|
type EndpointResquestResponse struct {
|
||||||
Success bool
|
Success bool
|
||||||
Error string
|
Error string
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
|
// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
|
||||||
func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
|
func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
|
||||||
endpoint := &HNSEndpoint{}
|
endpoint := &HNSEndpoint{}
|
||||||
err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
|
err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoint, nil
|
return endpoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
|
// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
|
||||||
func HNSListEndpointRequest() ([]HNSEndpoint, error) {
|
func HNSListEndpointRequest() ([]HNSEndpoint, error) {
|
||||||
var endpoint []HNSEndpoint
|
var endpoint []HNSEndpoint
|
||||||
err := hnsCall("GET", "/endpoints/", "", &endpoint)
|
err := hnsCall("GET", "/endpoints/", "", &endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoint, nil
|
return endpoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
|
// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
|
||||||
func HotAttachEndpoint(containerID string, endpointID string) error {
|
func HotAttachEndpoint(containerID string, endpointID string) error {
|
||||||
return modifyNetworkEndpoint(containerID, endpointID, Add)
|
return modifyNetworkEndpoint(containerID, endpointID, Add)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container
|
// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container
|
||||||
func HotDetachEndpoint(containerID string, endpointID string) error {
|
func HotDetachEndpoint(containerID string, endpointID string) error {
|
||||||
return modifyNetworkEndpoint(containerID, endpointID, Remove)
|
return modifyNetworkEndpoint(containerID, endpointID, Remove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModifyContainer corresponding to the container id, by sending a request
|
// ModifyContainer corresponding to the container id, by sending a request
|
||||||
func modifyContainer(id string, request *ResourceModificationRequestResponse) error {
|
func modifyContainer(id string, request *ResourceModificationRequestResponse) error {
|
||||||
container, err := OpenContainer(id)
|
container, err := OpenContainer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsNotExist(err) {
|
if IsNotExist(err) {
|
||||||
return ErrComputeSystemDoesNotExist
|
return ErrComputeSystemDoesNotExist
|
||||||
}
|
}
|
||||||
return getInnerError(err)
|
return getInnerError(err)
|
||||||
}
|
}
|
||||||
defer container.Close()
|
defer container.Close()
|
||||||
err = container.Modify(request)
|
err = container.Modify(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsNotSupported(err) {
|
if IsNotSupported(err) {
|
||||||
return ErrPlatformNotSupported
|
return ErrPlatformNotSupported
|
||||||
}
|
}
|
||||||
return getInnerError(err)
|
return getInnerError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error {
|
func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error {
|
||||||
requestMessage := &ResourceModificationRequestResponse{
|
requestMessage := &ResourceModificationRequestResponse{
|
||||||
Resource: Network,
|
Resource: Network,
|
||||||
Request: request,
|
Request: request,
|
||||||
Data: endpointID,
|
Data: endpointID,
|
||||||
}
|
}
|
||||||
err := modifyContainer(containerID, requestMessage)
|
err := modifyContainer(containerID, requestMessage)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHNSEndpointByID get the Endpoint by ID
|
// GetHNSEndpointByID get the Endpoint by ID
|
||||||
func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
|
func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
|
||||||
return HNSEndpointRequest("GET", endpointID, "")
|
return HNSEndpointRequest("GET", endpointID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHNSEndpointByName gets the endpoint filtered by Name
|
// GetHNSEndpointByName gets the endpoint filtered by Name
|
||||||
func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
|
func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
|
||||||
hnsResponse, err := HNSListEndpointRequest()
|
hnsResponse, err := HNSListEndpointRequest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, hnsEndpoint := range hnsResponse {
|
for _, hnsEndpoint := range hnsResponse {
|
||||||
if hnsEndpoint.Name == endpointName {
|
if hnsEndpoint.Name == endpointName {
|
||||||
return &hnsEndpoint, nil
|
return &hnsEndpoint, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, EndpointNotFoundError{EndpointName: endpointName}
|
return nil, EndpointNotFoundError{EndpointName: endpointName}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
|
// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
|
||||||
func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
|
func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
|
||||||
operation := "Create"
|
operation := "Create"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
jsonString, err := json.Marshal(endpoint)
|
jsonString, err := json.Marshal(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return HNSEndpointRequest("POST", "", string(jsonString))
|
return HNSEndpointRequest("POST", "", string(jsonString))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete Endpoint by sending EndpointRequest to HNS
|
// Delete Endpoint by sending EndpointRequest to HNS
|
||||||
func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
|
func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
|
||||||
operation := "Delete"
|
operation := "Delete"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
return HNSEndpointRequest("DELETE", endpoint.Id, "")
|
return HNSEndpointRequest("DELETE", endpoint.Id, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Endpoint
|
// Update Endpoint
|
||||||
func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
|
func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
|
||||||
operation := "Update"
|
operation := "Update"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
jsonString, err := json.Marshal(endpoint)
|
jsonString, err := json.Marshal(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
|
err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
|
||||||
|
|
||||||
return endpoint, err
|
return endpoint, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerHotAttach attaches an endpoint to a running container
|
// ContainerHotAttach attaches an endpoint to a running container
|
||||||
func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error {
|
func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error {
|
||||||
operation := "ContainerHotAttach"
|
operation := "ContainerHotAttach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
|
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
|
||||||
|
|
||||||
return modifyNetworkEndpoint(containerID, endpoint.Id, Add)
|
return modifyNetworkEndpoint(containerID, endpoint.Id, Add)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerHotDetach detaches an endpoint from a running container
|
// ContainerHotDetach detaches an endpoint from a running container
|
||||||
func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error {
|
func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error {
|
||||||
operation := "ContainerHotDetach"
|
operation := "ContainerHotDetach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
|
logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
|
||||||
|
|
||||||
return modifyNetworkEndpoint(containerID, endpoint.Id, Remove)
|
return modifyNetworkEndpoint(containerID, endpoint.Id, Remove)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyACLPolicy applies a set of ACL Policies on the Endpoint
|
// ApplyACLPolicy applies a set of ACL Policies on the Endpoint
|
||||||
func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error {
|
func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error {
|
||||||
operation := "ApplyACLPolicy"
|
operation := "ApplyACLPolicy"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
if policy == nil {
|
if policy == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
jsonString, err := json.Marshal(policy)
|
jsonString, err := json.Marshal(policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
endpoint.Policies = append(endpoint.Policies, jsonString)
|
endpoint.Policies = append(endpoint.Policies, jsonString)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := endpoint.Update()
|
_, err := endpoint.Update()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerAttach attaches an endpoint to container
|
// ContainerAttach attaches an endpoint to container
|
||||||
func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
|
func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
|
||||||
operation := "ContainerAttach"
|
operation := "ContainerAttach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
ContainerID: containerID,
|
ContainerID: containerID,
|
||||||
CompartmentID: compartmentID,
|
CompartmentID: compartmentID,
|
||||||
SystemType: ContainerType,
|
SystemType: ContainerType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerDetach detaches an endpoint from container
|
// ContainerDetach detaches an endpoint from container
|
||||||
func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
|
func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
|
||||||
operation := "ContainerDetach"
|
operation := "ContainerDetach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
ContainerID: containerID,
|
ContainerID: containerID,
|
||||||
SystemType: ContainerType,
|
SystemType: ContainerType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostAttach attaches a nic on the host
|
// HostAttach attaches a nic on the host
|
||||||
func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
|
func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
|
||||||
operation := "HostAttach"
|
operation := "HostAttach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
CompartmentID: compartmentID,
|
CompartmentID: compartmentID,
|
||||||
SystemType: HostType,
|
SystemType: HostType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostDetach detaches a nic on the host
|
// HostDetach detaches a nic on the host
|
||||||
func (endpoint *HNSEndpoint) HostDetach() error {
|
func (endpoint *HNSEndpoint) HostDetach() error {
|
||||||
operation := "HostDetach"
|
operation := "HostDetach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
SystemType: HostType,
|
SystemType: HostType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtualMachineNICAttach attaches a endpoint to a virtual machine
|
// VirtualMachineNICAttach attaches a endpoint to a virtual machine
|
||||||
func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
|
func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
|
||||||
operation := "VirtualMachineNicAttach"
|
operation := "VirtualMachineNicAttach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
VirtualNICName: virtualMachineNICName,
|
VirtualNICName: virtualMachineNICName,
|
||||||
SystemType: VirtualMachineType,
|
SystemType: VirtualMachineType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtualMachineNICDetach detaches a endpoint from a virtual machine
|
// VirtualMachineNICDetach detaches a endpoint from a virtual machine
|
||||||
func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
|
func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
|
||||||
operation := "VirtualMachineNicDetach"
|
operation := "VirtualMachineNicDetach"
|
||||||
title := "HCSShim::HNSEndpoint::" + operation
|
title := "HCSShim::HNSEndpoint::" + operation
|
||||||
logrus.Debugf(title+" id=%s", endpoint.Id)
|
logrus.Debugf(title+" id=%s", endpoint.Id)
|
||||||
|
|
||||||
requestMessage := &EndpointAttachDetachRequest{
|
requestMessage := &EndpointAttachDetachRequest{
|
||||||
SystemType: VirtualMachineType,
|
SystemType: VirtualMachineType,
|
||||||
}
|
}
|
||||||
response := &EndpointResquestResponse{}
|
response := &EndpointResquestResponse{}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(requestMessage)
|
jsonString, err := json.Marshal(requestMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
|
||||||
}
|
}
|
||||||
|
282
vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
generated
vendored
282
vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
generated
vendored
@ -1,141 +1,141 @@
|
|||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Subnet is assoicated with a network and represents a list
|
// Subnet is assoicated with a network and represents a list
|
||||||
// of subnets available to the network
|
// of subnets available to the network
|
||||||
type Subnet struct {
|
type Subnet struct {
|
||||||
AddressPrefix string `json:",omitempty"`
|
AddressPrefix string `json:",omitempty"`
|
||||||
GatewayAddress string `json:",omitempty"`
|
GatewayAddress string `json:",omitempty"`
|
||||||
Policies []json.RawMessage `json:",omitempty"`
|
Policies []json.RawMessage `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MacPool is assoicated with a network and represents a list
|
// MacPool is assoicated with a network and represents a list
|
||||||
// of macaddresses available to the network
|
// of macaddresses available to the network
|
||||||
type MacPool struct {
|
type MacPool struct {
|
||||||
StartMacAddress string `json:",omitempty"`
|
StartMacAddress string `json:",omitempty"`
|
||||||
EndMacAddress string `json:",omitempty"`
|
EndMacAddress string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSNetwork represents a network in HNS
|
// HNSNetwork represents a network in HNS
|
||||||
type HNSNetwork struct {
|
type HNSNetwork struct {
|
||||||
Id string `json:"ID,omitempty"`
|
Id string `json:"ID,omitempty"`
|
||||||
Name string `json:",omitempty"`
|
Name string `json:",omitempty"`
|
||||||
Type string `json:",omitempty"`
|
Type string `json:",omitempty"`
|
||||||
NetworkAdapterName string `json:",omitempty"`
|
NetworkAdapterName string `json:",omitempty"`
|
||||||
SourceMac string `json:",omitempty"`
|
SourceMac string `json:",omitempty"`
|
||||||
Policies []json.RawMessage `json:",omitempty"`
|
Policies []json.RawMessage `json:",omitempty"`
|
||||||
MacPools []MacPool `json:",omitempty"`
|
MacPools []MacPool `json:",omitempty"`
|
||||||
Subnets []Subnet `json:",omitempty"`
|
Subnets []Subnet `json:",omitempty"`
|
||||||
DNSSuffix string `json:",omitempty"`
|
DNSSuffix string `json:",omitempty"`
|
||||||
DNSServerList string `json:",omitempty"`
|
DNSServerList string `json:",omitempty"`
|
||||||
DNSServerCompartment uint32 `json:",omitempty"`
|
DNSServerCompartment uint32 `json:",omitempty"`
|
||||||
ManagementIP string `json:",omitempty"`
|
ManagementIP string `json:",omitempty"`
|
||||||
AutomaticDNS bool `json:",omitempty"`
|
AutomaticDNS bool `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type hnsNetworkResponse struct {
|
type hnsNetworkResponse struct {
|
||||||
Success bool
|
Success bool
|
||||||
Error string
|
Error string
|
||||||
Output HNSNetwork
|
Output HNSNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
type hnsResponse struct {
|
type hnsResponse struct {
|
||||||
Success bool
|
Success bool
|
||||||
Error string
|
Error string
|
||||||
Output json.RawMessage
|
Output json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSNetworkRequest makes a call into HNS to update/query a single network
|
// HNSNetworkRequest makes a call into HNS to update/query a single network
|
||||||
func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
|
func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
|
||||||
var network HNSNetwork
|
var network HNSNetwork
|
||||||
err := hnsCall(method, "/networks/"+path, request, &network)
|
err := hnsCall(method, "/networks/"+path, request, &network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &network, nil
|
return &network, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSListNetworkRequest makes a HNS call to query the list of available networks
|
// HNSListNetworkRequest makes a HNS call to query the list of available networks
|
||||||
func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
|
func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
|
||||||
var network []HNSNetwork
|
var network []HNSNetwork
|
||||||
err := hnsCall(method, "/networks/"+path, request, &network)
|
err := hnsCall(method, "/networks/"+path, request, &network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHNSNetworkByID
|
// GetHNSNetworkByID
|
||||||
func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
|
func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
|
||||||
return HNSNetworkRequest("GET", networkID, "")
|
return HNSNetworkRequest("GET", networkID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHNSNetworkName filtered by Name
|
// GetHNSNetworkName filtered by Name
|
||||||
func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
|
func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
|
||||||
hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
|
hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, hnsnetwork := range hsnnetworks {
|
for _, hnsnetwork := range hsnnetworks {
|
||||||
if hnsnetwork.Name == networkName {
|
if hnsnetwork.Name == networkName {
|
||||||
return &hnsnetwork, nil
|
return &hnsnetwork, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, NetworkNotFoundError{NetworkName: networkName}
|
return nil, NetworkNotFoundError{NetworkName: networkName}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Network by sending NetworkRequest to HNS.
|
// Create Network by sending NetworkRequest to HNS.
|
||||||
func (network *HNSNetwork) Create() (*HNSNetwork, error) {
|
func (network *HNSNetwork) Create() (*HNSNetwork, error) {
|
||||||
operation := "Create"
|
operation := "Create"
|
||||||
title := "HCSShim::HNSNetwork::" + operation
|
title := "HCSShim::HNSNetwork::" + operation
|
||||||
logrus.Debugf(title+" id=%s", network.Id)
|
logrus.Debugf(title+" id=%s", network.Id)
|
||||||
|
|
||||||
jsonString, err := json.Marshal(network)
|
jsonString, err := json.Marshal(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return HNSNetworkRequest("POST", "", string(jsonString))
|
return HNSNetworkRequest("POST", "", string(jsonString))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete Network by sending NetworkRequest to HNS
|
// Delete Network by sending NetworkRequest to HNS
|
||||||
func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
|
func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
|
||||||
operation := "Delete"
|
operation := "Delete"
|
||||||
title := "HCSShim::HNSNetwork::" + operation
|
title := "HCSShim::HNSNetwork::" + operation
|
||||||
logrus.Debugf(title+" id=%s", network.Id)
|
logrus.Debugf(title+" id=%s", network.Id)
|
||||||
|
|
||||||
return HNSNetworkRequest("DELETE", network.Id, "")
|
return HNSNetworkRequest("DELETE", network.Id, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an endpoint on the Network.
|
// Creates an endpoint on the Network.
|
||||||
func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
|
func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
|
||||||
return &HNSEndpoint{
|
return &HNSEndpoint{
|
||||||
VirtualNetwork: network.Id,
|
VirtualNetwork: network.Id,
|
||||||
IPAddress: ipAddress,
|
IPAddress: ipAddress,
|
||||||
MacAddress: string(macAddress),
|
MacAddress: string(macAddress),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
|
func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
|
||||||
operation := "CreateEndpoint"
|
operation := "CreateEndpoint"
|
||||||
title := "HCSShim::HNSNetwork::" + operation
|
title := "HCSShim::HNSNetwork::" + operation
|
||||||
logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
|
logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
|
||||||
|
|
||||||
endpoint.VirtualNetwork = network.Id
|
endpoint.VirtualNetwork = network.Id
|
||||||
return endpoint.Create()
|
return endpoint.Create()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
|
func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
|
||||||
operation := "CreateRemoteEndpoint"
|
operation := "CreateRemoteEndpoint"
|
||||||
title := "HCSShim::HNSNetwork::" + operation
|
title := "HCSShim::HNSNetwork::" + operation
|
||||||
logrus.Debugf(title+" id=%s", network.Id)
|
logrus.Debugf(title+" id=%s", network.Id)
|
||||||
endpoint.IsRemoteEndpoint = true
|
endpoint.IsRemoteEndpoint = true
|
||||||
return network.CreateEndpoint(endpoint)
|
return network.CreateEndpoint(endpoint)
|
||||||
}
|
}
|
||||||
|
188
vendor/github.com/Microsoft/hcsshim/hnspolicy.go
generated
vendored
188
vendor/github.com/Microsoft/hcsshim/hnspolicy.go
generated
vendored
@ -1,94 +1,94 @@
|
|||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
// Type of Request Support in ModifySystem
|
// Type of Request Support in ModifySystem
|
||||||
type PolicyType string
|
type PolicyType string
|
||||||
|
|
||||||
// RequestType const
|
// RequestType const
|
||||||
const (
|
const (
|
||||||
Nat PolicyType = "NAT"
|
Nat PolicyType = "NAT"
|
||||||
ACL PolicyType = "ACL"
|
ACL PolicyType = "ACL"
|
||||||
PA PolicyType = "PA"
|
PA PolicyType = "PA"
|
||||||
VLAN PolicyType = "VLAN"
|
VLAN PolicyType = "VLAN"
|
||||||
VSID PolicyType = "VSID"
|
VSID PolicyType = "VSID"
|
||||||
VNet PolicyType = "VNET"
|
VNet PolicyType = "VNET"
|
||||||
L2Driver PolicyType = "L2Driver"
|
L2Driver PolicyType = "L2Driver"
|
||||||
Isolation PolicyType = "Isolation"
|
Isolation PolicyType = "Isolation"
|
||||||
QOS PolicyType = "QOS"
|
QOS PolicyType = "QOS"
|
||||||
OutboundNat PolicyType = "OutBoundNAT"
|
OutboundNat PolicyType = "OutBoundNAT"
|
||||||
ExternalLoadBalancer PolicyType = "ELB"
|
ExternalLoadBalancer PolicyType = "ELB"
|
||||||
Route PolicyType = "ROUTE"
|
Route PolicyType = "ROUTE"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NatPolicy struct {
|
type NatPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
Protocol string
|
Protocol string
|
||||||
InternalPort uint16
|
InternalPort uint16
|
||||||
ExternalPort uint16
|
ExternalPort uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type QosPolicy struct {
|
type QosPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
MaximumOutgoingBandwidthInBytes uint64
|
MaximumOutgoingBandwidthInBytes uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type IsolationPolicy struct {
|
type IsolationPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
VLAN uint
|
VLAN uint
|
||||||
VSID uint
|
VSID uint
|
||||||
InDefaultIsolation bool
|
InDefaultIsolation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type VlanPolicy struct {
|
type VlanPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
VLAN uint
|
VLAN uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type VsidPolicy struct {
|
type VsidPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
VSID uint
|
VSID uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaPolicy struct {
|
type PaPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
PA string `json:"PA"`
|
PA string `json:"PA"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutboundNatPolicy struct {
|
type OutboundNatPolicy struct {
|
||||||
Policy
|
Policy
|
||||||
VIP string `json:"VIP,omitempty"`
|
VIP string `json:"VIP,omitempty"`
|
||||||
Exceptions []string `json:"ExceptionList,omitempty"`
|
Exceptions []string `json:"ExceptionList,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionType string
|
type ActionType string
|
||||||
type DirectionType string
|
type DirectionType string
|
||||||
type RuleType string
|
type RuleType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Allow ActionType = "Allow"
|
Allow ActionType = "Allow"
|
||||||
Block ActionType = "Block"
|
Block ActionType = "Block"
|
||||||
|
|
||||||
In DirectionType = "In"
|
In DirectionType = "In"
|
||||||
Out DirectionType = "Out"
|
Out DirectionType = "Out"
|
||||||
|
|
||||||
Host RuleType = "Host"
|
Host RuleType = "Host"
|
||||||
Switch RuleType = "Switch"
|
Switch RuleType = "Switch"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ACLPolicy struct {
|
type ACLPolicy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
Protocol uint16
|
Protocol uint16
|
||||||
InternalPort uint16
|
InternalPort uint16
|
||||||
Action ActionType
|
Action ActionType
|
||||||
Direction DirectionType
|
Direction DirectionType
|
||||||
LocalAddresses string
|
LocalAddresses string
|
||||||
RemoteAddresses string
|
RemoteAddresses string
|
||||||
LocalPort uint16
|
LocalPort uint16
|
||||||
RemotePort uint16
|
RemotePort uint16
|
||||||
RuleType RuleType `json:"RuleType,omitempty"`
|
RuleType RuleType `json:"RuleType,omitempty"`
|
||||||
Priority uint16
|
Priority uint16
|
||||||
ServiceName string
|
ServiceName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
Type PolicyType `json:"Type"`
|
Type PolicyType `json:"Type"`
|
||||||
}
|
}
|
||||||
|
400
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
400
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
@ -1,200 +1,200 @@
|
|||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RoutePolicy is a structure defining schema for Route based Policy
|
// RoutePolicy is a structure defining schema for Route based Policy
|
||||||
type RoutePolicy struct {
|
type RoutePolicy struct {
|
||||||
Policy
|
Policy
|
||||||
DestinationPrefix string `json:"DestinationPrefix,omitempty"`
|
DestinationPrefix string `json:"DestinationPrefix,omitempty"`
|
||||||
NextHop string `json:"NextHop,omitempty"`
|
NextHop string `json:"NextHop,omitempty"`
|
||||||
EncapEnabled bool `json:"NeedEncap,omitempty"`
|
EncapEnabled bool `json:"NeedEncap,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
|
// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
|
||||||
type ELBPolicy struct {
|
type ELBPolicy struct {
|
||||||
LBPolicy
|
LBPolicy
|
||||||
SourceVIP string `json:"SourceVIP,omitempty"`
|
SourceVIP string `json:"SourceVIP,omitempty"`
|
||||||
VIPs []string `json:"VIPs,omitempty"`
|
VIPs []string `json:"VIPs,omitempty"`
|
||||||
ILB bool `json:"ILB,omitempty"`
|
ILB bool `json:"ILB,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LBPolicy is a structure defining schema for LoadBalancing based Policy
|
// LBPolicy is a structure defining schema for LoadBalancing based Policy
|
||||||
type LBPolicy struct {
|
type LBPolicy struct {
|
||||||
Policy
|
Policy
|
||||||
Protocol uint16 `json:"Protocol,omitempty"`
|
Protocol uint16 `json:"Protocol,omitempty"`
|
||||||
InternalPort uint16
|
InternalPort uint16
|
||||||
ExternalPort uint16
|
ExternalPort uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// PolicyList is a structure defining schema for Policy list request
|
// PolicyList is a structure defining schema for Policy list request
|
||||||
type PolicyList struct {
|
type PolicyList struct {
|
||||||
ID string `json:"ID,omitempty"`
|
ID string `json:"ID,omitempty"`
|
||||||
EndpointReferences []string `json:"References,omitempty"`
|
EndpointReferences []string `json:"References,omitempty"`
|
||||||
Policies []json.RawMessage `json:"Policies,omitempty"`
|
Policies []json.RawMessage `json:"Policies,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSPolicyListRequest makes a call into HNS to update/query a single network
|
// HNSPolicyListRequest makes a call into HNS to update/query a single network
|
||||||
func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
|
func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
|
||||||
var policy PolicyList
|
var policy PolicyList
|
||||||
err := hnsCall(method, "/policylists/"+path, request, &policy)
|
err := hnsCall(method, "/policylists/"+path, request, &policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &policy, nil
|
return &policy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HNSListPolicyListRequest gets all the policy list
|
// HNSListPolicyListRequest gets all the policy list
|
||||||
func HNSListPolicyListRequest() ([]PolicyList, error) {
|
func HNSListPolicyListRequest() ([]PolicyList, error) {
|
||||||
var plist []PolicyList
|
var plist []PolicyList
|
||||||
err := hnsCall("GET", "/policylists/", "", &plist)
|
err := hnsCall("GET", "/policylists/", "", &plist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return plist, nil
|
return plist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PolicyListRequest makes a HNS call to modify/query a network policy list
|
// PolicyListRequest makes a HNS call to modify/query a network policy list
|
||||||
func PolicyListRequest(method, path, request string) (*PolicyList, error) {
|
func PolicyListRequest(method, path, request string) (*PolicyList, error) {
|
||||||
policylist := &PolicyList{}
|
policylist := &PolicyList{}
|
||||||
err := hnsCall(method, "/policylists/"+path, request, &policylist)
|
err := hnsCall(method, "/policylists/"+path, request, &policylist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return policylist, nil
|
return policylist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPolicyListByID get the policy list by ID
|
// GetPolicyListByID get the policy list by ID
|
||||||
func GetPolicyListByID(policyListID string) (*PolicyList, error) {
|
func GetPolicyListByID(policyListID string) (*PolicyList, error) {
|
||||||
return PolicyListRequest("GET", policyListID, "")
|
return PolicyListRequest("GET", policyListID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PolicyList by sending PolicyListRequest to HNS.
|
// Create PolicyList by sending PolicyListRequest to HNS.
|
||||||
func (policylist *PolicyList) Create() (*PolicyList, error) {
|
func (policylist *PolicyList) Create() (*PolicyList, error) {
|
||||||
operation := "Create"
|
operation := "Create"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
title := "HCSShim::PolicyList::" + operation
|
||||||
logrus.Debugf(title+" id=%s", policylist.ID)
|
logrus.Debugf(title+" id=%s", policylist.ID)
|
||||||
jsonString, err := json.Marshal(policylist)
|
jsonString, err := json.Marshal(policylist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return PolicyListRequest("POST", "", string(jsonString))
|
return PolicyListRequest("POST", "", string(jsonString))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes PolicyList
|
// Delete deletes PolicyList
|
||||||
func (policylist *PolicyList) Delete() (*PolicyList, error) {
|
func (policylist *PolicyList) Delete() (*PolicyList, error) {
|
||||||
operation := "Delete"
|
operation := "Delete"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
title := "HCSShim::PolicyList::" + operation
|
||||||
logrus.Debugf(title+" id=%s", policylist.ID)
|
logrus.Debugf(title+" id=%s", policylist.ID)
|
||||||
|
|
||||||
return PolicyListRequest("DELETE", policylist.ID, "")
|
return PolicyListRequest("DELETE", policylist.ID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddEndpoint add an endpoint to a Policy List
|
// AddEndpoint add an endpoint to a Policy List
|
||||||
func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
|
func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
|
||||||
operation := "AddEndpoint"
|
operation := "AddEndpoint"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
title := "HCSShim::PolicyList::" + operation
|
||||||
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
|
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
|
||||||
|
|
||||||
_, err := policylist.Delete()
|
_, err := policylist.Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Endpoint to the Existing List
|
// Add Endpoint to the Existing List
|
||||||
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
||||||
|
|
||||||
return policylist.Create()
|
return policylist.Create()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveEndpoint removes an endpoint from the Policy List
|
// RemoveEndpoint removes an endpoint from the Policy List
|
||||||
func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
|
func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
|
||||||
operation := "RemoveEndpoint"
|
operation := "RemoveEndpoint"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
title := "HCSShim::PolicyList::" + operation
|
||||||
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
|
logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
|
||||||
|
|
||||||
_, err := policylist.Delete()
|
_, err := policylist.Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
elementToRemove := "/endpoints/" + endpoint.Id
|
elementToRemove := "/endpoints/" + endpoint.Id
|
||||||
|
|
||||||
var references []string
|
var references []string
|
||||||
|
|
||||||
for _, endpointReference := range policylist.EndpointReferences {
|
for _, endpointReference := range policylist.EndpointReferences {
|
||||||
if endpointReference == elementToRemove {
|
if endpointReference == elementToRemove {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
references = append(references, endpointReference)
|
references = append(references, endpointReference)
|
||||||
}
|
}
|
||||||
policylist.EndpointReferences = references
|
policylist.EndpointReferences = references
|
||||||
return policylist.Create()
|
return policylist.Create()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLoadBalancer policy list for the specified endpoints
|
// AddLoadBalancer policy list for the specified endpoints
|
||||||
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
||||||
operation := "AddLoadBalancer"
|
operation := "AddLoadBalancer"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
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)
|
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{}
|
policylist := &PolicyList{}
|
||||||
|
|
||||||
elbPolicy := &ELBPolicy{
|
elbPolicy := &ELBPolicy{
|
||||||
SourceVIP: sourceVIP,
|
SourceVIP: sourceVIP,
|
||||||
ILB: isILB,
|
ILB: isILB,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vip) > 0 {
|
if len(vip) > 0 {
|
||||||
elbPolicy.VIPs = []string{vip}
|
elbPolicy.VIPs = []string{vip}
|
||||||
}
|
}
|
||||||
elbPolicy.Type = ExternalLoadBalancer
|
elbPolicy.Type = ExternalLoadBalancer
|
||||||
elbPolicy.Protocol = protocol
|
elbPolicy.Protocol = protocol
|
||||||
elbPolicy.InternalPort = internalPort
|
elbPolicy.InternalPort = internalPort
|
||||||
elbPolicy.ExternalPort = externalPort
|
elbPolicy.ExternalPort = externalPort
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(elbPolicy)
|
jsonString, err := json.Marshal(elbPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
policylist.Policies = append(policylist.Policies, jsonString)
|
policylist.Policies = append(policylist.Policies, jsonString)
|
||||||
return policylist.Create()
|
return policylist.Create()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRoute adds route policy list for the specified endpoints
|
// AddRoute adds route policy list for the specified endpoints
|
||||||
func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) {
|
func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) {
|
||||||
operation := "AddRoute"
|
operation := "AddRoute"
|
||||||
title := "HCSShim::PolicyList::" + operation
|
title := "HCSShim::PolicyList::" + operation
|
||||||
logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix)
|
logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix)
|
||||||
|
|
||||||
policylist := &PolicyList{}
|
policylist := &PolicyList{}
|
||||||
|
|
||||||
rPolicy := &RoutePolicy{
|
rPolicy := &RoutePolicy{
|
||||||
DestinationPrefix: destinationPrefix,
|
DestinationPrefix: destinationPrefix,
|
||||||
NextHop: nextHop,
|
NextHop: nextHop,
|
||||||
EncapEnabled: encapEnabled,
|
EncapEnabled: encapEnabled,
|
||||||
}
|
}
|
||||||
rPolicy.Type = Route
|
rPolicy.Type = Route
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonString, err := json.Marshal(rPolicy)
|
jsonString, err := json.Marshal(rPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
policylist.Policies = append(policylist.Policies, jsonString)
|
policylist.Policies = append(policylist.Policies, jsonString)
|
||||||
return policylist.Create()
|
return policylist.Create()
|
||||||
}
|
}
|
||||||
|
40
vendor/github.com/Microsoft/hcsshim/importlayer.go
generated
vendored
40
vendor/github.com/Microsoft/hcsshim/importlayer.go
generated
vendored
@ -129,37 +129,39 @@ type legacyLayerWriterWrapper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *legacyLayerWriterWrapper) Close() error {
|
func (r *legacyLayerWriterWrapper) Close() error {
|
||||||
defer os.RemoveAll(r.root)
|
defer os.RemoveAll(r.root.Name())
|
||||||
|
defer r.legacyLayerWriter.CloseRoots()
|
||||||
err := r.legacyLayerWriter.Close()
|
err := r.legacyLayerWriter.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the original path here because ImportLayer does not support long paths for the source in TP5.
|
|
||||||
// But do use a long path for the destination to work around another bug with directories
|
|
||||||
// with MAX_PATH - 12 < length < MAX_PATH.
|
|
||||||
info := r.info
|
info := r.info
|
||||||
fullPath, err := makeLongAbsPath(filepath.Join(info.HomeDir, r.layerID))
|
info.HomeDir = ""
|
||||||
if err != nil {
|
if err = ImportLayer(info, r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, name := range r.Tombstones {
|
||||||
info.HomeDir = ""
|
if err = removeRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) {
|
||||||
if err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
}
|
||||||
// Add any hard links that were collected.
|
// Add any hard links that were collected.
|
||||||
for _, lnk := range r.PendingLinks {
|
for _, lnk := range r.PendingLinks {
|
||||||
if err = os.Remove(lnk.Path); err != nil && !os.IsNotExist(err) {
|
if err = removeRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = os.Link(lnk.Target, lnk.Path); err != nil {
|
if err = linkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Prepare the utility VM for use if one is present in the layer.
|
// Prepare the utility VM for use if one is present in the layer.
|
||||||
if r.HasUtilityVM {
|
if r.HasUtilityVM {
|
||||||
err = ProcessUtilityVMImage(filepath.Join(fullPath, "UtilityVM"))
|
err := ensureNotReparsePointRelative("UtilityVM", r.destRoot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -173,8 +175,12 @@ func (r *legacyLayerWriterWrapper) Close() error {
|
|||||||
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
|
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
|
||||||
if len(parentLayerPaths) == 0 {
|
if len(parentLayerPaths) == 0 {
|
||||||
// This is a base layer. It gets imported differently.
|
// This is a base layer. It gets imported differently.
|
||||||
|
f, err := openRoot(filepath.Join(info.HomeDir, layerID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &baseLayerWriter{
|
return &baseLayerWriter{
|
||||||
root: filepath.Join(info.HomeDir, layerID),
|
root: f,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +191,12 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
w, err := newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &legacyLayerWriterWrapper{
|
return &legacyLayerWriterWrapper{
|
||||||
legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)),
|
legacyLayerWriter: w,
|
||||||
info: info,
|
info: info,
|
||||||
layerID: layerID,
|
layerID: layerID,
|
||||||
path: path,
|
path: path,
|
||||||
|
289
vendor/github.com/Microsoft/hcsshim/legacy.go
generated
vendored
289
vendor/github.com/Microsoft/hcsshim/legacy.go
generated
vendored
@ -121,6 +121,16 @@ func (r *legacyLayerReader) walkUntilCancelled() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 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$") {
|
if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -326,59 +336,79 @@ func (r *legacyLayerReader) Close() error {
|
|||||||
|
|
||||||
type pendingLink struct {
|
type pendingLink struct {
|
||||||
Path, Target string
|
Path, Target string
|
||||||
|
TargetRoot *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
type pendingDir struct {
|
||||||
|
Path string
|
||||||
|
Root *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type legacyLayerWriter struct {
|
type legacyLayerWriter struct {
|
||||||
root string
|
root *os.File
|
||||||
parentRoots []string
|
destRoot *os.File
|
||||||
destRoot string
|
parentRoots []*os.File
|
||||||
currentFile *os.File
|
currentFile *os.File
|
||||||
backupWriter *winio.BackupFileWriter
|
currentFileName string
|
||||||
tombstones []string
|
currentFileRoot *os.File
|
||||||
pathFixed bool
|
backupWriter *winio.BackupFileWriter
|
||||||
HasUtilityVM bool
|
Tombstones []string
|
||||||
uvmDi []dirInfo
|
HasUtilityVM bool
|
||||||
addedFiles map[string]bool
|
uvmDi []dirInfo
|
||||||
PendingLinks []pendingLink
|
addedFiles map[string]bool
|
||||||
|
PendingLinks []pendingLink
|
||||||
|
pendingDirs []pendingDir
|
||||||
|
currentIsDir bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
|
// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
|
||||||
// transport format to disk.
|
// transport format to disk.
|
||||||
func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) *legacyLayerWriter {
|
func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) {
|
||||||
return &legacyLayerWriter{
|
w = &legacyLayerWriter{
|
||||||
root: root,
|
addedFiles: make(map[string]bool),
|
||||||
parentRoots: parentRoots,
|
|
||||||
destRoot: destRoot,
|
|
||||||
addedFiles: make(map[string]bool),
|
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
w.CloseRoots()
|
||||||
|
w = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
w.root, err = openRoot(root)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.destRoot, err = openRoot(destRoot)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, r := range parentRoots {
|
||||||
|
f, err := openRoot(r)
|
||||||
|
if err != nil {
|
||||||
|
return w, err
|
||||||
|
}
|
||||||
|
w.parentRoots = append(w.parentRoots, f)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) init() error {
|
func (w *legacyLayerWriter) CloseRoots() {
|
||||||
if !w.pathFixed {
|
if w.root != nil {
|
||||||
path, err := makeLongAbsPath(w.root)
|
w.root.Close()
|
||||||
if err != nil {
|
w.root = nil
|
||||||
return err
|
|
||||||
}
|
|
||||||
for i, p := range w.parentRoots {
|
|
||||||
w.parentRoots[i], err = makeLongAbsPath(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
destPath, err := makeLongAbsPath(w.destRoot)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.root = path
|
|
||||||
w.destRoot = destPath
|
|
||||||
w.pathFixed = true
|
|
||||||
}
|
}
|
||||||
return 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 {
|
func (w *legacyLayerWriter) initUtilityVM() error {
|
||||||
if !w.HasUtilityVM {
|
if !w.HasUtilityVM {
|
||||||
err := os.Mkdir(filepath.Join(w.destRoot, utilityVMPath), 0)
|
err := mkdirRelative(utilityVMPath, w.destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -386,7 +416,7 @@ func (w *legacyLayerWriter) initUtilityVM() error {
|
|||||||
// clone the utility VM from the parent layer into this layer. Use hard
|
// clone the utility VM from the parent layer into this layer. Use hard
|
||||||
// links to avoid unnecessary copying, since most of the files are
|
// links to avoid unnecessary copying, since most of the files are
|
||||||
// immutable.
|
// immutable.
|
||||||
err = cloneTree(filepath.Join(w.parentRoots[0], utilityVMFilesPath), filepath.Join(w.destRoot, utilityVMFilesPath), mutatedUtilityVMFiles)
|
err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
|
return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
|
||||||
}
|
}
|
||||||
@ -395,7 +425,40 @@ func (w *legacyLayerWriter) initUtilityVM() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) reset() {
|
func (w *legacyLayerWriter) reset() error {
|
||||||
|
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 := 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 {
|
if w.backupWriter != nil {
|
||||||
w.backupWriter.Close()
|
w.backupWriter.Close()
|
||||||
w.backupWriter = nil
|
w.backupWriter = nil
|
||||||
@ -403,21 +466,21 @@ func (w *legacyLayerWriter) reset() {
|
|||||||
if w.currentFile != nil {
|
if w.currentFile != nil {
|
||||||
w.currentFile.Close()
|
w.currentFile.Close()
|
||||||
w.currentFile = nil
|
w.currentFile = nil
|
||||||
|
w.currentFileName = ""
|
||||||
|
w.currentFileRoot = nil
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
|
// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
|
||||||
func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
|
func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
|
||||||
createDisposition := uint32(syscall.CREATE_NEW)
|
src, err := openRelative(
|
||||||
if isDir {
|
subPath,
|
||||||
err = os.Mkdir(destPath, 0)
|
srcRoot,
|
||||||
if err != nil {
|
syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY,
|
||||||
return nil, err
|
syscall.FILE_SHARE_READ,
|
||||||
}
|
_FILE_OPEN,
|
||||||
createDisposition = syscall.OPEN_EXISTING
|
_FILE_OPEN_REPARSE_POINT)
|
||||||
}
|
|
||||||
|
|
||||||
src, err := openFileOrDir(srcPath, syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, syscall.OPEN_EXISTING)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -430,7 +493,17 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dest, err := openFileOrDir(destPath, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
|
extraFlags := uint32(0)
|
||||||
|
if isDir {
|
||||||
|
extraFlags |= _FILE_DIRECTORY_FILE
|
||||||
|
}
|
||||||
|
dest, err := openRelative(
|
||||||
|
subPath,
|
||||||
|
destRoot,
|
||||||
|
syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY,
|
||||||
|
syscall.FILE_SHARE_READ,
|
||||||
|
_FILE_CREATE,
|
||||||
|
extraFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -459,18 +532,21 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio
|
|||||||
|
|
||||||
// cloneTree clones a directory tree using hard links. It skips hard links for
|
// 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.
|
// the file names in the provided map and just copies those files.
|
||||||
func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error {
|
||||||
var di []dirInfo
|
var di []dirInfo
|
||||||
err := filepath.Walk(srcPath, func(srcFilePath string, info os.FileInfo, err error) error {
|
err := 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
relPath, err := filepath.Rel(srcPath, srcFilePath)
|
relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
destFilePath := filepath.Join(destPath, relPath)
|
|
||||||
|
|
||||||
fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||||
// Directories, reparse points, and files that will be mutated during
|
// Directories, reparse points, and files that will be mutated during
|
||||||
@ -482,15 +558,15 @@ func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
|||||||
isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
|
isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
|
||||||
|
|
||||||
if isDir || isReparsePoint || mutatedFiles[relPath] {
|
if isDir || isReparsePoint || mutatedFiles[relPath] {
|
||||||
fi, err := copyFileWithMetadata(srcFilePath, destFilePath, isDir)
|
fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if isDir && !isReparsePoint {
|
if isDir && !isReparsePoint {
|
||||||
di = append(di, dirInfo{path: destFilePath, fileInfo: *fi})
|
di = append(di, dirInfo{path: relPath, fileInfo: *fi})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = os.Link(srcFilePath, destFilePath)
|
err = linkRelative(relPath, srcRoot, relPath, destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -508,13 +584,11 @@ func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return reapplyDirectoryTimes(di)
|
return reapplyDirectoryTimes(destRoot, di)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,6 +596,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
return w.initUtilityVM()
|
return w.initUtilityVM()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = filepath.Clean(name)
|
||||||
if hasPathPrefix(name, utilityVMPath) {
|
if hasPathPrefix(name, utilityVMPath) {
|
||||||
if !w.HasUtilityVM {
|
if !w.HasUtilityVM {
|
||||||
return errors.New("missing UtilityVM directory")
|
return errors.New("missing UtilityVM directory")
|
||||||
@ -529,10 +604,9 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
|
if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
|
||||||
return errors.New("invalid UtilityVM layer")
|
return errors.New("invalid UtilityVM layer")
|
||||||
}
|
}
|
||||||
path := filepath.Join(w.destRoot, name)
|
createDisposition := uint32(_FILE_OPEN)
|
||||||
createDisposition := uint32(syscall.OPEN_EXISTING)
|
|
||||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||||
st, err := os.Lstat(path)
|
st, err := lstatRelative(name, w.destRoot)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -540,37 +614,44 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
// Delete the existing file/directory if it is not the same type as this directory.
|
// Delete the existing file/directory if it is not the same type as this directory.
|
||||||
existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||||
if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
||||||
if err = os.RemoveAll(path); err != nil {
|
if err = removeAllRelative(name, w.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
st = nil
|
st = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if st == nil {
|
if st == nil {
|
||||||
if err = os.Mkdir(path, 0); err != nil {
|
if err = mkdirRelative(name, w.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||||
w.uvmDi = append(w.uvmDi, dirInfo{path: path, fileInfo: *fileInfo})
|
w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Overwrite any existing hard link.
|
// Overwrite any existing hard link.
|
||||||
err = os.Remove(path)
|
err := removeRelative(name, w.destRoot)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
createDisposition = syscall.CREATE_NEW
|
createDisposition = _FILE_CREATE
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
|
f, err := openRelative(
|
||||||
|
name,
|
||||||
|
w.destRoot,
|
||||||
|
syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY,
|
||||||
|
syscall.FILE_SHARE_READ,
|
||||||
|
createDisposition,
|
||||||
|
_FILE_OPEN_REPARSE_POINT,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
os.Remove(path)
|
removeRelative(name, w.destRoot)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -581,28 +662,31 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
|
|
||||||
w.backupWriter = winio.NewBackupFileWriter(f, true)
|
w.backupWriter = winio.NewBackupFileWriter(f, true)
|
||||||
w.currentFile = f
|
w.currentFile = f
|
||||||
|
w.currentFileName = name
|
||||||
|
w.currentFileRoot = w.destRoot
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
f = nil
|
f = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(w.root, name)
|
fname := name
|
||||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||||
err := os.Mkdir(path, 0)
|
err := mkdirRelative(name, w.root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
path += ".$wcidirs$"
|
fname += ".$wcidirs$"
|
||||||
|
w.currentIsDir = true
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW)
|
f, err := openRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_CREATE, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
os.Remove(path)
|
removeRelative(fname, w.root)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -624,19 +708,20 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.currentFile = f
|
w.currentFile = f
|
||||||
|
w.currentFileName = name
|
||||||
|
w.currentFileRoot = w.root
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
f = nil
|
f = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var roots []string
|
target = filepath.Clean(target)
|
||||||
|
var roots []*os.File
|
||||||
if hasPathPrefix(target, filesPath) {
|
if hasPathPrefix(target, filesPath) {
|
||||||
// Look for cross-layer hard link targets in the parent layers, since
|
// Look for cross-layer hard link targets in the parent layers, since
|
||||||
// nothing is in the destination path yet.
|
// nothing is in the destination path yet.
|
||||||
@ -645,7 +730,7 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
// Since the utility VM is fully cloned into the destination path
|
// Since the utility VM is fully cloned into the destination path
|
||||||
// already, look for cross-layer hard link targets directly in the
|
// already, look for cross-layer hard link targets directly in the
|
||||||
// destination path.
|
// destination path.
|
||||||
roots = []string{w.destRoot}
|
roots = []*os.File{w.destRoot}
|
||||||
}
|
}
|
||||||
|
|
||||||
if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
|
if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
|
||||||
@ -654,12 +739,12 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
|
|
||||||
// Find to try the target of the link in a previously added file. If that
|
// Find to try the target of the link in a previously added file. If that
|
||||||
// fails, search in parent layers.
|
// fails, search in parent layers.
|
||||||
var selectedRoot string
|
var selectedRoot *os.File
|
||||||
if _, ok := w.addedFiles[target]; ok {
|
if _, ok := w.addedFiles[target]; ok {
|
||||||
selectedRoot = w.destRoot
|
selectedRoot = w.destRoot
|
||||||
} else {
|
} else {
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
if _, err = os.Lstat(filepath.Join(r, target)); err != nil {
|
if _, err := lstatRelative(target, r); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -668,22 +753,25 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if selectedRoot == "" {
|
if selectedRoot == nil {
|
||||||
return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
|
return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The link can't be written until after the ImportLayer call.
|
// The link can't be written until after the ImportLayer call.
|
||||||
w.PendingLinks = append(w.PendingLinks, pendingLink{
|
w.PendingLinks = append(w.PendingLinks, pendingLink{
|
||||||
Path: filepath.Join(w.destRoot, name),
|
Path: name,
|
||||||
Target: filepath.Join(selectedRoot, target),
|
Target: target,
|
||||||
|
TargetRoot: selectedRoot,
|
||||||
})
|
})
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Remove(name string) error {
|
func (w *legacyLayerWriter) Remove(name string) error {
|
||||||
|
name = filepath.Clean(name)
|
||||||
if hasPathPrefix(name, filesPath) {
|
if hasPathPrefix(name, filesPath) {
|
||||||
w.tombstones = append(w.tombstones, name[len(filesPath)+1:])
|
w.Tombstones = append(w.Tombstones, name)
|
||||||
} else if hasPathPrefix(name, utilityVMFilesPath) {
|
} else if hasPathPrefix(name, utilityVMFilesPath) {
|
||||||
err := w.initUtilityVM()
|
err := w.initUtilityVM()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -692,11 +780,10 @@ func (w *legacyLayerWriter) Remove(name string) error {
|
|||||||
// Make sure the path exists; os.RemoveAll will not fail if the file is
|
// 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
|
// already gone, and this needs to be a fatal error for diagnostics
|
||||||
// purposes.
|
// purposes.
|
||||||
path := filepath.Join(w.destRoot, name)
|
if _, err := lstatRelative(name, w.destRoot); err != nil {
|
||||||
if _, err := os.Lstat(path); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.RemoveAll(path)
|
err = removeAllRelative(name, w.destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -718,28 +805,20 @@ func (w *legacyLayerWriter) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Close() error {
|
func (w *legacyLayerWriter) Close() error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tf, err := os.Create(filepath.Join(w.root, "tombstones.txt"))
|
if err := removeRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer tf.Close()
|
for _, pd := range w.pendingDirs {
|
||||||
_, err = tf.Write([]byte("\xef\xbb\xbfVersion 1.0\n"))
|
err := mkdirRelative(pd.Path, pd.Root)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, t := range w.tombstones {
|
|
||||||
_, err = tf.Write([]byte(filepath.Join(`\`, t) + "\n"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if w.HasUtilityVM {
|
if w.HasUtilityVM {
|
||||||
err = reapplyDirectoryTimes(w.uvmDi)
|
err := reapplyDirectoryTimes(w.destRoot, w.uvmDi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/Microsoft/hcsshim/legacy18.go
generated
vendored
14
vendor/github.com/Microsoft/hcsshim/legacy18.go
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
// +build !go1.9
|
// +build !go1.9
|
||||||
|
|
||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
// Due to a bug in go1.8 and before, directory reparse points need to be skipped
|
// Due to a bug in go1.8 and before, directory reparse points need to be skipped
|
||||||
// during filepath.Walk. This is fixed in go1.9
|
// during filepath.Walk. This is fixed in go1.9
|
||||||
var shouldSkipDirectoryReparse = true
|
var shouldSkipDirectoryReparse = true
|
||||||
|
14
vendor/github.com/Microsoft/hcsshim/legacy19.go
generated
vendored
14
vendor/github.com/Microsoft/hcsshim/legacy19.go
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
// +build go1.9
|
// +build go1.9
|
||||||
|
|
||||||
package hcsshim
|
package hcsshim
|
||||||
|
|
||||||
// Due to a bug in go1.8 and before, directory reparse points need to be skipped
|
// Due to a bug in go1.8 and before, directory reparse points need to be skipped
|
||||||
// during filepath.Walk. This is fixed in go1.9
|
// during filepath.Walk. This is fixed in go1.9
|
||||||
var shouldSkipDirectoryReparse = false
|
var shouldSkipDirectoryReparse = false
|
||||||
|
427
vendor/github.com/Microsoft/hcsshim/safeopen.go
generated
vendored
Normal file
427
vendor/github.com/Microsoft/hcsshim/safeopen.go
generated
vendored
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
package hcsshim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
|
)
|
||||||
|
|
||||||
|
//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 := makeLongAbsPath(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 := makeLongAbsPath(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
|
||||||
|
}
|
38
vendor/github.com/Microsoft/hcsshim/zhcsshim.go
generated
vendored
38
vendor/github.com/Microsoft/hcsshim/zhcsshim.go
generated
vendored
@ -41,6 +41,8 @@ var (
|
|||||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||||
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
||||||
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
|
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
|
||||||
|
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
|
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
|
||||||
@ -94,6 +96,11 @@ var (
|
|||||||
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
||||||
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
|
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
|
||||||
procHNSCall = modvmcompute.NewProc("HNSCall")
|
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||||
|
procNtCreateFile = modntdll.NewProc("NtCreateFile")
|
||||||
|
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile")
|
||||||
|
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||||
|
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||||
|
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||||
)
|
)
|
||||||
|
|
||||||
func coTaskMemFree(buffer unsafe.Pointer) {
|
func coTaskMemFree(buffer unsafe.Pointer) {
|
||||||
@ -1040,3 +1047,34 @@ func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16)
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user