Update cri and cgroup packages
This change includes a cri master bump and a cgroup bump for windows support with cgroup stats and reusing the cgroup metric types. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
1009023783
commit
8ff5827e98
@ -25,7 +25,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/containerd/cgroups"
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@ -77,7 +77,7 @@ var metricsCommand = cli.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data, ok := anydata.(*cgroups.Metrics)
|
data, ok := anydata.(*v1.Metrics)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("cannot convert metric data to cgroups.Metrics")
|
return errors.New("cannot convert metric data to cgroups.Metrics")
|
||||||
}
|
}
|
||||||
|
@ -18,27 +18,29 @@
|
|||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import "github.com/containerd/cgroups"
|
import (
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Metrics alias
|
// Metrics alias
|
||||||
Metrics = cgroups.Metrics
|
Metrics = v1.Metrics
|
||||||
// BlkIOEntry alias
|
// BlkIOEntry alias
|
||||||
BlkIOEntry = cgroups.BlkIOEntry
|
BlkIOEntry = v1.BlkIOEntry
|
||||||
// MemoryStat alias
|
// MemoryStat alias
|
||||||
MemoryStat = cgroups.MemoryStat
|
MemoryStat = v1.MemoryStat
|
||||||
// CPUStat alias
|
// CPUStat alias
|
||||||
CPUStat = cgroups.CPUStat
|
CPUStat = v1.CPUStat
|
||||||
// CPUUsage alias
|
// CPUUsage alias
|
||||||
CPUUsage = cgroups.CPUUsage
|
CPUUsage = v1.CPUUsage
|
||||||
// BlkIOStat alias
|
// BlkIOStat alias
|
||||||
BlkIOStat = cgroups.BlkIOStat
|
BlkIOStat = v1.BlkIOStat
|
||||||
// PidsStat alias
|
// PidsStat alias
|
||||||
PidsStat = cgroups.PidsStat
|
PidsStat = v1.PidsStat
|
||||||
// RdmaStat alias
|
// RdmaStat alias
|
||||||
RdmaStat = cgroups.RdmaStat
|
RdmaStat = v1.RdmaStat
|
||||||
// RdmaEntry alias
|
// RdmaEntry alias
|
||||||
RdmaEntry = cgroups.RdmaEntry
|
RdmaEntry = v1.RdmaEntry
|
||||||
// HugetlbStat alias
|
// HugetlbStat alias
|
||||||
HugetlbStat = cgroups.HugetlbStat
|
HugetlbStat = v1.HugetlbStat
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
||||||
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
||||||
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
|
github.com/containerd/cgroups abd0b19954a6b05e0963f48427062d1481b7faad
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
||||||
@ -51,8 +51,8 @@ github.com/cpuguy83/go-md2man v1.0.10
|
|||||||
github.com/russross/blackfriday v1.5.2
|
github.com/russross/blackfriday v1.5.2
|
||||||
|
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/containerd/cri 5d49e7e51b43e36a6b9c4386257c7d08c602237f # release/1.3
|
github.com/containerd/cri 0ebf032aac5f6029f95a94e42161e9db7a7e84df # release/1.3+
|
||||||
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
github.com/containerd/go-cni 0d360c50b10b350b6bb23863fd4dfb1c232b01c9
|
||||||
github.com/containernetworking/cni v0.7.1
|
github.com/containernetworking/cni v0.7.1
|
||||||
github.com/containernetworking/plugins v0.7.6
|
github.com/containernetworking/plugins v0.7.6
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
|
177
vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
generated
vendored
Normal file
177
vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
// Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server
|
||||||
|
// containers and Hyper-V containers. Previous to RS5, HCN was referred to as Host Networking Service (HNS).
|
||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run ../mksyscall_windows.go -output zsyscall_windows.go hcn.go
|
||||||
|
|
||||||
|
/// HNS V1 API
|
||||||
|
|
||||||
|
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
||||||
|
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
|
||||||
|
|
||||||
|
/// HCN V2 API
|
||||||
|
|
||||||
|
// Network
|
||||||
|
//sys hcnEnumerateNetworks(query string, networks **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateNetworks?
|
||||||
|
//sys hcnCreateNetwork(id *_guid, settings string, network *hcnNetwork, result **uint16) (hr error) = computenetwork.HcnCreateNetwork?
|
||||||
|
//sys hcnOpenNetwork(id *_guid, network *hcnNetwork, result **uint16) (hr error) = computenetwork.HcnOpenNetwork?
|
||||||
|
//sys hcnModifyNetwork(network hcnNetwork, settings string, result **uint16) (hr error) = computenetwork.HcnModifyNetwork?
|
||||||
|
//sys hcnQueryNetworkProperties(network hcnNetwork, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryNetworkProperties?
|
||||||
|
//sys hcnDeleteNetwork(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteNetwork?
|
||||||
|
//sys hcnCloseNetwork(network hcnNetwork) (hr error) = computenetwork.HcnCloseNetwork?
|
||||||
|
|
||||||
|
// Endpoint
|
||||||
|
//sys hcnEnumerateEndpoints(query string, endpoints **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateEndpoints?
|
||||||
|
//sys hcnCreateEndpoint(network hcnNetwork, id *_guid, settings string, endpoint *hcnEndpoint, result **uint16) (hr error) = computenetwork.HcnCreateEndpoint?
|
||||||
|
//sys hcnOpenEndpoint(id *_guid, endpoint *hcnEndpoint, result **uint16) (hr error) = computenetwork.HcnOpenEndpoint?
|
||||||
|
//sys hcnModifyEndpoint(endpoint hcnEndpoint, settings string, result **uint16) (hr error) = computenetwork.HcnModifyEndpoint?
|
||||||
|
//sys hcnQueryEndpointProperties(endpoint hcnEndpoint, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryEndpointProperties?
|
||||||
|
//sys hcnDeleteEndpoint(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteEndpoint?
|
||||||
|
//sys hcnCloseEndpoint(endpoint hcnEndpoint) (hr error) = computenetwork.HcnCloseEndpoint?
|
||||||
|
|
||||||
|
// Namespace
|
||||||
|
//sys hcnEnumerateNamespaces(query string, namespaces **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateNamespaces?
|
||||||
|
//sys hcnCreateNamespace(id *_guid, settings string, namespace *hcnNamespace, result **uint16) (hr error) = computenetwork.HcnCreateNamespace?
|
||||||
|
//sys hcnOpenNamespace(id *_guid, namespace *hcnNamespace, result **uint16) (hr error) = computenetwork.HcnOpenNamespace?
|
||||||
|
//sys hcnModifyNamespace(namespace hcnNamespace, settings string, result **uint16) (hr error) = computenetwork.HcnModifyNamespace?
|
||||||
|
//sys hcnQueryNamespaceProperties(namespace hcnNamespace, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryNamespaceProperties?
|
||||||
|
//sys hcnDeleteNamespace(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteNamespace?
|
||||||
|
//sys hcnCloseNamespace(namespace hcnNamespace) (hr error) = computenetwork.HcnCloseNamespace?
|
||||||
|
|
||||||
|
// LoadBalancer
|
||||||
|
//sys hcnEnumerateLoadBalancers(query string, loadBalancers **uint16, result **uint16) (hr error) = computenetwork.HcnEnumerateLoadBalancers?
|
||||||
|
//sys hcnCreateLoadBalancer(id *_guid, settings string, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) = computenetwork.HcnCreateLoadBalancer?
|
||||||
|
//sys hcnOpenLoadBalancer(id *_guid, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) = computenetwork.HcnOpenLoadBalancer?
|
||||||
|
//sys hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings string, result **uint16) (hr error) = computenetwork.HcnModifyLoadBalancer?
|
||||||
|
//sys hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query string, properties **uint16, result **uint16) (hr error) = computenetwork.HcnQueryLoadBalancerProperties?
|
||||||
|
//sys hcnDeleteLoadBalancer(id *_guid, result **uint16) (hr error) = computenetwork.HcnDeleteLoadBalancer?
|
||||||
|
//sys hcnCloseLoadBalancer(loadBalancer hcnLoadBalancer) (hr error) = computenetwork.HcnCloseLoadBalancer?
|
||||||
|
|
||||||
|
// Service
|
||||||
|
//sys hcnOpenService(service *hcnService, result **uint16) (hr error) = computenetwork.HcnOpenService?
|
||||||
|
//sys hcnRegisterServiceCallback(service hcnService, callback int32, context int32, callbackHandle *hcnCallbackHandle) (hr error) = computenetwork.HcnRegisterServiceCallback?
|
||||||
|
//sys hcnUnregisterServiceCallback(callbackHandle hcnCallbackHandle) (hr error) = computenetwork.HcnUnregisterServiceCallback?
|
||||||
|
//sys hcnCloseService(service hcnService) (hr error) = computenetwork.HcnCloseService?
|
||||||
|
|
||||||
|
type _guid = guid.GUID
|
||||||
|
|
||||||
|
type hcnNetwork syscall.Handle
|
||||||
|
type hcnEndpoint syscall.Handle
|
||||||
|
type hcnNamespace syscall.Handle
|
||||||
|
type hcnLoadBalancer syscall.Handle
|
||||||
|
type hcnService syscall.Handle
|
||||||
|
type hcnCallbackHandle syscall.Handle
|
||||||
|
|
||||||
|
// SchemaVersion for HCN Objects/Queries.
|
||||||
|
type SchemaVersion = Version // hcnglobals.go
|
||||||
|
|
||||||
|
// HostComputeQueryFlags are passed in to a HostComputeQuery to determine which
|
||||||
|
// properties of an object are returned.
|
||||||
|
type HostComputeQueryFlags uint32
|
||||||
|
|
||||||
|
var (
|
||||||
|
// HostComputeQueryFlagsNone returns an object with the standard properties.
|
||||||
|
HostComputeQueryFlagsNone HostComputeQueryFlags
|
||||||
|
// HostComputeQueryFlagsDetailed returns an object with all properties.
|
||||||
|
HostComputeQueryFlagsDetailed HostComputeQueryFlags = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// HostComputeQuery is the format for HCN queries.
|
||||||
|
type HostComputeQuery struct {
|
||||||
|
SchemaVersion SchemaVersion `json:""`
|
||||||
|
Flags HostComputeQueryFlags `json:",omitempty"`
|
||||||
|
Filter string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultQuery generates HCN Query.
|
||||||
|
// Passed into get/enumerate calls to filter results.
|
||||||
|
func defaultQuery() HostComputeQuery {
|
||||||
|
query := HostComputeQuery{
|
||||||
|
SchemaVersion: SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
Flags: HostComputeQueryFlagsNone,
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultQueryJson() string {
|
||||||
|
query := defaultQuery()
|
||||||
|
queryJson, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(queryJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlatformDoesNotSupportError happens when users are attempting to use a newer shim on an older OS
|
||||||
|
func platformDoesNotSupportError(featureName string) error {
|
||||||
|
return fmt.Errorf("Platform does not support feature %s", featureName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// V2ApiSupported returns an error if the HCN version does not support the V2 Apis.
|
||||||
|
func V2ApiSupported() error {
|
||||||
|
supported := GetSupportedFeatures()
|
||||||
|
if supported.Api.V2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return platformDoesNotSupportError("V2 Api/Schema")
|
||||||
|
}
|
||||||
|
|
||||||
|
func V2SchemaVersion() SchemaVersion {
|
||||||
|
return SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteSubnetSupported returns an error if the HCN version does not support Remote Subnet policies.
|
||||||
|
func RemoteSubnetSupported() error {
|
||||||
|
supported := GetSupportedFeatures()
|
||||||
|
if supported.RemoteSubnet {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return platformDoesNotSupportError("Remote Subnet")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostRouteSupported returns an error if the HCN version does not support Host Route policies.
|
||||||
|
func HostRouteSupported() error {
|
||||||
|
supported := GetSupportedFeatures()
|
||||||
|
if supported.HostRoute {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return platformDoesNotSupportError("Host Route")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DSRSupported returns an error if the HCN version does not support Direct Server Return.
|
||||||
|
func DSRSupported() error {
|
||||||
|
supported := GetSupportedFeatures()
|
||||||
|
if supported.DSR {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return platformDoesNotSupportError("Direct Server Return (DSR)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestType are the different operations performed to settings.
|
||||||
|
// Used to update the settings of Endpoint/Namespace objects.
|
||||||
|
type RequestType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// RequestTypeAdd adds the provided settings object.
|
||||||
|
RequestTypeAdd RequestType = "Add"
|
||||||
|
// RequestTypeRemove removes the provided settings object.
|
||||||
|
RequestTypeRemove RequestType = "Remove"
|
||||||
|
// RequestTypeUpdate replaces settings with the ones provided.
|
||||||
|
RequestTypeUpdate RequestType = "Update"
|
||||||
|
// RequestTypeRefresh refreshes the settings provided.
|
||||||
|
RequestTypeRefresh RequestType = "Refresh"
|
||||||
|
)
|
380
vendor/github.com/Microsoft/hcsshim/hcn/hcnendpoint.go
generated
vendored
Normal file
380
vendor/github.com/Microsoft/hcsshim/hcn/hcnendpoint.go
generated
vendored
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IpConfig is assoicated with an endpoint
|
||||||
|
type IpConfig struct {
|
||||||
|
IpAddress string `json:",omitempty"`
|
||||||
|
PrefixLength uint8 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointFlags are special settings on an endpoint.
|
||||||
|
type EndpointFlags uint32
|
||||||
|
|
||||||
|
var (
|
||||||
|
// EndpointFlagsNone is the default.
|
||||||
|
EndpointFlagsNone EndpointFlags
|
||||||
|
// EndpointFlagsRemoteEndpoint means that an endpoint is on another host.
|
||||||
|
EndpointFlagsRemoteEndpoint EndpointFlags = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// HostComputeEndpoint represents a network endpoint
|
||||||
|
type HostComputeEndpoint struct {
|
||||||
|
Id string `json:"ID,omitempty"`
|
||||||
|
Name string `json:",omitempty"`
|
||||||
|
HostComputeNetwork string `json:",omitempty"` // GUID
|
||||||
|
HostComputeNamespace string `json:",omitempty"` // GUID
|
||||||
|
Policies []EndpointPolicy `json:",omitempty"`
|
||||||
|
IpConfigurations []IpConfig `json:",omitempty"`
|
||||||
|
Dns Dns `json:",omitempty"`
|
||||||
|
Routes []Route `json:",omitempty"`
|
||||||
|
MacAddress string `json:",omitempty"`
|
||||||
|
Flags EndpointFlags `json:",omitempty"`
|
||||||
|
SchemaVersion SchemaVersion `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointResourceType are the two different Endpoint settings resources.
|
||||||
|
type EndpointResourceType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// EndpointResourceTypePolicy is for Endpoint Policies. Ex: ACL, NAT
|
||||||
|
EndpointResourceTypePolicy EndpointResourceType = "Policy"
|
||||||
|
// EndpointResourceTypePort is for Endpoint Port settings.
|
||||||
|
EndpointResourceTypePort EndpointResourceType = "Port"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModifyEndpointSettingRequest is the structure used to send request to modify an endpoint.
|
||||||
|
// Used to update policy/port on an endpoint.
|
||||||
|
type ModifyEndpointSettingRequest struct {
|
||||||
|
ResourceType EndpointResourceType `json:",omitempty"` // Policy, Port
|
||||||
|
RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PolicyEndpointRequest struct {
|
||||||
|
Policies []EndpointPolicy `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEndpoint(endpointGuid guid.GUID, query string) (*HostComputeEndpoint, error) {
|
||||||
|
// Open endpoint.
|
||||||
|
var (
|
||||||
|
endpointHandle hcnEndpoint
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenEndpoint(&endpointGuid, &endpointHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query endpoint.
|
||||||
|
hr = hcnQueryEndpointProperties(endpointHandle, query, &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close endpoint.
|
||||||
|
hr = hcnCloseEndpoint(endpointHandle)
|
||||||
|
if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeEndpoint
|
||||||
|
var outputEndpoint HostComputeEndpoint
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumerateEndpoints(query string) ([]HostComputeEndpoint, error) {
|
||||||
|
// Enumerate all Endpoint Guids
|
||||||
|
var (
|
||||||
|
resultBuffer *uint16
|
||||||
|
endpointBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnEnumerateEndpoints(query, &endpointBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnEnumerateEndpoints", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints := interop.ConvertAndFreeCoTaskMemString(endpointBuffer)
|
||||||
|
var endpointIds []guid.GUID
|
||||||
|
err := json.Unmarshal([]byte(endpoints), &endpointIds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputEndpoints []HostComputeEndpoint
|
||||||
|
for _, endpointGuid := range endpointIds {
|
||||||
|
endpoint, err := getEndpoint(endpointGuid, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputEndpoints = append(outputEndpoints, *endpoint)
|
||||||
|
}
|
||||||
|
return outputEndpoints, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createEndpoint(networkId string, endpointSettings string) (*HostComputeEndpoint, error) {
|
||||||
|
networkGuid, err := guid.FromString(networkId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidNetworkID
|
||||||
|
}
|
||||||
|
// Open network.
|
||||||
|
var networkHandle hcnNetwork
|
||||||
|
var resultBuffer *uint16
|
||||||
|
hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Create endpoint.
|
||||||
|
endpointId := guid.GUID{}
|
||||||
|
var endpointHandle hcnEndpoint
|
||||||
|
hr = hcnCreateEndpoint(networkHandle, &endpointId, endpointSettings, &endpointHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnCreateEndpoint", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query endpoint.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var propertiesBuffer *uint16
|
||||||
|
hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close endpoint.
|
||||||
|
hr = hcnCloseEndpoint(endpointHandle)
|
||||||
|
if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Close network.
|
||||||
|
hr = hcnCloseNetwork(networkHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeEndpoint
|
||||||
|
var outputEndpoint HostComputeEndpoint
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyEndpoint(endpointId string, settings string) (*HostComputeEndpoint, error) {
|
||||||
|
endpointGuid, err := guid.FromString(endpointId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidEndpointID
|
||||||
|
}
|
||||||
|
// Open endpoint
|
||||||
|
var (
|
||||||
|
endpointHandle hcnEndpoint
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenEndpoint(&endpointGuid, &endpointHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Modify endpoint
|
||||||
|
hr = hcnModifyEndpoint(endpointHandle, settings, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnModifyEndpoint", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query endpoint.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close endpoint.
|
||||||
|
hr = hcnCloseEndpoint(endpointHandle)
|
||||||
|
if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeEndpoint
|
||||||
|
var outputEndpoint HostComputeEndpoint
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteEndpoint(endpointId string) error {
|
||||||
|
endpointGuid, err := guid.FromString(endpointId)
|
||||||
|
if err != nil {
|
||||||
|
return errInvalidEndpointID
|
||||||
|
}
|
||||||
|
var resultBuffer *uint16
|
||||||
|
hr := hcnDeleteEndpoint(&endpointGuid, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnDeleteEndpoint", hr, resultBuffer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEndpoints makes a call to list all available endpoints.
|
||||||
|
func ListEndpoints() ([]HostComputeEndpoint, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
endpoints, err := ListEndpointsQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return endpoints, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEndpointsQuery makes a call to query the list of available endpoints.
|
||||||
|
func ListEndpointsQuery(query HostComputeQuery) ([]HostComputeEndpoint, error) {
|
||||||
|
queryJson, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := enumerateEndpoints(string(queryJson))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return endpoints, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEndpointsOfNetwork queries the list of endpoints on a network.
|
||||||
|
func ListEndpointsOfNetwork(networkId string) ([]HostComputeEndpoint, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
// TODO: Once query can convert schema, change to {HostComputeNetwork:networkId}
|
||||||
|
mapA := map[string]string{"VirtualNetwork": networkId}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
return ListEndpointsQuery(hcnQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEndpointByID returns an endpoint specified by Id
|
||||||
|
func GetEndpointByID(endpointId string) (*HostComputeEndpoint, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
mapA := map[string]string{"ID": endpointId}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
endpoints, err := ListEndpointsQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(endpoints) == 0 {
|
||||||
|
return nil, EndpointNotFoundError{EndpointID: endpointId}
|
||||||
|
}
|
||||||
|
return &endpoints[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEndpointByName returns an endpoint specified by Name
|
||||||
|
func GetEndpointByName(endpointName string) (*HostComputeEndpoint, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
mapA := map[string]string{"Name": endpointName}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
endpoints, err := ListEndpointsQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(endpoints) == 0 {
|
||||||
|
return nil, EndpointNotFoundError{EndpointName: endpointName}
|
||||||
|
}
|
||||||
|
return &endpoints[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Endpoint.
|
||||||
|
func (endpoint *HostComputeEndpoint) Create() (*HostComputeEndpoint, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::Create id=%s", endpoint.Id)
|
||||||
|
|
||||||
|
if endpoint.HostComputeNamespace != "" {
|
||||||
|
return nil, errors.New("endpoint create error, endpoint json HostComputeNamespace is read only and should not be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonString, err := json.Marshal(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::Create JSON: %s", jsonString)
|
||||||
|
endpoint, hcnErr := createEndpoint(endpoint.HostComputeNetwork, string(jsonString))
|
||||||
|
if hcnErr != nil {
|
||||||
|
return nil, hcnErr
|
||||||
|
}
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Endpoint.
|
||||||
|
func (endpoint *HostComputeEndpoint) Delete() error {
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::Delete id=%s", endpoint.Id)
|
||||||
|
|
||||||
|
if err := deleteEndpoint(endpoint.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyEndpointSettings updates the Port/Policy of an Endpoint.
|
||||||
|
func ModifyEndpointSettings(endpointId string, request *ModifyEndpointSettingRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::ModifyEndpointSettings id=%s", endpointId)
|
||||||
|
|
||||||
|
endpointSettingsRequest, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = modifyEndpoint(endpointId, string(endpointSettingsRequest))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyPolicy applies a Policy (ex: ACL) on the Endpoint.
|
||||||
|
func (endpoint *HostComputeEndpoint) ApplyPolicy(requestType RequestType, endpointPolicy PolicyEndpointRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::ApplyPolicy id=%s", endpoint.Id)
|
||||||
|
|
||||||
|
settingsJson, err := json.Marshal(endpointPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestMessage := &ModifyEndpointSettingRequest{
|
||||||
|
ResourceType: EndpointResourceTypePolicy,
|
||||||
|
RequestType: requestType,
|
||||||
|
Settings: settingsJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModifyEndpointSettings(endpoint.Id, requestMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceAttach modifies a Namespace to add an endpoint.
|
||||||
|
func (endpoint *HostComputeEndpoint) NamespaceAttach(namespaceId string) error {
|
||||||
|
return AddNamespaceEndpoint(namespaceId, endpoint.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceDetach modifies a Namespace to remove an endpoint.
|
||||||
|
func (endpoint *HostComputeEndpoint) NamespaceDetach(namespaceId string) error {
|
||||||
|
return RemoveNamespaceEndpoint(namespaceId, endpoint.Id)
|
||||||
|
}
|
103
vendor/github.com/Microsoft/hcsshim/hcn/hcnerrors.go
generated
vendored
Normal file
103
vendor/github.com/Microsoft/hcsshim/hcn/hcnerrors.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server
|
||||||
|
// containers and Hyper-V containers. Previous to RS5, HCN was referred to as Host Networking Service (HNS).
|
||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidNetworkID = errors.New("invalid network ID")
|
||||||
|
errInvalidEndpointID = errors.New("invalid endpoint ID")
|
||||||
|
errInvalidNamespaceID = errors.New("invalid namespace ID")
|
||||||
|
errInvalidLoadBalancerID = errors.New("invalid load balancer ID")
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkForErrors(methodName string, hr error, resultBuffer *uint16) error {
|
||||||
|
errorFound := false
|
||||||
|
|
||||||
|
if hr != nil {
|
||||||
|
errorFound = true
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ""
|
||||||
|
if resultBuffer != nil {
|
||||||
|
result = interop.ConvertAndFreeCoTaskMemString(resultBuffer)
|
||||||
|
if result != "" {
|
||||||
|
errorFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errorFound {
|
||||||
|
returnError := hcserror.New(hr, methodName, result)
|
||||||
|
logrus.Debugf(returnError.Error()) // HCN errors logged for debugging.
|
||||||
|
return returnError
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkNotFoundError results from a failed seach for a network by Id or Name
|
||||||
|
type NetworkNotFoundError struct {
|
||||||
|
NetworkName string
|
||||||
|
NetworkID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e NetworkNotFoundError) Error() string {
|
||||||
|
if e.NetworkName == "" {
|
||||||
|
return fmt.Sprintf("Network Name %s not found", e.NetworkName)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Network Id %s not found", e.NetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointNotFoundError results from a failed seach for an endpoint by Id or Name
|
||||||
|
type EndpointNotFoundError struct {
|
||||||
|
EndpointName string
|
||||||
|
EndpointID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EndpointNotFoundError) Error() string {
|
||||||
|
if e.EndpointName == "" {
|
||||||
|
return fmt.Sprintf("Endpoint Name %s not found", e.EndpointName)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Endpoint Id %s not found", e.EndpointID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceNotFoundError results from a failed seach for a namsepace by Id
|
||||||
|
type NamespaceNotFoundError struct {
|
||||||
|
NamespaceID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e NamespaceNotFoundError) Error() string {
|
||||||
|
return fmt.Sprintf("Namespace %s not found", e.NamespaceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerNotFoundError results from a failed seach for a loadbalancer by Id
|
||||||
|
type LoadBalancerNotFoundError struct {
|
||||||
|
LoadBalancerId string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e LoadBalancerNotFoundError) Error() string {
|
||||||
|
return fmt.Sprintf("LoadBalancer %s not found", e.LoadBalancerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotFoundError returns a boolean indicating whether the error was caused by
|
||||||
|
// a resource not being found.
|
||||||
|
func IsNotFoundError(err error) bool {
|
||||||
|
switch err.(type) {
|
||||||
|
case NetworkNotFoundError:
|
||||||
|
return true
|
||||||
|
case EndpointNotFoundError:
|
||||||
|
return true
|
||||||
|
case NamespaceNotFoundError:
|
||||||
|
return true
|
||||||
|
case LoadBalancerNotFoundError:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
87
vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
generated
vendored
Normal file
87
vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim/internal/hcserror"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Globals are all global properties of the HCN Service.
|
||||||
|
type Globals struct {
|
||||||
|
Version Version `json:"Version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version is the HCN Service version.
|
||||||
|
type Version struct {
|
||||||
|
Major int `json:"Major"`
|
||||||
|
Minor int `json:"Minor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// HNSVersion1803 added ACL functionality.
|
||||||
|
HNSVersion1803 = Version{Major: 7, Minor: 2}
|
||||||
|
// V2ApiSupport allows the use of V2 Api calls and V2 Schema.
|
||||||
|
V2ApiSupport = Version{Major: 9, Minor: 2}
|
||||||
|
// Remote Subnet allows for Remote Subnet policies on Overlay networks
|
||||||
|
RemoteSubnetVersion = Version{Major: 9, Minor: 2}
|
||||||
|
// A Host Route policy allows for local container to local host communication Overlay networks
|
||||||
|
HostRouteVersion = Version{Major: 9, Minor: 2}
|
||||||
|
// HNS 10.2 allows for Direct Server Return for loadbalancing
|
||||||
|
DSRVersion = Version{Major: 10, Minor: 2}
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetGlobals returns the global properties of the HCN Service.
|
||||||
|
func GetGlobals() (*Globals, error) {
|
||||||
|
var version Version
|
||||||
|
err := hnsCall("GET", "/globals/version", "", &version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
globals := &Globals{
|
||||||
|
Version: version,
|
||||||
|
}
|
||||||
|
|
||||||
|
return globals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type hnsResponse struct {
|
||||||
|
Success bool
|
||||||
|
Error string
|
||||||
|
Output json.RawMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func hnsCall(method, path, request string, returnResponse interface{}) error {
|
||||||
|
var responseBuffer *uint16
|
||||||
|
logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request)
|
||||||
|
|
||||||
|
err := _hnsCall(method, path, request, &responseBuffer)
|
||||||
|
if err != nil {
|
||||||
|
return hcserror.New(err, "hnsCall ", "")
|
||||||
|
}
|
||||||
|
response := interop.ConvertAndFreeCoTaskMemString(responseBuffer)
|
||||||
|
|
||||||
|
hnsresponse := &hnsResponse{}
|
||||||
|
if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hnsresponse.Success {
|
||||||
|
return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hnsresponse.Output) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("Network Response : %s", hnsresponse.Output)
|
||||||
|
err = json.Unmarshal(hnsresponse.Output, returnResponse)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
341
vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
generated
vendored
Normal file
341
vendor/github.com/Microsoft/hcsshim/hcn/hcnloadbalancer.go
generated
vendored
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadBalancerPortMapping is associated with HostComputeLoadBalancer
|
||||||
|
type LoadBalancerPortMapping struct {
|
||||||
|
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
|
||||||
|
InternalPort uint16 `json:",omitempty"`
|
||||||
|
ExternalPort uint16 `json:",omitempty"`
|
||||||
|
Flags LoadBalancerPortMappingFlags `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostComputeLoadBalancer represents software load balancer.
|
||||||
|
type HostComputeLoadBalancer struct {
|
||||||
|
Id string `json:"ID,omitempty"`
|
||||||
|
HostComputeEndpoints []string `json:",omitempty"`
|
||||||
|
SourceVIP string `json:",omitempty"`
|
||||||
|
FrontendVIPs []string `json:",omitempty"`
|
||||||
|
PortMappings []LoadBalancerPortMapping `json:",omitempty"`
|
||||||
|
SchemaVersion SchemaVersion `json:",omitempty"`
|
||||||
|
Flags LoadBalancerFlags `json:",omitempty"` // 0: None, 1: EnableDirectServerReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
//LoadBalancerFlags modify settings for a loadbalancer.
|
||||||
|
type LoadBalancerFlags uint32
|
||||||
|
|
||||||
|
var (
|
||||||
|
// LoadBalancerFlagsNone is the default.
|
||||||
|
LoadBalancerFlagsNone LoadBalancerFlags = 0
|
||||||
|
// LoadBalancerFlagsDSR enables Direct Server Return (DSR)
|
||||||
|
LoadBalancerFlagsDSR LoadBalancerFlags = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadBalancerPortMappingFlags are special settings on a loadbalancer.
|
||||||
|
type LoadBalancerPortMappingFlags uint32
|
||||||
|
|
||||||
|
var (
|
||||||
|
// LoadBalancerPortMappingFlagsNone is the default.
|
||||||
|
LoadBalancerPortMappingFlagsNone LoadBalancerPortMappingFlags
|
||||||
|
// LoadBalancerPortMappingFlagsILB enables internal loadbalancing.
|
||||||
|
LoadBalancerPortMappingFlagsILB LoadBalancerPortMappingFlags = 1
|
||||||
|
// LoadBalancerPortMappingFlagsLocalRoutedVIP enables VIP access from the host.
|
||||||
|
LoadBalancerPortMappingFlagsLocalRoutedVIP LoadBalancerPortMappingFlags = 2
|
||||||
|
// LoadBalancerPortMappingFlagsUseMux enables DSR for NodePort access of VIP.
|
||||||
|
LoadBalancerPortMappingFlagsUseMux LoadBalancerPortMappingFlags = 4
|
||||||
|
// LoadBalancerPortMappingFlagsPreserveDIP delivers packets with destination IP as the VIP.
|
||||||
|
LoadBalancerPortMappingFlagsPreserveDIP LoadBalancerPortMappingFlags = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
func getLoadBalancer(loadBalancerGuid guid.GUID, query string) (*HostComputeLoadBalancer, error) {
|
||||||
|
// Open loadBalancer.
|
||||||
|
var (
|
||||||
|
loadBalancerHandle hcnLoadBalancer
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenLoadBalancer(&loadBalancerGuid, &loadBalancerHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenLoadBalancer", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query loadBalancer.
|
||||||
|
hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, query, &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close loadBalancer.
|
||||||
|
hr = hcnCloseLoadBalancer(loadBalancerHandle)
|
||||||
|
if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeLoadBalancer
|
||||||
|
var outputLoadBalancer HostComputeLoadBalancer
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputLoadBalancer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumerateLoadBalancers(query string) ([]HostComputeLoadBalancer, error) {
|
||||||
|
// Enumerate all LoadBalancer Guids
|
||||||
|
var (
|
||||||
|
resultBuffer *uint16
|
||||||
|
loadBalancerBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnEnumerateLoadBalancers(query, &loadBalancerBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnEnumerateLoadBalancers", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBalancers := interop.ConvertAndFreeCoTaskMemString(loadBalancerBuffer)
|
||||||
|
var loadBalancerIds []guid.GUID
|
||||||
|
if err := json.Unmarshal([]byte(loadBalancers), &loadBalancerIds); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputLoadBalancers []HostComputeLoadBalancer
|
||||||
|
for _, loadBalancerGuid := range loadBalancerIds {
|
||||||
|
loadBalancer, err := getLoadBalancer(loadBalancerGuid, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputLoadBalancers = append(outputLoadBalancers, *loadBalancer)
|
||||||
|
}
|
||||||
|
return outputLoadBalancers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createLoadBalancer(settings string) (*HostComputeLoadBalancer, error) {
|
||||||
|
// Create new loadBalancer.
|
||||||
|
var (
|
||||||
|
loadBalancerHandle hcnLoadBalancer
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
loadBalancerGuid := guid.GUID{}
|
||||||
|
hr := hcnCreateLoadBalancer(&loadBalancerGuid, settings, &loadBalancerHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnCreateLoadBalancer", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query loadBalancer.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close loadBalancer.
|
||||||
|
hr = hcnCloseLoadBalancer(loadBalancerHandle)
|
||||||
|
if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeLoadBalancer
|
||||||
|
var outputLoadBalancer HostComputeLoadBalancer
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputLoadBalancer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyLoadBalancer(loadBalancerId string, settings string) (*HostComputeLoadBalancer, error) {
|
||||||
|
loadBalancerGuid, err := guid.FromString(loadBalancerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidLoadBalancerID
|
||||||
|
}
|
||||||
|
// Open loadBalancer.
|
||||||
|
var (
|
||||||
|
loadBalancerHandle hcnLoadBalancer
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenLoadBalancer(&loadBalancerGuid, &loadBalancerHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenLoadBalancer", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Modify loadBalancer.
|
||||||
|
hr = hcnModifyLoadBalancer(loadBalancerHandle, settings, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnModifyLoadBalancer", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query loadBalancer.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close loadBalancer.
|
||||||
|
hr = hcnCloseLoadBalancer(loadBalancerHandle)
|
||||||
|
if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to LoadBalancer
|
||||||
|
var outputLoadBalancer HostComputeLoadBalancer
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputLoadBalancer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteLoadBalancer(loadBalancerId string) error {
|
||||||
|
loadBalancerGuid, err := guid.FromString(loadBalancerId)
|
||||||
|
if err != nil {
|
||||||
|
return errInvalidLoadBalancerID
|
||||||
|
}
|
||||||
|
var resultBuffer *uint16
|
||||||
|
hr := hcnDeleteLoadBalancer(&loadBalancerGuid, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnDeleteLoadBalancer", hr, resultBuffer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLoadBalancers makes a call to list all available loadBalancers.
|
||||||
|
func ListLoadBalancers() ([]HostComputeLoadBalancer, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
loadBalancers, err := ListLoadBalancersQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return loadBalancers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLoadBalancersQuery makes a call to query the list of available loadBalancers.
|
||||||
|
func ListLoadBalancersQuery(query HostComputeQuery) ([]HostComputeLoadBalancer, error) {
|
||||||
|
queryJson, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBalancers, err := enumerateLoadBalancers(string(queryJson))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return loadBalancers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLoadBalancerByID returns the LoadBalancer specified by Id.
|
||||||
|
func GetLoadBalancerByID(loadBalancerId string) (*HostComputeLoadBalancer, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
mapA := map[string]string{"ID": loadBalancerId}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
loadBalancers, err := ListLoadBalancersQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(loadBalancers) == 0 {
|
||||||
|
return nil, LoadBalancerNotFoundError{LoadBalancerId: loadBalancerId}
|
||||||
|
}
|
||||||
|
return &loadBalancers[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create LoadBalancer.
|
||||||
|
func (loadBalancer *HostComputeLoadBalancer) Create() (*HostComputeLoadBalancer, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::Create id=%s", loadBalancer.Id)
|
||||||
|
|
||||||
|
jsonString, err := json.Marshal(loadBalancer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::Create JSON: %s", jsonString)
|
||||||
|
loadBalancer, hcnErr := createLoadBalancer(string(jsonString))
|
||||||
|
if hcnErr != nil {
|
||||||
|
return nil, hcnErr
|
||||||
|
}
|
||||||
|
return loadBalancer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete LoadBalancer.
|
||||||
|
func (loadBalancer *HostComputeLoadBalancer) Delete() error {
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::Delete id=%s", loadBalancer.Id)
|
||||||
|
|
||||||
|
if err := deleteLoadBalancer(loadBalancer.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEndpoint add an endpoint to a LoadBalancer
|
||||||
|
func (loadBalancer *HostComputeLoadBalancer) AddEndpoint(endpoint *HostComputeEndpoint) (*HostComputeLoadBalancer, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::AddEndpoint loadBalancer=%s endpoint=%s", loadBalancer.Id, endpoint.Id)
|
||||||
|
|
||||||
|
err := loadBalancer.Delete()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Endpoint to the Existing List
|
||||||
|
loadBalancer.HostComputeEndpoints = append(loadBalancer.HostComputeEndpoints, endpoint.Id)
|
||||||
|
|
||||||
|
return loadBalancer.Create()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEndpoint removes an endpoint from a LoadBalancer
|
||||||
|
func (loadBalancer *HostComputeLoadBalancer) RemoveEndpoint(endpoint *HostComputeEndpoint) (*HostComputeLoadBalancer, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::RemoveEndpoint loadBalancer=%s endpoint=%s", loadBalancer.Id, endpoint.Id)
|
||||||
|
|
||||||
|
err := loadBalancer.Delete()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a list of all the endpoints besides the one being removed
|
||||||
|
var endpoints []string
|
||||||
|
for _, endpointReference := range loadBalancer.HostComputeEndpoints {
|
||||||
|
if endpointReference == endpoint.Id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
endpoints = append(endpoints, endpointReference)
|
||||||
|
}
|
||||||
|
loadBalancer.HostComputeEndpoints = endpoints
|
||||||
|
return loadBalancer.Create()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLoadBalancer for the specified endpoints
|
||||||
|
func AddLoadBalancer(endpoints []HostComputeEndpoint, flags LoadBalancerFlags, portMappingFlags LoadBalancerPortMappingFlags, sourceVIP string, frontendVIPs []string, protocol uint16, internalPort uint16, externalPort uint16) (*HostComputeLoadBalancer, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeLoadBalancer::AddLoadBalancer endpointId=%v, LoadBalancerFlags=%v, LoadBalancerPortMappingFlags=%v, sourceVIP=%s, frontendVIPs=%v, protocol=%v, internalPort=%v, externalPort=%v", endpoints, flags, portMappingFlags, sourceVIP, frontendVIPs, protocol, internalPort, externalPort)
|
||||||
|
|
||||||
|
loadBalancer := &HostComputeLoadBalancer{
|
||||||
|
SourceVIP: sourceVIP,
|
||||||
|
PortMappings: []LoadBalancerPortMapping{
|
||||||
|
{
|
||||||
|
Protocol: uint32(protocol),
|
||||||
|
InternalPort: internalPort,
|
||||||
|
ExternalPort: externalPort,
|
||||||
|
Flags: portMappingFlags,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FrontendVIPs: frontendVIPs,
|
||||||
|
SchemaVersion: SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
Flags: flags,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
loadBalancer.HostComputeEndpoints = append(loadBalancer.HostComputeEndpoints, endpoint.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadBalancer.Create()
|
||||||
|
}
|
434
vendor/github.com/Microsoft/hcsshim/hcn/hcnnamespace.go
generated
vendored
Normal file
434
vendor/github.com/Microsoft/hcsshim/hcn/hcnnamespace.go
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
icni "github.com/Microsoft/hcsshim/internal/cni"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/regstate"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/runhcs"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NamespaceResourceEndpoint represents an Endpoint attached to a Namespace.
|
||||||
|
type NamespaceResourceEndpoint struct {
|
||||||
|
Id string `json:"ID,"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceResourceContainer represents a Container attached to a Namespace.
|
||||||
|
type NamespaceResourceContainer struct {
|
||||||
|
Id string `json:"ID,"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceResourceType determines whether the Namespace resource is a Container or Endpoint.
|
||||||
|
type NamespaceResourceType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NamespaceResourceTypeContainer are contianers associated with a Namespace.
|
||||||
|
NamespaceResourceTypeContainer NamespaceResourceType = "Container"
|
||||||
|
// NamespaceResourceTypeEndpoint are endpoints associated with a Namespace.
|
||||||
|
NamespaceResourceTypeEndpoint NamespaceResourceType = "Endpoint"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NamespaceResource is associated with a namespace
|
||||||
|
type NamespaceResource struct {
|
||||||
|
Type NamespaceResourceType `json:","` // Container, Endpoint
|
||||||
|
Data json.RawMessage `json:","`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamespaceType determines whether the Namespace is for a Host or Guest
|
||||||
|
type NamespaceType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NamespaceTypeHost are host namespaces.
|
||||||
|
NamespaceTypeHost NamespaceType = "Host"
|
||||||
|
// NamespaceTypeHostDefault are host namespaces in the default compartment.
|
||||||
|
NamespaceTypeHostDefault NamespaceType = "HostDefault"
|
||||||
|
// NamespaceTypeGuest are guest namespaces.
|
||||||
|
NamespaceTypeGuest NamespaceType = "Guest"
|
||||||
|
// NamespaceTypeGuestDefault are guest namespaces in the default compartment.
|
||||||
|
NamespaceTypeGuestDefault NamespaceType = "GuestDefault"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HostComputeNamespace represents a namespace (AKA compartment) in
|
||||||
|
type HostComputeNamespace struct {
|
||||||
|
Id string `json:"ID,omitempty"`
|
||||||
|
NamespaceId uint32 `json:",omitempty"`
|
||||||
|
Type NamespaceType `json:",omitempty"` // Host, HostDefault, Guest, GuestDefault
|
||||||
|
Resources []NamespaceResource `json:",omitempty"`
|
||||||
|
SchemaVersion SchemaVersion `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyNamespaceSettingRequest is the structure used to send request to modify a namespace.
|
||||||
|
// Used to Add/Remove an endpoints and containers to/from a namespace.
|
||||||
|
type ModifyNamespaceSettingRequest struct {
|
||||||
|
ResourceType NamespaceResourceType `json:",omitempty"` // Container, Endpoint
|
||||||
|
RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespace(namespaceGuid guid.GUID, query string) (*HostComputeNamespace, error) {
|
||||||
|
// Open namespace.
|
||||||
|
var (
|
||||||
|
namespaceHandle hcnNamespace
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenNamespace(&namespaceGuid, &namespaceHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenNamespace", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query namespace.
|
||||||
|
hr = hcnQueryNamespaceProperties(namespaceHandle, query, &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close namespace.
|
||||||
|
hr = hcnCloseNamespace(namespaceHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeNamespace
|
||||||
|
var outputNamespace HostComputeNamespace
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNamespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumerateNamespaces(query string) ([]HostComputeNamespace, error) {
|
||||||
|
// Enumerate all Namespace Guids
|
||||||
|
var (
|
||||||
|
resultBuffer *uint16
|
||||||
|
namespaceBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnEnumerateNamespaces(query, &namespaceBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnEnumerateNamespaces", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces := interop.ConvertAndFreeCoTaskMemString(namespaceBuffer)
|
||||||
|
var namespaceIds []guid.GUID
|
||||||
|
if err := json.Unmarshal([]byte(namespaces), &namespaceIds); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputNamespaces []HostComputeNamespace
|
||||||
|
for _, namespaceGuid := range namespaceIds {
|
||||||
|
namespace, err := getNamespace(namespaceGuid, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputNamespaces = append(outputNamespaces, *namespace)
|
||||||
|
}
|
||||||
|
return outputNamespaces, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNamespace(settings string) (*HostComputeNamespace, error) {
|
||||||
|
// Create new namespace.
|
||||||
|
var (
|
||||||
|
namespaceHandle hcnNamespace
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
namespaceGuid := guid.GUID{}
|
||||||
|
hr := hcnCreateNamespace(&namespaceGuid, settings, &namespaceHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnCreateNamespace", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query namespace.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryNamespaceProperties(namespaceHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close namespace.
|
||||||
|
hr = hcnCloseNamespace(namespaceHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeNamespace
|
||||||
|
var outputNamespace HostComputeNamespace
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNamespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyNamespace(namespaceId string, settings string) (*HostComputeNamespace, error) {
|
||||||
|
namespaceGuid, err := guid.FromString(namespaceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidNamespaceID
|
||||||
|
}
|
||||||
|
// Open namespace.
|
||||||
|
var (
|
||||||
|
namespaceHandle hcnNamespace
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenNamespace(&namespaceGuid, &namespaceHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenNamespace", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Modify namespace.
|
||||||
|
hr = hcnModifyNamespace(namespaceHandle, settings, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnModifyNamespace", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query namespace.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryNamespaceProperties(namespaceHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNamespaceProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close namespace.
|
||||||
|
hr = hcnCloseNamespace(namespaceHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNamespace", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to Namespace
|
||||||
|
var outputNamespace HostComputeNamespace
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNamespace); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNamespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteNamespace(namespaceId string) error {
|
||||||
|
namespaceGuid, err := guid.FromString(namespaceId)
|
||||||
|
if err != nil {
|
||||||
|
return errInvalidNamespaceID
|
||||||
|
}
|
||||||
|
var resultBuffer *uint16
|
||||||
|
hr := hcnDeleteNamespace(&namespaceGuid, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnDeleteNamespace", hr, resultBuffer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNamespaces makes a call to list all available namespaces.
|
||||||
|
func ListNamespaces() ([]HostComputeNamespace, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
namespaces, err := ListNamespacesQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namespaces, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNamespacesQuery makes a call to query the list of available namespaces.
|
||||||
|
func ListNamespacesQuery(query HostComputeQuery) ([]HostComputeNamespace, error) {
|
||||||
|
queryJson, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces, err := enumerateNamespaces(string(queryJson))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namespaces, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNamespaceByID returns the Namespace specified by Id.
|
||||||
|
func GetNamespaceByID(namespaceId string) (*HostComputeNamespace, error) {
|
||||||
|
g, err := guid.FromString(namespaceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidNamespaceID
|
||||||
|
}
|
||||||
|
return getNamespace(g, defaultQueryJson())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNamespaceEndpointIds returns the endpoints of the Namespace specified by Id.
|
||||||
|
func GetNamespaceEndpointIds(namespaceId string) ([]string, error) {
|
||||||
|
namespace, err := GetNamespaceByID(namespaceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var endpointsIds []string
|
||||||
|
for _, resource := range namespace.Resources {
|
||||||
|
if resource.Type == "Endpoint" {
|
||||||
|
var endpointResource NamespaceResourceEndpoint
|
||||||
|
if err := json.Unmarshal([]byte(resource.Data), &endpointResource); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
endpointsIds = append(endpointsIds, endpointResource.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endpointsIds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNamespaceContainerIds returns the containers of the Namespace specified by Id.
|
||||||
|
func GetNamespaceContainerIds(namespaceId string) ([]string, error) {
|
||||||
|
namespace, err := GetNamespaceByID(namespaceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var containerIds []string
|
||||||
|
for _, resource := range namespace.Resources {
|
||||||
|
if resource.Type == "Container" {
|
||||||
|
var contaienrResource NamespaceResourceContainer
|
||||||
|
if err := json.Unmarshal([]byte(resource.Data), &contaienrResource); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
containerIds = append(containerIds, contaienrResource.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return containerIds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNamespace creates a new Namespace object
|
||||||
|
func NewNamespace(nsType NamespaceType) *HostComputeNamespace {
|
||||||
|
return &HostComputeNamespace{
|
||||||
|
Type: nsType,
|
||||||
|
SchemaVersion: V2SchemaVersion(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Namespace.
|
||||||
|
func (namespace *HostComputeNamespace) Create() (*HostComputeNamespace, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeNamespace::Create id=%s", namespace.Id)
|
||||||
|
|
||||||
|
jsonString, err := json.Marshal(namespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("hcn::HostComputeNamespace::Create JSON: %s", jsonString)
|
||||||
|
namespace, hcnErr := createNamespace(string(jsonString))
|
||||||
|
if hcnErr != nil {
|
||||||
|
return nil, hcnErr
|
||||||
|
}
|
||||||
|
return namespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Namespace.
|
||||||
|
func (namespace *HostComputeNamespace) Delete() error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNamespace::Delete id=%s", namespace.Id)
|
||||||
|
|
||||||
|
if err := deleteNamespace(namespace.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync Namespace endpoints with the appropriate sandbox container holding the
|
||||||
|
// network namespace open. If no sandbox container is found for this namespace
|
||||||
|
// this method is determined to be a success and will not return an error in
|
||||||
|
// this case. If the sandbox container is found and a sync is initiated any
|
||||||
|
// failures will be returned via this method.
|
||||||
|
//
|
||||||
|
// This call initiates a sync between endpoints and the matching UtilityVM
|
||||||
|
// hosting those endpoints. It is safe to call for any `NamespaceType` but
|
||||||
|
// `NamespaceTypeGuest` is the only case when a sync will actually occur. For
|
||||||
|
// `NamespaceTypeHost` the process container will be automatically synchronized
|
||||||
|
// when the the endpoint is added via `AddNamespaceEndpoint`.
|
||||||
|
//
|
||||||
|
// Note: This method sync's both additions and removals of endpoints from a
|
||||||
|
// `NamespaceTypeGuest` namespace.
|
||||||
|
func (namespace *HostComputeNamespace) Sync() error {
|
||||||
|
logrus.WithField("id", namespace.Id).Debugf("hcs::HostComputeNamespace::Sync")
|
||||||
|
|
||||||
|
// We only attempt a sync for namespace guest.
|
||||||
|
if namespace.Type != NamespaceTypeGuest {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look in the registry for the key to map from namespace id to pod-id
|
||||||
|
cfg, err := icni.LoadPersistedNamespaceConfig(namespace.Id)
|
||||||
|
if err != nil {
|
||||||
|
if regstate.IsNotFoundError(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req := runhcs.VMRequest{
|
||||||
|
ID: cfg.ContainerID,
|
||||||
|
Op: runhcs.OpSyncNamespace,
|
||||||
|
}
|
||||||
|
shimPath := runhcs.VMPipePath(cfg.HostUniqueID)
|
||||||
|
if err := runhcs.IssueVMRequest(shimPath, &req); err != nil {
|
||||||
|
// The shim is likey gone. Simply ignore the sync as if it didn't exist.
|
||||||
|
if perr, ok := err.(*os.PathError); ok && perr.Err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
// Remove the reg key there is no point to try again
|
||||||
|
cfg.Remove()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
f := map[string]interface{}{
|
||||||
|
"id": namespace.Id,
|
||||||
|
"container-id": cfg.ContainerID,
|
||||||
|
}
|
||||||
|
logrus.WithFields(f).
|
||||||
|
WithError(err).
|
||||||
|
Debugf("hcs::HostComputeNamespace::Sync failed to connect to shim pipe: '%s'", shimPath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyNamespaceSettings updates the Endpoints/Containers of a Namespace.
|
||||||
|
func ModifyNamespaceSettings(namespaceId string, request *ModifyNamespaceSettingRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNamespace::ModifyNamespaceSettings id=%s", namespaceId)
|
||||||
|
|
||||||
|
namespaceSettings, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = modifyNamespace(namespaceId, string(namespaceSettings))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNamespaceEndpoint adds an endpoint to a Namespace.
|
||||||
|
func AddNamespaceEndpoint(namespaceId string, endpointId string) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeEndpoint::AddNamespaceEndpoint id=%s", endpointId)
|
||||||
|
|
||||||
|
mapA := map[string]string{"EndpointId": endpointId}
|
||||||
|
settingsJson, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestMessage := &ModifyNamespaceSettingRequest{
|
||||||
|
ResourceType: NamespaceResourceTypeEndpoint,
|
||||||
|
RequestType: RequestTypeAdd,
|
||||||
|
Settings: settingsJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModifyNamespaceSettings(namespaceId, requestMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveNamespaceEndpoint removes an endpoint from a Namespace.
|
||||||
|
func RemoveNamespaceEndpoint(namespaceId string, endpointId string) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNamespace::RemoveNamespaceEndpoint id=%s", endpointId)
|
||||||
|
|
||||||
|
mapA := map[string]string{"EndpointId": endpointId}
|
||||||
|
settingsJson, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestMessage := &ModifyNamespaceSettingRequest{
|
||||||
|
ResourceType: NamespaceResourceTypeEndpoint,
|
||||||
|
RequestType: RequestTypeRemove,
|
||||||
|
Settings: settingsJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModifyNamespaceSettings(namespaceId, requestMessage)
|
||||||
|
}
|
461
vendor/github.com/Microsoft/hcsshim/hcn/hcnnetwork.go
generated
vendored
Normal file
461
vendor/github.com/Microsoft/hcsshim/hcn/hcnnetwork.go
generated
vendored
Normal file
@ -0,0 +1,461 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/interop"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Route is assoicated with a subnet.
|
||||||
|
type Route struct {
|
||||||
|
NextHop string `json:",omitempty"`
|
||||||
|
DestinationPrefix string `json:",omitempty"`
|
||||||
|
Metric uint16 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subnet is assoicated with a Ipam.
|
||||||
|
type Subnet struct {
|
||||||
|
IpAddressPrefix string `json:",omitempty"`
|
||||||
|
Policies []json.RawMessage `json:",omitempty"`
|
||||||
|
Routes []Route `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ipam (Internet Protocol Addres Management) is assoicated with a network
|
||||||
|
// and represents the address space(s) of a network.
|
||||||
|
type Ipam struct {
|
||||||
|
Type string `json:",omitempty"` // Ex: Static, DHCP
|
||||||
|
Subnets []Subnet `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MacRange is associated with MacPool and respresents the start and end addresses.
|
||||||
|
type MacRange struct {
|
||||||
|
StartMacAddress string `json:",omitempty"`
|
||||||
|
EndMacAddress string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MacPool is assoicated with a network and represents pool of MacRanges.
|
||||||
|
type MacPool struct {
|
||||||
|
Ranges []MacRange `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dns (Domain Name System is associated with a network.
|
||||||
|
type Dns struct {
|
||||||
|
Domain string `json:",omitempty"`
|
||||||
|
Search []string `json:",omitempty"`
|
||||||
|
ServerList []string `json:",omitempty"`
|
||||||
|
Options []string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkType are various networks.
|
||||||
|
type NetworkType string
|
||||||
|
|
||||||
|
// NetworkType const
|
||||||
|
const (
|
||||||
|
NAT NetworkType = "NAT"
|
||||||
|
Transparent NetworkType = "Transparent"
|
||||||
|
L2Bridge NetworkType = "L2Bridge"
|
||||||
|
L2Tunnel NetworkType = "L2Tunnel"
|
||||||
|
ICS NetworkType = "ICS"
|
||||||
|
Private NetworkType = "Private"
|
||||||
|
Overlay NetworkType = "Overlay"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NetworkFlags are various network flags.
|
||||||
|
type NetworkFlags uint32
|
||||||
|
|
||||||
|
// NetworkFlags const
|
||||||
|
const (
|
||||||
|
None NetworkFlags = 0
|
||||||
|
EnableNonPersistent NetworkFlags = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
// HostComputeNetwork represents a network
|
||||||
|
type HostComputeNetwork struct {
|
||||||
|
Id string `json:"ID,omitempty"`
|
||||||
|
Name string `json:",omitempty"`
|
||||||
|
Type NetworkType `json:",omitempty"`
|
||||||
|
Policies []NetworkPolicy `json:",omitempty"`
|
||||||
|
MacPool MacPool `json:",omitempty"`
|
||||||
|
Dns Dns `json:",omitempty"`
|
||||||
|
Ipams []Ipam `json:",omitempty"`
|
||||||
|
Flags NetworkFlags `json:",omitempty"` // 0: None
|
||||||
|
SchemaVersion SchemaVersion `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkResourceType are the 3 different Network settings resources.
|
||||||
|
type NetworkResourceType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NetworkResourceTypePolicy is for Network's policies. Ex: RemoteSubnet
|
||||||
|
NetworkResourceTypePolicy NetworkResourceType = "Policy"
|
||||||
|
// NetworkResourceTypeDNS is for Network's DNS settings.
|
||||||
|
NetworkResourceTypeDNS NetworkResourceType = "DNS"
|
||||||
|
// NetworkResourceTypeExtension is for Network's extension settings.
|
||||||
|
NetworkResourceTypeExtension NetworkResourceType = "Extension"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModifyNetworkSettingRequest is the structure used to send request to modify an network.
|
||||||
|
// Used to update DNS/extension/policy on an network.
|
||||||
|
type ModifyNetworkSettingRequest struct {
|
||||||
|
ResourceType NetworkResourceType `json:",omitempty"` // Policy, DNS, Extension
|
||||||
|
RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PolicyNetworkRequest struct {
|
||||||
|
Policies []NetworkPolicy `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetwork(networkGuid guid.GUID, query string) (*HostComputeNetwork, error) {
|
||||||
|
// Open network.
|
||||||
|
var (
|
||||||
|
networkHandle hcnNetwork
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query network.
|
||||||
|
hr = hcnQueryNetworkProperties(networkHandle, query, &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close network.
|
||||||
|
hr = hcnCloseNetwork(networkHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeNetwork
|
||||||
|
var outputNetwork HostComputeNetwork
|
||||||
|
|
||||||
|
// If HNS sets the network type to NAT (i.e. '0' in HNS.Schema.Network.NetworkMode),
|
||||||
|
// the value will be omitted from the JSON blob. We therefore need to initialize NAT here before
|
||||||
|
// unmarshaling the JSON blob.
|
||||||
|
outputNetwork.Type = NAT
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNetwork, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumerateNetworks(query string) ([]HostComputeNetwork, error) {
|
||||||
|
// Enumerate all Network Guids
|
||||||
|
var (
|
||||||
|
resultBuffer *uint16
|
||||||
|
networkBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnEnumerateNetworks(query, &networkBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnEnumerateNetworks", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
networks := interop.ConvertAndFreeCoTaskMemString(networkBuffer)
|
||||||
|
var networkIds []guid.GUID
|
||||||
|
if err := json.Unmarshal([]byte(networks), &networkIds); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputNetworks []HostComputeNetwork
|
||||||
|
for _, networkGuid := range networkIds {
|
||||||
|
network, err := getNetwork(networkGuid, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputNetworks = append(outputNetworks, *network)
|
||||||
|
}
|
||||||
|
return outputNetworks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNetwork(settings string) (*HostComputeNetwork, error) {
|
||||||
|
// Create new network.
|
||||||
|
var (
|
||||||
|
networkHandle hcnNetwork
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
networkGuid := guid.GUID{}
|
||||||
|
hr := hcnCreateNetwork(&networkGuid, settings, &networkHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnCreateNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query network.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close network.
|
||||||
|
hr = hcnCloseNetwork(networkHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeNetwork
|
||||||
|
var outputNetwork HostComputeNetwork
|
||||||
|
|
||||||
|
// If HNS sets the network type to NAT (i.e. '0' in HNS.Schema.Network.NetworkMode),
|
||||||
|
// the value will be omitted from the JSON blob. We therefore need to initialize NAT here before
|
||||||
|
// unmarshaling the JSON blob.
|
||||||
|
outputNetwork.Type = NAT
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNetwork, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyNetwork(networkId string, settings string) (*HostComputeNetwork, error) {
|
||||||
|
networkGuid, err := guid.FromString(networkId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errInvalidNetworkID
|
||||||
|
}
|
||||||
|
// Open Network
|
||||||
|
var (
|
||||||
|
networkHandle hcnNetwork
|
||||||
|
resultBuffer *uint16
|
||||||
|
propertiesBuffer *uint16
|
||||||
|
)
|
||||||
|
hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Modify Network
|
||||||
|
hr = hcnModifyNetwork(networkHandle, settings, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnModifyNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Query network.
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
query, err := json.Marshal(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
|
||||||
|
// Close network.
|
||||||
|
hr = hcnCloseNetwork(networkHandle)
|
||||||
|
if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert output to HostComputeNetwork
|
||||||
|
var outputNetwork HostComputeNetwork
|
||||||
|
|
||||||
|
// If HNS sets the network type to NAT (i.e. '0' in HNS.Schema.Network.NetworkMode),
|
||||||
|
// the value will be omitted from the JSON blob. We therefore need to initialize NAT here before
|
||||||
|
// unmarshaling the JSON blob.
|
||||||
|
outputNetwork.Type = NAT
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &outputNetwork, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteNetwork(networkId string) error {
|
||||||
|
networkGuid, err := guid.FromString(networkId)
|
||||||
|
if err != nil {
|
||||||
|
return errInvalidNetworkID
|
||||||
|
}
|
||||||
|
var resultBuffer *uint16
|
||||||
|
hr := hcnDeleteNetwork(&networkGuid, &resultBuffer)
|
||||||
|
if err := checkForErrors("hcnDeleteNetwork", hr, resultBuffer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNetworks makes a call to list all available networks.
|
||||||
|
func ListNetworks() ([]HostComputeNetwork, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
networks, err := ListNetworksQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return networks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNetworksQuery makes a call to query the list of available networks.
|
||||||
|
func ListNetworksQuery(query HostComputeQuery) ([]HostComputeNetwork, error) {
|
||||||
|
queryJson, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
networks, err := enumerateNetworks(string(queryJson))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return networks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkByID returns the network specified by Id.
|
||||||
|
func GetNetworkByID(networkID string) (*HostComputeNetwork, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
mapA := map[string]string{"ID": networkID}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
networks, err := ListNetworksQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(networks) == 0 {
|
||||||
|
return nil, NetworkNotFoundError{NetworkID: networkID}
|
||||||
|
}
|
||||||
|
return &networks[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkByName returns the network specified by Name.
|
||||||
|
func GetNetworkByName(networkName string) (*HostComputeNetwork, error) {
|
||||||
|
hcnQuery := defaultQuery()
|
||||||
|
mapA := map[string]string{"Name": networkName}
|
||||||
|
filter, err := json.Marshal(mapA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hcnQuery.Filter = string(filter)
|
||||||
|
|
||||||
|
networks, err := ListNetworksQuery(hcnQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(networks) == 0 {
|
||||||
|
return nil, NetworkNotFoundError{NetworkName: networkName}
|
||||||
|
}
|
||||||
|
return &networks[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Network.
|
||||||
|
func (network *HostComputeNetwork) Create() (*HostComputeNetwork, error) {
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::Create id=%s", network.Id)
|
||||||
|
for _, ipam := range network.Ipams {
|
||||||
|
for _, subnet := range ipam.Subnets {
|
||||||
|
if subnet.IpAddressPrefix != "" {
|
||||||
|
hasDefault := false
|
||||||
|
for _, route := range subnet.Routes {
|
||||||
|
if route.NextHop == "" {
|
||||||
|
return nil, errors.New("network create error, subnet has address prefix but no gateway specified")
|
||||||
|
}
|
||||||
|
if route.DestinationPrefix == "0.0.0.0/0" || route.DestinationPrefix == "::/0" {
|
||||||
|
hasDefault = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasDefault {
|
||||||
|
return nil, errors.New("network create error, no default gateway")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonString, err := json.Marshal(network)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::Create JSON: %s", jsonString)
|
||||||
|
network, hcnErr := createNetwork(string(jsonString))
|
||||||
|
if hcnErr != nil {
|
||||||
|
return nil, hcnErr
|
||||||
|
}
|
||||||
|
return network, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Network.
|
||||||
|
func (network *HostComputeNetwork) Delete() error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::Delete id=%s", network.Id)
|
||||||
|
|
||||||
|
if err := deleteNetwork(network.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyNetworkSettings updates the Policy for a network.
|
||||||
|
func (network *HostComputeNetwork) ModifyNetworkSettings(request *ModifyNetworkSettingRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::ModifyNetworkSettings id=%s", network.Id)
|
||||||
|
|
||||||
|
networkSettingsRequest, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = modifyNetwork(network.Id, string(networkSettingsRequest))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPolicy applies a Policy (ex: RemoteSubnet) on the Network.
|
||||||
|
func (network *HostComputeNetwork) AddPolicy(networkPolicy PolicyNetworkRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::AddPolicy id=%s", network.Id)
|
||||||
|
|
||||||
|
settingsJson, err := json.Marshal(networkPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestMessage := &ModifyNetworkSettingRequest{
|
||||||
|
ResourceType: NetworkResourceTypePolicy,
|
||||||
|
RequestType: RequestTypeAdd,
|
||||||
|
Settings: settingsJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
return network.ModifyNetworkSettings(requestMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePolicy removes a Policy (ex: RemoteSubnet) from the Network.
|
||||||
|
func (network *HostComputeNetwork) RemovePolicy(networkPolicy PolicyNetworkRequest) error {
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::RemovePolicy id=%s", network.Id)
|
||||||
|
|
||||||
|
settingsJson, err := json.Marshal(networkPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestMessage := &ModifyNetworkSettingRequest{
|
||||||
|
ResourceType: NetworkResourceTypePolicy,
|
||||||
|
RequestType: RequestTypeRemove,
|
||||||
|
Settings: settingsJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
return network.ModifyNetworkSettings(requestMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateEndpoint creates an endpoint on the Network.
|
||||||
|
func (network *HostComputeNetwork) CreateEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) {
|
||||||
|
isRemote := endpoint.Flags&EndpointFlagsRemoteEndpoint != 0
|
||||||
|
logrus.Debugf("hcn::HostComputeNetwork::CreatEndpoint, networkId=%s remote=%t", network.Id, isRemote)
|
||||||
|
|
||||||
|
endpoint.HostComputeNetwork = network.Id
|
||||||
|
endpointSettings, err := json.Marshal(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newEndpoint, err := createEndpoint(network.Id, string(endpointSettings))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRemoteEndpoint creates a remote endpoint on the Network.
|
||||||
|
func (network *HostComputeNetwork) CreateRemoteEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) {
|
||||||
|
endpoint.Flags = EndpointFlagsRemoteEndpoint | endpoint.Flags
|
||||||
|
return network.CreateEndpoint(endpoint)
|
||||||
|
}
|
249
vendor/github.com/Microsoft/hcsshim/hcn/hcnpolicy.go
generated
vendored
Normal file
249
vendor/github.com/Microsoft/hcsshim/hcn/hcnpolicy.go
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndpointPolicyType are the potential Policies that apply to Endpoints.
|
||||||
|
type EndpointPolicyType string
|
||||||
|
|
||||||
|
// EndpointPolicyType const
|
||||||
|
const (
|
||||||
|
PortMapping EndpointPolicyType = "PortMapping"
|
||||||
|
ACL EndpointPolicyType = "ACL"
|
||||||
|
QOS EndpointPolicyType = "QOS"
|
||||||
|
L2Driver EndpointPolicyType = "L2Driver"
|
||||||
|
OutBoundNAT EndpointPolicyType = "OutBoundNAT"
|
||||||
|
SDNRoute EndpointPolicyType = "SDNRoute"
|
||||||
|
L4Proxy EndpointPolicyType = "L4Proxy"
|
||||||
|
PortName EndpointPolicyType = "PortName"
|
||||||
|
EncapOverhead EndpointPolicyType = "EncapOverhead"
|
||||||
|
// Endpoint and Network have InterfaceConstraint and ProviderAddress
|
||||||
|
NetworkProviderAddress EndpointPolicyType = "ProviderAddress"
|
||||||
|
NetworkInterfaceConstraint EndpointPolicyType = "InterfaceConstraint"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndpointPolicy is a collection of Policy settings for an Endpoint.
|
||||||
|
type EndpointPolicy struct {
|
||||||
|
Type EndpointPolicyType `json:""`
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPolicyType are the potential Policies that apply to Networks.
|
||||||
|
type NetworkPolicyType string
|
||||||
|
|
||||||
|
// NetworkPolicyType const
|
||||||
|
const (
|
||||||
|
SourceMacAddress NetworkPolicyType = "SourceMacAddress"
|
||||||
|
NetAdapterName NetworkPolicyType = "NetAdapterName"
|
||||||
|
VSwitchExtension NetworkPolicyType = "VSwitchExtension"
|
||||||
|
DrMacAddress NetworkPolicyType = "DrMacAddress"
|
||||||
|
AutomaticDNS NetworkPolicyType = "AutomaticDNS"
|
||||||
|
InterfaceConstraint NetworkPolicyType = "InterfaceConstraint"
|
||||||
|
ProviderAddress NetworkPolicyType = "ProviderAddress"
|
||||||
|
RemoteSubnetRoute NetworkPolicyType = "RemoteSubnetRoute"
|
||||||
|
HostRoute NetworkPolicyType = "HostRoute"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NetworkPolicy is a collection of Policy settings for a Network.
|
||||||
|
type NetworkPolicy struct {
|
||||||
|
Type NetworkPolicyType `json:""`
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubnetPolicyType are the potential Policies that apply to Subnets.
|
||||||
|
type SubnetPolicyType string
|
||||||
|
|
||||||
|
// SubnetPolicyType const
|
||||||
|
const (
|
||||||
|
VLAN SubnetPolicyType = "VLAN"
|
||||||
|
VSID SubnetPolicyType = "VSID"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SubnetPolicy is a collection of Policy settings for a Subnet.
|
||||||
|
type SubnetPolicy struct {
|
||||||
|
Type SubnetPolicyType `json:""`
|
||||||
|
Settings json.RawMessage `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NatFlags are flags for portmappings.
|
||||||
|
type NatFlags uint32
|
||||||
|
|
||||||
|
/// Endpoint Policy objects
|
||||||
|
|
||||||
|
// PortMappingPolicySetting defines Port Mapping (NAT)
|
||||||
|
type PortMappingPolicySetting struct {
|
||||||
|
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
|
||||||
|
InternalPort uint16 `json:",omitempty"`
|
||||||
|
ExternalPort uint16 `json:",omitempty"`
|
||||||
|
VIP string `json:",omitempty"`
|
||||||
|
Flags NatFlags `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionType associated with ACLs. Value is either Allow or Block.
|
||||||
|
type ActionType string
|
||||||
|
|
||||||
|
// DirectionType associated with ACLs. Value is either In or Out.
|
||||||
|
type DirectionType string
|
||||||
|
|
||||||
|
// RuleType associated with ACLs. Value is either Host (WFP) or Switch (VFP).
|
||||||
|
type RuleType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Allow traffic
|
||||||
|
ActionTypeAllow ActionType = "Allow"
|
||||||
|
// Block traffic
|
||||||
|
ActionTypeBlock ActionType = "Block"
|
||||||
|
|
||||||
|
// In is traffic coming to the Endpoint
|
||||||
|
DirectionTypeIn DirectionType = "In"
|
||||||
|
// Out is traffic leaving the Endpoint
|
||||||
|
DirectionTypeOut DirectionType = "Out"
|
||||||
|
|
||||||
|
// Host creates WFP (Windows Firewall) rules
|
||||||
|
RuleTypeHost RuleType = "Host"
|
||||||
|
// Switch creates VFP (Virtual Filter Platform) rules
|
||||||
|
RuleTypeSwitch RuleType = "Switch"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AclPolicySetting creates firewall rules on an endpoint
|
||||||
|
type AclPolicySetting struct {
|
||||||
|
Protocols string `json:",omitempty"` // EX: 6 (TCP), 17 (UDP), 1 (ICMPv4), 58 (ICMPv6), 2 (IGMP)
|
||||||
|
Action ActionType `json:","`
|
||||||
|
Direction DirectionType `json:","`
|
||||||
|
LocalAddresses string `json:",omitempty"`
|
||||||
|
RemoteAddresses string `json:",omitempty"`
|
||||||
|
LocalPorts string `json:",omitempty"`
|
||||||
|
RemotePorts string `json:",omitempty"`
|
||||||
|
RuleType RuleType `json:",omitempty"`
|
||||||
|
Priority uint16 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// QosPolicySetting sets Quality of Service bandwidth caps on an Endpoint.
|
||||||
|
type QosPolicySetting struct {
|
||||||
|
MaximumOutgoingBandwidthInBytes uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutboundNatPolicySetting sets outbound Network Address Translation on an Endpoint.
|
||||||
|
type OutboundNatPolicySetting struct {
|
||||||
|
VirtualIP string `json:",omitempty"`
|
||||||
|
Exceptions []string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDNRoutePolicySetting sets SDN Route on an Endpoint.
|
||||||
|
type SDNRoutePolicySetting struct {
|
||||||
|
DestinationPrefix string `json:",omitempty"`
|
||||||
|
NextHop string `json:",omitempty"`
|
||||||
|
NeedEncap bool `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ProxyType is a type of proxy used by the L4 proxy policy.
|
||||||
|
type ProxyType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ProxyTypeVFP specifies a Virtual Filtering Protocol proxy.
|
||||||
|
ProxyTypeVFP ProxyType = iota
|
||||||
|
// ProxyTypeWFP specifies a Windows Filtering Platform proxy.
|
||||||
|
ProxyTypeWFP
|
||||||
|
)
|
||||||
|
|
||||||
|
// FiveTuple is nested in L4ProxyPolicySetting for WFP support.
|
||||||
|
type FiveTuple struct {
|
||||||
|
Protocols string `json:",omitempty"`
|
||||||
|
LocalAddresses string `json:",omitempty"`
|
||||||
|
RemoteAddresses string `json:",omitempty"`
|
||||||
|
LocalPorts string `json:",omitempty"`
|
||||||
|
RemotePorts string `json:",omitempty"`
|
||||||
|
Priority uint16 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// L4ProxyPolicySetting sets Layer-4 Proxy on an endpoint.
|
||||||
|
type L4ProxyPolicySetting struct {
|
||||||
|
IP string `json:",omitempty"`
|
||||||
|
Port string `json:",omitempty"`
|
||||||
|
Protocol uint32 `json:",omitempty"` // EX: TCP = 6, UDP = 17
|
||||||
|
ExceptionList []string `json:",omitempty"`
|
||||||
|
Destination string `json:","`
|
||||||
|
OutboundNat bool `json:",omitempty"`
|
||||||
|
|
||||||
|
// For the WFP proxy
|
||||||
|
FilterTuple FiveTuple `json:",omitempty"`
|
||||||
|
ProxyType ProxyType `json:",omitempty"`
|
||||||
|
UserSID string `json:",omitempty"`
|
||||||
|
NetworkCompartmentID uint32 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortnameEndpointPolicySetting sets the port name for an endpoint.
|
||||||
|
type PortnameEndpointPolicySetting struct {
|
||||||
|
Name string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncapOverheadEndpointPolicySetting sets the encap overhead for an endpoint.
|
||||||
|
type EncapOverheadEndpointPolicySetting struct {
|
||||||
|
Overhead uint16 `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Endpoint and Network Policy objects
|
||||||
|
|
||||||
|
// ProviderAddressEndpointPolicySetting sets the PA for an endpoint.
|
||||||
|
type ProviderAddressEndpointPolicySetting struct {
|
||||||
|
ProviderAddress string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceConstraintPolicySetting limits an Endpoint or Network to a specific Nic.
|
||||||
|
type InterfaceConstraintPolicySetting struct {
|
||||||
|
InterfaceGuid string `json:",omitempty"`
|
||||||
|
InterfaceLuid uint64 `json:",omitempty"`
|
||||||
|
InterfaceIndex uint32 `json:",omitempty"`
|
||||||
|
InterfaceMediaType uint32 `json:",omitempty"`
|
||||||
|
InterfaceAlias string `json:",omitempty"`
|
||||||
|
InterfaceDescription string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Network Policy objects
|
||||||
|
|
||||||
|
// SourceMacAddressNetworkPolicySetting sets source MAC for a network.
|
||||||
|
type SourceMacAddressNetworkPolicySetting struct {
|
||||||
|
SourceMacAddress string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetAdapterNameNetworkPolicySetting sets network adapter of a network.
|
||||||
|
type NetAdapterNameNetworkPolicySetting struct {
|
||||||
|
NetworkAdapterName string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VSwitchExtensionNetworkPolicySetting enables/disabled VSwitch extensions for a network.
|
||||||
|
type VSwitchExtensionNetworkPolicySetting struct {
|
||||||
|
ExtensionID string `json:",omitempty"`
|
||||||
|
Enable bool `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrMacAddressNetworkPolicySetting sets the DR MAC for a network.
|
||||||
|
type DrMacAddressNetworkPolicySetting struct {
|
||||||
|
Address string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutomaticDNSNetworkPolicySetting enables/disables automatic DNS on a network.
|
||||||
|
type AutomaticDNSNetworkPolicySetting struct {
|
||||||
|
Enable bool `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subnet Policy objects
|
||||||
|
|
||||||
|
// VlanPolicySetting isolates a subnet with VLAN tagging.
|
||||||
|
type VlanPolicySetting struct {
|
||||||
|
IsolationId uint32 `json:","`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VsidPolicySetting isolates a subnet with VSID tagging.
|
||||||
|
type VsidPolicySetting struct {
|
||||||
|
IsolationId uint32 `json:","`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteSubnetRoutePolicySetting creates remote subnet route rules on a network
|
||||||
|
type RemoteSubnetRoutePolicySetting struct {
|
||||||
|
DestinationPrefix string
|
||||||
|
IsolationId uint16
|
||||||
|
ProviderAddress string
|
||||||
|
DistributedRouterMacAddress string
|
||||||
|
}
|
71
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
Normal file
71
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportedFeatures are the features provided by the Service.
|
||||||
|
type SupportedFeatures struct {
|
||||||
|
Acl AclFeatures `json:"ACL"`
|
||||||
|
Api ApiSupport `json:"API"`
|
||||||
|
RemoteSubnet bool `json:"RemoteSubnet"`
|
||||||
|
HostRoute bool `json:"HostRoute"`
|
||||||
|
DSR bool `json:"DSR"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AclFeatures are the supported ACL possibilities.
|
||||||
|
type AclFeatures struct {
|
||||||
|
AclAddressLists bool `json:"AclAddressLists"`
|
||||||
|
AclNoHostRulePriority bool `json:"AclHostRulePriority"`
|
||||||
|
AclPortRanges bool `json:"AclPortRanges"`
|
||||||
|
AclRuleId bool `json:"AclRuleId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApiSupport lists the supported API versions.
|
||||||
|
type ApiSupport struct {
|
||||||
|
V1 bool `json:"V1"`
|
||||||
|
V2 bool `json:"V2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSupportedFeatures returns the features supported by the Service.
|
||||||
|
func GetSupportedFeatures() SupportedFeatures {
|
||||||
|
var features SupportedFeatures
|
||||||
|
|
||||||
|
globals, err := GetGlobals()
|
||||||
|
if err != nil {
|
||||||
|
// Expected on pre-1803 builds, all features will be false/unsupported
|
||||||
|
logrus.Debugf("Unable to obtain globals: %s", err)
|
||||||
|
return features
|
||||||
|
}
|
||||||
|
|
||||||
|
features.Acl = AclFeatures{
|
||||||
|
AclAddressLists: isFeatureSupported(globals.Version, HNSVersion1803),
|
||||||
|
AclNoHostRulePriority: isFeatureSupported(globals.Version, HNSVersion1803),
|
||||||
|
AclPortRanges: isFeatureSupported(globals.Version, HNSVersion1803),
|
||||||
|
AclRuleId: isFeatureSupported(globals.Version, HNSVersion1803),
|
||||||
|
}
|
||||||
|
|
||||||
|
features.Api = ApiSupport{
|
||||||
|
V2: isFeatureSupported(globals.Version, V2ApiSupport),
|
||||||
|
V1: true, // HNSCall is still available.
|
||||||
|
}
|
||||||
|
|
||||||
|
features.RemoteSubnet = isFeatureSupported(globals.Version, RemoteSubnetVersion)
|
||||||
|
features.HostRoute = isFeatureSupported(globals.Version, HostRouteVersion)
|
||||||
|
features.DSR = isFeatureSupported(globals.Version, DSRVersion)
|
||||||
|
|
||||||
|
return features
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFeatureSupported(currentVersion Version, minVersionSupported Version) bool {
|
||||||
|
if currentVersion.Major < minVersionSupported.Major {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if currentVersion.Major > minVersionSupported.Major {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if currentVersion.Minor < minVersionSupported.Minor {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
714
vendor/github.com/Microsoft/hcsshim/hcn/zsyscall_windows.go
generated
vendored
Normal file
714
vendor/github.com/Microsoft/hcsshim/hcn/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,714 @@
|
|||||||
|
// Code generated mksyscall_windows.exe DO NOT EDIT
|
||||||
|
|
||||||
|
package hcn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ unsafe.Pointer
|
||||||
|
|
||||||
|
// Do the interface allocations only once for common
|
||||||
|
// Errno values.
|
||||||
|
const (
|
||||||
|
errnoERROR_IO_PENDING = 997
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case errnoERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
}
|
||||||
|
// TODO: add more here, after collecting data on the common
|
||||||
|
// error values see on Windows. (perhaps when running
|
||||||
|
// all.bat?)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
||||||
|
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
|
||||||
|
modcomputenetwork = windows.NewLazySystemDLL("computenetwork.dll")
|
||||||
|
|
||||||
|
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
|
||||||
|
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||||
|
procHcnEnumerateNetworks = modcomputenetwork.NewProc("HcnEnumerateNetworks")
|
||||||
|
procHcnCreateNetwork = modcomputenetwork.NewProc("HcnCreateNetwork")
|
||||||
|
procHcnOpenNetwork = modcomputenetwork.NewProc("HcnOpenNetwork")
|
||||||
|
procHcnModifyNetwork = modcomputenetwork.NewProc("HcnModifyNetwork")
|
||||||
|
procHcnQueryNetworkProperties = modcomputenetwork.NewProc("HcnQueryNetworkProperties")
|
||||||
|
procHcnDeleteNetwork = modcomputenetwork.NewProc("HcnDeleteNetwork")
|
||||||
|
procHcnCloseNetwork = modcomputenetwork.NewProc("HcnCloseNetwork")
|
||||||
|
procHcnEnumerateEndpoints = modcomputenetwork.NewProc("HcnEnumerateEndpoints")
|
||||||
|
procHcnCreateEndpoint = modcomputenetwork.NewProc("HcnCreateEndpoint")
|
||||||
|
procHcnOpenEndpoint = modcomputenetwork.NewProc("HcnOpenEndpoint")
|
||||||
|
procHcnModifyEndpoint = modcomputenetwork.NewProc("HcnModifyEndpoint")
|
||||||
|
procHcnQueryEndpointProperties = modcomputenetwork.NewProc("HcnQueryEndpointProperties")
|
||||||
|
procHcnDeleteEndpoint = modcomputenetwork.NewProc("HcnDeleteEndpoint")
|
||||||
|
procHcnCloseEndpoint = modcomputenetwork.NewProc("HcnCloseEndpoint")
|
||||||
|
procHcnEnumerateNamespaces = modcomputenetwork.NewProc("HcnEnumerateNamespaces")
|
||||||
|
procHcnCreateNamespace = modcomputenetwork.NewProc("HcnCreateNamespace")
|
||||||
|
procHcnOpenNamespace = modcomputenetwork.NewProc("HcnOpenNamespace")
|
||||||
|
procHcnModifyNamespace = modcomputenetwork.NewProc("HcnModifyNamespace")
|
||||||
|
procHcnQueryNamespaceProperties = modcomputenetwork.NewProc("HcnQueryNamespaceProperties")
|
||||||
|
procHcnDeleteNamespace = modcomputenetwork.NewProc("HcnDeleteNamespace")
|
||||||
|
procHcnCloseNamespace = modcomputenetwork.NewProc("HcnCloseNamespace")
|
||||||
|
procHcnEnumerateLoadBalancers = modcomputenetwork.NewProc("HcnEnumerateLoadBalancers")
|
||||||
|
procHcnCreateLoadBalancer = modcomputenetwork.NewProc("HcnCreateLoadBalancer")
|
||||||
|
procHcnOpenLoadBalancer = modcomputenetwork.NewProc("HcnOpenLoadBalancer")
|
||||||
|
procHcnModifyLoadBalancer = modcomputenetwork.NewProc("HcnModifyLoadBalancer")
|
||||||
|
procHcnQueryLoadBalancerProperties = modcomputenetwork.NewProc("HcnQueryLoadBalancerProperties")
|
||||||
|
procHcnDeleteLoadBalancer = modcomputenetwork.NewProc("HcnDeleteLoadBalancer")
|
||||||
|
procHcnCloseLoadBalancer = modcomputenetwork.NewProc("HcnCloseLoadBalancer")
|
||||||
|
procHcnOpenService = modcomputenetwork.NewProc("HcnOpenService")
|
||||||
|
procHcnRegisterServiceCallback = modcomputenetwork.NewProc("HcnRegisterServiceCallback")
|
||||||
|
procHcnUnregisterServiceCallback = modcomputenetwork.NewProc("HcnUnregisterServiceCallback")
|
||||||
|
procHcnCloseService = modcomputenetwork.NewProc("HcnCloseService")
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(method)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p1 *uint16
|
||||||
|
_p1, hr = syscall.UTF16PtrFromString(path)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var _p2 *uint16
|
||||||
|
_p2, hr = syscall.UTF16PtrFromString(object)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return __hnsCall(_p0, _p1, _p2, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) {
|
||||||
|
if hr = procHNSCall.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnEnumerateNetworks(query string, networks **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnEnumerateNetworks(_p0, networks, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnEnumerateNetworks(query *uint16, networks **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnEnumerateNetworks.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnEnumerateNetworks.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(networks)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCreateNetwork(id *_guid, settings string, network *hcnNetwork, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnCreateNetwork(id, _p0, network, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnCreateNetwork(id *_guid, settings *uint16, network *hcnNetwork, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnCreateNetwork.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnCreateNetwork.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(network)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnOpenNetwork(id *_guid, network *hcnNetwork, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnOpenNetwork.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnOpenNetwork.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(network)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnModifyNetwork(network hcnNetwork, settings string, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnModifyNetwork(network, _p0, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnModifyNetwork(network hcnNetwork, settings *uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnModifyNetwork.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnModifyNetwork.Addr(), 3, uintptr(network), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnQueryNetworkProperties(network hcnNetwork, query string, properties **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnQueryNetworkProperties(network, _p0, properties, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnQueryNetworkProperties(network hcnNetwork, query *uint16, properties **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnQueryNetworkProperties.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnQueryNetworkProperties.Addr(), 4, uintptr(network), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnDeleteNetwork(id *_guid, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnDeleteNetwork.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnDeleteNetwork.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCloseNetwork(network hcnNetwork) (hr error) {
|
||||||
|
if hr = procHcnCloseNetwork.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnCloseNetwork.Addr(), 1, uintptr(network), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnEnumerateEndpoints(query string, endpoints **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnEnumerateEndpoints(_p0, endpoints, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnEnumerateEndpoints(query *uint16, endpoints **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnEnumerateEndpoints.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnEnumerateEndpoints.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(endpoints)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCreateEndpoint(network hcnNetwork, id *_guid, settings string, endpoint *hcnEndpoint, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnCreateEndpoint(network, id, _p0, endpoint, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnCreateEndpoint(network hcnNetwork, id *_guid, settings *uint16, endpoint *hcnEndpoint, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnCreateEndpoint.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnCreateEndpoint.Addr(), 5, uintptr(network), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(endpoint)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnOpenEndpoint(id *_guid, endpoint *hcnEndpoint, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnOpenEndpoint.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnOpenEndpoint.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(endpoint)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnModifyEndpoint(endpoint hcnEndpoint, settings string, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnModifyEndpoint(endpoint, _p0, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnModifyEndpoint(endpoint hcnEndpoint, settings *uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnModifyEndpoint.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnModifyEndpoint.Addr(), 3, uintptr(endpoint), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnQueryEndpointProperties(endpoint hcnEndpoint, query string, properties **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnQueryEndpointProperties(endpoint, _p0, properties, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnQueryEndpointProperties(endpoint hcnEndpoint, query *uint16, properties **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnQueryEndpointProperties.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnQueryEndpointProperties.Addr(), 4, uintptr(endpoint), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnDeleteEndpoint(id *_guid, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnDeleteEndpoint.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnDeleteEndpoint.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCloseEndpoint(endpoint hcnEndpoint) (hr error) {
|
||||||
|
if hr = procHcnCloseEndpoint.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnCloseEndpoint.Addr(), 1, uintptr(endpoint), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnEnumerateNamespaces(query string, namespaces **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnEnumerateNamespaces(_p0, namespaces, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnEnumerateNamespaces(query *uint16, namespaces **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnEnumerateNamespaces.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnEnumerateNamespaces.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(namespaces)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCreateNamespace(id *_guid, settings string, namespace *hcnNamespace, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnCreateNamespace(id, _p0, namespace, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnCreateNamespace(id *_guid, settings *uint16, namespace *hcnNamespace, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnCreateNamespace.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnCreateNamespace.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(namespace)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnOpenNamespace(id *_guid, namespace *hcnNamespace, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnOpenNamespace.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnOpenNamespace.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(namespace)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnModifyNamespace(namespace hcnNamespace, settings string, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnModifyNamespace(namespace, _p0, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnModifyNamespace(namespace hcnNamespace, settings *uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnModifyNamespace.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnModifyNamespace.Addr(), 3, uintptr(namespace), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnQueryNamespaceProperties(namespace hcnNamespace, query string, properties **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnQueryNamespaceProperties(namespace, _p0, properties, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnQueryNamespaceProperties(namespace hcnNamespace, query *uint16, properties **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnQueryNamespaceProperties.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnQueryNamespaceProperties.Addr(), 4, uintptr(namespace), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnDeleteNamespace(id *_guid, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnDeleteNamespace.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnDeleteNamespace.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCloseNamespace(namespace hcnNamespace) (hr error) {
|
||||||
|
if hr = procHcnCloseNamespace.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnCloseNamespace.Addr(), 1, uintptr(namespace), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnEnumerateLoadBalancers(query string, loadBalancers **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnEnumerateLoadBalancers(_p0, loadBalancers, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnEnumerateLoadBalancers(query *uint16, loadBalancers **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnEnumerateLoadBalancers.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnEnumerateLoadBalancers.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(loadBalancers)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCreateLoadBalancer(id *_guid, settings string, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnCreateLoadBalancer(id, _p0, loadBalancer, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnCreateLoadBalancer(id *_guid, settings *uint16, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnCreateLoadBalancer.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnCreateLoadBalancer.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(loadBalancer)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnOpenLoadBalancer(id *_guid, loadBalancer *hcnLoadBalancer, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnOpenLoadBalancer.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnOpenLoadBalancer.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(loadBalancer)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings string, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnModifyLoadBalancer(loadBalancer, _p0, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnModifyLoadBalancer(loadBalancer hcnLoadBalancer, settings *uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnModifyLoadBalancer.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnModifyLoadBalancer.Addr(), 3, uintptr(loadBalancer), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query string, properties **uint16, result **uint16) (hr error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||||
|
if hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _hcnQueryLoadBalancerProperties(loadBalancer, _p0, properties, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hcnQueryLoadBalancerProperties(loadBalancer hcnLoadBalancer, query *uint16, properties **uint16, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnQueryLoadBalancerProperties.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnQueryLoadBalancerProperties.Addr(), 4, uintptr(loadBalancer), uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnDeleteLoadBalancer(id *_guid, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnDeleteLoadBalancer.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnDeleteLoadBalancer.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCloseLoadBalancer(loadBalancer hcnLoadBalancer) (hr error) {
|
||||||
|
if hr = procHcnCloseLoadBalancer.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnCloseLoadBalancer.Addr(), 1, uintptr(loadBalancer), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnOpenService(service *hcnService, result **uint16) (hr error) {
|
||||||
|
if hr = procHcnOpenService.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnOpenService.Addr(), 2, uintptr(unsafe.Pointer(service)), uintptr(unsafe.Pointer(result)), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnRegisterServiceCallback(service hcnService, callback int32, context int32, callbackHandle *hcnCallbackHandle) (hr error) {
|
||||||
|
if hr = procHcnRegisterServiceCallback.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall6(procHcnRegisterServiceCallback.Addr(), 4, uintptr(service), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnUnregisterServiceCallback(callbackHandle hcnCallbackHandle) (hr error) {
|
||||||
|
if hr = procHcnUnregisterServiceCallback.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnUnregisterServiceCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hcnCloseService(service hcnService) (hr error) {
|
||||||
|
if hr = procHcnCloseService.Find(); hr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.Syscall(procHcnCloseService.Addr(), 1, uintptr(service), 0, 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
if r0&0x1fff0000 == 0x00070000 {
|
||||||
|
r0 &= 0xffff
|
||||||
|
}
|
||||||
|
hr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
110
vendor/github.com/Microsoft/hcsshim/internal/cni/registry.go
generated
vendored
Normal file
110
vendor/github.com/Microsoft/hcsshim/internal/cni/registry.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package cni
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
"github.com/Microsoft/hcsshim/internal/regstate"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cniRoot = "cni"
|
||||||
|
cniKey = "cfg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PersistedNamespaceConfig is the registry version of the `NamespaceID` to UVM
|
||||||
|
// map.
|
||||||
|
type PersistedNamespaceConfig struct {
|
||||||
|
namespaceID string
|
||||||
|
stored bool
|
||||||
|
|
||||||
|
ContainerID string
|
||||||
|
HostUniqueID guid.GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPersistedNamespaceConfig creates an in-memory namespace config that can be
|
||||||
|
// persisted to the registry.
|
||||||
|
func NewPersistedNamespaceConfig(namespaceID, containerID string, containerHostUniqueID guid.GUID) *PersistedNamespaceConfig {
|
||||||
|
return &PersistedNamespaceConfig{
|
||||||
|
namespaceID: namespaceID,
|
||||||
|
ContainerID: containerID,
|
||||||
|
HostUniqueID: containerHostUniqueID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPersistedNamespaceConfig loads a persisted config from the registry that matches
|
||||||
|
// `namespaceID`. If not found returns `regstate.NotFoundError`
|
||||||
|
func LoadPersistedNamespaceConfig(namespaceID string) (*PersistedNamespaceConfig, error) {
|
||||||
|
sk, err := regstate.Open(cniRoot, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
|
||||||
|
pnc := PersistedNamespaceConfig{
|
||||||
|
namespaceID: namespaceID,
|
||||||
|
stored: true,
|
||||||
|
}
|
||||||
|
if err := sk.Get(namespaceID, cniKey, &pnc); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pnc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store stores or updates the in-memory config to its registry state. If the
|
||||||
|
// store failes returns the store error.
|
||||||
|
func (pnc *PersistedNamespaceConfig) Store() error {
|
||||||
|
if pnc.namespaceID == "" {
|
||||||
|
return errors.New("invalid namespaceID ''")
|
||||||
|
}
|
||||||
|
if pnc.ContainerID == "" {
|
||||||
|
return errors.New("invalid containerID ''")
|
||||||
|
}
|
||||||
|
empty := guid.GUID{}
|
||||||
|
if pnc.HostUniqueID == empty {
|
||||||
|
return errors.New("invalid containerHostUniqueID 'empy'")
|
||||||
|
}
|
||||||
|
sk, err := regstate.Open(cniRoot, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
|
||||||
|
if pnc.stored {
|
||||||
|
if err := sk.Set(pnc.namespaceID, cniKey, pnc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := sk.Create(pnc.namespaceID, cniKey, pnc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnc.stored = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes any persisted state associated with this config. If the config
|
||||||
|
// is not found in the registery `Remove` returns no error.
|
||||||
|
func (pnc *PersistedNamespaceConfig) Remove() error {
|
||||||
|
if pnc.stored {
|
||||||
|
sk, err := regstate.Open(cniRoot, false)
|
||||||
|
if err != nil {
|
||||||
|
if regstate.IsNotFoundError(err) {
|
||||||
|
pnc.stored = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
|
||||||
|
if err := sk.Remove(pnc.namespaceID); err != nil {
|
||||||
|
if regstate.IsNotFoundError(err) {
|
||||||
|
pnc.stored = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnc.stored = false
|
||||||
|
return nil
|
||||||
|
}
|
287
vendor/github.com/Microsoft/hcsshim/internal/regstate/regstate.go
generated
vendored
Normal file
287
vendor/github.com/Microsoft/hcsshim/internal/regstate/regstate.go
generated
vendored
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
package regstate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go regstate.go
|
||||||
|
|
||||||
|
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
||||||
|
|
||||||
|
const (
|
||||||
|
_REG_OPTION_VOLATILE = 1
|
||||||
|
|
||||||
|
_REG_CREATED_NEW_KEY = 1
|
||||||
|
_REG_OPENED_EXISTING_KEY = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Key struct {
|
||||||
|
registry.Key
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var localMachine = &Key{registry.LOCAL_MACHINE, "HKEY_LOCAL_MACHINE"}
|
||||||
|
var localUser = &Key{registry.CURRENT_USER, "HKEY_CURRENT_USER"}
|
||||||
|
|
||||||
|
var rootPath = `SOFTWARE\Microsoft\runhcs`
|
||||||
|
|
||||||
|
type NotFoundError struct {
|
||||||
|
Id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *NotFoundError) Error() string {
|
||||||
|
return fmt.Sprintf("ID '%s' was not found", err.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsNotFoundError(err error) bool {
|
||||||
|
_, ok := err.(*NotFoundError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoStateError struct {
|
||||||
|
ID string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *NoStateError) Error() string {
|
||||||
|
return fmt.Sprintf("state '%s' is not present for ID '%s'", err.Key, err.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createVolatileKey(k *Key, path string, access uint32) (newk *Key, openedExisting bool, err error) {
|
||||||
|
var (
|
||||||
|
h syscall.Handle
|
||||||
|
d uint32
|
||||||
|
)
|
||||||
|
fullpath := filepath.Join(k.Name, path)
|
||||||
|
err = regCreateKeyEx(syscall.Handle(k.Key), syscall.StringToUTF16Ptr(path), 0, nil, _REG_OPTION_VOLATILE, access, nil, &h, &d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, &os.PathError{Op: "RegCreateKeyEx", Path: fullpath, Err: err}
|
||||||
|
}
|
||||||
|
return &Key{registry.Key(h), fullpath}, d == _REG_OPENED_EXISTING_KEY, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hive(perUser bool) *Key {
|
||||||
|
r := localMachine
|
||||||
|
if perUser {
|
||||||
|
r = localUser
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func Open(root string, perUser bool) (*Key, error) {
|
||||||
|
k, _, err := createVolatileKey(hive(perUser), rootPath, registry.ALL_ACCESS)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer k.Close()
|
||||||
|
|
||||||
|
k2, _, err := createVolatileKey(k, url.PathEscape(root), registry.ALL_ACCESS)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return k2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveAll(root string, perUser bool) error {
|
||||||
|
k, err := hive(perUser).open(rootPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer k.Close()
|
||||||
|
r, err := k.open(url.PathEscape(root))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
ids, err := r.Enumerate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, id := range ids {
|
||||||
|
err = r.Remove(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Close()
|
||||||
|
return k.Remove(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Close() error {
|
||||||
|
err := k.Key.Close()
|
||||||
|
k.Key = 0
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Enumerate() ([]string, error) {
|
||||||
|
escapedIDs, err := k.ReadSubKeyNames(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var ids []string
|
||||||
|
for _, e := range escapedIDs {
|
||||||
|
id, err := url.PathUnescape(e)
|
||||||
|
if err == nil {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) open(name string) (*Key, error) {
|
||||||
|
fullpath := filepath.Join(k.Name, name)
|
||||||
|
nk, err := registry.OpenKey(k.Key, name, registry.ALL_ACCESS)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &os.PathError{Op: "RegOpenKey", Path: fullpath, Err: err}
|
||||||
|
}
|
||||||
|
return &Key{nk, fullpath}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) openid(id string) (*Key, error) {
|
||||||
|
escaped := url.PathEscape(id)
|
||||||
|
fullpath := filepath.Join(k.Name, escaped)
|
||||||
|
nk, err := k.open(escaped)
|
||||||
|
if perr, ok := err.(*os.PathError); ok && perr.Err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
return nil, &NotFoundError{id}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, &os.PathError{Op: "RegOpenKey", Path: fullpath, Err: err}
|
||||||
|
}
|
||||||
|
return nk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Remove(id string) error {
|
||||||
|
escaped := url.PathEscape(id)
|
||||||
|
err := registry.DeleteKey(k.Key, escaped)
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
return &NotFoundError{id}
|
||||||
|
}
|
||||||
|
return &os.PathError{Op: "RegDeleteKey", Path: filepath.Join(k.Name, escaped), Err: err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) set(id string, create bool, key string, state interface{}) error {
|
||||||
|
var sk *Key
|
||||||
|
var err error
|
||||||
|
if create {
|
||||||
|
var existing bool
|
||||||
|
eid := url.PathEscape(id)
|
||||||
|
sk, existing, err = createVolatileKey(k, eid, registry.ALL_ACCESS)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
if existing {
|
||||||
|
sk.Close()
|
||||||
|
return fmt.Errorf("container %s already exists", id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sk, err = k.openid(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
}
|
||||||
|
switch reflect.TypeOf(state).Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
v := uint32(0)
|
||||||
|
if state.(bool) {
|
||||||
|
v = 1
|
||||||
|
}
|
||||||
|
err = sk.SetDWordValue(key, v)
|
||||||
|
case reflect.Int:
|
||||||
|
err = sk.SetQWordValue(key, uint64(state.(int)))
|
||||||
|
case reflect.String:
|
||||||
|
err = sk.SetStringValue(key, state.(string))
|
||||||
|
default:
|
||||||
|
var js []byte
|
||||||
|
js, err = json.Marshal(state)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = sk.SetBinaryValue(key, js)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
return &NoStateError{id, key}
|
||||||
|
}
|
||||||
|
return &os.PathError{Op: "RegSetValueEx", Path: sk.Name + ":" + key, Err: err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Create(id, key string, state interface{}) error {
|
||||||
|
return k.set(id, true, key, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Set(id, key string, state interface{}) error {
|
||||||
|
return k.set(id, false, key, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Clear(id, key string) error {
|
||||||
|
sk, err := k.openid(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
err = sk.DeleteValue(key)
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
return &NoStateError{id, key}
|
||||||
|
}
|
||||||
|
return &os.PathError{Op: "RegDeleteValue", Path: sk.Name + ":" + key, Err: err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) Get(id, key string, state interface{}) error {
|
||||||
|
sk, err := k.openid(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sk.Close()
|
||||||
|
|
||||||
|
var js []byte
|
||||||
|
switch reflect.TypeOf(state).Elem().Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
var v uint64
|
||||||
|
v, _, err = sk.GetIntegerValue(key)
|
||||||
|
if err == nil {
|
||||||
|
*state.(*bool) = v != 0
|
||||||
|
}
|
||||||
|
case reflect.Int:
|
||||||
|
var v uint64
|
||||||
|
v, _, err = sk.GetIntegerValue(key)
|
||||||
|
if err == nil {
|
||||||
|
*state.(*int) = int(v)
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
var v string
|
||||||
|
v, _, err = sk.GetStringValue(key)
|
||||||
|
if err == nil {
|
||||||
|
*state.(*string) = string(v)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
js, _, err = sk.GetBinaryValue(key)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND {
|
||||||
|
return &NoStateError{id, key}
|
||||||
|
}
|
||||||
|
return &os.PathError{Op: "RegQueryValueEx", Path: sk.Name + ":" + key, Err: err}
|
||||||
|
}
|
||||||
|
if js != nil {
|
||||||
|
err = json.Unmarshal(js, state)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
51
vendor/github.com/Microsoft/hcsshim/internal/regstate/zsyscall_windows.go
generated
vendored
Normal file
51
vendor/github.com/Microsoft/hcsshim/internal/regstate/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Code generated by 'go generate'; DO NOT EDIT.
|
||||||
|
|
||||||
|
package regstate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ unsafe.Pointer
|
||||||
|
|
||||||
|
// Do the interface allocations only once for common
|
||||||
|
// Errno values.
|
||||||
|
const (
|
||||||
|
errnoERROR_IO_PENDING = 997
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case errnoERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
}
|
||||||
|
// TODO: add more here, after collecting data on the common
|
||||||
|
// error values see on Windows. (perhaps when running
|
||||||
|
// all.bat?)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
|
|
||||||
|
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
36
vendor/github.com/containerd/cgroups/blkio.go
generated
vendored
36
vendor/github.com/containerd/cgroups/blkio.go
generated
vendored
@ -26,17 +26,33 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBlkio(root string) *blkioController {
|
// NewBlkio returns a Blkio controller given the root folder of cgroups.
|
||||||
return &blkioController{
|
// It may optionally accept other configuration options, such as ProcRoot(path)
|
||||||
root: filepath.Join(root, string(Blkio)),
|
func NewBlkio(root string, options ...func(controller *blkioController)) *blkioController {
|
||||||
|
ctrl := &blkioController{
|
||||||
|
root: filepath.Join(root, string(Blkio)),
|
||||||
|
procRoot: "/proc",
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(ctrl)
|
||||||
|
}
|
||||||
|
return ctrl
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcRoot overrides the default location of the "/proc" filesystem
|
||||||
|
func ProcRoot(path string) func(controller *blkioController) {
|
||||||
|
return func(c *blkioController) {
|
||||||
|
c.procRoot = path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type blkioController struct {
|
type blkioController struct {
|
||||||
root string
|
root string
|
||||||
|
procRoot string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blkioController) Name() Name {
|
func (b *blkioController) Name() Name {
|
||||||
@ -72,8 +88,8 @@ func (b *blkioController) Update(path string, resources *specs.LinuxResources) e
|
|||||||
return b.Create(path, resources)
|
return b.Create(path, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blkioController) Stat(path string, stats *Metrics) error {
|
func (b *blkioController) Stat(path string, stats *v1.Metrics) error {
|
||||||
stats.Blkio = &BlkIOStat{}
|
stats.Blkio = &v1.BlkIOStat{}
|
||||||
settings := []blkioStatSettings{
|
settings := []blkioStatSettings{
|
||||||
{
|
{
|
||||||
name: "throttle.io_serviced",
|
name: "throttle.io_serviced",
|
||||||
@ -122,7 +138,7 @@ func (b *blkioController) Stat(path string, stats *Metrics) error {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
f, err := os.Open("/proc/diskstats")
|
f, err := os.Open(filepath.Join(b.procRoot, "diskstats"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -141,7 +157,7 @@ func (b *blkioController) Stat(path string, stats *Metrics) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*BlkIOEntry) error {
|
func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*v1.BlkIOEntry) error {
|
||||||
f, err := os.Open(filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", name)))
|
f, err := os.Open(filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", name)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -180,7 +196,7 @@ func (b *blkioController) readEntry(devices map[deviceKey]string, path, name str
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*entry = append(*entry, &BlkIOEntry{
|
*entry = append(*entry, &v1.BlkIOEntry{
|
||||||
Device: devices[deviceKey{major, minor}],
|
Device: devices[deviceKey{major, minor}],
|
||||||
Major: major,
|
Major: major,
|
||||||
Minor: minor,
|
Minor: minor,
|
||||||
@ -268,7 +284,7 @@ type blkioSettings struct {
|
|||||||
|
|
||||||
type blkioStatSettings struct {
|
type blkioStatSettings struct {
|
||||||
name string
|
name string
|
||||||
entry *[]*BlkIOEntry
|
entry *[]*v1.BlkIOEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
func uintf(v interface{}) []byte {
|
func uintf(v interface{}) []byte {
|
||||||
|
11
vendor/github.com/containerd/cgroups/cgroup.go
generated
vendored
11
vendor/github.com/containerd/cgroups/cgroup.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -246,7 +247,7 @@ func (c *cgroup) Delete() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns the current metrics for the cgroup
|
// Stat returns the current metrics for the cgroup
|
||||||
func (c *cgroup) Stat(handlers ...ErrorHandler) (*Metrics, error) {
|
func (c *cgroup) Stat(handlers ...ErrorHandler) (*v1.Metrics, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
if c.err != nil {
|
if c.err != nil {
|
||||||
@ -256,10 +257,10 @@ func (c *cgroup) Stat(handlers ...ErrorHandler) (*Metrics, error) {
|
|||||||
handlers = append(handlers, errPassthrough)
|
handlers = append(handlers, errPassthrough)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
stats = &Metrics{
|
stats = &v1.Metrics{
|
||||||
CPU: &CPUStat{
|
CPU: &v1.CPUStat{
|
||||||
Throttling: &Throttle{},
|
Throttling: &v1.Throttle{},
|
||||||
Usage: &CPUUsage{},
|
Usage: &v1.CPUUsage{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
wg = &sync.WaitGroup{}
|
wg = &sync.WaitGroup{}
|
||||||
|
3
vendor/github.com/containerd/cgroups/control.go
generated
vendored
3
vendor/github.com/containerd/cgroups/control.go
generated
vendored
@ -19,6 +19,7 @@ package cgroups
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ type Cgroup interface {
|
|||||||
// subsystems are moved one at a time
|
// subsystems are moved one at a time
|
||||||
MoveTo(Cgroup) error
|
MoveTo(Cgroup) error
|
||||||
// Stat returns the stats for all subsystems in the cgroup
|
// Stat returns the stats for all subsystems in the cgroup
|
||||||
Stat(...ErrorHandler) (*Metrics, error)
|
Stat(...ErrorHandler) (*v1.Metrics, error)
|
||||||
// Update updates all the subsystems with the provided resource changes
|
// Update updates all the subsystems with the provided resource changes
|
||||||
Update(resources *specs.LinuxResources) error
|
Update(resources *specs.LinuxResources) error
|
||||||
// Processes returns all the processes in a select subsystem for the cgroup
|
// Processes returns all the processes in a select subsystem for the cgroup
|
||||||
|
3
vendor/github.com/containerd/cgroups/cpu.go
generated
vendored
3
vendor/github.com/containerd/cgroups/cpu.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ func (c *cpuController) Update(path string, resources *specs.LinuxResources) err
|
|||||||
return c.Create(path, resources)
|
return c.Create(path, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cpuController) Stat(path string, stats *Metrics) error {
|
func (c *cpuController) Stat(path string, stats *v1.Metrics) error {
|
||||||
f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat"))
|
f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
4
vendor/github.com/containerd/cgroups/cpuacct.go
generated
vendored
4
vendor/github.com/containerd/cgroups/cpuacct.go
generated
vendored
@ -22,6 +22,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const nanosecondsInSecond = 1000000000
|
const nanosecondsInSecond = 1000000000
|
||||||
@ -46,7 +48,7 @@ func (c *cpuacctController) Path(path string) string {
|
|||||||
return filepath.Join(c.root, path)
|
return filepath.Join(c.root, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cpuacctController) Stat(path string, stats *Metrics) error {
|
func (c *cpuacctController) Stat(path string, stats *v1.Metrics) error {
|
||||||
user, kernel, err := c.getUsage(path)
|
user, kernel, err := c.getUsage(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
13
vendor/github.com/containerd/cgroups/go.mod
generated
vendored
Normal file
13
vendor/github.com/containerd/cgroups/go.mod
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module github.com/containerd/cgroups
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||||
|
github.com/docker/go-units v0.4.0
|
||||||
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e
|
||||||
|
github.com/gogo/protobuf v1.2.1
|
||||||
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f
|
||||||
|
)
|
7
vendor/github.com/containerd/cgroups/hugetlb.go
generated
vendored
7
vendor/github.com/containerd/cgroups/hugetlb.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ func (h *hugetlbController) Create(path string, resources *specs.LinuxResources)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hugetlbController) Stat(path string, stats *Metrics) error {
|
func (h *hugetlbController) Stat(path string, stats *v1.Metrics) error {
|
||||||
for _, size := range h.sizes {
|
for _, size := range h.sizes {
|
||||||
s, err := h.readSizeStat(path, size)
|
s, err := h.readSizeStat(path, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -78,8 +79,8 @@ func (h *hugetlbController) Stat(path string, stats *Metrics) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hugetlbController) readSizeStat(path, size string) (*HugetlbStat, error) {
|
func (h *hugetlbController) readSizeStat(path, size string) (*v1.HugetlbStat, error) {
|
||||||
s := HugetlbStat{
|
s := v1.HugetlbStat{
|
||||||
Pagesize: size,
|
Pagesize: size,
|
||||||
}
|
}
|
||||||
for _, t := range []struct {
|
for _, t := range []struct {
|
||||||
|
62
vendor/github.com/containerd/cgroups/memory.go
generated
vendored
62
vendor/github.com/containerd/cgroups/memory.go
generated
vendored
@ -27,19 +27,48 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewMemory(root string) *memoryController {
|
// NewMemory returns a Memory controller given the root folder of cgroups.
|
||||||
return &memoryController{
|
// It may optionally accept other configuration options, such as IgnoreModules(...)
|
||||||
root: filepath.Join(root, string(Memory)),
|
func NewMemory(root string, options ...func(*memoryController)) *memoryController {
|
||||||
|
mc := &memoryController{
|
||||||
|
root: filepath.Join(root, string(Memory)),
|
||||||
|
ignored: map[string]struct{}{},
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(mc)
|
||||||
|
}
|
||||||
|
return mc
|
||||||
|
}
|
||||||
|
|
||||||
|
// IgnoreModules configure the memory controller to not read memory metrics for some
|
||||||
|
// module names (e.g. passing "memsw" would avoid all the memory.memsw.* entries)
|
||||||
|
func IgnoreModules(names ...string) func(*memoryController) {
|
||||||
|
return func(mc *memoryController) {
|
||||||
|
for _, name := range names {
|
||||||
|
mc.ignored[name] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalSwap allows the memory controller to not fail if cgroups is not accounting
|
||||||
|
// Swap memory (there are no memory.memsw.* entries)
|
||||||
|
func OptionalSwap() func(*memoryController) {
|
||||||
|
return func(mc *memoryController) {
|
||||||
|
_, err := os.Stat(filepath.Join(mc.root, "memory.memsw.usage_in_bytes"))
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
mc.ignored["memsw"] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type memoryController struct {
|
type memoryController struct {
|
||||||
root string
|
root string
|
||||||
|
ignored map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memoryController) Name() Name {
|
func (m *memoryController) Name() Name {
|
||||||
@ -97,24 +126,24 @@ func (m *memoryController) Update(path string, resources *specs.LinuxResources)
|
|||||||
return m.set(path, settings)
|
return m.set(path, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memoryController) Stat(path string, stats *Metrics) error {
|
func (m *memoryController) Stat(path string, stats *v1.Metrics) error {
|
||||||
f, err := os.Open(filepath.Join(m.Path(path), "memory.stat"))
|
f, err := os.Open(filepath.Join(m.Path(path), "memory.stat"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
stats.Memory = &MemoryStat{
|
stats.Memory = &v1.MemoryStat{
|
||||||
Usage: &MemoryEntry{},
|
Usage: &v1.MemoryEntry{},
|
||||||
Swap: &MemoryEntry{},
|
Swap: &v1.MemoryEntry{},
|
||||||
Kernel: &MemoryEntry{},
|
Kernel: &v1.MemoryEntry{},
|
||||||
KernelTCP: &MemoryEntry{},
|
KernelTCP: &v1.MemoryEntry{},
|
||||||
}
|
}
|
||||||
if err := m.parseStats(f, stats.Memory); err != nil {
|
if err := m.parseStats(f, stats.Memory); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, t := range []struct {
|
for _, t := range []struct {
|
||||||
module string
|
module string
|
||||||
entry *MemoryEntry
|
entry *v1.MemoryEntry
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
module: "",
|
module: "",
|
||||||
@ -133,6 +162,9 @@ func (m *memoryController) Stat(path string, stats *Metrics) error {
|
|||||||
entry: stats.Memory.KernelTCP,
|
entry: stats.Memory.KernelTCP,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
if _, ok := m.ignored[t.module]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
name string
|
name string
|
||||||
value *uint64
|
value *uint64
|
||||||
@ -197,7 +229,7 @@ func writeEventFD(root string, cfd, efd uintptr) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memoryController) parseStats(r io.Reader, stat *MemoryStat) error {
|
func (m *memoryController) parseStats(r io.Reader, stat *v1.MemoryStat) error {
|
||||||
var (
|
var (
|
||||||
raw = make(map[string]uint64)
|
raw = make(map[string]uint64)
|
||||||
sc = bufio.NewScanner(r)
|
sc = bufio.NewScanner(r)
|
||||||
@ -282,7 +314,7 @@ func getMemorySettings(resources *specs.LinuxResources) []memorySettings {
|
|||||||
value: mem.Limit,
|
value: mem.Limit,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "soft_limit_in_bytes",
|
name: "soft_limit_in_bytes",
|
||||||
value: mem.Reservation,
|
value: mem.Reservation,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
5
vendor/github.com/containerd/cgroups/pids.go
generated
vendored
5
vendor/github.com/containerd/cgroups/pids.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ func (p *pidsController) Update(path string, resources *specs.LinuxResources) er
|
|||||||
return p.Create(path, resources)
|
return p.Create(path, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pidsController) Stat(path string, stats *Metrics) error {
|
func (p *pidsController) Stat(path string, stats *v1.Metrics) error {
|
||||||
current, err := readUint(filepath.Join(p.Path(path), "pids.current"))
|
current, err := readUint(filepath.Join(p.Path(path), "pids.current"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -77,7 +78,7 @@ func (p *pidsController) Stat(path string, stats *Metrics) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stats.Pids = &PidsStat{
|
stats.Pids = &v1.PidsStat{
|
||||||
Current: current,
|
Current: current,
|
||||||
Limit: max,
|
Limit: max,
|
||||||
}
|
}
|
||||||
|
13
vendor/github.com/containerd/cgroups/rdma.go
generated
vendored
13
vendor/github.com/containerd/cgroups/rdma.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ func (p *rdmaController) Update(path string, resources *specs.LinuxResources) er
|
|||||||
return p.Create(path, resources)
|
return p.Create(path, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRdmaKV(raw string, entry *RdmaEntry) {
|
func parseRdmaKV(raw string, entry *v1.RdmaEntry) {
|
||||||
var value uint64
|
var value uint64
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -103,13 +104,13 @@ func parseRdmaKV(raw string, entry *RdmaEntry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toRdmaEntry(strEntries []string) []*RdmaEntry {
|
func toRdmaEntry(strEntries []string) []*v1.RdmaEntry {
|
||||||
var rdmaEntries []*RdmaEntry
|
var rdmaEntries []*v1.RdmaEntry
|
||||||
for i := range strEntries {
|
for i := range strEntries {
|
||||||
parts := strings.Fields(strEntries[i])
|
parts := strings.Fields(strEntries[i])
|
||||||
switch len(parts) {
|
switch len(parts) {
|
||||||
case 3:
|
case 3:
|
||||||
entry := new(RdmaEntry)
|
entry := new(v1.RdmaEntry)
|
||||||
entry.Device = parts[0]
|
entry.Device = parts[0]
|
||||||
parseRdmaKV(parts[1], entry)
|
parseRdmaKV(parts[1], entry)
|
||||||
parseRdmaKV(parts[2], entry)
|
parseRdmaKV(parts[2], entry)
|
||||||
@ -122,7 +123,7 @@ func toRdmaEntry(strEntries []string) []*RdmaEntry {
|
|||||||
return rdmaEntries
|
return rdmaEntries
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *rdmaController) Stat(path string, stats *Metrics) error {
|
func (p *rdmaController) Stat(path string, stats *v1.Metrics) error {
|
||||||
|
|
||||||
currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
|
currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -145,7 +146,7 @@ func (p *rdmaController) Stat(path string, stats *Metrics) error {
|
|||||||
currentEntries := toRdmaEntry(currentPerDevices)
|
currentEntries := toRdmaEntry(currentPerDevices)
|
||||||
maxEntries := toRdmaEntry(maxPerDevices)
|
maxEntries := toRdmaEntry(maxPerDevices)
|
||||||
|
|
||||||
stats.Rdma = &RdmaStat{
|
stats.Rdma = &v1.RdmaStat{
|
||||||
Current: currentEntries,
|
Current: currentEntries,
|
||||||
Limit: maxEntries,
|
Limit: maxEntries,
|
||||||
}
|
}
|
||||||
|
17
vendor/github.com/containerd/cgroups/stats/v1/doc.go
generated
vendored
Normal file
17
vendor/github.com/containerd/cgroups/stats/v1/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
File diff suppressed because it is too large
Load Diff
3
vendor/github.com/containerd/cgroups/subsystem.go
generated
vendored
3
vendor/github.com/containerd/cgroups/subsystem.go
generated
vendored
@ -19,6 +19,7 @@ package cgroups
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
v1 "github.com/containerd/cgroups/stats/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ type deleter interface {
|
|||||||
|
|
||||||
type stater interface {
|
type stater interface {
|
||||||
Subsystem
|
Subsystem
|
||||||
Stat(path string, stats *Metrics) error
|
Stat(path string, stats *v1.Metrics) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type updater interface {
|
type updater interface {
|
||||||
|
2
vendor/github.com/containerd/cri/README.md
generated
vendored
2
vendor/github.com/containerd/cri/README.md
generated
vendored
@ -82,7 +82,7 @@ specifications as appropriate.
|
|||||||
backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
|
backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
|
||||||
* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
|
* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
|
||||||
2. Install **`socat`** (required by portforward).
|
2. Install **`socat`** (required by portforward).
|
||||||
2. Install and setup a go 1.10 development environment.
|
2. Install and setup a go 1.12.9 development environment. (Note: You can check the travis logs for a recent pull request to confirm the version(s) of golang currently being used to build and test master.)
|
||||||
3. Make a local clone of this repository.
|
3. Make a local clone of this repository.
|
||||||
4. Install binary dependencies by running the following command from your cloned `cri/` project directory:
|
4. Install binary dependencies by running the following command from your cloned `cri/` project directory:
|
||||||
```bash
|
```bash
|
||||||
|
2
vendor/github.com/containerd/cri/cri.go
generated
vendored
2
vendor/github.com/containerd/cri/cri.go
generated
vendored
@ -40,6 +40,7 @@ import (
|
|||||||
|
|
||||||
criconfig "github.com/containerd/cri/pkg/config"
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
"github.com/containerd/cri/pkg/constants"
|
"github.com/containerd/cri/pkg/constants"
|
||||||
|
criplatforms "github.com/containerd/cri/pkg/containerd/platforms"
|
||||||
"github.com/containerd/cri/pkg/server"
|
"github.com/containerd/cri/pkg/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
|||||||
client, err := containerd.New(
|
client, err := containerd.New(
|
||||||
"",
|
"",
|
||||||
containerd.WithDefaultNamespace(constants.K8sContainerdNamespace),
|
containerd.WithDefaultNamespace(constants.K8sContainerdNamespace),
|
||||||
|
containerd.WithDefaultPlatform(criplatforms.Default()),
|
||||||
containerd.WithServices(servicesOpts...),
|
containerd.WithServices(servicesOpts...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
53
vendor/github.com/containerd/cri/pkg/config/config.go
generated
vendored
53
vendor/github.com/containerd/cri/pkg/config/config.go
generated
vendored
@ -21,11 +21,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Runtime struct to contain the type(ID), engine, and root variables for a default runtime
|
// Runtime struct to contain the type(ID), engine, and root variables for a default runtime
|
||||||
@ -40,6 +38,10 @@ type Runtime struct {
|
|||||||
// PodAnnotations is a list of pod annotations passed to both pod sandbox as well as
|
// PodAnnotations is a list of pod annotations passed to both pod sandbox as well as
|
||||||
// container OCI annotations.
|
// container OCI annotations.
|
||||||
PodAnnotations []string `toml:"pod_annotations" json:"PodAnnotations"`
|
PodAnnotations []string `toml:"pod_annotations" json:"PodAnnotations"`
|
||||||
|
// ContainerAnnotations is a list of container annotations passed through to the OCI config of the containers.
|
||||||
|
// Container annotations in CRI are usually generated by other Kubernetes node components (i.e., not users).
|
||||||
|
// Currently, only device plugins populate the annotations.
|
||||||
|
ContainerAnnotations []string `toml:"container_annotations" json:"ContainerAnnotations"`
|
||||||
// Root is the directory used by containerd for runtime state.
|
// Root is the directory used by containerd for runtime state.
|
||||||
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
||||||
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
||||||
@ -132,7 +134,7 @@ type Registry struct {
|
|||||||
// Mirrors are namespace to mirror mapping for all namespaces.
|
// Mirrors are namespace to mirror mapping for all namespaces.
|
||||||
Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"`
|
Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"`
|
||||||
// Configs are configs for each registry.
|
// Configs are configs for each registry.
|
||||||
// The key is the FDQN or IP of the registry.
|
// The key is the domain name or IP of the registry.
|
||||||
Configs map[string]RegistryConfig `toml:"configs" json:"configs"`
|
Configs map[string]RegistryConfig `toml:"configs" json:"configs"`
|
||||||
|
|
||||||
// Auths are registry endpoint to auth config mapping. The registry endpoint must
|
// Auths are registry endpoint to auth config mapping. The registry endpoint must
|
||||||
@ -228,51 +230,6 @@ type Config struct {
|
|||||||
StateDir string `json:"stateDir"`
|
StateDir string `json:"stateDir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig returns default configurations of cri plugin.
|
|
||||||
func DefaultConfig() PluginConfig {
|
|
||||||
return PluginConfig{
|
|
||||||
CniConfig: CniConfig{
|
|
||||||
NetworkPluginBinDir: "/opt/cni/bin",
|
|
||||||
NetworkPluginConfDir: "/etc/cni/net.d",
|
|
||||||
NetworkPluginMaxConfNum: 1, // only one CNI plugin config file will be loaded
|
|
||||||
NetworkPluginConfTemplate: "",
|
|
||||||
},
|
|
||||||
ContainerdConfig: ContainerdConfig{
|
|
||||||
Snapshotter: containerd.DefaultSnapshotter,
|
|
||||||
DefaultRuntimeName: "runc",
|
|
||||||
NoPivot: false,
|
|
||||||
Runtimes: map[string]Runtime{
|
|
||||||
"runc": {
|
|
||||||
Type: "io.containerd.runc.v1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
DisableTCPService: true,
|
|
||||||
StreamServerAddress: "127.0.0.1",
|
|
||||||
StreamServerPort: "0",
|
|
||||||
StreamIdleTimeout: streaming.DefaultConfig.StreamIdleTimeout.String(), // 4 hour
|
|
||||||
EnableSelinux: false,
|
|
||||||
EnableTLSStreaming: false,
|
|
||||||
X509KeyPairStreaming: X509KeyPairStreaming{
|
|
||||||
TLSKeyFile: "",
|
|
||||||
TLSCertFile: "",
|
|
||||||
},
|
|
||||||
SandboxImage: "k8s.gcr.io/pause:3.1",
|
|
||||||
StatsCollectPeriod: 10,
|
|
||||||
SystemdCgroup: false,
|
|
||||||
MaxContainerLogLineSize: 16 * 1024,
|
|
||||||
Registry: Registry{
|
|
||||||
Mirrors: map[string]Mirror{
|
|
||||||
"docker.io": {
|
|
||||||
Endpoints: []string{"https://registry-1.docker.io"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MaxConcurrentDownloads: 3,
|
|
||||||
DisableProcMount: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RuntimeUntrusted is the implicit runtime defined for ContainerdConfig.UntrustedWorkloadRuntime
|
// RuntimeUntrusted is the implicit runtime defined for ContainerdConfig.UntrustedWorkloadRuntime
|
||||||
RuntimeUntrusted = "untrusted"
|
RuntimeUntrusted = "untrusted"
|
||||||
|
69
vendor/github.com/containerd/cri/pkg/config/config_unix.go
generated
vendored
Normal file
69
vendor/github.com/containerd/cri/pkg/config/config_unix.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultConfig returns default configurations of cri plugin.
|
||||||
|
func DefaultConfig() PluginConfig {
|
||||||
|
return PluginConfig{
|
||||||
|
CniConfig: CniConfig{
|
||||||
|
NetworkPluginBinDir: "/opt/cni/bin",
|
||||||
|
NetworkPluginConfDir: "/etc/cni/net.d",
|
||||||
|
NetworkPluginMaxConfNum: 1, // only one CNI plugin config file will be loaded
|
||||||
|
NetworkPluginConfTemplate: "",
|
||||||
|
},
|
||||||
|
ContainerdConfig: ContainerdConfig{
|
||||||
|
Snapshotter: containerd.DefaultSnapshotter,
|
||||||
|
DefaultRuntimeName: "runc",
|
||||||
|
NoPivot: false,
|
||||||
|
Runtimes: map[string]Runtime{
|
||||||
|
"runc": {
|
||||||
|
Type: "io.containerd.runc.v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DisableTCPService: true,
|
||||||
|
StreamServerAddress: "127.0.0.1",
|
||||||
|
StreamServerPort: "0",
|
||||||
|
StreamIdleTimeout: streaming.DefaultConfig.StreamIdleTimeout.String(), // 4 hour
|
||||||
|
EnableSelinux: false,
|
||||||
|
EnableTLSStreaming: false,
|
||||||
|
X509KeyPairStreaming: X509KeyPairStreaming{
|
||||||
|
TLSKeyFile: "",
|
||||||
|
TLSCertFile: "",
|
||||||
|
},
|
||||||
|
SandboxImage: "k8s.gcr.io/pause:3.1",
|
||||||
|
StatsCollectPeriod: 10,
|
||||||
|
SystemdCgroup: false,
|
||||||
|
MaxContainerLogLineSize: 16 * 1024,
|
||||||
|
Registry: Registry{
|
||||||
|
Mirrors: map[string]Mirror{
|
||||||
|
"docker.io": {
|
||||||
|
Endpoints: []string{"https://registry-1.docker.io"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxConcurrentDownloads: 3,
|
||||||
|
DisableProcMount: false,
|
||||||
|
}
|
||||||
|
}
|
70
vendor/github.com/containerd/cri/pkg/config/config_windows.go
generated
vendored
Normal file
70
vendor/github.com/containerd/cri/pkg/config/config_windows.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultConfig returns default configurations of cri plugin.
|
||||||
|
func DefaultConfig() PluginConfig {
|
||||||
|
return PluginConfig{
|
||||||
|
CniConfig: CniConfig{
|
||||||
|
NetworkPluginBinDir: filepath.Join(os.Getenv("ProgramFiles"), "containerd", "cni", "bin"),
|
||||||
|
NetworkPluginConfDir: filepath.Join(os.Getenv("ProgramFiles"), "containerd", "cni", "conf"),
|
||||||
|
NetworkPluginMaxConfNum: 1,
|
||||||
|
NetworkPluginConfTemplate: "",
|
||||||
|
},
|
||||||
|
ContainerdConfig: ContainerdConfig{
|
||||||
|
Snapshotter: containerd.DefaultSnapshotter,
|
||||||
|
DefaultRuntimeName: "runhcs-wcow-process",
|
||||||
|
NoPivot: false,
|
||||||
|
Runtimes: map[string]Runtime{
|
||||||
|
"runhcs-wcow-process": {
|
||||||
|
Type: "io.containerd.runhcs.v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DisableTCPService: true,
|
||||||
|
StreamServerAddress: "127.0.0.1",
|
||||||
|
StreamServerPort: "0",
|
||||||
|
StreamIdleTimeout: streaming.DefaultConfig.StreamIdleTimeout.String(), // 4 hour
|
||||||
|
EnableTLSStreaming: false,
|
||||||
|
X509KeyPairStreaming: X509KeyPairStreaming{
|
||||||
|
TLSKeyFile: "",
|
||||||
|
TLSCertFile: "",
|
||||||
|
},
|
||||||
|
SandboxImage: "mcr.microsoft.com/k8s/core/pause:1.2.0",
|
||||||
|
StatsCollectPeriod: 10,
|
||||||
|
MaxContainerLogLineSize: 16 * 1024,
|
||||||
|
Registry: Registry{
|
||||||
|
Mirrors: map[string]Mirror{
|
||||||
|
"docker.io": {
|
||||||
|
Endpoints: []string{"https://registry-1.docker.io"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxConcurrentDownloads: 3,
|
||||||
|
// TODO(windows): Add platform specific config, so that most common defaults can be shared.
|
||||||
|
}
|
||||||
|
}
|
650
vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go
generated
vendored
650
vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go
generated
vendored
@ -18,99 +18,22 @@ package opts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/mount"
|
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
|
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/opencontainers/runc/libcontainer/devices"
|
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
osinterface "github.com/containerd/cri/pkg/os"
|
|
||||||
"github.com/containerd/cri/pkg/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// DefaultSandboxCPUshares is default cpu shares for sandbox container.
|
||||||
// DefaultSandboxCPUshares is default cpu shares for sandbox container.
|
// TODO(windows): Revisit cpu shares for windows (https://github.com/containerd/cri/issues/1297)
|
||||||
DefaultSandboxCPUshares = 2
|
const DefaultSandboxCPUshares = 2
|
||||||
)
|
|
||||||
|
|
||||||
// WithAdditionalGIDs adds any additional groups listed for a particular user in the
|
|
||||||
// /etc/groups file of the image's root filesystem to the OCI spec's additionalGids array.
|
|
||||||
func WithAdditionalGIDs(userstr string) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
gids := s.Process.User.AdditionalGids
|
|
||||||
if err := oci.WithAdditionalGIDs(userstr)(ctx, client, c, s); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Merge existing gids and new gids.
|
|
||||||
s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, gids)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeGids(gids1, gids2 []uint32) []uint32 {
|
|
||||||
gidsMap := make(map[uint32]struct{})
|
|
||||||
for _, gid1 := range gids1 {
|
|
||||||
gidsMap[gid1] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, gid2 := range gids2 {
|
|
||||||
gidsMap[gid2] = struct{}{}
|
|
||||||
}
|
|
||||||
var gids []uint32
|
|
||||||
for gid := range gidsMap {
|
|
||||||
gids = append(gids, gid)
|
|
||||||
}
|
|
||||||
sort.Slice(gids, func(i, j int) bool { return gids[i] < gids[j] })
|
|
||||||
return gids
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutRunMount removes the `/run` inside the spec
|
|
||||||
func WithoutRunMount(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
var (
|
|
||||||
mounts []runtimespec.Mount
|
|
||||||
current = s.Mounts
|
|
||||||
)
|
|
||||||
for _, m := range current {
|
|
||||||
if filepath.Clean(m.Destination) == "/run" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mounts = append(mounts, m)
|
|
||||||
}
|
|
||||||
s.Mounts = mounts
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutDefaultSecuritySettings removes the default security settings generated on a spec
|
|
||||||
func WithoutDefaultSecuritySettings(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
// Make sure no default seccomp/apparmor is specified
|
|
||||||
s.Process.ApparmorProfile = ""
|
|
||||||
if s.Linux != nil {
|
|
||||||
s.Linux.Seccomp = nil
|
|
||||||
}
|
|
||||||
// Remove default rlimits (See issue #515)
|
|
||||||
s.Process.Rlimits = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRelativeRoot sets the root for the container
|
// WithRelativeRoot sets the root for the container
|
||||||
func WithRelativeRoot(root string) oci.SpecOpts {
|
func WithRelativeRoot(root string) oci.SpecOpts {
|
||||||
@ -123,6 +46,12 @@ func WithRelativeRoot(root string) oci.SpecOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithoutRoot sets the root to nil for the container.
|
||||||
|
func WithoutRoot(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
s.Root = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// WithProcessArgs sets the process args on the spec based on the image and runtime config
|
// WithProcessArgs sets the process args on the spec based on the image and runtime config
|
||||||
func WithProcessArgs(config *runtime.ContainerConfig, image *imagespec.ImageConfig) oci.SpecOpts {
|
func WithProcessArgs(config *runtime.ContainerConfig, image *imagespec.ImageConfig) oci.SpecOpts {
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
@ -145,141 +74,6 @@ func WithProcessArgs(config *runtime.ContainerConfig, image *imagespec.ImageConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithMounts sorts and adds runtime and CRI mounts to the spec
|
|
||||||
func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount, mountLabel string) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) (err error) {
|
|
||||||
// mergeMounts merge CRI mounts with extra mounts. If a mount destination
|
|
||||||
// is mounted by both a CRI mount and an extra mount, the CRI mount will
|
|
||||||
// be kept.
|
|
||||||
var (
|
|
||||||
criMounts = config.GetMounts()
|
|
||||||
mounts = append([]*runtime.Mount{}, criMounts...)
|
|
||||||
)
|
|
||||||
// Copy all mounts from extra mounts, except for mounts overriden by CRI.
|
|
||||||
for _, e := range extra {
|
|
||||||
found := false
|
|
||||||
for _, c := range criMounts {
|
|
||||||
if filepath.Clean(e.ContainerPath) == filepath.Clean(c.ContainerPath) {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
mounts = append(mounts, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ---
|
|
||||||
|
|
||||||
// Sort mounts in number of parts. This ensures that high level mounts don't
|
|
||||||
// shadow other mounts.
|
|
||||||
sort.Sort(orderedMounts(mounts))
|
|
||||||
|
|
||||||
// Mount cgroup into the container as readonly, which inherits docker's behavior.
|
|
||||||
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
|
||||||
Source: "cgroup",
|
|
||||||
Destination: "/sys/fs/cgroup",
|
|
||||||
Type: "cgroup",
|
|
||||||
Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Copy all mounts from default mounts, except for
|
|
||||||
// - mounts overriden by supplied mount;
|
|
||||||
// - all mounts under /dev if a supplied /dev is present.
|
|
||||||
mountSet := make(map[string]struct{})
|
|
||||||
for _, m := range mounts {
|
|
||||||
mountSet[filepath.Clean(m.ContainerPath)] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultMounts := s.Mounts
|
|
||||||
s.Mounts = nil
|
|
||||||
|
|
||||||
for _, m := range defaultMounts {
|
|
||||||
dst := filepath.Clean(m.Destination)
|
|
||||||
if _, ok := mountSet[dst]; ok {
|
|
||||||
// filter out mount overridden by a supplied mount
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, mountDev := mountSet["/dev"]; mountDev && strings.HasPrefix(dst, "/dev/") {
|
|
||||||
// filter out everything under /dev if /dev is a supplied mount
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s.Mounts = append(s.Mounts, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mount := range mounts {
|
|
||||||
var (
|
|
||||||
dst = mount.GetContainerPath()
|
|
||||||
src = mount.GetHostPath()
|
|
||||||
)
|
|
||||||
// Create the host path if it doesn't exist.
|
|
||||||
// TODO(random-liu): Add CRI validation test for this case.
|
|
||||||
if _, err := osi.Stat(src); err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return errors.Wrapf(err, "failed to stat %q", src)
|
|
||||||
}
|
|
||||||
if err := osi.MkdirAll(src, 0755); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to mkdir %q", src)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO(random-liu): Add cri-containerd integration test or cri validation test
|
|
||||||
// for this.
|
|
||||||
src, err := osi.ResolveSymbolicLink(src)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to resolve symlink %q", src)
|
|
||||||
}
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
options := []string{"rbind"}
|
|
||||||
switch mount.GetPropagation() {
|
|
||||||
case runtime.MountPropagation_PROPAGATION_PRIVATE:
|
|
||||||
options = append(options, "rprivate")
|
|
||||||
// Since default root propogation in runc is rprivate ignore
|
|
||||||
// setting the root propagation
|
|
||||||
case runtime.MountPropagation_PROPAGATION_BIDIRECTIONAL:
|
|
||||||
if err := ensureShared(src, osi.LookupMount); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
options = append(options, "rshared")
|
|
||||||
s.Linux.RootfsPropagation = "rshared"
|
|
||||||
case runtime.MountPropagation_PROPAGATION_HOST_TO_CONTAINER:
|
|
||||||
if err := ensureSharedOrSlave(src, osi.LookupMount); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
options = append(options, "rslave")
|
|
||||||
if s.Linux.RootfsPropagation != "rshared" &&
|
|
||||||
s.Linux.RootfsPropagation != "rslave" {
|
|
||||||
s.Linux.RootfsPropagation = "rslave"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.G(ctx).Warnf("Unknown propagation mode for hostPath %q", mount.HostPath)
|
|
||||||
options = append(options, "rprivate")
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(random-liu): we don't change all mounts to `ro` when root filesystem
|
|
||||||
// is readonly. This is different from docker's behavior, but make more sense.
|
|
||||||
if mount.GetReadonly() {
|
|
||||||
options = append(options, "ro")
|
|
||||||
} else {
|
|
||||||
options = append(options, "rw")
|
|
||||||
}
|
|
||||||
|
|
||||||
if mount.GetSelinuxRelabel() {
|
|
||||||
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
|
|
||||||
return errors.Wrapf(err, "relabel %q with %q failed", src, mountLabel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
|
||||||
Source: src,
|
|
||||||
Destination: dst,
|
|
||||||
Type: "bind",
|
|
||||||
Options: options,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mounts defines how to sort runtime.Mount.
|
// mounts defines how to sort runtime.Mount.
|
||||||
// This is the same with the Docker implementation:
|
// This is the same with the Docker implementation:
|
||||||
// https://github.com/moby/moby/blob/17.05.x/daemon/volumes.go#L26
|
// https://github.com/moby/moby/blob/17.05.x/daemon/volumes.go#L26
|
||||||
@ -307,325 +101,6 @@ func (m orderedMounts) parts(i int) int {
|
|||||||
return strings.Count(filepath.Clean(m[i].ContainerPath), string(os.PathSeparator))
|
return strings.Count(filepath.Clean(m[i].ContainerPath), string(os.PathSeparator))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure mount point on which path is mounted, is shared.
|
|
||||||
func ensureShared(path string, lookupMount func(string) (mount.Info, error)) error {
|
|
||||||
mountInfo, err := lookupMount(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure source mount point is shared.
|
|
||||||
optsSplit := strings.Split(mountInfo.Optional, " ")
|
|
||||||
for _, opt := range optsSplit {
|
|
||||||
if strings.HasPrefix(opt, "shared:") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.Errorf("path %q is mounted on %q but it is not a shared mount", path, mountInfo.Mountpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure mount point on which path is mounted, is either shared or slave.
|
|
||||||
func ensureSharedOrSlave(path string, lookupMount func(string) (mount.Info, error)) error {
|
|
||||||
mountInfo, err := lookupMount(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Make sure source mount point is shared.
|
|
||||||
optsSplit := strings.Split(mountInfo.Optional, " ")
|
|
||||||
for _, opt := range optsSplit {
|
|
||||||
if strings.HasPrefix(opt, "shared:") {
|
|
||||||
return nil
|
|
||||||
} else if strings.HasPrefix(opt, "master:") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.Errorf("path %q is mounted on %q but it is not a shared or slave mount", path, mountInfo.Mountpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPrivilegedDevices allows all host devices inside the container
|
|
||||||
func WithPrivilegedDevices(_ context.Context, _ oci.Client, _ *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources == nil {
|
|
||||||
s.Linux.Resources = &runtimespec.LinuxResources{}
|
|
||||||
}
|
|
||||||
hostDevices, err := devices.HostDevices()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, hostDevice := range hostDevices {
|
|
||||||
rd := runtimespec.LinuxDevice{
|
|
||||||
Path: hostDevice.Path,
|
|
||||||
Type: string(hostDevice.Type),
|
|
||||||
Major: hostDevice.Major,
|
|
||||||
Minor: hostDevice.Minor,
|
|
||||||
UID: &hostDevice.Uid,
|
|
||||||
GID: &hostDevice.Gid,
|
|
||||||
}
|
|
||||||
if hostDevice.Major == 0 && hostDevice.Minor == 0 {
|
|
||||||
// Invalid device, most likely a symbolic link, skip it.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
addDevice(s, rd)
|
|
||||||
}
|
|
||||||
s.Linux.Resources.Devices = []runtimespec.LinuxDeviceCgroup{
|
|
||||||
{
|
|
||||||
Allow: true,
|
|
||||||
Access: "rwm",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addDevice(s *runtimespec.Spec, rd runtimespec.LinuxDevice) {
|
|
||||||
for i, dev := range s.Linux.Devices {
|
|
||||||
if dev.Path == rd.Path {
|
|
||||||
s.Linux.Devices[i] = rd
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Linux.Devices = append(s.Linux.Devices, rd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDevices sets the provided devices onto the container spec
|
|
||||||
func WithDevices(osi osinterface.OS, config *runtime.ContainerConfig) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources == nil {
|
|
||||||
s.Linux.Resources = &runtimespec.LinuxResources{}
|
|
||||||
}
|
|
||||||
for _, device := range config.GetDevices() {
|
|
||||||
path, err := osi.ResolveSymbolicLink(device.HostPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dev, err := devices.DeviceFromPath(path, device.Permissions)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rd := runtimespec.LinuxDevice{
|
|
||||||
Path: device.ContainerPath,
|
|
||||||
Type: string(dev.Type),
|
|
||||||
Major: dev.Major,
|
|
||||||
Minor: dev.Minor,
|
|
||||||
UID: &dev.Uid,
|
|
||||||
GID: &dev.Gid,
|
|
||||||
}
|
|
||||||
|
|
||||||
addDevice(s, rd)
|
|
||||||
|
|
||||||
s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, runtimespec.LinuxDeviceCgroup{
|
|
||||||
Allow: true,
|
|
||||||
Type: string(dev.Type),
|
|
||||||
Major: &dev.Major,
|
|
||||||
Minor: &dev.Minor,
|
|
||||||
Access: dev.Permissions,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithCapabilities sets the provided capabilties from the security context
|
|
||||||
func WithCapabilities(sc *runtime.LinuxContainerSecurityContext) oci.SpecOpts {
|
|
||||||
capabilities := sc.GetCapabilities()
|
|
||||||
if capabilities == nil {
|
|
||||||
return nullOpt
|
|
||||||
}
|
|
||||||
|
|
||||||
var opts []oci.SpecOpts
|
|
||||||
// Add/drop all capabilities if "all" is specified, so that
|
|
||||||
// following individual add/drop could still work. E.g.
|
|
||||||
// AddCapabilities: []string{"ALL"}, DropCapabilities: []string{"CHOWN"}
|
|
||||||
// will be all capabilities without `CAP_CHOWN`.
|
|
||||||
if util.InStringSlice(capabilities.GetAddCapabilities(), "ALL") {
|
|
||||||
opts = append(opts, oci.WithAllCapabilities)
|
|
||||||
}
|
|
||||||
if util.InStringSlice(capabilities.GetDropCapabilities(), "ALL") {
|
|
||||||
opts = append(opts, oci.WithCapabilities(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
var caps []string
|
|
||||||
for _, c := range capabilities.GetAddCapabilities() {
|
|
||||||
if strings.ToUpper(c) == "ALL" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Capabilities in CRI doesn't have `CAP_` prefix, so add it.
|
|
||||||
caps = append(caps, "CAP_"+strings.ToUpper(c))
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithAddedCapabilities(caps))
|
|
||||||
|
|
||||||
caps = []string{}
|
|
||||||
for _, c := range capabilities.GetDropCapabilities() {
|
|
||||||
if strings.ToUpper(c) == "ALL" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
caps = append(caps, "CAP_"+strings.ToUpper(c))
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithDroppedCapabilities(caps))
|
|
||||||
return oci.Compose(opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutAmbientCaps removes the ambient caps from the spec
|
|
||||||
func WithoutAmbientCaps(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
if s.Process.Capabilities == nil {
|
|
||||||
s.Process.Capabilities = &runtimespec.LinuxCapabilities{}
|
|
||||||
}
|
|
||||||
s.Process.Capabilities.Ambient = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDisabledCgroups clears the Cgroups Path from the spec
|
|
||||||
func WithDisabledCgroups(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
s.Linux.CgroupsPath = ""
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithSelinuxLabels sets the mount and process labels
|
|
||||||
func WithSelinuxLabels(process, mount string) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
s.Linux.MountLabel = mount
|
|
||||||
s.Process.SelinuxLabel = process
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithResources sets the provided resource restrictions
|
|
||||||
func WithResources(resources *runtime.LinuxContainerResources) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
|
||||||
if resources == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources == nil {
|
|
||||||
s.Linux.Resources = &runtimespec.LinuxResources{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources.CPU == nil {
|
|
||||||
s.Linux.Resources.CPU = &runtimespec.LinuxCPU{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources.Memory == nil {
|
|
||||||
s.Linux.Resources.Memory = &runtimespec.LinuxMemory{}
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
p = uint64(resources.GetCpuPeriod())
|
|
||||||
q = resources.GetCpuQuota()
|
|
||||||
shares = uint64(resources.GetCpuShares())
|
|
||||||
limit = resources.GetMemoryLimitInBytes()
|
|
||||||
)
|
|
||||||
|
|
||||||
if p != 0 {
|
|
||||||
s.Linux.Resources.CPU.Period = &p
|
|
||||||
}
|
|
||||||
if q != 0 {
|
|
||||||
s.Linux.Resources.CPU.Quota = &q
|
|
||||||
}
|
|
||||||
if shares != 0 {
|
|
||||||
s.Linux.Resources.CPU.Shares = &shares
|
|
||||||
}
|
|
||||||
if cpus := resources.GetCpusetCpus(); cpus != "" {
|
|
||||||
s.Linux.Resources.CPU.Cpus = cpus
|
|
||||||
}
|
|
||||||
if mems := resources.GetCpusetMems(); mems != "" {
|
|
||||||
s.Linux.Resources.CPU.Mems = resources.GetCpusetMems()
|
|
||||||
}
|
|
||||||
if limit != 0 {
|
|
||||||
s.Linux.Resources.Memory.Limit = &limit
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithOOMScoreAdj sets the oom score
|
|
||||||
func WithOOMScoreAdj(config *runtime.ContainerConfig, restrict bool) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
|
|
||||||
resources := config.GetLinux().GetResources()
|
|
||||||
if resources == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
adj := int(resources.GetOomScoreAdj())
|
|
||||||
if restrict {
|
|
||||||
var err error
|
|
||||||
adj, err = restrictOOMScoreAdj(adj)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Process.OOMScoreAdj = &adj
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithSysctls sets the provided sysctls onto the spec
|
|
||||||
func WithSysctls(sysctls map[string]string) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Linux.Sysctl == nil {
|
|
||||||
s.Linux.Sysctl = make(map[string]string)
|
|
||||||
}
|
|
||||||
for k, v := range sysctls {
|
|
||||||
s.Linux.Sysctl[k] = v
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPodOOMScoreAdj sets the oom score for the pod sandbox
|
|
||||||
func WithPodOOMScoreAdj(adj int, restrict bool) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
if restrict {
|
|
||||||
var err error
|
|
||||||
adj, err = restrictOOMScoreAdj(adj)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Process.OOMScoreAdj = &adj
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithSupplementalGroups sets the supplemental groups for the process
|
|
||||||
func WithSupplementalGroups(groups []int64) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Process == nil {
|
|
||||||
s.Process = &runtimespec.Process{}
|
|
||||||
}
|
|
||||||
var guids []uint32
|
|
||||||
for _, g := range groups {
|
|
||||||
guids = append(guids, uint32(g))
|
|
||||||
}
|
|
||||||
s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, guids)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAnnotation sets the provided annotation
|
// WithAnnotation sets the provided annotation
|
||||||
func WithAnnotation(k, v string) oci.SpecOpts {
|
func WithAnnotation(k, v string) oci.SpecOpts {
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
@ -636,110 +111,3 @@ func WithAnnotation(k, v string) oci.SpecOpts {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithPodNamespaces sets the pod namespaces for the container
|
|
||||||
func WithPodNamespaces(config *runtime.LinuxContainerSecurityContext, pid uint32) oci.SpecOpts {
|
|
||||||
namespaces := config.GetNamespaceOptions()
|
|
||||||
|
|
||||||
opts := []oci.SpecOpts{
|
|
||||||
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.NetworkNamespace, Path: GetNetworkNamespace(pid)}),
|
|
||||||
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.IPCNamespace, Path: GetIPCNamespace(pid)}),
|
|
||||||
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.UTSNamespace, Path: GetUTSNamespace(pid)}),
|
|
||||||
}
|
|
||||||
if namespaces.GetPid() != runtime.NamespaceMode_CONTAINER {
|
|
||||||
opts = append(opts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.PIDNamespace, Path: GetPIDNamespace(pid)}))
|
|
||||||
}
|
|
||||||
return oci.Compose(opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDefaultSandboxShares sets the default sandbox CPU shares
|
|
||||||
func WithDefaultSandboxShares(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Linux == nil {
|
|
||||||
s.Linux = &runtimespec.Linux{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources == nil {
|
|
||||||
s.Linux.Resources = &runtimespec.LinuxResources{}
|
|
||||||
}
|
|
||||||
if s.Linux.Resources.CPU == nil {
|
|
||||||
s.Linux.Resources.CPU = &runtimespec.LinuxCPU{}
|
|
||||||
}
|
|
||||||
i := uint64(DefaultSandboxCPUshares)
|
|
||||||
s.Linux.Resources.CPU.Shares = &i
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutNamespace removes the provided namespace
|
|
||||||
func WithoutNamespace(t runtimespec.LinuxNamespaceType) oci.SpecOpts {
|
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
|
||||||
if s.Linux == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var namespaces []runtimespec.LinuxNamespace
|
|
||||||
for i, ns := range s.Linux.Namespaces {
|
|
||||||
if ns.Type != t {
|
|
||||||
namespaces = append(namespaces, s.Linux.Namespaces[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.Linux.Namespaces = namespaces
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func nullOpt(_ context.Context, _ oci.Client, _ *containers.Container, _ *runtimespec.Spec) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCurrentOOMScoreAdj() (int, error) {
|
|
||||||
b, err := ioutil.ReadFile("/proc/self/oom_score_adj")
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
|
||||||
}
|
|
||||||
s := strings.TrimSpace(string(b))
|
|
||||||
i, err := strconv.Atoi(s)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func restrictOOMScoreAdj(preferredOOMScoreAdj int) (int, error) {
|
|
||||||
currentOOMScoreAdj, err := getCurrentOOMScoreAdj()
|
|
||||||
if err != nil {
|
|
||||||
return preferredOOMScoreAdj, err
|
|
||||||
}
|
|
||||||
if preferredOOMScoreAdj < currentOOMScoreAdj {
|
|
||||||
return currentOOMScoreAdj, nil
|
|
||||||
}
|
|
||||||
return preferredOOMScoreAdj, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// netNSFormat is the format of network namespace of a process.
|
|
||||||
netNSFormat = "/proc/%v/ns/net"
|
|
||||||
// ipcNSFormat is the format of ipc namespace of a process.
|
|
||||||
ipcNSFormat = "/proc/%v/ns/ipc"
|
|
||||||
// utsNSFormat is the format of uts namespace of a process.
|
|
||||||
utsNSFormat = "/proc/%v/ns/uts"
|
|
||||||
// pidNSFormat is the format of pid namespace of a process.
|
|
||||||
pidNSFormat = "/proc/%v/ns/pid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetNetworkNamespace returns the network namespace of a process.
|
|
||||||
func GetNetworkNamespace(pid uint32) string {
|
|
||||||
return fmt.Sprintf(netNSFormat, pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIPCNamespace returns the ipc namespace of a process.
|
|
||||||
func GetIPCNamespace(pid uint32) string {
|
|
||||||
return fmt.Sprintf(ipcNSFormat, pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUTSNamespace returns the uts namespace of a process.
|
|
||||||
func GetUTSNamespace(pid uint32) string {
|
|
||||||
return fmt.Sprintf(utsNSFormat, pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPIDNamespace returns the pid namespace of a process.
|
|
||||||
func GetPIDNamespace(pid uint32) string {
|
|
||||||
return fmt.Sprintf(pidNSFormat, pid)
|
|
||||||
}
|
|
||||||
|
668
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go
generated
vendored
Normal file
668
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go
generated
vendored
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package opts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
osinterface "github.com/containerd/cri/pkg/os"
|
||||||
|
"github.com/containerd/cri/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithAdditionalGIDs adds any additional groups listed for a particular user in the
|
||||||
|
// /etc/groups file of the image's root filesystem to the OCI spec's additionalGids array.
|
||||||
|
func WithAdditionalGIDs(userstr string) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
gids := s.Process.User.AdditionalGids
|
||||||
|
if err := oci.WithAdditionalGIDs(userstr)(ctx, client, c, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Merge existing gids and new gids.
|
||||||
|
s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, gids)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeGids(gids1, gids2 []uint32) []uint32 {
|
||||||
|
gidsMap := make(map[uint32]struct{})
|
||||||
|
for _, gid1 := range gids1 {
|
||||||
|
gidsMap[gid1] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, gid2 := range gids2 {
|
||||||
|
gidsMap[gid2] = struct{}{}
|
||||||
|
}
|
||||||
|
var gids []uint32
|
||||||
|
for gid := range gidsMap {
|
||||||
|
gids = append(gids, gid)
|
||||||
|
}
|
||||||
|
sort.Slice(gids, func(i, j int) bool { return gids[i] < gids[j] })
|
||||||
|
return gids
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutRunMount removes the `/run` inside the spec
|
||||||
|
func WithoutRunMount(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
var (
|
||||||
|
mounts []runtimespec.Mount
|
||||||
|
current = s.Mounts
|
||||||
|
)
|
||||||
|
for _, m := range current {
|
||||||
|
if filepath.Clean(m.Destination) == "/run" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mounts = append(mounts, m)
|
||||||
|
}
|
||||||
|
s.Mounts = mounts
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutDefaultSecuritySettings removes the default security settings generated on a spec
|
||||||
|
func WithoutDefaultSecuritySettings(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
// Make sure no default seccomp/apparmor is specified
|
||||||
|
s.Process.ApparmorProfile = ""
|
||||||
|
if s.Linux != nil {
|
||||||
|
s.Linux.Seccomp = nil
|
||||||
|
}
|
||||||
|
// Remove default rlimits (See issue #515)
|
||||||
|
s.Process.Rlimits = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMounts sorts and adds runtime and CRI mounts to the spec
|
||||||
|
func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount, mountLabel string) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
|
// mergeMounts merge CRI mounts with extra mounts. If a mount destination
|
||||||
|
// is mounted by both a CRI mount and an extra mount, the CRI mount will
|
||||||
|
// be kept.
|
||||||
|
var (
|
||||||
|
criMounts = config.GetMounts()
|
||||||
|
mounts = append([]*runtime.Mount{}, criMounts...)
|
||||||
|
)
|
||||||
|
// Copy all mounts from extra mounts, except for mounts overridden by CRI.
|
||||||
|
for _, e := range extra {
|
||||||
|
found := false
|
||||||
|
for _, c := range criMounts {
|
||||||
|
if filepath.Clean(e.ContainerPath) == filepath.Clean(c.ContainerPath) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
mounts = append(mounts, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort mounts in number of parts. This ensures that high level mounts don't
|
||||||
|
// shadow other mounts.
|
||||||
|
sort.Sort(orderedMounts(mounts))
|
||||||
|
|
||||||
|
// Mount cgroup into the container as readonly, which inherits docker's behavior.
|
||||||
|
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
||||||
|
Source: "cgroup",
|
||||||
|
Destination: "/sys/fs/cgroup",
|
||||||
|
Type: "cgroup",
|
||||||
|
Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Copy all mounts from default mounts, except for
|
||||||
|
// - mounts overridden by supplied mount;
|
||||||
|
// - all mounts under /dev if a supplied /dev is present.
|
||||||
|
mountSet := make(map[string]struct{})
|
||||||
|
for _, m := range mounts {
|
||||||
|
mountSet[filepath.Clean(m.ContainerPath)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultMounts := s.Mounts
|
||||||
|
s.Mounts = nil
|
||||||
|
|
||||||
|
for _, m := range defaultMounts {
|
||||||
|
dst := filepath.Clean(m.Destination)
|
||||||
|
if _, ok := mountSet[dst]; ok {
|
||||||
|
// filter out mount overridden by a supplied mount
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, mountDev := mountSet["/dev"]; mountDev && strings.HasPrefix(dst, "/dev/") {
|
||||||
|
// filter out everything under /dev if /dev is a supplied mount
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Mounts = append(s.Mounts, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mount := range mounts {
|
||||||
|
var (
|
||||||
|
dst = mount.GetContainerPath()
|
||||||
|
src = mount.GetHostPath()
|
||||||
|
)
|
||||||
|
// Create the host path if it doesn't exist.
|
||||||
|
// TODO(random-liu): Add CRI validation test for this case.
|
||||||
|
if _, err := osi.Stat(src); err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return errors.Wrapf(err, "failed to stat %q", src)
|
||||||
|
}
|
||||||
|
if err := osi.MkdirAll(src, 0755); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to mkdir %q", src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO(random-liu): Add cri-containerd integration test or cri validation test
|
||||||
|
// for this.
|
||||||
|
src, err := osi.ResolveSymbolicLink(src)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to resolve symlink %q", src)
|
||||||
|
}
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
options := []string{"rbind"}
|
||||||
|
switch mount.GetPropagation() {
|
||||||
|
case runtime.MountPropagation_PROPAGATION_PRIVATE:
|
||||||
|
options = append(options, "rprivate")
|
||||||
|
// Since default root propagation in runc is rprivate ignore
|
||||||
|
// setting the root propagation
|
||||||
|
case runtime.MountPropagation_PROPAGATION_BIDIRECTIONAL:
|
||||||
|
if err := ensureShared(src, osi.(osinterface.UNIX).LookupMount); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
options = append(options, "rshared")
|
||||||
|
s.Linux.RootfsPropagation = "rshared"
|
||||||
|
case runtime.MountPropagation_PROPAGATION_HOST_TO_CONTAINER:
|
||||||
|
if err := ensureSharedOrSlave(src, osi.(osinterface.UNIX).LookupMount); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
options = append(options, "rslave")
|
||||||
|
if s.Linux.RootfsPropagation != "rshared" &&
|
||||||
|
s.Linux.RootfsPropagation != "rslave" {
|
||||||
|
s.Linux.RootfsPropagation = "rslave"
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.G(ctx).Warnf("Unknown propagation mode for hostPath %q", mount.HostPath)
|
||||||
|
options = append(options, "rprivate")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(random-liu): we don't change all mounts to `ro` when root filesystem
|
||||||
|
// is readonly. This is different from docker's behavior, but make more sense.
|
||||||
|
if mount.GetReadonly() {
|
||||||
|
options = append(options, "ro")
|
||||||
|
} else {
|
||||||
|
options = append(options, "rw")
|
||||||
|
}
|
||||||
|
|
||||||
|
if mount.GetSelinuxRelabel() {
|
||||||
|
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
|
||||||
|
return errors.Wrapf(err, "relabel %q with %q failed", src, mountLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
||||||
|
Source: src,
|
||||||
|
Destination: dst,
|
||||||
|
Type: "bind",
|
||||||
|
Options: options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure mount point on which path is mounted, is shared.
|
||||||
|
func ensureShared(path string, lookupMount func(string) (mount.Info, error)) error {
|
||||||
|
mountInfo, err := lookupMount(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure source mount point is shared.
|
||||||
|
optsSplit := strings.Split(mountInfo.Optional, " ")
|
||||||
|
for _, opt := range optsSplit {
|
||||||
|
if strings.HasPrefix(opt, "shared:") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Errorf("path %q is mounted on %q but it is not a shared mount", path, mountInfo.Mountpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure mount point on which path is mounted, is either shared or slave.
|
||||||
|
func ensureSharedOrSlave(path string, lookupMount func(string) (mount.Info, error)) error {
|
||||||
|
mountInfo, err := lookupMount(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Make sure source mount point is shared.
|
||||||
|
optsSplit := strings.Split(mountInfo.Optional, " ")
|
||||||
|
for _, opt := range optsSplit {
|
||||||
|
if strings.HasPrefix(opt, "shared:") {
|
||||||
|
return nil
|
||||||
|
} else if strings.HasPrefix(opt, "master:") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.Errorf("path %q is mounted on %q but it is not a shared or slave mount", path, mountInfo.Mountpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPrivilegedDevices allows all host devices inside the container
|
||||||
|
func WithPrivilegedDevices(_ context.Context, _ oci.Client, _ *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources == nil {
|
||||||
|
s.Linux.Resources = &runtimespec.LinuxResources{}
|
||||||
|
}
|
||||||
|
hostDevices, err := devices.HostDevices()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, hostDevice := range hostDevices {
|
||||||
|
rd := runtimespec.LinuxDevice{
|
||||||
|
Path: hostDevice.Path,
|
||||||
|
Type: string(hostDevice.Type),
|
||||||
|
Major: hostDevice.Major,
|
||||||
|
Minor: hostDevice.Minor,
|
||||||
|
UID: &hostDevice.Uid,
|
||||||
|
GID: &hostDevice.Gid,
|
||||||
|
}
|
||||||
|
if hostDevice.Major == 0 && hostDevice.Minor == 0 {
|
||||||
|
// Invalid device, most likely a symbolic link, skip it.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addDevice(s, rd)
|
||||||
|
}
|
||||||
|
s.Linux.Resources.Devices = []runtimespec.LinuxDeviceCgroup{
|
||||||
|
{
|
||||||
|
Allow: true,
|
||||||
|
Access: "rwm",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addDevice(s *runtimespec.Spec, rd runtimespec.LinuxDevice) {
|
||||||
|
for i, dev := range s.Linux.Devices {
|
||||||
|
if dev.Path == rd.Path {
|
||||||
|
s.Linux.Devices[i] = rd
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Linux.Devices = append(s.Linux.Devices, rd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDevices sets the provided devices onto the container spec
|
||||||
|
func WithDevices(osi osinterface.OS, config *runtime.ContainerConfig) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources == nil {
|
||||||
|
s.Linux.Resources = &runtimespec.LinuxResources{}
|
||||||
|
}
|
||||||
|
for _, device := range config.GetDevices() {
|
||||||
|
path, err := osi.ResolveSymbolicLink(device.HostPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dev, err := devices.DeviceFromPath(path, device.Permissions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rd := runtimespec.LinuxDevice{
|
||||||
|
Path: device.ContainerPath,
|
||||||
|
Type: string(dev.Type),
|
||||||
|
Major: dev.Major,
|
||||||
|
Minor: dev.Minor,
|
||||||
|
UID: &dev.Uid,
|
||||||
|
GID: &dev.Gid,
|
||||||
|
}
|
||||||
|
|
||||||
|
addDevice(s, rd)
|
||||||
|
|
||||||
|
s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, runtimespec.LinuxDeviceCgroup{
|
||||||
|
Allow: true,
|
||||||
|
Type: string(dev.Type),
|
||||||
|
Major: &dev.Major,
|
||||||
|
Minor: &dev.Minor,
|
||||||
|
Access: dev.Permissions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCapabilities sets the provided capabilties from the security context
|
||||||
|
func WithCapabilities(sc *runtime.LinuxContainerSecurityContext) oci.SpecOpts {
|
||||||
|
capabilities := sc.GetCapabilities()
|
||||||
|
if capabilities == nil {
|
||||||
|
return nullOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts []oci.SpecOpts
|
||||||
|
// Add/drop all capabilities if "all" is specified, so that
|
||||||
|
// following individual add/drop could still work. E.g.
|
||||||
|
// AddCapabilities: []string{"ALL"}, DropCapabilities: []string{"CHOWN"}
|
||||||
|
// will be all capabilities without `CAP_CHOWN`.
|
||||||
|
if util.InStringSlice(capabilities.GetAddCapabilities(), "ALL") {
|
||||||
|
opts = append(opts, oci.WithAllCapabilities)
|
||||||
|
}
|
||||||
|
if util.InStringSlice(capabilities.GetDropCapabilities(), "ALL") {
|
||||||
|
opts = append(opts, oci.WithCapabilities(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
var caps []string
|
||||||
|
for _, c := range capabilities.GetAddCapabilities() {
|
||||||
|
if strings.ToUpper(c) == "ALL" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Capabilities in CRI doesn't have `CAP_` prefix, so add it.
|
||||||
|
caps = append(caps, "CAP_"+strings.ToUpper(c))
|
||||||
|
}
|
||||||
|
opts = append(opts, oci.WithAddedCapabilities(caps))
|
||||||
|
|
||||||
|
caps = []string{}
|
||||||
|
for _, c := range capabilities.GetDropCapabilities() {
|
||||||
|
if strings.ToUpper(c) == "ALL" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
caps = append(caps, "CAP_"+strings.ToUpper(c))
|
||||||
|
}
|
||||||
|
opts = append(opts, oci.WithDroppedCapabilities(caps))
|
||||||
|
return oci.Compose(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutAmbientCaps removes the ambient caps from the spec
|
||||||
|
func WithoutAmbientCaps(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
if s.Process.Capabilities == nil {
|
||||||
|
s.Process.Capabilities = &runtimespec.LinuxCapabilities{}
|
||||||
|
}
|
||||||
|
s.Process.Capabilities.Ambient = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDisabledCgroups clears the Cgroups Path from the spec
|
||||||
|
func WithDisabledCgroups(_ context.Context, _ oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
s.Linux.CgroupsPath = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSelinuxLabels sets the mount and process labels
|
||||||
|
func WithSelinuxLabels(process, mount string) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
s.Linux.MountLabel = mount
|
||||||
|
s.Process.SelinuxLabel = process
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithResources sets the provided resource restrictions
|
||||||
|
func WithResources(resources *runtime.LinuxContainerResources) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
|
if resources == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources == nil {
|
||||||
|
s.Linux.Resources = &runtimespec.LinuxResources{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources.CPU == nil {
|
||||||
|
s.Linux.Resources.CPU = &runtimespec.LinuxCPU{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources.Memory == nil {
|
||||||
|
s.Linux.Resources.Memory = &runtimespec.LinuxMemory{}
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
p = uint64(resources.GetCpuPeriod())
|
||||||
|
q = resources.GetCpuQuota()
|
||||||
|
shares = uint64(resources.GetCpuShares())
|
||||||
|
limit = resources.GetMemoryLimitInBytes()
|
||||||
|
)
|
||||||
|
|
||||||
|
if p != 0 {
|
||||||
|
s.Linux.Resources.CPU.Period = &p
|
||||||
|
}
|
||||||
|
if q != 0 {
|
||||||
|
s.Linux.Resources.CPU.Quota = &q
|
||||||
|
}
|
||||||
|
if shares != 0 {
|
||||||
|
s.Linux.Resources.CPU.Shares = &shares
|
||||||
|
}
|
||||||
|
if cpus := resources.GetCpusetCpus(); cpus != "" {
|
||||||
|
s.Linux.Resources.CPU.Cpus = cpus
|
||||||
|
}
|
||||||
|
if mems := resources.GetCpusetMems(); mems != "" {
|
||||||
|
s.Linux.Resources.CPU.Mems = resources.GetCpusetMems()
|
||||||
|
}
|
||||||
|
if limit != 0 {
|
||||||
|
s.Linux.Resources.Memory.Limit = &limit
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOOMScoreAdj sets the oom score
|
||||||
|
func WithOOMScoreAdj(config *runtime.ContainerConfig, restrict bool) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources := config.GetLinux().GetResources()
|
||||||
|
if resources == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
adj := int(resources.GetOomScoreAdj())
|
||||||
|
if restrict {
|
||||||
|
var err error
|
||||||
|
adj, err = restrictOOMScoreAdj(adj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Process.OOMScoreAdj = &adj
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSysctls sets the provided sysctls onto the spec
|
||||||
|
func WithSysctls(sysctls map[string]string) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Linux.Sysctl == nil {
|
||||||
|
s.Linux.Sysctl = make(map[string]string)
|
||||||
|
}
|
||||||
|
for k, v := range sysctls {
|
||||||
|
s.Linux.Sysctl[k] = v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPodOOMScoreAdj sets the oom score for the pod sandbox
|
||||||
|
func WithPodOOMScoreAdj(adj int, restrict bool) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
if restrict {
|
||||||
|
var err error
|
||||||
|
adj, err = restrictOOMScoreAdj(adj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Process.OOMScoreAdj = &adj
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSupplementalGroups sets the supplemental groups for the process
|
||||||
|
func WithSupplementalGroups(groups []int64) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Process == nil {
|
||||||
|
s.Process = &runtimespec.Process{}
|
||||||
|
}
|
||||||
|
var guids []uint32
|
||||||
|
for _, g := range groups {
|
||||||
|
guids = append(guids, uint32(g))
|
||||||
|
}
|
||||||
|
s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, guids)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPodNamespaces sets the pod namespaces for the container
|
||||||
|
func WithPodNamespaces(config *runtime.LinuxContainerSecurityContext, pid uint32) oci.SpecOpts {
|
||||||
|
namespaces := config.GetNamespaceOptions()
|
||||||
|
|
||||||
|
opts := []oci.SpecOpts{
|
||||||
|
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.NetworkNamespace, Path: GetNetworkNamespace(pid)}),
|
||||||
|
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.IPCNamespace, Path: GetIPCNamespace(pid)}),
|
||||||
|
oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.UTSNamespace, Path: GetUTSNamespace(pid)}),
|
||||||
|
}
|
||||||
|
if namespaces.GetPid() != runtime.NamespaceMode_CONTAINER {
|
||||||
|
opts = append(opts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.PIDNamespace, Path: GetPIDNamespace(pid)}))
|
||||||
|
}
|
||||||
|
return oci.Compose(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDefaultSandboxShares sets the default sandbox CPU shares
|
||||||
|
func WithDefaultSandboxShares(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Linux == nil {
|
||||||
|
s.Linux = &runtimespec.Linux{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources == nil {
|
||||||
|
s.Linux.Resources = &runtimespec.LinuxResources{}
|
||||||
|
}
|
||||||
|
if s.Linux.Resources.CPU == nil {
|
||||||
|
s.Linux.Resources.CPU = &runtimespec.LinuxCPU{}
|
||||||
|
}
|
||||||
|
i := uint64(DefaultSandboxCPUshares)
|
||||||
|
s.Linux.Resources.CPU.Shares = &i
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutNamespace removes the provided namespace
|
||||||
|
func WithoutNamespace(t runtimespec.LinuxNamespaceType) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Linux == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var namespaces []runtimespec.LinuxNamespace
|
||||||
|
for i, ns := range s.Linux.Namespaces {
|
||||||
|
if ns.Type != t {
|
||||||
|
namespaces = append(namespaces, s.Linux.Namespaces[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Linux.Namespaces = namespaces
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nullOpt(_ context.Context, _ oci.Client, _ *containers.Container, _ *runtimespec.Spec) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCurrentOOMScoreAdj() (int, error) {
|
||||||
|
b, err := ioutil.ReadFile("/proc/self/oom_score_adj")
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
||||||
|
}
|
||||||
|
s := strings.TrimSpace(string(b))
|
||||||
|
i, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
||||||
|
}
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func restrictOOMScoreAdj(preferredOOMScoreAdj int) (int, error) {
|
||||||
|
currentOOMScoreAdj, err := getCurrentOOMScoreAdj()
|
||||||
|
if err != nil {
|
||||||
|
return preferredOOMScoreAdj, err
|
||||||
|
}
|
||||||
|
if preferredOOMScoreAdj < currentOOMScoreAdj {
|
||||||
|
return currentOOMScoreAdj, nil
|
||||||
|
}
|
||||||
|
return preferredOOMScoreAdj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// netNSFormat is the format of network namespace of a process.
|
||||||
|
netNSFormat = "/proc/%v/ns/net"
|
||||||
|
// ipcNSFormat is the format of ipc namespace of a process.
|
||||||
|
ipcNSFormat = "/proc/%v/ns/ipc"
|
||||||
|
// utsNSFormat is the format of uts namespace of a process.
|
||||||
|
utsNSFormat = "/proc/%v/ns/uts"
|
||||||
|
// pidNSFormat is the format of pid namespace of a process.
|
||||||
|
pidNSFormat = "/proc/%v/ns/pid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetNetworkNamespace returns the network namespace of a process.
|
||||||
|
func GetNetworkNamespace(pid uint32) string {
|
||||||
|
return fmt.Sprintf(netNSFormat, pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIPCNamespace returns the ipc namespace of a process.
|
||||||
|
func GetIPCNamespace(pid uint32) string {
|
||||||
|
return fmt.Sprintf(ipcNSFormat, pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUTSNamespace returns the uts namespace of a process.
|
||||||
|
func GetUTSNamespace(pid uint32) string {
|
||||||
|
return fmt.Sprintf(utsNSFormat, pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPIDNamespace returns the pid namespace of a process.
|
||||||
|
func GetPIDNamespace(pid uint32) string {
|
||||||
|
return fmt.Sprintf(pidNSFormat, pid)
|
||||||
|
}
|
190
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go
generated
vendored
Normal file
190
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package opts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
osinterface "github.com/containerd/cri/pkg/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithWindowsNetworkNamespace sets windows network namespace for container.
|
||||||
|
// TODO(windows): Move this into container/containerd.
|
||||||
|
func WithWindowsNetworkNamespace(path string) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Windows == nil {
|
||||||
|
s.Windows = &runtimespec.Windows{}
|
||||||
|
}
|
||||||
|
if s.Windows.Network == nil {
|
||||||
|
s.Windows.Network = &runtimespec.WindowsNetwork{}
|
||||||
|
}
|
||||||
|
s.Windows.Network.NetworkNamespace = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWindowsMounts sorts and adds runtime and CRI mounts to the spec for
|
||||||
|
// windows container.
|
||||||
|
func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
// mergeMounts merge CRI mounts with extra mounts. If a mount destination
|
||||||
|
// is mounted by both a CRI mount and an extra mount, the CRI mount will
|
||||||
|
// be kept.
|
||||||
|
var (
|
||||||
|
criMounts = config.GetMounts()
|
||||||
|
mounts = append([]*runtime.Mount{}, criMounts...)
|
||||||
|
)
|
||||||
|
// Copy all mounts from extra mounts, except for mounts overridden by CRI.
|
||||||
|
for _, e := range extra {
|
||||||
|
found := false
|
||||||
|
for _, c := range criMounts {
|
||||||
|
if filepath.Clean(e.ContainerPath) == filepath.Clean(c.ContainerPath) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
mounts = append(mounts, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort mounts in number of parts. This ensures that high level mounts don't
|
||||||
|
// shadow other mounts.
|
||||||
|
sort.Sort(orderedMounts(mounts))
|
||||||
|
|
||||||
|
// Copy all mounts from default mounts, except for
|
||||||
|
// - mounts overridden by supplied mount;
|
||||||
|
// - all mounts under /dev if a supplied /dev is present.
|
||||||
|
mountSet := make(map[string]struct{})
|
||||||
|
for _, m := range mounts {
|
||||||
|
mountSet[filepath.Clean(m.ContainerPath)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultMounts := s.Mounts
|
||||||
|
s.Mounts = nil
|
||||||
|
|
||||||
|
for _, m := range defaultMounts {
|
||||||
|
dst := filepath.Clean(m.Destination)
|
||||||
|
if _, ok := mountSet[dst]; ok {
|
||||||
|
// filter out mount overridden by a supplied mount
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Mounts = append(s.Mounts, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mount := range mounts {
|
||||||
|
var (
|
||||||
|
dst = mount.GetContainerPath()
|
||||||
|
src = mount.GetHostPath()
|
||||||
|
)
|
||||||
|
// TODO(windows): Support special mount sources, e.g. named pipe.
|
||||||
|
// Create the host path if it doesn't exist.
|
||||||
|
if _, err := osi.Stat(src); err != nil {
|
||||||
|
// If the source doesn't exist, return an error instead
|
||||||
|
// of creating the source. This aligns with Docker's
|
||||||
|
// behavior on windows.
|
||||||
|
return errors.Wrapf(err, "failed to stat %q", src)
|
||||||
|
}
|
||||||
|
src, err := osi.ResolveSymbolicLink(src)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to resolve symlink %q", src)
|
||||||
|
}
|
||||||
|
|
||||||
|
var options []string
|
||||||
|
// NOTE(random-liu): we don't change all mounts to `ro` when root filesystem
|
||||||
|
// is readonly. This is different from docker's behavior, but make more sense.
|
||||||
|
if mount.GetReadonly() {
|
||||||
|
options = append(options, "ro")
|
||||||
|
} else {
|
||||||
|
options = append(options, "rw")
|
||||||
|
}
|
||||||
|
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
||||||
|
Source: src,
|
||||||
|
Destination: dst,
|
||||||
|
Options: options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWindowsResources sets the provided resource restrictions for windows.
|
||||||
|
func WithWindowsResources(resources *runtime.WindowsContainerResources) oci.SpecOpts {
|
||||||
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if resources == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if s.Windows == nil {
|
||||||
|
s.Windows = &runtimespec.Windows{}
|
||||||
|
}
|
||||||
|
if s.Windows.Resources == nil {
|
||||||
|
s.Windows.Resources = &runtimespec.WindowsResources{}
|
||||||
|
}
|
||||||
|
if s.Windows.Resources.CPU == nil {
|
||||||
|
s.Windows.Resources.CPU = &runtimespec.WindowsCPUResources{}
|
||||||
|
}
|
||||||
|
if s.Windows.Resources.Memory == nil {
|
||||||
|
s.Windows.Resources.Memory = &runtimespec.WindowsMemoryResources{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
count = uint64(resources.GetCpuCount())
|
||||||
|
shares = uint16(resources.GetCpuShares())
|
||||||
|
max = uint16(resources.GetCpuMaximum())
|
||||||
|
limit = uint64(resources.GetMemoryLimitInBytes())
|
||||||
|
)
|
||||||
|
if count != 0 {
|
||||||
|
s.Windows.Resources.CPU.Count = &count
|
||||||
|
}
|
||||||
|
if shares != 0 {
|
||||||
|
s.Windows.Resources.CPU.Shares = &shares
|
||||||
|
}
|
||||||
|
if max != 0 {
|
||||||
|
s.Windows.Resources.CPU.Maximum = &max
|
||||||
|
}
|
||||||
|
if limit != 0 {
|
||||||
|
s.Windows.Resources.Memory.Limit = &limit
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWindowsDefaultSandboxShares sets the default sandbox CPU shares
|
||||||
|
func WithWindowsDefaultSandboxShares(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {
|
||||||
|
if s.Windows == nil {
|
||||||
|
s.Windows = &runtimespec.Windows{}
|
||||||
|
}
|
||||||
|
if s.Windows.Resources == nil {
|
||||||
|
s.Windows.Resources = &runtimespec.WindowsResources{}
|
||||||
|
}
|
||||||
|
if s.Windows.Resources.CPU == nil {
|
||||||
|
s.Windows.Resources.CPU = &runtimespec.WindowsCPUResources{}
|
||||||
|
}
|
||||||
|
i := uint16(DefaultSandboxCPUshares)
|
||||||
|
s.Windows.Resources.CPU.Shares = &i
|
||||||
|
return nil
|
||||||
|
}
|
28
vendor/github.com/containerd/cri/pkg/containerd/platforms/default_unix.go
generated
vendored
Normal file
28
vendor/github.com/containerd/cri/pkg/containerd/platforms/default_unix.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package platforms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Default returns the current platform's default platform specification.
|
||||||
|
func Default() platforms.MatchComparer {
|
||||||
|
return platforms.Default()
|
||||||
|
}
|
77
vendor/github.com/containerd/cri/pkg/containerd/platforms/default_windows.go
generated
vendored
Normal file
77
vendor/github.com/containerd/cri/pkg/containerd/platforms/default_windows.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package platforms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type matchComparer struct {
|
||||||
|
defaults platforms.Matcher
|
||||||
|
osVersionPrefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match matches platform with the same windows major, minor
|
||||||
|
// and build version.
|
||||||
|
func (m matchComparer) Match(p imagespec.Platform) bool {
|
||||||
|
if m.defaults.Match(p) {
|
||||||
|
// TODO(windows): Figure out whether OSVersion is deprecated.
|
||||||
|
return strings.HasPrefix(p.OSVersion, m.osVersionPrefix)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less sorts matched platforms in front of other platforms.
|
||||||
|
// For matched platforms, it puts platforms with larger revision
|
||||||
|
// number in front.
|
||||||
|
func (m matchComparer) Less(p1, p2 imagespec.Platform) bool {
|
||||||
|
m1, m2 := m.Match(p1), m.Match(p2)
|
||||||
|
if m1 && m2 {
|
||||||
|
r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
|
||||||
|
return r1 > r2
|
||||||
|
}
|
||||||
|
return m1 && !m2
|
||||||
|
}
|
||||||
|
|
||||||
|
func revision(v string) int {
|
||||||
|
parts := strings.Split(v, ".")
|
||||||
|
if len(parts) < 4 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
r, err := strconv.Atoi(parts[3])
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default returns the current platform's default platform specification.
|
||||||
|
func Default() platforms.MatchComparer {
|
||||||
|
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||||
|
return matchComparer{
|
||||||
|
defaults: platforms.Only(platforms.DefaultSpec()),
|
||||||
|
osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build),
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2018 The Containerd Authors.
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
78
vendor/github.com/containerd/cri/pkg/netns/netns_windows.go
generated
vendored
Normal file
78
vendor/github.com/containerd/cri/pkg/netns/netns_windows.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package netns
|
||||||
|
|
||||||
|
import "github.com/Microsoft/hcsshim/hcn"
|
||||||
|
|
||||||
|
// NetNS holds network namespace for sandbox
|
||||||
|
type NetNS struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetNS creates a network namespace for the sandbox
|
||||||
|
func NewNetNS() (*NetNS, error) {
|
||||||
|
temp := hcn.HostComputeNamespace{}
|
||||||
|
hcnNamespace, err := temp.Create()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NetNS{path: hcnNamespace.Id}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadNetNS loads existing network namespace.
|
||||||
|
func LoadNetNS(path string) *NetNS {
|
||||||
|
return &NetNS{path: path}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes network namepace if it exists and not closed. Remove is idempotent,
|
||||||
|
// meaning it might be invoked multiple times and provides consistent result.
|
||||||
|
func (n *NetNS) Remove() error {
|
||||||
|
hcnNamespace, err := hcn.GetNamespaceByID(n.path)
|
||||||
|
if err != nil {
|
||||||
|
if hcn.IsNotFoundError(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = hcnNamespace.Delete()
|
||||||
|
if err == nil || hcn.IsNotFoundError(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closed checks whether the network namespace has been closed.
|
||||||
|
func (n *NetNS) Closed() (bool, error) {
|
||||||
|
_, err := hcn.GetNamespaceByID(n.path)
|
||||||
|
if err == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if hcn.IsNotFoundError(err) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPath returns network namespace path for sandbox container
|
||||||
|
func (n *NetNS) GetPath() string {
|
||||||
|
return n.path
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Do function is not supported.
|
40
vendor/github.com/containerd/cri/pkg/os/os.go
generated
vendored
40
vendor/github.com/containerd/cri/pkg/os/os.go
generated
vendored
@ -22,11 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
|
||||||
"github.com/containerd/fifo"
|
|
||||||
"github.com/docker/docker/pkg/symlink"
|
"github.com/docker/docker/pkg/symlink"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OS collects system level operations that need to be mocked out
|
// OS collects system level operations that need to be mocked out
|
||||||
@ -34,15 +30,11 @@ import (
|
|||||||
type OS interface {
|
type OS interface {
|
||||||
MkdirAll(path string, perm os.FileMode) error
|
MkdirAll(path string, perm os.FileMode) error
|
||||||
RemoveAll(path string) error
|
RemoveAll(path string) error
|
||||||
OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)
|
|
||||||
Stat(name string) (os.FileInfo, error)
|
Stat(name string) (os.FileInfo, error)
|
||||||
ResolveSymbolicLink(name string) (string, error)
|
ResolveSymbolicLink(name string) (string, error)
|
||||||
FollowSymlinkInScope(path, scope string) (string, error)
|
FollowSymlinkInScope(path, scope string) (string, error)
|
||||||
CopyFile(src, dest string, perm os.FileMode) error
|
CopyFile(src, dest string, perm os.FileMode) error
|
||||||
WriteFile(filename string, data []byte, perm os.FileMode) error
|
WriteFile(filename string, data []byte, perm os.FileMode) error
|
||||||
Mount(source string, target string, fstype string, flags uintptr, data string) error
|
|
||||||
Unmount(target string) error
|
|
||||||
LookupMount(path string) (mount.Info, error)
|
|
||||||
Hostname() (string, error)
|
Hostname() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +51,6 @@ func (RealOS) RemoveAll(path string) error {
|
|||||||
return os.RemoveAll(path)
|
return os.RemoveAll(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFifo will call fifo.OpenFifo to open a fifo.
|
|
||||||
func (RealOS) OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
|
||||||
return fifo.OpenFifo(ctx, fn, flag, perm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat will call os.Stat to get the status of the given file.
|
// Stat will call os.Stat to get the status of the given file.
|
||||||
func (RealOS) Stat(name string) (os.FileInfo, error) {
|
func (RealOS) Stat(name string) (os.FileInfo, error) {
|
||||||
return os.Stat(name)
|
return os.Stat(name)
|
||||||
@ -109,33 +96,6 @@ func (RealOS) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
|||||||
return ioutil.WriteFile(filename, data, perm)
|
return ioutil.WriteFile(filename, data, perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount will call unix.Mount to mount the file.
|
|
||||||
func (RealOS) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
|
||||||
return unix.Mount(source, target, fstype, flags, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount will call Unmount to unmount the file.
|
|
||||||
func (RealOS) Unmount(target string) error {
|
|
||||||
return Unmount(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupMount gets mount info of a given path.
|
|
||||||
func (RealOS) LookupMount(path string) (mount.Info, error) {
|
|
||||||
return mount.Lookup(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount unmounts the target. It does not return an error in case the target is not mounted.
|
|
||||||
// In case the target does not exist, the appropriate error is returned.
|
|
||||||
func Unmount(target string) error {
|
|
||||||
err := unix.Unmount(target, unix.MNT_DETACH)
|
|
||||||
if err == unix.EINVAL {
|
|
||||||
// ignore "not mounted" error
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hostname will call os.Hostname to get the hostname of the host.
|
// Hostname will call os.Hostname to get the hostname of the host.
|
||||||
func (RealOS) Hostname() (string, error) {
|
func (RealOS) Hostname() (string, error) {
|
||||||
return os.Hostname()
|
return os.Hostname()
|
||||||
|
59
vendor/github.com/containerd/cri/pkg/os/os_unix.go
generated
vendored
Normal file
59
vendor/github.com/containerd/cri/pkg/os/os_unix.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UNIX collects unix system level operations that need to be
|
||||||
|
// mocked out during tests.
|
||||||
|
type UNIX interface {
|
||||||
|
Mount(source string, target string, fstype string, flags uintptr, data string) error
|
||||||
|
Unmount(target string) error
|
||||||
|
LookupMount(path string) (mount.Info, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount will call unix.Mount to mount the file.
|
||||||
|
func (RealOS) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
|
return unix.Mount(source, target, fstype, flags, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmount will call Unmount to unmount the file.
|
||||||
|
func (RealOS) Unmount(target string) error {
|
||||||
|
return Unmount(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupMount gets mount info of a given path.
|
||||||
|
func (RealOS) LookupMount(path string) (mount.Info, error) {
|
||||||
|
return mount.Lookup(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmount unmounts the target. It does not return an error in case the target is not mounted.
|
||||||
|
// In case the target does not exist, the appropriate error is returned.
|
||||||
|
func Unmount(target string) error {
|
||||||
|
err := unix.Unmount(target, unix.MNT_DETACH)
|
||||||
|
if err == unix.EINVAL {
|
||||||
|
// ignore "not mounted" error
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
368
vendor/github.com/containerd/cri/pkg/server/container_create.go
generated
vendored
368
vendor/github.com/containerd/cri/pkg/server/container_create.go
generated
vendored
@ -18,23 +18,12 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/contrib/apparmor"
|
|
||||||
"github.com/containerd/containerd/contrib/seccomp"
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/cri/pkg/annotations"
|
|
||||||
"github.com/containerd/cri/pkg/config"
|
|
||||||
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
|
||||||
cio "github.com/containerd/cri/pkg/server/io"
|
|
||||||
containerstore "github.com/containerd/cri/pkg/store/container"
|
|
||||||
"github.com/containerd/cri/pkg/util"
|
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -42,21 +31,12 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
// profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName.
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747
|
cio "github.com/containerd/cri/pkg/server/io"
|
||||||
// runtimeDefault indicates that we should use or create a runtime default profile.
|
containerstore "github.com/containerd/cri/pkg/store/container"
|
||||||
runtimeDefault = "runtime/default"
|
"github.com/containerd/cri/pkg/util"
|
||||||
// dockerDefault indicates that we should use or create a docker default profile.
|
|
||||||
dockerDefault = "docker/default"
|
|
||||||
// appArmorDefaultProfileName is name to use when creating a default apparmor profile.
|
|
||||||
appArmorDefaultProfileName = "cri-containerd.apparmor.d"
|
|
||||||
// unconfinedProfile is a string indicating one should run a pod/containerd without a security profile
|
|
||||||
unconfinedProfile = "unconfined"
|
|
||||||
// seccompDefaultProfile is the default seccomp profile.
|
|
||||||
seccompDefaultProfile = dockerDefault
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -156,10 +136,10 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Create container volumes mounts.
|
// Create container volumes mounts.
|
||||||
volumeMounts := c.generateVolumeMounts(containerRootDir, config.GetMounts(), &image.ImageSpec.Config)
|
volumeMounts := c.volumeMounts(containerRootDir, config.GetMounts(), &image.ImageSpec.Config)
|
||||||
|
|
||||||
// Generate container runtime spec.
|
// Generate container mounts.
|
||||||
mounts := c.generateContainerMounts(sandboxID, config)
|
mounts := c.containerMounts(sandboxID, config)
|
||||||
|
|
||||||
ociRuntime, err := c.getSandboxRuntime(sandboxConfig, sandbox.Metadata.RuntimeHandler)
|
ociRuntime, err := c.getSandboxRuntime(sandboxConfig, sandbox.Metadata.RuntimeHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -167,7 +147,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
}
|
}
|
||||||
log.G(ctx).Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id)
|
log.G(ctx).Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id)
|
||||||
|
|
||||||
spec, err := c.generateContainerSpec(id, sandboxID, sandboxPid, config, sandboxConfig,
|
spec, err := c.containerSpec(id, sandboxID, sandboxPid, sandbox.NetNSPath, config, sandboxConfig,
|
||||||
&image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime)
|
&image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
||||||
@ -185,7 +165,6 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
// rootfs readonly (requested by spec.Root.Readonly).
|
// rootfs readonly (requested by spec.Root.Readonly).
|
||||||
customopts.WithNewSnapshot(id, containerdImage),
|
customopts.WithNewSnapshot(id, containerdImage),
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(volumeMounts) > 0 {
|
if len(volumeMounts) > 0 {
|
||||||
mountMap := make(map[string]string)
|
mountMap := make(map[string]string)
|
||||||
for _, v := range volumeMounts {
|
for _, v := range volumeMounts {
|
||||||
@ -219,58 +198,11 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var specOpts []oci.SpecOpts
|
specOpts, err := c.containerSpecOpts(config, &image.ImageSpec.Config)
|
||||||
securityContext := config.GetLinux().GetSecurityContext()
|
|
||||||
// Set container username. This could only be done by containerd, because it needs
|
|
||||||
// access to the container rootfs. Pass user name to containerd, and let it overwrite
|
|
||||||
// the spec for us.
|
|
||||||
userstr, err := generateUserString(
|
|
||||||
securityContext.GetRunAsUsername(),
|
|
||||||
securityContext.GetRunAsUser(),
|
|
||||||
securityContext.GetRunAsGroup())
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to generate user string")
|
return nil, errors.Wrap(err, "")
|
||||||
}
|
|
||||||
if userstr == "" {
|
|
||||||
// Lastly, since no user override was passed via CRI try to set via OCI
|
|
||||||
// Image
|
|
||||||
userstr = image.ImageSpec.Config.User
|
|
||||||
}
|
|
||||||
if userstr != "" {
|
|
||||||
specOpts = append(specOpts, oci.WithUser(userstr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if securityContext.GetRunAsUsername() != "" {
|
|
||||||
userstr = securityContext.GetRunAsUsername()
|
|
||||||
} else {
|
|
||||||
// Even if RunAsUser is not set, we still call `GetValue` to get uid 0.
|
|
||||||
// Because it is still useful to get additional gids for uid 0.
|
|
||||||
userstr = strconv.FormatInt(securityContext.GetRunAsUser().GetValue(), 10)
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr))
|
|
||||||
|
|
||||||
apparmorSpecOpts, err := generateApparmorSpecOpts(
|
|
||||||
securityContext.GetApparmorProfile(),
|
|
||||||
securityContext.GetPrivileged(),
|
|
||||||
c.apparmorEnabled)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to generate apparmor spec opts")
|
|
||||||
}
|
|
||||||
if apparmorSpecOpts != nil {
|
|
||||||
specOpts = append(specOpts, apparmorSpecOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
seccompSpecOpts, err := generateSeccompSpecOpts(
|
|
||||||
securityContext.GetSeccompProfilePath(),
|
|
||||||
securityContext.GetPrivileged(),
|
|
||||||
c.seccompEnabled)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to generate seccomp spec opts")
|
|
||||||
}
|
|
||||||
if seccompSpecOpts != nil {
|
|
||||||
specOpts = append(specOpts, seccompSpecOpts)
|
|
||||||
}
|
|
||||||
containerLabels := buildLabels(config.Labels, containerKindContainer)
|
containerLabels := buildLabels(config.Labels, containerKindContainer)
|
||||||
|
|
||||||
runtimeOptions, err := getRuntimeOptions(sandboxInfo)
|
runtimeOptions, err := getRuntimeOptions(sandboxInfo)
|
||||||
@ -322,129 +254,10 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
return &runtime.CreateContainerResponse{ContainerId: id}, nil
|
return &runtime.CreateContainerResponse{ContainerId: id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
|
// volumeMounts sets up image volumes for container. Rely on the removal of container
|
||||||
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount,
|
|
||||||
ociRuntime config.Runtime) (*runtimespec.Spec, error) {
|
|
||||||
|
|
||||||
specOpts := []oci.SpecOpts{
|
|
||||||
customopts.WithoutRunMount,
|
|
||||||
customopts.WithoutDefaultSecuritySettings,
|
|
||||||
customopts.WithRelativeRoot(relativeRootfsPath),
|
|
||||||
customopts.WithProcessArgs(config, imageConfig),
|
|
||||||
oci.WithDefaultPathEnv,
|
|
||||||
// this will be set based on the security context below
|
|
||||||
oci.WithNewPrivileges,
|
|
||||||
}
|
|
||||||
if config.GetWorkingDir() != "" {
|
|
||||||
specOpts = append(specOpts, oci.WithProcessCwd(config.GetWorkingDir()))
|
|
||||||
} else if imageConfig.WorkingDir != "" {
|
|
||||||
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.GetTty() {
|
|
||||||
specOpts = append(specOpts, oci.WithTTY)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add HOSTNAME env.
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
hostname = sandboxConfig.GetHostname()
|
|
||||||
)
|
|
||||||
if hostname == "" {
|
|
||||||
if hostname, err = c.os.Hostname(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, oci.WithEnv([]string{hostnameEnv + "=" + hostname}))
|
|
||||||
|
|
||||||
// Apply envs from image config first, so that envs from container config
|
|
||||||
// can override them.
|
|
||||||
env := imageConfig.Env
|
|
||||||
for _, e := range config.GetEnvs() {
|
|
||||||
env = append(env, e.GetKey()+"="+e.GetValue())
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, oci.WithEnv(env))
|
|
||||||
|
|
||||||
securityContext := config.GetLinux().GetSecurityContext()
|
|
||||||
selinuxOpt := securityContext.GetSelinuxOptions()
|
|
||||||
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))
|
|
||||||
|
|
||||||
if !c.config.DisableProcMount {
|
|
||||||
// Apply masked paths if specified.
|
|
||||||
// If the container is privileged, this will be cleared later on.
|
|
||||||
specOpts = append(specOpts, oci.WithMaskedPaths(securityContext.GetMaskedPaths()))
|
|
||||||
|
|
||||||
// Apply readonly paths if specified.
|
|
||||||
// If the container is privileged, this will be cleared later on.
|
|
||||||
specOpts = append(specOpts, oci.WithReadonlyPaths(securityContext.GetReadonlyPaths()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if securityContext.GetPrivileged() {
|
|
||||||
if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() {
|
|
||||||
return nil, errors.New("no privileged container allowed in sandbox")
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, oci.WithPrivileged)
|
|
||||||
if !ociRuntime.PrivilegedWithoutHostDevices {
|
|
||||||
specOpts = append(specOpts, customopts.WithPrivilegedDevices)
|
|
||||||
}
|
|
||||||
} else { // not privileged
|
|
||||||
specOpts = append(specOpts, customopts.WithDevices(c.os, config), customopts.WithCapabilities(securityContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear all ambient capabilities. The implication of non-root + caps
|
|
||||||
// is not clearly defined in Kubernetes.
|
|
||||||
// See https://github.com/kubernetes/kubernetes/issues/56374
|
|
||||||
// Keep docker's behavior for now.
|
|
||||||
specOpts = append(specOpts,
|
|
||||||
customopts.WithoutAmbientCaps,
|
|
||||||
customopts.WithSelinuxLabels(processLabel, mountLabel),
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Figure out whether we should set no new privilege for sandbox container by default
|
|
||||||
if securityContext.GetNoNewPrivs() {
|
|
||||||
specOpts = append(specOpts, oci.WithNoNewPrivileges)
|
|
||||||
}
|
|
||||||
// TODO(random-liu): [P1] Set selinux options (privileged or not).
|
|
||||||
if securityContext.GetReadonlyRootfs() {
|
|
||||||
specOpts = append(specOpts, oci.WithRootFSReadonly())
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.config.DisableCgroup {
|
|
||||||
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
|
||||||
} else {
|
|
||||||
specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources()))
|
|
||||||
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
|
||||||
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id)
|
|
||||||
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
supplementalGroups := securityContext.GetSupplementalGroups()
|
|
||||||
|
|
||||||
for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations,
|
|
||||||
ociRuntime.PodAnnotations) {
|
|
||||||
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
|
||||||
}
|
|
||||||
|
|
||||||
specOpts = append(specOpts,
|
|
||||||
customopts.WithOOMScoreAdj(config, c.config.RestrictOOMScoreAdj),
|
|
||||||
customopts.WithPodNamespaces(securityContext, sandboxPid),
|
|
||||||
customopts.WithSupplementalGroups(supplementalGroups),
|
|
||||||
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer),
|
|
||||||
customopts.WithAnnotation(annotations.SandboxID, sandboxID),
|
|
||||||
)
|
|
||||||
|
|
||||||
return runtimeSpec(id, specOpts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateVolumeMounts sets up image volumes for container. Rely on the removal of container
|
|
||||||
// root directory to do cleanup. Note that image volume will be skipped, if there is criMounts
|
// root directory to do cleanup. Note that image volume will be skipped, if there is criMounts
|
||||||
// specified with the same destination.
|
// specified with the same destination.
|
||||||
func (c *criService) generateVolumeMounts(containerRootDir string, criMounts []*runtime.Mount, config *imagespec.ImageConfig) []*runtime.Mount {
|
func (c *criService) volumeMounts(containerRootDir string, criMounts []*runtime.Mount, config *imagespec.ImageConfig) []*runtime.Mount {
|
||||||
if len(config.Volumes) == 0 {
|
if len(config.Volumes) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -470,59 +283,6 @@ func (c *criService) generateVolumeMounts(containerRootDir string, criMounts []*
|
|||||||
return mounts
|
return mounts
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateContainerMounts sets up necessary container mounts including /dev/shm, /etc/hosts
|
|
||||||
// and /etc/resolv.conf.
|
|
||||||
func (c *criService) generateContainerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount {
|
|
||||||
var mounts []*runtime.Mount
|
|
||||||
securityContext := config.GetLinux().GetSecurityContext()
|
|
||||||
if !isInCRIMounts(etcHostname, config.GetMounts()) {
|
|
||||||
// /etc/hostname is added since 1.1.6, 1.2.4 and 1.3.
|
|
||||||
// For in-place upgrade, the old sandbox doesn't have the hostname file,
|
|
||||||
// do not mount this in that case.
|
|
||||||
// TODO(random-liu): Remove the check and always mount this when
|
|
||||||
// containerd 1.1 and 1.2 are deprecated.
|
|
||||||
hostpath := c.getSandboxHostname(sandboxID)
|
|
||||||
if _, err := c.os.Stat(hostpath); err == nil {
|
|
||||||
mounts = append(mounts, &runtime.Mount{
|
|
||||||
ContainerPath: etcHostname,
|
|
||||||
HostPath: hostpath,
|
|
||||||
Readonly: securityContext.GetReadonlyRootfs(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isInCRIMounts(etcHosts, config.GetMounts()) {
|
|
||||||
mounts = append(mounts, &runtime.Mount{
|
|
||||||
ContainerPath: etcHosts,
|
|
||||||
HostPath: c.getSandboxHosts(sandboxID),
|
|
||||||
Readonly: securityContext.GetReadonlyRootfs(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mount sandbox resolv.config.
|
|
||||||
// TODO: Need to figure out whether we should always mount it as read-only
|
|
||||||
if !isInCRIMounts(resolvConfPath, config.GetMounts()) {
|
|
||||||
mounts = append(mounts, &runtime.Mount{
|
|
||||||
ContainerPath: resolvConfPath,
|
|
||||||
HostPath: c.getResolvPath(sandboxID),
|
|
||||||
Readonly: securityContext.GetReadonlyRootfs(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isInCRIMounts(devShm, config.GetMounts()) {
|
|
||||||
sandboxDevShm := c.getSandboxDevShm(sandboxID)
|
|
||||||
if securityContext.GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE {
|
|
||||||
sandboxDevShm = devShm
|
|
||||||
}
|
|
||||||
mounts = append(mounts, &runtime.Mount{
|
|
||||||
ContainerPath: devShm,
|
|
||||||
HostPath: sandboxDevShm,
|
|
||||||
Readonly: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return mounts
|
|
||||||
}
|
|
||||||
|
|
||||||
// runtimeSpec returns a default runtime spec used in cri-containerd.
|
// runtimeSpec returns a default runtime spec used in cri-containerd.
|
||||||
func runtimeSpec(id string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) {
|
func runtimeSpec(id string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) {
|
||||||
// GenerateSpec needs namespace.
|
// GenerateSpec needs namespace.
|
||||||
@ -533,105 +293,3 @@ func runtimeSpec(id string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) {
|
|||||||
}
|
}
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateSeccompSpecOpts generates containerd SpecOpts for seccomp.
|
|
||||||
func generateSeccompSpecOpts(seccompProf string, privileged, seccompEnabled bool) (oci.SpecOpts, error) {
|
|
||||||
if privileged {
|
|
||||||
// Do not set seccomp profile when container is privileged
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
// Set seccomp profile
|
|
||||||
if seccompProf == runtimeDefault || seccompProf == dockerDefault {
|
|
||||||
// use correct default profile (Eg. if not configured otherwise, the default is docker/default)
|
|
||||||
seccompProf = seccompDefaultProfile
|
|
||||||
}
|
|
||||||
if !seccompEnabled {
|
|
||||||
if seccompProf != "" && seccompProf != unconfinedProfile {
|
|
||||||
return nil, errors.New("seccomp is not supported")
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
switch seccompProf {
|
|
||||||
case "", unconfinedProfile:
|
|
||||||
// Do not set seccomp profile.
|
|
||||||
return nil, nil
|
|
||||||
case dockerDefault:
|
|
||||||
// Note: WithDefaultProfile specOpts must be added after capabilities
|
|
||||||
return seccomp.WithDefaultProfile(), nil
|
|
||||||
default:
|
|
||||||
// Require and Trim default profile name prefix
|
|
||||||
if !strings.HasPrefix(seccompProf, profileNamePrefix) {
|
|
||||||
return nil, errors.Errorf("invalid seccomp profile %q", seccompProf)
|
|
||||||
}
|
|
||||||
return seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateApparmorSpecOpts generates containerd SpecOpts for apparmor.
|
|
||||||
func generateApparmorSpecOpts(apparmorProf string, privileged, apparmorEnabled bool) (oci.SpecOpts, error) {
|
|
||||||
if !apparmorEnabled {
|
|
||||||
// Should fail loudly if user try to specify apparmor profile
|
|
||||||
// but we don't support it.
|
|
||||||
if apparmorProf != "" && apparmorProf != unconfinedProfile {
|
|
||||||
return nil, errors.New("apparmor is not supported")
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
switch apparmorProf {
|
|
||||||
// Based on kubernetes#51746, default apparmor profile should be applied
|
|
||||||
// for when apparmor is not specified.
|
|
||||||
case runtimeDefault, "":
|
|
||||||
if privileged {
|
|
||||||
// Do not set apparmor profile when container is privileged
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
// TODO (mikebrow): delete created apparmor default profile
|
|
||||||
return apparmor.WithDefaultProfile(appArmorDefaultProfileName), nil
|
|
||||||
case unconfinedProfile:
|
|
||||||
return nil, nil
|
|
||||||
default:
|
|
||||||
// Require and Trim default profile name prefix
|
|
||||||
if !strings.HasPrefix(apparmorProf, profileNamePrefix) {
|
|
||||||
return nil, errors.Errorf("invalid apparmor profile %q", apparmorProf)
|
|
||||||
}
|
|
||||||
return apparmor.WithProfile(strings.TrimPrefix(apparmorProf, profileNamePrefix)), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateUserString generates valid user string based on OCI Image Spec
|
|
||||||
// v1.0.0.
|
|
||||||
//
|
|
||||||
// CRI defines that the following combinations are valid:
|
|
||||||
//
|
|
||||||
// (none) -> ""
|
|
||||||
// username -> username
|
|
||||||
// username, uid -> username
|
|
||||||
// username, uid, gid -> username:gid
|
|
||||||
// username, gid -> username:gid
|
|
||||||
// uid -> uid
|
|
||||||
// uid, gid -> uid:gid
|
|
||||||
// gid -> error
|
|
||||||
//
|
|
||||||
// TODO(random-liu): Add group name support in CRI.
|
|
||||||
func generateUserString(username string, uid, gid *runtime.Int64Value) (string, error) {
|
|
||||||
var userstr, groupstr string
|
|
||||||
if uid != nil {
|
|
||||||
userstr = strconv.FormatInt(uid.GetValue(), 10)
|
|
||||||
}
|
|
||||||
if username != "" {
|
|
||||||
userstr = username
|
|
||||||
}
|
|
||||||
if gid != nil {
|
|
||||||
groupstr = strconv.FormatInt(gid.GetValue(), 10)
|
|
||||||
}
|
|
||||||
if userstr == "" {
|
|
||||||
if groupstr != "" {
|
|
||||||
return "", errors.Errorf("user group %q is specified without user", groupstr)
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
if groupstr != "" {
|
|
||||||
userstr = userstr + ":" + groupstr
|
|
||||||
}
|
|
||||||
return userstr, nil
|
|
||||||
}
|
|
||||||
|
385
vendor/github.com/containerd/cri/pkg/server/container_create_unix.go
generated
vendored
Normal file
385
vendor/github.com/containerd/cri/pkg/server/container_create_unix.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/contrib/apparmor"
|
||||||
|
"github.com/containerd/containerd/contrib/seccomp"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
|
"github.com/containerd/cri/pkg/config"
|
||||||
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName.
|
||||||
|
profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747
|
||||||
|
// runtimeDefault indicates that we should use or create a runtime default profile.
|
||||||
|
runtimeDefault = "runtime/default"
|
||||||
|
// dockerDefault indicates that we should use or create a docker default profile.
|
||||||
|
dockerDefault = "docker/default"
|
||||||
|
// appArmorDefaultProfileName is name to use when creating a default apparmor profile.
|
||||||
|
appArmorDefaultProfileName = "cri-containerd.apparmor.d"
|
||||||
|
// unconfinedProfile is a string indicating one should run a pod/containerd without a security profile
|
||||||
|
unconfinedProfile = "unconfined"
|
||||||
|
// seccompDefaultProfile is the default seccomp profile.
|
||||||
|
seccompDefaultProfile = dockerDefault
|
||||||
|
)
|
||||||
|
|
||||||
|
// containerMounts sets up necessary container system file mounts
|
||||||
|
// including /dev/shm, /etc/hosts and /etc/resolv.conf.
|
||||||
|
func (c *criService) containerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount {
|
||||||
|
var mounts []*runtime.Mount
|
||||||
|
securityContext := config.GetLinux().GetSecurityContext()
|
||||||
|
if !isInCRIMounts(etcHostname, config.GetMounts()) {
|
||||||
|
// /etc/hostname is added since 1.1.6, 1.2.4 and 1.3.
|
||||||
|
// For in-place upgrade, the old sandbox doesn't have the hostname file,
|
||||||
|
// do not mount this in that case.
|
||||||
|
// TODO(random-liu): Remove the check and always mount this when
|
||||||
|
// containerd 1.1 and 1.2 are deprecated.
|
||||||
|
hostpath := c.getSandboxHostname(sandboxID)
|
||||||
|
if _, err := c.os.Stat(hostpath); err == nil {
|
||||||
|
mounts = append(mounts, &runtime.Mount{
|
||||||
|
ContainerPath: etcHostname,
|
||||||
|
HostPath: hostpath,
|
||||||
|
Readonly: securityContext.GetReadonlyRootfs(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isInCRIMounts(etcHosts, config.GetMounts()) {
|
||||||
|
mounts = append(mounts, &runtime.Mount{
|
||||||
|
ContainerPath: etcHosts,
|
||||||
|
HostPath: c.getSandboxHosts(sandboxID),
|
||||||
|
Readonly: securityContext.GetReadonlyRootfs(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount sandbox resolv.config.
|
||||||
|
// TODO: Need to figure out whether we should always mount it as read-only
|
||||||
|
if !isInCRIMounts(resolvConfPath, config.GetMounts()) {
|
||||||
|
mounts = append(mounts, &runtime.Mount{
|
||||||
|
ContainerPath: resolvConfPath,
|
||||||
|
HostPath: c.getResolvPath(sandboxID),
|
||||||
|
Readonly: securityContext.GetReadonlyRootfs(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isInCRIMounts(devShm, config.GetMounts()) {
|
||||||
|
sandboxDevShm := c.getSandboxDevShm(sandboxID)
|
||||||
|
if securityContext.GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE {
|
||||||
|
sandboxDevShm = devShm
|
||||||
|
}
|
||||||
|
mounts = append(mounts, &runtime.Mount{
|
||||||
|
ContainerPath: devShm,
|
||||||
|
HostPath: sandboxDevShm,
|
||||||
|
Readonly: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint32, netNSPath string,
|
||||||
|
config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig,
|
||||||
|
extraMounts []*runtime.Mount, ociRuntime config.Runtime) (*runtimespec.Spec, error) {
|
||||||
|
|
||||||
|
specOpts := []oci.SpecOpts{
|
||||||
|
customopts.WithoutRunMount,
|
||||||
|
customopts.WithoutDefaultSecuritySettings,
|
||||||
|
customopts.WithRelativeRoot(relativeRootfsPath),
|
||||||
|
customopts.WithProcessArgs(config, imageConfig),
|
||||||
|
oci.WithDefaultPathEnv,
|
||||||
|
// this will be set based on the security context below
|
||||||
|
oci.WithNewPrivileges,
|
||||||
|
}
|
||||||
|
if config.GetWorkingDir() != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(config.GetWorkingDir()))
|
||||||
|
} else if imageConfig.WorkingDir != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.GetTty() {
|
||||||
|
specOpts = append(specOpts, oci.WithTTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HOSTNAME env.
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
hostname = sandboxConfig.GetHostname()
|
||||||
|
)
|
||||||
|
if hostname == "" {
|
||||||
|
if hostname, err = c.os.Hostname(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithEnv([]string{hostnameEnv + "=" + hostname}))
|
||||||
|
|
||||||
|
// Apply envs from image config first, so that envs from container config
|
||||||
|
// can override them.
|
||||||
|
env := imageConfig.Env
|
||||||
|
for _, e := range config.GetEnvs() {
|
||||||
|
env = append(env, e.GetKey()+"="+e.GetValue())
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithEnv(env))
|
||||||
|
|
||||||
|
securityContext := config.GetLinux().GetSecurityContext()
|
||||||
|
selinuxOpt := securityContext.GetSelinuxOptions()
|
||||||
|
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))
|
||||||
|
|
||||||
|
if !c.config.DisableProcMount {
|
||||||
|
// Apply masked paths if specified.
|
||||||
|
// If the container is privileged, this will be cleared later on.
|
||||||
|
specOpts = append(specOpts, oci.WithMaskedPaths(securityContext.GetMaskedPaths()))
|
||||||
|
|
||||||
|
// Apply readonly paths if specified.
|
||||||
|
// If the container is privileged, this will be cleared later on.
|
||||||
|
specOpts = append(specOpts, oci.WithReadonlyPaths(securityContext.GetReadonlyPaths()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if securityContext.GetPrivileged() {
|
||||||
|
if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() {
|
||||||
|
return nil, errors.New("no privileged container allowed in sandbox")
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithPrivileged)
|
||||||
|
if !ociRuntime.PrivilegedWithoutHostDevices {
|
||||||
|
specOpts = append(specOpts, customopts.WithPrivilegedDevices)
|
||||||
|
}
|
||||||
|
} else { // not privileged
|
||||||
|
specOpts = append(specOpts, customopts.WithDevices(c.os, config), customopts.WithCapabilities(securityContext))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all ambient capabilities. The implication of non-root + caps
|
||||||
|
// is not clearly defined in Kubernetes.
|
||||||
|
// See https://github.com/kubernetes/kubernetes/issues/56374
|
||||||
|
// Keep docker's behavior for now.
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithoutAmbientCaps,
|
||||||
|
customopts.WithSelinuxLabels(processLabel, mountLabel),
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: Figure out whether we should set no new privilege for sandbox container by default
|
||||||
|
if securityContext.GetNoNewPrivs() {
|
||||||
|
specOpts = append(specOpts, oci.WithNoNewPrivileges)
|
||||||
|
}
|
||||||
|
// TODO(random-liu): [P1] Set selinux options (privileged or not).
|
||||||
|
if securityContext.GetReadonlyRootfs() {
|
||||||
|
specOpts = append(specOpts, oci.WithRootFSReadonly())
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.DisableCgroup {
|
||||||
|
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
||||||
|
} else {
|
||||||
|
specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources()))
|
||||||
|
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
||||||
|
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id)
|
||||||
|
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
supplementalGroups := securityContext.GetSupplementalGroups()
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations,
|
||||||
|
ociRuntime.PodAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
||||||
|
ociRuntime.ContainerAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithOOMScoreAdj(config, c.config.RestrictOOMScoreAdj),
|
||||||
|
customopts.WithPodNamespaces(securityContext, sandboxPid),
|
||||||
|
customopts.WithSupplementalGroups(supplementalGroups),
|
||||||
|
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxID, sandboxID),
|
||||||
|
)
|
||||||
|
|
||||||
|
return runtimeSpec(id, specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) {
|
||||||
|
var specOpts []oci.SpecOpts
|
||||||
|
securityContext := config.GetLinux().GetSecurityContext()
|
||||||
|
// Set container username. This could only be done by containerd, because it needs
|
||||||
|
// access to the container rootfs. Pass user name to containerd, and let it overwrite
|
||||||
|
// the spec for us.
|
||||||
|
userstr, err := generateUserString(
|
||||||
|
securityContext.GetRunAsUsername(),
|
||||||
|
securityContext.GetRunAsUser(),
|
||||||
|
securityContext.GetRunAsGroup())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to generate user string")
|
||||||
|
}
|
||||||
|
if userstr == "" {
|
||||||
|
// Lastly, since no user override was passed via CRI try to set via OCI
|
||||||
|
// Image
|
||||||
|
userstr = imageConfig.User
|
||||||
|
}
|
||||||
|
if userstr != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithUser(userstr))
|
||||||
|
}
|
||||||
|
|
||||||
|
if securityContext.GetRunAsUsername() != "" {
|
||||||
|
userstr = securityContext.GetRunAsUsername()
|
||||||
|
} else {
|
||||||
|
// Even if RunAsUser is not set, we still call `GetValue` to get uid 0.
|
||||||
|
// Because it is still useful to get additional gids for uid 0.
|
||||||
|
userstr = strconv.FormatInt(securityContext.GetRunAsUser().GetValue(), 10)
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr))
|
||||||
|
|
||||||
|
apparmorSpecOpts, err := generateApparmorSpecOpts(
|
||||||
|
securityContext.GetApparmorProfile(),
|
||||||
|
securityContext.GetPrivileged(),
|
||||||
|
c.apparmorEnabled())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to generate apparmor spec opts")
|
||||||
|
}
|
||||||
|
if apparmorSpecOpts != nil {
|
||||||
|
specOpts = append(specOpts, apparmorSpecOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
seccompSpecOpts, err := generateSeccompSpecOpts(
|
||||||
|
securityContext.GetSeccompProfilePath(),
|
||||||
|
securityContext.GetPrivileged(),
|
||||||
|
c.seccompEnabled())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to generate seccomp spec opts")
|
||||||
|
}
|
||||||
|
if seccompSpecOpts != nil {
|
||||||
|
specOpts = append(specOpts, seccompSpecOpts)
|
||||||
|
}
|
||||||
|
return specOpts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateSeccompSpecOpts generates containerd SpecOpts for seccomp.
|
||||||
|
func generateSeccompSpecOpts(seccompProf string, privileged, seccompEnabled bool) (oci.SpecOpts, error) {
|
||||||
|
if privileged {
|
||||||
|
// Do not set seccomp profile when container is privileged
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// Set seccomp profile
|
||||||
|
if seccompProf == runtimeDefault || seccompProf == dockerDefault {
|
||||||
|
// use correct default profile (Eg. if not configured otherwise, the default is docker/default)
|
||||||
|
seccompProf = seccompDefaultProfile
|
||||||
|
}
|
||||||
|
if !seccompEnabled {
|
||||||
|
if seccompProf != "" && seccompProf != unconfinedProfile {
|
||||||
|
return nil, errors.New("seccomp is not supported")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
switch seccompProf {
|
||||||
|
case "", unconfinedProfile:
|
||||||
|
// Do not set seccomp profile.
|
||||||
|
return nil, nil
|
||||||
|
case dockerDefault:
|
||||||
|
// Note: WithDefaultProfile specOpts must be added after capabilities
|
||||||
|
return seccomp.WithDefaultProfile(), nil
|
||||||
|
default:
|
||||||
|
// Require and Trim default profile name prefix
|
||||||
|
if !strings.HasPrefix(seccompProf, profileNamePrefix) {
|
||||||
|
return nil, errors.Errorf("invalid seccomp profile %q", seccompProf)
|
||||||
|
}
|
||||||
|
return seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateApparmorSpecOpts generates containerd SpecOpts for apparmor.
|
||||||
|
func generateApparmorSpecOpts(apparmorProf string, privileged, apparmorEnabled bool) (oci.SpecOpts, error) {
|
||||||
|
if !apparmorEnabled {
|
||||||
|
// Should fail loudly if user try to specify apparmor profile
|
||||||
|
// but we don't support it.
|
||||||
|
if apparmorProf != "" && apparmorProf != unconfinedProfile {
|
||||||
|
return nil, errors.New("apparmor is not supported")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
switch apparmorProf {
|
||||||
|
// Based on kubernetes#51746, default apparmor profile should be applied
|
||||||
|
// for when apparmor is not specified.
|
||||||
|
case runtimeDefault, "":
|
||||||
|
if privileged {
|
||||||
|
// Do not set apparmor profile when container is privileged
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// TODO (mikebrow): delete created apparmor default profile
|
||||||
|
return apparmor.WithDefaultProfile(appArmorDefaultProfileName), nil
|
||||||
|
case unconfinedProfile:
|
||||||
|
return nil, nil
|
||||||
|
default:
|
||||||
|
// Require and Trim default profile name prefix
|
||||||
|
if !strings.HasPrefix(apparmorProf, profileNamePrefix) {
|
||||||
|
return nil, errors.Errorf("invalid apparmor profile %q", apparmorProf)
|
||||||
|
}
|
||||||
|
return apparmor.WithProfile(strings.TrimPrefix(apparmorProf, profileNamePrefix)), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateUserString generates valid user string based on OCI Image Spec
|
||||||
|
// v1.0.0.
|
||||||
|
//
|
||||||
|
// CRI defines that the following combinations are valid:
|
||||||
|
//
|
||||||
|
// (none) -> ""
|
||||||
|
// username -> username
|
||||||
|
// username, uid -> username
|
||||||
|
// username, uid, gid -> username:gid
|
||||||
|
// username, gid -> username:gid
|
||||||
|
// uid -> uid
|
||||||
|
// uid, gid -> uid:gid
|
||||||
|
// gid -> error
|
||||||
|
//
|
||||||
|
// TODO(random-liu): Add group name support in CRI.
|
||||||
|
func generateUserString(username string, uid, gid *runtime.Int64Value) (string, error) {
|
||||||
|
var userstr, groupstr string
|
||||||
|
if uid != nil {
|
||||||
|
userstr = strconv.FormatInt(uid.GetValue(), 10)
|
||||||
|
}
|
||||||
|
if username != "" {
|
||||||
|
userstr = username
|
||||||
|
}
|
||||||
|
if gid != nil {
|
||||||
|
groupstr = strconv.FormatInt(gid.GetValue(), 10)
|
||||||
|
}
|
||||||
|
if userstr == "" {
|
||||||
|
if groupstr != "" {
|
||||||
|
return "", errors.Errorf("user group %q is specified without user", groupstr)
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if groupstr != "" {
|
||||||
|
userstr = userstr + ":" + groupstr
|
||||||
|
}
|
||||||
|
return userstr, nil
|
||||||
|
}
|
100
vendor/github.com/containerd/cri/pkg/server/container_create_windows.go
generated
vendored
Normal file
100
vendor/github.com/containerd/cri/pkg/server/container_create_windows.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
|
"github.com/containerd/cri/pkg/config"
|
||||||
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// No container mounts for windows.
|
||||||
|
func (c *criService) containerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint32, netNSPath string,
|
||||||
|
config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig,
|
||||||
|
extraMounts []*runtime.Mount, ociRuntime config.Runtime) (*runtimespec.Spec, error) {
|
||||||
|
specOpts := []oci.SpecOpts{
|
||||||
|
customopts.WithProcessArgs(config, imageConfig),
|
||||||
|
}
|
||||||
|
if config.GetWorkingDir() != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(config.GetWorkingDir()))
|
||||||
|
} else if imageConfig.WorkingDir != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.GetTty() {
|
||||||
|
specOpts = append(specOpts, oci.WithTTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply envs from image config first, so that envs from container config
|
||||||
|
// can override them.
|
||||||
|
env := imageConfig.Env
|
||||||
|
for _, e := range config.GetEnvs() {
|
||||||
|
env = append(env, e.GetKey()+"="+e.GetValue())
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithEnv(env))
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
// Clear the root location since hcsshim expects it.
|
||||||
|
// NOTE: readonly rootfs doesn't work on windows.
|
||||||
|
customopts.WithoutRoot,
|
||||||
|
customopts.WithWindowsNetworkNamespace(netNSPath),
|
||||||
|
oci.WithHostname(sandboxConfig.GetHostname()),
|
||||||
|
)
|
||||||
|
|
||||||
|
specOpts = append(specOpts, customopts.WithWindowsMounts(c.os, config, extraMounts))
|
||||||
|
|
||||||
|
specOpts = append(specOpts, customopts.WithWindowsResources(config.GetWindows().GetResources()))
|
||||||
|
|
||||||
|
username := config.GetWindows().GetSecurityContext().GetRunAsUsername()
|
||||||
|
if username != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithUser(username))
|
||||||
|
}
|
||||||
|
// TODO(windows): Add CredentialSpec support.
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations,
|
||||||
|
ociRuntime.PodAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
||||||
|
ociRuntime.ContainerAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxID, sandboxID),
|
||||||
|
)
|
||||||
|
|
||||||
|
return runtimeSpec(id, specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No extra spec options needed for windows.
|
||||||
|
func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
46
vendor/github.com/containerd/cri/pkg/server/container_execsync.go
generated
vendored
46
vendor/github.com/containerd/cri/pkg/server/container_execsync.go
generated
vendored
@ -70,28 +70,13 @@ type execOptions struct {
|
|||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// execInContainer executes a command inside the container synchronously, and
|
func (c *criService) execInternal(ctx context.Context, container containerd.Container, id string, opts execOptions) (*uint32, error) {
|
||||||
// redirects stdio stream properly.
|
|
||||||
func (c *criService) execInContainer(ctx context.Context, id string, opts execOptions) (*uint32, error) {
|
|
||||||
// Cancel the context before returning to ensure goroutines are stopped.
|
// Cancel the context before returning to ensure goroutines are stopped.
|
||||||
// This is important, because if `Start` returns error, `Wait` will hang
|
// This is important, because if `Start` returns error, `Wait` will hang
|
||||||
// forever unless we cancel the context.
|
// forever unless we cancel the context.
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Get container from our container store.
|
|
||||||
cntr, err := c.containerStore.Get(id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to find container %q in store", id)
|
|
||||||
}
|
|
||||||
id = cntr.ID
|
|
||||||
|
|
||||||
state := cntr.Status.Get().State()
|
|
||||||
if state != runtime.ContainerState_CONTAINER_RUNNING {
|
|
||||||
return nil, errors.Errorf("container is in %s state", criContainerStateToString(state))
|
|
||||||
}
|
|
||||||
|
|
||||||
container := cntr.Container
|
|
||||||
spec, err := container.Spec(ctx)
|
spec, err := container.Spec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get container spec")
|
return nil, errors.Wrap(err, "failed to get container spec")
|
||||||
@ -195,3 +180,32 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp
|
|||||||
return &code, nil
|
return &code, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execInContainer executes a command inside the container synchronously, and
|
||||||
|
// redirects stdio stream properly.
|
||||||
|
// This function only returns when the exec process exits, this means that:
|
||||||
|
// 1) As long as the exec process is running, the goroutine in the cri plugin
|
||||||
|
// will be running and wait for the exit code;
|
||||||
|
// 2) `kubectl exec -it` will hang until the exec process exits, even after io
|
||||||
|
// is detached. This is different from dockershim, which leaves the exec process
|
||||||
|
// running in background after io is detached.
|
||||||
|
// https://github.com/kubernetes/kubernetes/blob/v1.15.0/pkg/kubelet/dockershim/exec.go#L127
|
||||||
|
// For example, if the `kubectl exec -it` process is killed, IO will be closed. In
|
||||||
|
// this case, the CRI plugin will still have a goroutine waiting for the exec process
|
||||||
|
// to exit and log the exit code, but dockershim won't.
|
||||||
|
func (c *criService) execInContainer(ctx context.Context, id string, opts execOptions) (*uint32, error) {
|
||||||
|
// Get container from our container store.
|
||||||
|
cntr, err := c.containerStore.Get(id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to find container %q in store", id)
|
||||||
|
}
|
||||||
|
id = cntr.ID
|
||||||
|
|
||||||
|
state := cntr.Status.Get().State()
|
||||||
|
if state != runtime.ContainerState_CONTAINER_RUNNING {
|
||||||
|
return nil, errors.Errorf("container is in %s state", criContainerStateToString(state))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.execInternal(ctx, cntr.Container, id, opts)
|
||||||
|
}
|
||||||
|
10
vendor/github.com/containerd/cri/pkg/server/container_start.go
generated
vendored
10
vendor/github.com/containerd/cri/pkg/server/container_start.go
generated
vendored
@ -18,14 +18,12 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
containerdio "github.com/containerd/containerd/cio"
|
containerdio "github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/plugin"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -99,11 +97,7 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain
|
|||||||
return nil, errors.Wrap(err, "failed to get container info")
|
return nil, errors.Wrap(err, "failed to get container info")
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskOpts []containerd.NewTaskOpts
|
taskOpts := c.taskOpts(ctrInfo.Runtime.Name)
|
||||||
// TODO(random-liu): Remove this after shim v1 is deprecated.
|
|
||||||
if c.config.NoPivot && ctrInfo.Runtime.Name == plugin.RuntimeLinuxV1 {
|
|
||||||
taskOpts = append(taskOpts, containerd.WithNoPivotRoot)
|
|
||||||
}
|
|
||||||
task, err := container.NewTask(ctx, ioCreation, taskOpts...)
|
task, err := container.NewTask(ctx, ioCreation, taskOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to create containerd task")
|
return nil, errors.Wrap(err, "failed to create containerd task")
|
||||||
@ -180,7 +174,7 @@ func resetContainerStarting(container containerstore.Container) error {
|
|||||||
func (c *criService) createContainerLoggers(logPath string, tty bool) (stdout io.WriteCloser, stderr io.WriteCloser, err error) {
|
func (c *criService) createContainerLoggers(logPath string, tty bool) (stdout io.WriteCloser, stderr io.WriteCloser, err error) {
|
||||||
if logPath != "" {
|
if logPath != "" {
|
||||||
// Only generate container log when log path is specified.
|
// Only generate container log when log path is specified.
|
||||||
f, err := os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640)
|
f, err := openLogFile(logPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "failed to create and open log file")
|
return nil, nil, errors.Wrap(err, "failed to create and open log file")
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/server/container_stats.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/container_stats.go
generated
vendored
@ -39,7 +39,7 @@ func (c *criService) ContainerStats(ctx context.Context, in *runtime.ContainerSt
|
|||||||
return nil, errors.Errorf("unexpected metrics response: %+v", resp.Metrics)
|
return nil, errors.Errorf("unexpected metrics response: %+v", resp.Metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs, err := c.getContainerMetrics(cntr.Metadata, resp.Metrics[0])
|
cs, err := c.containerMetrics(cntr.Metadata, resp.Metrics[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to decode container metrics")
|
return nil, errors.Wrap(err, "failed to decode container metrics")
|
||||||
}
|
}
|
||||||
|
71
vendor/github.com/containerd/cri/pkg/server/container_stats_list.go
generated
vendored
71
vendor/github.com/containerd/cri/pkg/server/container_stats_list.go
generated
vendored
@ -17,10 +17,8 @@ limitations under the License.
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containerd/cgroups"
|
|
||||||
tasks "github.com/containerd/containerd/api/services/tasks/v1"
|
tasks "github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
@ -58,7 +56,7 @@ func (c *criService) toCRIContainerStats(
|
|||||||
}
|
}
|
||||||
containerStats := new(runtime.ListContainerStatsResponse)
|
containerStats := new(runtime.ListContainerStatsResponse)
|
||||||
for _, cntr := range containers {
|
for _, cntr := range containers {
|
||||||
cs, err := c.getContainerMetrics(cntr.Metadata, statsMap[cntr.ID])
|
cs, err := c.containerMetrics(cntr.Metadata, statsMap[cntr.ID])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to decode container metrics for %q", cntr.ID)
|
return nil, errors.Wrapf(err, "failed to decode container metrics for %q", cntr.ID)
|
||||||
}
|
}
|
||||||
@ -67,59 +65,6 @@ func (c *criService) toCRIContainerStats(
|
|||||||
return containerStats, nil
|
return containerStats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) getContainerMetrics(
|
|
||||||
meta containerstore.Metadata,
|
|
||||||
stats *types.Metric,
|
|
||||||
) (*runtime.ContainerStats, error) {
|
|
||||||
var cs runtime.ContainerStats
|
|
||||||
var usedBytes, inodesUsed uint64
|
|
||||||
sn, err := c.snapshotStore.Get(meta.ID)
|
|
||||||
// If snapshotstore doesn't have cached snapshot information
|
|
||||||
// set WritableLayer usage to zero
|
|
||||||
if err == nil {
|
|
||||||
usedBytes = sn.Size
|
|
||||||
inodesUsed = sn.Inodes
|
|
||||||
}
|
|
||||||
cs.WritableLayer = &runtime.FilesystemUsage{
|
|
||||||
Timestamp: sn.Timestamp,
|
|
||||||
FsId: &runtime.FilesystemIdentifier{
|
|
||||||
Mountpoint: c.imageFSPath,
|
|
||||||
},
|
|
||||||
UsedBytes: &runtime.UInt64Value{Value: usedBytes},
|
|
||||||
InodesUsed: &runtime.UInt64Value{Value: inodesUsed},
|
|
||||||
}
|
|
||||||
cs.Attributes = &runtime.ContainerAttributes{
|
|
||||||
Id: meta.ID,
|
|
||||||
Metadata: meta.Config.GetMetadata(),
|
|
||||||
Labels: meta.Config.GetLabels(),
|
|
||||||
Annotations: meta.Config.GetAnnotations(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if stats != nil {
|
|
||||||
s, err := typeurl.UnmarshalAny(stats.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to extract container metrics")
|
|
||||||
}
|
|
||||||
metrics := s.(*cgroups.Metrics)
|
|
||||||
if metrics.CPU != nil && metrics.CPU.Usage != nil {
|
|
||||||
cs.Cpu = &runtime.CpuUsage{
|
|
||||||
Timestamp: stats.Timestamp.UnixNano(),
|
|
||||||
UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if metrics.Memory != nil && metrics.Memory.Usage != nil {
|
|
||||||
cs.Memory = &runtime.MemoryUsage{
|
|
||||||
Timestamp: stats.Timestamp.UnixNano(),
|
|
||||||
WorkingSetBytes: &runtime.UInt64Value{
|
|
||||||
Value: getWorkingSet(metrics.Memory),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *criService) normalizeContainerStatsFilter(filter *runtime.ContainerStatsFilter) {
|
func (c *criService) normalizeContainerStatsFilter(filter *runtime.ContainerStatsFilter) {
|
||||||
if cntr, err := c.containerStore.Get(filter.GetId()); err == nil {
|
if cntr, err := c.containerStore.Get(filter.GetId()); err == nil {
|
||||||
filter.Id = cntr.ID
|
filter.Id = cntr.ID
|
||||||
@ -169,17 +114,3 @@ func matchLabelSelector(selector, labels map[string]string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// getWorkingSet calculates workingset memory from cgroup memory stats.
|
|
||||||
// The caller should make sure memory is not nil.
|
|
||||||
// workingset = usage - total_inactive_file
|
|
||||||
func getWorkingSet(memory *cgroups.MemoryStat) uint64 {
|
|
||||||
if memory.Usage == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var workingSet uint64
|
|
||||||
if memory.TotalInactiveFile < memory.Usage.Usage {
|
|
||||||
workingSet = memory.Usage.Usage - memory.TotalInactiveFile
|
|
||||||
}
|
|
||||||
return workingSet
|
|
||||||
}
|
|
||||||
|
96
vendor/github.com/containerd/cri/pkg/server/container_stats_list_unix.go
generated
vendored
Normal file
96
vendor/github.com/containerd/cri/pkg/server/container_stats_list_unix.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/api/types"
|
||||||
|
v1 "github.com/containerd/containerd/metrics/types/v1"
|
||||||
|
"github.com/containerd/typeurl"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
containerstore "github.com/containerd/cri/pkg/store/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *criService) containerMetrics(
|
||||||
|
meta containerstore.Metadata,
|
||||||
|
stats *types.Metric,
|
||||||
|
) (*runtime.ContainerStats, error) {
|
||||||
|
var cs runtime.ContainerStats
|
||||||
|
var usedBytes, inodesUsed uint64
|
||||||
|
sn, err := c.snapshotStore.Get(meta.ID)
|
||||||
|
// If snapshotstore doesn't have cached snapshot information
|
||||||
|
// set WritableLayer usage to zero
|
||||||
|
if err == nil {
|
||||||
|
usedBytes = sn.Size
|
||||||
|
inodesUsed = sn.Inodes
|
||||||
|
}
|
||||||
|
cs.WritableLayer = &runtime.FilesystemUsage{
|
||||||
|
Timestamp: sn.Timestamp,
|
||||||
|
FsId: &runtime.FilesystemIdentifier{
|
||||||
|
Mountpoint: c.imageFSPath,
|
||||||
|
},
|
||||||
|
UsedBytes: &runtime.UInt64Value{Value: usedBytes},
|
||||||
|
InodesUsed: &runtime.UInt64Value{Value: inodesUsed},
|
||||||
|
}
|
||||||
|
cs.Attributes = &runtime.ContainerAttributes{
|
||||||
|
Id: meta.ID,
|
||||||
|
Metadata: meta.Config.GetMetadata(),
|
||||||
|
Labels: meta.Config.GetLabels(),
|
||||||
|
Annotations: meta.Config.GetAnnotations(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if stats != nil {
|
||||||
|
s, err := typeurl.UnmarshalAny(stats.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to extract container metrics")
|
||||||
|
}
|
||||||
|
metrics := s.(*v1.Metrics)
|
||||||
|
if metrics.CPU != nil && metrics.CPU.Usage != nil {
|
||||||
|
cs.Cpu = &runtime.CpuUsage{
|
||||||
|
Timestamp: stats.Timestamp.UnixNano(),
|
||||||
|
UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if metrics.Memory != nil && metrics.Memory.Usage != nil {
|
||||||
|
cs.Memory = &runtime.MemoryUsage{
|
||||||
|
Timestamp: stats.Timestamp.UnixNano(),
|
||||||
|
WorkingSetBytes: &runtime.UInt64Value{
|
||||||
|
Value: getWorkingSet(metrics.Memory),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWorkingSet calculates workingset memory from cgroup memory stats.
|
||||||
|
// The caller should make sure memory is not nil.
|
||||||
|
// workingset = usage - total_inactive_file
|
||||||
|
func getWorkingSet(memory *v1.MemoryStat) uint64 {
|
||||||
|
if memory.Usage == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var workingSet uint64
|
||||||
|
if memory.TotalInactiveFile < memory.Usage.Usage {
|
||||||
|
workingSet = memory.Usage.Usage - memory.TotalInactiveFile
|
||||||
|
}
|
||||||
|
return workingSet
|
||||||
|
}
|
60
vendor/github.com/containerd/cri/pkg/server/container_stats_list_windows.go
generated
vendored
Normal file
60
vendor/github.com/containerd/cri/pkg/server/container_stats_list_windows.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/api/types"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
containerstore "github.com/containerd/cri/pkg/store/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *criService) containerMetrics(
|
||||||
|
meta containerstore.Metadata,
|
||||||
|
stats *types.Metric,
|
||||||
|
) (*runtime.ContainerStats, error) {
|
||||||
|
var cs runtime.ContainerStats
|
||||||
|
var usedBytes, inodesUsed uint64
|
||||||
|
sn, err := c.snapshotStore.Get(meta.ID)
|
||||||
|
// If snapshotstore doesn't have cached snapshot information
|
||||||
|
// set WritableLayer usage to zero
|
||||||
|
if err == nil {
|
||||||
|
usedBytes = sn.Size
|
||||||
|
inodesUsed = sn.Inodes
|
||||||
|
}
|
||||||
|
cs.WritableLayer = &runtime.FilesystemUsage{
|
||||||
|
Timestamp: sn.Timestamp,
|
||||||
|
FsId: &runtime.FilesystemIdentifier{
|
||||||
|
Mountpoint: c.imageFSPath,
|
||||||
|
},
|
||||||
|
UsedBytes: &runtime.UInt64Value{Value: usedBytes},
|
||||||
|
InodesUsed: &runtime.UInt64Value{Value: inodesUsed},
|
||||||
|
}
|
||||||
|
cs.Attributes = &runtime.ContainerAttributes{
|
||||||
|
Id: meta.ID,
|
||||||
|
Metadata: meta.Config.GetMetadata(),
|
||||||
|
Labels: meta.Config.GetLabels(),
|
||||||
|
Annotations: meta.Config.GetAnnotations(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(windows): hcsshim Stats is not implemented, add windows support after
|
||||||
|
// that is implemented.
|
||||||
|
|
||||||
|
return &cs, nil
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
31
vendor/github.com/containerd/cri/pkg/server/container_update_resources_windows.go
generated
vendored
Normal file
31
vendor/github.com/containerd/cri/pkg/server/container_update_resources_windows.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateContainerResources updates ContainerConfig of the container.
|
||||||
|
// TODO(windows): Figure out whether windows support this.
|
||||||
|
func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (*runtime.UpdateContainerResourcesResponse, error) {
|
||||||
|
return nil, errdefs.ErrNotImplemented
|
||||||
|
}
|
120
vendor/github.com/containerd/cri/pkg/server/helpers.go
generated
vendored
120
vendor/github.com/containerd/cri/pkg/server/helpers.go
generated
vendored
@ -20,11 +20,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
|
runhcsoptions "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
imagedigest "github.com/opencontainers/go-digest"
|
imagedigest "github.com/opencontainers/go-digest"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
@ -51,6 +50,7 @@ const (
|
|||||||
errorStartReason = "StartError"
|
errorStartReason = "StartError"
|
||||||
// errorStartExitCode is the exit code when fails to start container.
|
// errorStartExitCode is the exit code when fails to start container.
|
||||||
// 128 is the same with Docker's behavior.
|
// 128 is the same with Docker's behavior.
|
||||||
|
// TODO(windows): Figure out what should be used for windows.
|
||||||
errorStartExitCode = 128
|
errorStartExitCode = 128
|
||||||
// completeExitReason is the exit reason when container exits with code 0.
|
// completeExitReason is the exit reason when container exits with code 0.
|
||||||
completeExitReason = "Completed"
|
completeExitReason = "Completed"
|
||||||
@ -58,39 +58,16 @@ const (
|
|||||||
errorExitReason = "Error"
|
errorExitReason = "Error"
|
||||||
// oomExitReason is the exit reason when process in container is oom killed.
|
// oomExitReason is the exit reason when process in container is oom killed.
|
||||||
oomExitReason = "OOMKilled"
|
oomExitReason = "OOMKilled"
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// defaultSandboxOOMAdj is default omm adj for sandbox container. (kubernetes#47938).
|
|
||||||
defaultSandboxOOMAdj = -998
|
|
||||||
// defaultShmSize is the default size of the sandbox shm.
|
|
||||||
defaultShmSize = int64(1024 * 1024 * 64)
|
|
||||||
// relativeRootfsPath is the rootfs path relative to bundle path.
|
|
||||||
relativeRootfsPath = "rootfs"
|
|
||||||
// sandboxesDir contains all sandbox root. A sandbox root is the running
|
// sandboxesDir contains all sandbox root. A sandbox root is the running
|
||||||
// directory of the sandbox, all files created for the sandbox will be
|
// directory of the sandbox, all files created for the sandbox will be
|
||||||
// placed under this directory.
|
// placed under this directory.
|
||||||
sandboxesDir = "sandboxes"
|
sandboxesDir = "sandboxes"
|
||||||
// containersDir contains all container root.
|
// containersDir contains all container root.
|
||||||
containersDir = "containers"
|
containersDir = "containers"
|
||||||
// According to http://man7.org/linux/man-pages/man5/resolv.conf.5.html:
|
|
||||||
// "The search list is currently limited to six domains with a total of 256 characters."
|
|
||||||
maxDNSSearches = 6
|
|
||||||
// Delimiter used to construct container/sandbox names.
|
// Delimiter used to construct container/sandbox names.
|
||||||
nameDelimiter = "_"
|
nameDelimiter = "_"
|
||||||
// devShm is the default path of /dev/shm.
|
|
||||||
devShm = "/dev/shm"
|
|
||||||
// etcHosts is the default path of /etc/hosts file.
|
|
||||||
etcHosts = "/etc/hosts"
|
|
||||||
// etcHostname is the default path of /etc/hostname file.
|
|
||||||
etcHostname = "/etc/hostname"
|
|
||||||
// resolvConfPath is the abs path of resolv.conf on host or container.
|
|
||||||
resolvConfPath = "/etc/resolv.conf"
|
|
||||||
// hostnameEnv is the key for HOSTNAME env.
|
|
||||||
hostnameEnv = "HOSTNAME"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// criContainerdPrefix is common prefix for cri-containerd
|
// criContainerdPrefix is common prefix for cri-containerd
|
||||||
criContainerdPrefix = "io.cri-containerd"
|
criContainerdPrefix = "io.cri-containerd"
|
||||||
// containerKindLabel is a label key indicating container is sandbox container or application container
|
// containerKindLabel is a label key indicating container is sandbox container or application container
|
||||||
@ -107,14 +84,12 @@ const (
|
|||||||
sandboxMetadataExtension = criContainerdPrefix + ".sandbox.metadata"
|
sandboxMetadataExtension = criContainerdPrefix + ".sandbox.metadata"
|
||||||
// containerMetadataExtension is an extension name that identify metadata of container in CreateContainerRequest
|
// containerMetadataExtension is an extension name that identify metadata of container in CreateContainerRequest
|
||||||
containerMetadataExtension = criContainerdPrefix + ".container.metadata"
|
containerMetadataExtension = criContainerdPrefix + ".container.metadata"
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// defaultIfName is the default network interface for the pods
|
// defaultIfName is the default network interface for the pods
|
||||||
defaultIfName = "eth0"
|
defaultIfName = "eth0"
|
||||||
// networkAttachCount is the minimum number of networks the PodSandbox
|
|
||||||
// attaches to
|
// runtimeRunhcsV1 is the runtime type for runhcs.
|
||||||
networkAttachCount = 2
|
runtimeRunhcsV1 = "io.containerd.runhcs.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// makeSandboxName generates sandbox name from sandbox metadata. The name
|
// makeSandboxName generates sandbox name from sandbox metadata. The name
|
||||||
@ -141,17 +116,6 @@ func makeContainerName(c *runtime.ContainerMetadata, s *runtime.PodSandboxMetada
|
|||||||
}, nameDelimiter)
|
}, nameDelimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCgroupsPath generates container cgroups path.
|
|
||||||
func getCgroupsPath(cgroupsParent, id string) string {
|
|
||||||
base := path.Base(cgroupsParent)
|
|
||||||
if strings.HasSuffix(base, ".slice") {
|
|
||||||
// For a.slice/b.slice/c.slice, base is c.slice.
|
|
||||||
// runc systemd cgroup path format is "slice:prefix:name".
|
|
||||||
return strings.Join([]string{base, "cri-containerd", id}, ":")
|
|
||||||
}
|
|
||||||
return filepath.Join(cgroupsParent, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSandboxRootDir returns the root directory for managing sandbox files,
|
// getSandboxRootDir returns the root directory for managing sandbox files,
|
||||||
// e.g. hosts files.
|
// e.g. hosts files.
|
||||||
func (c *criService) getSandboxRootDir(id string) string {
|
func (c *criService) getSandboxRootDir(id string) string {
|
||||||
@ -176,26 +140,6 @@ func (c *criService) getVolatileContainerRootDir(id string) string {
|
|||||||
return filepath.Join(c.config.StateDir, containersDir, id)
|
return filepath.Join(c.config.StateDir, containersDir, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSandboxHostname returns the hostname file path inside the sandbox root directory.
|
|
||||||
func (c *criService) getSandboxHostname(id string) string {
|
|
||||||
return filepath.Join(c.getSandboxRootDir(id), "hostname")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSandboxHosts returns the hosts file path inside the sandbox root directory.
|
|
||||||
func (c *criService) getSandboxHosts(id string) string {
|
|
||||||
return filepath.Join(c.getSandboxRootDir(id), "hosts")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getResolvPath returns resolv.conf filepath for specified sandbox.
|
|
||||||
func (c *criService) getResolvPath(id string) string {
|
|
||||||
return filepath.Join(c.getSandboxRootDir(id), "resolv.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSandboxDevShm returns the shm file path inside the sandbox root directory.
|
|
||||||
func (c *criService) getSandboxDevShm(id string) string {
|
|
||||||
return filepath.Join(c.getVolatileSandboxRootDir(id), "shm")
|
|
||||||
}
|
|
||||||
|
|
||||||
// criContainerStateToString formats CRI container state to string.
|
// criContainerStateToString formats CRI container state to string.
|
||||||
func criContainerStateToString(state runtime.ContainerState) string {
|
func criContainerStateToString(state runtime.ContainerState) string {
|
||||||
return runtime.ContainerState_name[int32(state)]
|
return runtime.ContainerState_name[int32(state)]
|
||||||
@ -298,49 +242,6 @@ func (c *criService) ensureImageExists(ctx context.Context, ref string, config *
|
|||||||
return &newImage, nil
|
return &newImage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
|
|
||||||
if selinuxOpt == nil {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should ignored selinuxOpts if they are incomplete.
|
|
||||||
if selinuxOpt.GetUser() == "" ||
|
|
||||||
selinuxOpt.GetRole() == "" ||
|
|
||||||
selinuxOpt.GetType() == "" {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the format of "level" is correct.
|
|
||||||
ok, err := checkSelinuxLevel(selinuxOpt.GetLevel())
|
|
||||||
if err != nil || !ok {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
labelOpts := fmt.Sprintf("%s:%s:%s:%s",
|
|
||||||
selinuxOpt.GetUser(),
|
|
||||||
selinuxOpt.GetRole(),
|
|
||||||
selinuxOpt.GetType(),
|
|
||||||
selinuxOpt.GetLevel())
|
|
||||||
|
|
||||||
options, err := label.DupSecOpt(labelOpts)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return label.InitLabels(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSelinuxLevel(level string) (bool, error) {
|
|
||||||
if len(level) == 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}((.c\d{1,4})?,c\d{1,4})*(.c\d{1,4})?(,c\d{1,4}(.c\d{1,4})?)*)?$`, level)
|
|
||||||
if err != nil || !matched {
|
|
||||||
return false, errors.Wrapf(err, "the format of 'level' %q is not correct", level)
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isInCRIMounts checks whether a destination is in CRI mount list.
|
// isInCRIMounts checks whether a destination is in CRI mount list.
|
||||||
func isInCRIMounts(dst string, mounts []*runtime.Mount) bool {
|
func isInCRIMounts(dst string, mounts []*runtime.Mount) bool {
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
@ -367,15 +268,6 @@ func buildLabels(configLabels map[string]string, containerType string) map[strin
|
|||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPodCNILabels(id string, config *runtime.PodSandboxConfig) map[string]string {
|
|
||||||
return map[string]string{
|
|
||||||
"K8S_POD_NAMESPACE": config.GetMetadata().GetNamespace(),
|
|
||||||
"K8S_POD_NAME": config.GetMetadata().GetName(),
|
|
||||||
"K8S_POD_INFRA_CONTAINER_ID": id,
|
|
||||||
"IgnoreUnknown": "1",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toRuntimeAuthConfig converts cri plugin auth config to runtime auth config.
|
// toRuntimeAuthConfig converts cri plugin auth config to runtime auth config.
|
||||||
func toRuntimeAuthConfig(a criconfig.AuthConfig) *runtime.AuthConfig {
|
func toRuntimeAuthConfig(a criconfig.AuthConfig) *runtime.AuthConfig {
|
||||||
return &runtime.AuthConfig{
|
return &runtime.AuthConfig{
|
||||||
@ -433,6 +325,8 @@ func getRuntimeOptionsType(t string) interface{} {
|
|||||||
return &runcoptions.Options{}
|
return &runcoptions.Options{}
|
||||||
case plugin.RuntimeLinuxV1:
|
case plugin.RuntimeLinuxV1:
|
||||||
return &runctypes.RuncOptions{}
|
return &runctypes.RuncOptions{}
|
||||||
|
case runtimeRunhcsV1:
|
||||||
|
return &runhcsoptions.Options{}
|
||||||
default:
|
default:
|
||||||
return &runtimeoptions.Options{}
|
return &runtimeoptions.Options{}
|
||||||
}
|
}
|
||||||
|
143
vendor/github.com/containerd/cri/pkg/server/helpers_unix.go
generated
vendored
Normal file
143
vendor/github.com/containerd/cri/pkg/server/helpers_unix.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
|
||||||
|
runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultSandboxOOMAdj is default omm adj for sandbox container. (kubernetes#47938).
|
||||||
|
defaultSandboxOOMAdj = -998
|
||||||
|
// defaultShmSize is the default size of the sandbox shm.
|
||||||
|
defaultShmSize = int64(1024 * 1024 * 64)
|
||||||
|
// relativeRootfsPath is the rootfs path relative to bundle path.
|
||||||
|
relativeRootfsPath = "rootfs"
|
||||||
|
// According to http://man7.org/linux/man-pages/man5/resolv.conf.5.html:
|
||||||
|
// "The search list is currently limited to six domains with a total of 256 characters."
|
||||||
|
maxDNSSearches = 6
|
||||||
|
// devShm is the default path of /dev/shm.
|
||||||
|
devShm = "/dev/shm"
|
||||||
|
// etcHosts is the default path of /etc/hosts file.
|
||||||
|
etcHosts = "/etc/hosts"
|
||||||
|
// etcHostname is the default path of /etc/hostname file.
|
||||||
|
etcHostname = "/etc/hostname"
|
||||||
|
// resolvConfPath is the abs path of resolv.conf on host or container.
|
||||||
|
resolvConfPath = "/etc/resolv.conf"
|
||||||
|
// hostnameEnv is the key for HOSTNAME env.
|
||||||
|
hostnameEnv = "HOSTNAME"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getCgroupsPath generates container cgroups path.
|
||||||
|
func getCgroupsPath(cgroupsParent, id string) string {
|
||||||
|
base := path.Base(cgroupsParent)
|
||||||
|
if strings.HasSuffix(base, ".slice") {
|
||||||
|
// For a.slice/b.slice/c.slice, base is c.slice.
|
||||||
|
// runc systemd cgroup path format is "slice:prefix:name".
|
||||||
|
return strings.Join([]string{base, "cri-containerd", id}, ":")
|
||||||
|
}
|
||||||
|
return filepath.Join(cgroupsParent, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSandboxHostname returns the hostname file path inside the sandbox root directory.
|
||||||
|
func (c *criService) getSandboxHostname(id string) string {
|
||||||
|
return filepath.Join(c.getSandboxRootDir(id), "hostname")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSandboxHosts returns the hosts file path inside the sandbox root directory.
|
||||||
|
func (c *criService) getSandboxHosts(id string) string {
|
||||||
|
return filepath.Join(c.getSandboxRootDir(id), "hosts")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getResolvPath returns resolv.conf filepath for specified sandbox.
|
||||||
|
func (c *criService) getResolvPath(id string) string {
|
||||||
|
return filepath.Join(c.getSandboxRootDir(id), "resolv.conf")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSandboxDevShm returns the shm file path inside the sandbox root directory.
|
||||||
|
func (c *criService) getSandboxDevShm(id string) string {
|
||||||
|
return filepath.Join(c.getVolatileSandboxRootDir(id), "shm")
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
|
||||||
|
if selinuxOpt == nil {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should ignored selinuxOpts if they are incomplete.
|
||||||
|
if selinuxOpt.GetUser() == "" ||
|
||||||
|
selinuxOpt.GetRole() == "" ||
|
||||||
|
selinuxOpt.GetType() == "" {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the format of "level" is correct.
|
||||||
|
ok, err := checkSelinuxLevel(selinuxOpt.GetLevel())
|
||||||
|
if err != nil || !ok {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
labelOpts := fmt.Sprintf("%s:%s:%s:%s",
|
||||||
|
selinuxOpt.GetUser(),
|
||||||
|
selinuxOpt.GetRole(),
|
||||||
|
selinuxOpt.GetType(),
|
||||||
|
selinuxOpt.GetLevel())
|
||||||
|
|
||||||
|
options, err := label.DupSecOpt(labelOpts)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return label.InitLabels(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSelinuxLevel(level string) (bool, error) {
|
||||||
|
if len(level) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}((.c\d{1,4})?,c\d{1,4})*(.c\d{1,4})?(,c\d{1,4}(.c\d{1,4})?)*)?$`, level)
|
||||||
|
if err != nil || !matched {
|
||||||
|
return false, errors.Wrapf(err, "the format of 'level' %q is not correct", level)
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) apparmorEnabled() bool {
|
||||||
|
return runcapparmor.IsEnabled() && !c.config.DisableApparmor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) seccompEnabled() bool {
|
||||||
|
return runcseccomp.IsEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
// openLogFile opens/creates a container log file.
|
||||||
|
func openLogFile(path string) (*os.File, error) {
|
||||||
|
return os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640)
|
||||||
|
}
|
158
vendor/github.com/containerd/cri/pkg/server/helpers_windows.go
generated
vendored
Normal file
158
vendor/github.com/containerd/cri/pkg/server/helpers_windows.go
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// openLogFile opens/creates a container log file.
|
||||||
|
// It specifies `FILE_SHARE_DELETE` option to make sure
|
||||||
|
// log files can be rotated by kubelet.
|
||||||
|
// TODO(windows): Use golang support after 1.14. (https://github.com/golang/go/issues/32088)
|
||||||
|
func openLogFile(path string) (*os.File, error) {
|
||||||
|
path = fixLongPath(path)
|
||||||
|
if len(path) == 0 {
|
||||||
|
return nil, syscall.ERROR_FILE_NOT_FOUND
|
||||||
|
}
|
||||||
|
pathp, err := syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
createmode := uint32(syscall.OPEN_ALWAYS)
|
||||||
|
access := uint32(syscall.FILE_APPEND_DATA)
|
||||||
|
sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE)
|
||||||
|
h, err := syscall.CreateFile(pathp, access, sharemode, nil, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return os.NewFile(uintptr(h), path), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// fixLongPath returns the extended-length (\\?\-prefixed) form of
|
||||||
|
// path when needed, in order to avoid the default 260 character file
|
||||||
|
// path limit imposed by Windows. If path is not easily converted to
|
||||||
|
// the extended-length form (for example, if path is a relative path
|
||||||
|
// or contains .. elements), or is short enough, fixLongPath returns
|
||||||
|
// path unmodified.
|
||||||
|
//
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
|
||||||
|
//
|
||||||
|
// This is copied from https://golang.org/src/path/filepath/path_windows.go.
|
||||||
|
func fixLongPath(path string) string {
|
||||||
|
// Do nothing (and don't allocate) if the path is "short".
|
||||||
|
// Empirically (at least on the Windows Server 2013 builder),
|
||||||
|
// the kernel is arbitrarily okay with < 248 bytes. That
|
||||||
|
// matches what the docs above say:
|
||||||
|
// "When using an API to create a directory, the specified
|
||||||
|
// path cannot be so long that you cannot append an 8.3 file
|
||||||
|
// name (that is, the directory name cannot exceed MAX_PATH
|
||||||
|
// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
|
||||||
|
//
|
||||||
|
// The MSDN docs appear to say that a normal path that is 248 bytes long
|
||||||
|
// will work; empirically the path must be less then 248 bytes long.
|
||||||
|
if len(path) < 248 {
|
||||||
|
// Don't fix. (This is how Go 1.7 and earlier worked,
|
||||||
|
// not automatically generating the \\?\ form)
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// The extended form begins with \\?\, as in
|
||||||
|
// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
|
||||||
|
// The extended form disables evaluation of . and .. path
|
||||||
|
// elements and disables the interpretation of / as equivalent
|
||||||
|
// to \. The conversion here rewrites / to \ and elides
|
||||||
|
// . elements as well as trailing or duplicate separators. For
|
||||||
|
// simplicity it avoids the conversion entirely for relative
|
||||||
|
// paths or paths containing .. elements. For now,
|
||||||
|
// \\server\share paths are not converted to
|
||||||
|
// \\?\UNC\server\share paths because the rules for doing so
|
||||||
|
// are less well-specified.
|
||||||
|
if len(path) >= 2 && path[:2] == `\\` {
|
||||||
|
// Don't canonicalize UNC paths.
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
if !filepath.IsAbs(path) {
|
||||||
|
// Relative path
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix = `\\?`
|
||||||
|
|
||||||
|
pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
|
||||||
|
copy(pathbuf, prefix)
|
||||||
|
n := len(path)
|
||||||
|
r, w := 0, len(prefix)
|
||||||
|
for r < n {
|
||||||
|
switch {
|
||||||
|
case os.IsPathSeparator(path[r]):
|
||||||
|
// empty block
|
||||||
|
r++
|
||||||
|
case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
|
||||||
|
// /./
|
||||||
|
r++
|
||||||
|
case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
|
||||||
|
// /../ is currently unhandled
|
||||||
|
return path
|
||||||
|
default:
|
||||||
|
pathbuf[w] = '\\'
|
||||||
|
w++
|
||||||
|
for ; r < n && !os.IsPathSeparator(path[r]); r++ {
|
||||||
|
pathbuf[w] = path[r]
|
||||||
|
w++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A drive's root directory needs a trailing \
|
||||||
|
if w == len(`\\?\c:`) {
|
||||||
|
pathbuf[w] = '\\'
|
||||||
|
w++
|
||||||
|
}
|
||||||
|
return string(pathbuf[:w])
|
||||||
|
}
|
1
vendor/github.com/containerd/cri/pkg/server/imagefs_info.go
generated
vendored
1
vendor/github.com/containerd/cri/pkg/server/imagefs_info.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ImageFsInfo returns information of the filesystem that is used to store images.
|
// ImageFsInfo returns information of the filesystem that is used to store images.
|
||||||
|
// TODO(windows): Usage for windows is always 0 right now. Support this for windows.
|
||||||
func (c *criService) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (*runtime.ImageFsInfoResponse, error) {
|
func (c *criService) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (*runtime.ImageFsInfoResponse, error) {
|
||||||
snapshots := c.snapshotStore.List()
|
snapshots := c.snapshotStore.List()
|
||||||
timestamp := time.Now().UnixNano()
|
timestamp := time.Now().UnixNano()
|
||||||
|
7
vendor/github.com/containerd/cri/pkg/server/io/helpers.go
generated
vendored
7
vendor/github.com/containerd/cri/pkg/server/io/helpers.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/fifo"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
)
|
)
|
||||||
@ -113,7 +112,7 @@ func newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, _ *wgCloser, err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
if fifos.Stdin != "" {
|
if fifos.Stdin != "" {
|
||||||
if f, err = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
if f, err = openPipe(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
p.stdin = f
|
p.stdin = f
|
||||||
@ -121,7 +120,7 @@ func newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, _ *wgCloser, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fifos.Stdout != "" {
|
if fifos.Stdout != "" {
|
||||||
if f, err = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
if f, err = openPipe(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
p.stdout = f
|
p.stdout = f
|
||||||
@ -129,7 +128,7 @@ func newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, _ *wgCloser, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fifos.Stderr != "" {
|
if fifos.Stderr != "" {
|
||||||
if f, err = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
if f, err = openPipe(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
p.stderr = f
|
p.stderr = f
|
||||||
|
31
vendor/github.com/containerd/cri/pkg/server/io/helpers_unix.go
generated
vendored
Normal file
31
vendor/github.com/containerd/cri/pkg/server/io/helpers_unix.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/containerd/fifo"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openPipe(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||||
|
return fifo.OpenFifo(ctx, fn, flag, perm)
|
||||||
|
}
|
81
vendor/github.com/containerd/cri/pkg/server/io/helpers_windows.go
generated
vendored
Normal file
81
vendor/github.com/containerd/cri/pkg/server/io/helpers_windows.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pipe struct {
|
||||||
|
l net.Listener
|
||||||
|
con net.Conn
|
||||||
|
conErr error
|
||||||
|
conWg sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func openPipe(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||||
|
l, err := winio.ListenPipe(fn, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p := &pipe{l: l}
|
||||||
|
p.conWg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer p.conWg.Done()
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
p.conErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.con = c
|
||||||
|
}()
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) Write(b []byte) (int, error) {
|
||||||
|
p.conWg.Wait()
|
||||||
|
if p.conErr != nil {
|
||||||
|
return 0, errors.Wrap(p.conErr, "connection error")
|
||||||
|
}
|
||||||
|
return p.con.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) Read(b []byte) (int, error) {
|
||||||
|
p.conWg.Wait()
|
||||||
|
if p.conErr != nil {
|
||||||
|
return 0, errors.Wrap(p.conErr, "connection error")
|
||||||
|
}
|
||||||
|
return p.con.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) Close() error {
|
||||||
|
p.l.Close()
|
||||||
|
p.conWg.Wait()
|
||||||
|
if p.con != nil {
|
||||||
|
return p.con.Close()
|
||||||
|
}
|
||||||
|
return p.conErr
|
||||||
|
}
|
4
vendor/github.com/containerd/cri/pkg/server/restart.go
generated
vendored
4
vendor/github.com/containerd/cri/pkg/server/restart.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
goruntime "runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
@ -407,7 +408,8 @@ func (c *criService) loadSandbox(ctx context.Context, cntr containerd.Container)
|
|||||||
sandbox.Container = cntr
|
sandbox.Container = cntr
|
||||||
|
|
||||||
// Load network namespace.
|
// Load network namespace.
|
||||||
if meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE {
|
if goruntime.GOOS != "windows" &&
|
||||||
|
meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE {
|
||||||
// Don't need to load netns for host network sandbox.
|
// Don't need to load netns for host network sandbox.
|
||||||
return sandbox, nil
|
return sandbox, nil
|
||||||
}
|
}
|
||||||
|
90
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go
generated
vendored
90
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -17,16 +17,7 @@ limitations under the License.
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
@ -45,82 +36,3 @@ func (c *criService) PortForward(ctx context.Context, r *runtime.PortForwardRequ
|
|||||||
// TODO(random-liu): Verify that ports are exposed.
|
// TODO(random-liu): Verify that ports are exposed.
|
||||||
return c.streamServer.GetPortForward(r)
|
return c.streamServer.GetPortForward(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// portForward requires `socat` on the node. It uses netns to enter the sandbox namespace,
|
|
||||||
// and run `socat` insidethe namespace to forward stream for a specific port. The `socat`
|
|
||||||
// command keeps running until it exits or client disconnect.
|
|
||||||
func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error {
|
|
||||||
s, err := c.sandboxStore.Get(id)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to find sandbox %q in store", id)
|
|
||||||
}
|
|
||||||
var netNSDo func(func(ns.NetNS) error) error
|
|
||||||
// netNSPath is the network namespace path for logging.
|
|
||||||
var netNSPath string
|
|
||||||
securityContext := s.Config.GetLinux().GetSecurityContext()
|
|
||||||
hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE
|
|
||||||
if !hostNet {
|
|
||||||
if closed, err := s.NetNS.Closed(); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to check netwok namespace closed for sandbox %q", id)
|
|
||||||
} else if closed {
|
|
||||||
return errors.Errorf("network namespace for sandbox %q is closed", id)
|
|
||||||
}
|
|
||||||
netNSDo = s.NetNS.Do
|
|
||||||
netNSPath = s.NetNS.GetPath()
|
|
||||||
} else {
|
|
||||||
// Run the function directly for host network.
|
|
||||||
netNSDo = func(do func(_ ns.NetNS) error) error {
|
|
||||||
return do(nil)
|
|
||||||
}
|
|
||||||
netNSPath = "host"
|
|
||||||
}
|
|
||||||
|
|
||||||
socat, err := exec.LookPath("socat")
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to find socat")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check https://linux.die.net/man/1/socat for meaning of the options.
|
|
||||||
args := []string{socat, "-", fmt.Sprintf("TCP4:localhost:%d", port)}
|
|
||||||
|
|
||||||
log.G(ctx).Infof("Executing port forwarding command %q in network namespace %q", strings.Join(args, " "), netNSPath)
|
|
||||||
err = netNSDo(func(_ ns.NetNS) error {
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
|
||||||
cmd.Stdout = stream
|
|
||||||
|
|
||||||
stderr := new(bytes.Buffer)
|
|
||||||
cmd.Stderr = stderr
|
|
||||||
|
|
||||||
// If we use Stdin, command.Run() won't return until the goroutine that's copying
|
|
||||||
// from stream finishes. Unfortunately, if you have a client like telnet connected
|
|
||||||
// via port forwarding, as long as the user's telnet client is connected to the user's
|
|
||||||
// local listener that port forwarding sets up, the telnet session never exits. This
|
|
||||||
// means that even if socat has finished running, command.Run() won't ever return
|
|
||||||
// (because the client still has the connection and stream open).
|
|
||||||
//
|
|
||||||
// The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe
|
|
||||||
// when the command (socat) exits.
|
|
||||||
in, err := cmd.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to create stdin pipe")
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
if _, err := io.Copy(in, stream); err != nil {
|
|
||||||
logrus.WithError(err).Errorf("Failed to copy port forward input for %q port %d", id, port)
|
|
||||||
}
|
|
||||||
in.Close()
|
|
||||||
logrus.Debugf("Finish copying port forward input for %q port %d", id, port)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
return errors.Errorf("socat command returns error: %v, stderr: %q", err, stderr.String())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to execute portforward in network namespace %q", netNSPath)
|
|
||||||
}
|
|
||||||
log.G(ctx).Infof("Finish port forwarding for %q port %d", id, port)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
113
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_unix.go
generated
vendored
Normal file
113
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_unix.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// portForward requires `socat` on the node. It uses netns to enter the sandbox namespace,
|
||||||
|
// and run `socat` inside the namespace to forward stream for a specific port. The `socat`
|
||||||
|
// command keeps running until it exits or client disconnect.
|
||||||
|
func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error {
|
||||||
|
s, err := c.sandboxStore.Get(id)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to find sandbox %q in store", id)
|
||||||
|
}
|
||||||
|
var netNSDo func(func(ns.NetNS) error) error
|
||||||
|
// netNSPath is the network namespace path for logging.
|
||||||
|
var netNSPath string
|
||||||
|
securityContext := s.Config.GetLinux().GetSecurityContext()
|
||||||
|
hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE
|
||||||
|
if !hostNet {
|
||||||
|
if closed, err := s.NetNS.Closed(); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to check netwok namespace closed for sandbox %q", id)
|
||||||
|
} else if closed {
|
||||||
|
return errors.Errorf("network namespace for sandbox %q is closed", id)
|
||||||
|
}
|
||||||
|
netNSDo = s.NetNS.Do
|
||||||
|
netNSPath = s.NetNS.GetPath()
|
||||||
|
} else {
|
||||||
|
// Run the function directly for host network.
|
||||||
|
netNSDo = func(do func(_ ns.NetNS) error) error {
|
||||||
|
return do(nil)
|
||||||
|
}
|
||||||
|
netNSPath = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
socat, err := exec.LookPath("socat")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to find socat")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check https://linux.die.net/man/1/socat for meaning of the options.
|
||||||
|
args := []string{socat, "-", fmt.Sprintf("TCP4:localhost:%d", port)}
|
||||||
|
|
||||||
|
log.G(ctx).Infof("Executing port forwarding command %q in network namespace %q", strings.Join(args, " "), netNSPath)
|
||||||
|
err = netNSDo(func(_ ns.NetNS) error {
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Stdout = stream
|
||||||
|
|
||||||
|
stderr := new(bytes.Buffer)
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
|
// If we use Stdin, command.Run() won't return until the goroutine that's copying
|
||||||
|
// from stream finishes. Unfortunately, if you have a client like telnet connected
|
||||||
|
// via port forwarding, as long as the user's telnet client is connected to the user's
|
||||||
|
// local listener that port forwarding sets up, the telnet session never exits. This
|
||||||
|
// means that even if socat has finished running, command.Run() won't ever return
|
||||||
|
// (because the client still has the connection and stream open).
|
||||||
|
//
|
||||||
|
// The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe
|
||||||
|
// when the command (socat) exits.
|
||||||
|
in, err := cmd.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create stdin pipe")
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
if _, err := io.Copy(in, stream); err != nil {
|
||||||
|
logrus.WithError(err).Errorf("Failed to copy port forward input for %q port %d", id, port)
|
||||||
|
}
|
||||||
|
in.Close()
|
||||||
|
logrus.Debugf("Finish copying port forward input for %q port %d", id, port)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return errors.Errorf("socat command returns error: %v, stderr: %q", err, stderr.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to execute portforward in network namespace %q", netNSPath)
|
||||||
|
}
|
||||||
|
log.G(ctx).Infof("Finish port forwarding for %q port %d", id, port)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
80
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_windows.go
generated
vendored
Normal file
80
vendor/github.com/containerd/cri/pkg/server/sandbox_portforward_windows.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"k8s.io/utils/exec"
|
||||||
|
|
||||||
|
"github.com/containerd/cri/pkg/ioutil"
|
||||||
|
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error {
|
||||||
|
stdout := ioutil.NewNopWriteCloser(stream)
|
||||||
|
stderrBuffer := new(bytes.Buffer)
|
||||||
|
stderr := ioutil.NewNopWriteCloser(stderrBuffer)
|
||||||
|
// localhost is resolved to 127.0.0.1 in ipv4, and ::1 in ipv6.
|
||||||
|
// Explicitly using ipv4 IP address in here to avoid flakiness.
|
||||||
|
cmd := []string{"wincat.exe", "127.0.0.1", fmt.Sprint(port)}
|
||||||
|
err := c.execInSandbox(ctx, id, cmd, stream, stdout, stderr)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to execute port forward in sandbox: %s", stderrBuffer.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) execInSandbox(ctx context.Context, sandboxID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser) error {
|
||||||
|
// Get sandbox from our sandbox store.
|
||||||
|
sb, err := c.sandboxStore.Get(sandboxID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to find sandbox %q in store", sandboxID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the sandbox state
|
||||||
|
state := sb.Status.Get().State
|
||||||
|
if state != sandboxstore.StateReady {
|
||||||
|
return errors.Errorf("sandbox is in %s state", fmt.Sprint(state))
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := execOptions{
|
||||||
|
cmd: cmd,
|
||||||
|
stdin: stdin,
|
||||||
|
stdout: stdout,
|
||||||
|
stderr: stderr,
|
||||||
|
tty: false,
|
||||||
|
resize: nil,
|
||||||
|
}
|
||||||
|
exitCode, err := c.execInternal(ctx, sb.Container, sandboxID, opts)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to exec in sandbox")
|
||||||
|
}
|
||||||
|
if *exitCode == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &exec.CodeExitError{
|
||||||
|
Err: errors.Errorf("error executing command %v, exit code %d", cmd, *exitCode),
|
||||||
|
Code: int(*exitCode),
|
||||||
|
}
|
||||||
|
}
|
356
vendor/github.com/containerd/cri/pkg/server/sandbox_run.go
generated
vendored
356
vendor/github.com/containerd/cri/pkg/server/sandbox_run.go
generated
vendored
@ -18,26 +18,20 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
goruntime "runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
containerdio "github.com/containerd/containerd/cio"
|
containerdio "github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
"github.com/containerd/containerd/plugin"
|
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
"k8s.io/kubernetes/pkg/util/bandwidth"
|
"k8s.io/kubernetes/pkg/util/bandwidth"
|
||||||
|
|
||||||
@ -110,10 +104,14 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
}
|
}
|
||||||
log.G(ctx).Debugf("Use OCI %+v for sandbox %q", ociRuntime, id)
|
log.G(ctx).Debugf("Use OCI %+v for sandbox %q", ociRuntime, id)
|
||||||
|
|
||||||
securityContext := config.GetLinux().GetSecurityContext()
|
podNetwork := true
|
||||||
//Create Network Namespace if it is not in host network
|
// Pod network is always needed on windows.
|
||||||
hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE
|
if goruntime.GOOS != "windows" &&
|
||||||
if !hostNet {
|
config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE {
|
||||||
|
// Pod network is not needed on linux with host network.
|
||||||
|
podNetwork = false
|
||||||
|
}
|
||||||
|
if podNetwork {
|
||||||
// If it is not in host network namespace then create a namespace and set the sandbox
|
// If it is not in host network namespace then create a namespace and set the sandbox
|
||||||
// handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network
|
// handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network
|
||||||
// namespaces. If the pod is in host network namespace then both are empty and should not
|
// namespaces. If the pod is in host network namespace then both are empty and should not
|
||||||
@ -153,39 +151,19 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create sandbox container.
|
// Create sandbox container.
|
||||||
spec, err := c.generateSandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath, ociRuntime.PodAnnotations)
|
// NOTE: sandboxContainerSpec SHOULD NOT have side
|
||||||
|
// effect, e.g. accessing/creating files, so that we can test
|
||||||
|
// it safely.
|
||||||
|
spec, err := c.sandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath, ociRuntime.PodAnnotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
||||||
}
|
}
|
||||||
log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec))
|
log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec))
|
||||||
|
|
||||||
var specOpts []oci.SpecOpts
|
// Generate spec options that will be applied to the spec later.
|
||||||
userstr, err := generateUserString(
|
specOpts, err := c.sandboxContainerSpecOpts(config, &image.ImageSpec.Config)
|
||||||
"",
|
|
||||||
securityContext.GetRunAsUser(),
|
|
||||||
securityContext.GetRunAsGroup(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to generate user string")
|
return nil, errors.Wrap(err, "failed to generate sanbdox container spec options")
|
||||||
}
|
|
||||||
if userstr == "" {
|
|
||||||
// Lastly, since no user override was passed via CRI try to set via OCI
|
|
||||||
// Image
|
|
||||||
userstr = image.ImageSpec.Config.User
|
|
||||||
}
|
|
||||||
if userstr != "" {
|
|
||||||
specOpts = append(specOpts, oci.WithUser(userstr))
|
|
||||||
}
|
|
||||||
|
|
||||||
seccompSpecOpts, err := generateSeccompSpecOpts(
|
|
||||||
securityContext.GetSeccompProfilePath(),
|
|
||||||
securityContext.GetPrivileged(),
|
|
||||||
c.seccompEnabled)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to generate seccomp spec opts")
|
|
||||||
}
|
|
||||||
if seccompSpecOpts != nil {
|
|
||||||
specOpts = append(specOpts, seccompSpecOpts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sandboxLabels := buildLabels(config.Labels, containerKindSandbox)
|
sandboxLabels := buildLabels(config.Labels, containerKindSandbox)
|
||||||
@ -246,14 +224,14 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Setup sandbox /dev/shm, /etc/hosts, /etc/resolv.conf and /etc/hostname.
|
// Setup files required for the sandbox.
|
||||||
if err = c.setupSandboxFiles(id, config); err != nil {
|
if err = c.setupSandboxFiles(id, config); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to setup sandbox files")
|
return nil, errors.Wrapf(err, "failed to setup sandbox files")
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
if err = c.unmountSandboxFiles(id, config); err != nil {
|
if err = c.cleanupSandboxFiles(id, config); err != nil {
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to unmount sandbox files in %q",
|
log.G(ctx).WithError(err).Errorf("Failed to cleanup sandbox files in %q",
|
||||||
sandboxRootDir)
|
sandboxRootDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,11 +247,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
log.G(ctx).Tracef("Create sandbox container (id=%q, name=%q).",
|
log.G(ctx).Tracef("Create sandbox container (id=%q, name=%q).",
|
||||||
id, name)
|
id, name)
|
||||||
|
|
||||||
var taskOpts []containerd.NewTaskOpts
|
taskOpts := c.taskOpts(ociRuntime.Type)
|
||||||
// TODO(random-liu): Remove this after shim v1 is deprecated.
|
|
||||||
if c.config.NoPivot && ociRuntime.Type == plugin.RuntimeRuncV1 {
|
|
||||||
taskOpts = append(taskOpts, containerd.WithNoPivotRoot)
|
|
||||||
}
|
|
||||||
// We don't need stdio for sandbox container.
|
// We don't need stdio for sandbox container.
|
||||||
task, err := container.NewTask(ctx, containerdio.NullIO, taskOpts...)
|
task, err := container.NewTask(ctx, containerdio.NullIO, taskOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -327,222 +301,6 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
return &runtime.RunPodSandboxResponse{PodSandboxId: id}, nil
|
return &runtime.RunPodSandboxResponse{PodSandboxId: id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
|
||||||
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
|
||||||
// Creates a spec Generator with the default spec.
|
|
||||||
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
|
||||||
specOpts := []oci.SpecOpts{
|
|
||||||
customopts.WithoutRunMount,
|
|
||||||
customopts.WithoutDefaultSecuritySettings,
|
|
||||||
customopts.WithRelativeRoot(relativeRootfsPath),
|
|
||||||
oci.WithEnv(imageConfig.Env),
|
|
||||||
oci.WithRootFSReadonly(),
|
|
||||||
oci.WithHostname(config.GetHostname()),
|
|
||||||
}
|
|
||||||
if imageConfig.WorkingDir != "" {
|
|
||||||
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(imageConfig.Entrypoint) == 0 && len(imageConfig.Cmd) == 0 {
|
|
||||||
// Pause image must have entrypoint or cmd.
|
|
||||||
return nil, errors.Errorf("invalid empty entrypoint and cmd in image config %+v", imageConfig)
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, oci.WithProcessArgs(append(imageConfig.Entrypoint, imageConfig.Cmd...)...))
|
|
||||||
|
|
||||||
// TODO(random-liu): [P2] Consider whether to add labels and annotations to the container.
|
|
||||||
|
|
||||||
// Set cgroups parent.
|
|
||||||
if c.config.DisableCgroup {
|
|
||||||
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
|
||||||
} else {
|
|
||||||
if config.GetLinux().GetCgroupParent() != "" {
|
|
||||||
cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id)
|
|
||||||
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When cgroup parent is not set, containerd-shim will create container in a child cgroup
|
|
||||||
// of the cgroup itself is in.
|
|
||||||
// TODO(random-liu): [P2] Set default cgroup path if cgroup parent is not specified.
|
|
||||||
|
|
||||||
// Set namespace options.
|
|
||||||
var (
|
|
||||||
securityContext = config.GetLinux().GetSecurityContext()
|
|
||||||
nsOptions = securityContext.GetNamespaceOptions()
|
|
||||||
)
|
|
||||||
if nsOptions.GetNetwork() == runtime.NamespaceMode_NODE {
|
|
||||||
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.NetworkNamespace))
|
|
||||||
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.UTSNamespace))
|
|
||||||
} else {
|
|
||||||
//TODO(Abhi): May be move this to containerd spec opts (WithLinuxSpaceOption)
|
|
||||||
specOpts = append(specOpts, oci.WithLinuxNamespace(
|
|
||||||
runtimespec.LinuxNamespace{
|
|
||||||
Type: runtimespec.NetworkNamespace,
|
|
||||||
Path: nsPath,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
if nsOptions.GetPid() == runtime.NamespaceMode_NODE {
|
|
||||||
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.PIDNamespace))
|
|
||||||
}
|
|
||||||
if nsOptions.GetIpc() == runtime.NamespaceMode_NODE {
|
|
||||||
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.IPCNamespace))
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's fine to generate the spec before the sandbox /dev/shm
|
|
||||||
// is actually created.
|
|
||||||
sandboxDevShm := c.getSandboxDevShm(id)
|
|
||||||
if nsOptions.GetIpc() == runtime.NamespaceMode_NODE {
|
|
||||||
sandboxDevShm = devShm
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, oci.WithMounts([]runtimespec.Mount{
|
|
||||||
{
|
|
||||||
Source: sandboxDevShm,
|
|
||||||
Destination: devShm,
|
|
||||||
Type: "bind",
|
|
||||||
Options: []string{"rbind", "ro"},
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
selinuxOpt := securityContext.GetSelinuxOptions()
|
|
||||||
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
|
||||||
}
|
|
||||||
|
|
||||||
supplementalGroups := securityContext.GetSupplementalGroups()
|
|
||||||
specOpts = append(specOpts,
|
|
||||||
customopts.WithSelinuxLabels(processLabel, mountLabel),
|
|
||||||
customopts.WithSupplementalGroups(supplementalGroups),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Add sysctls
|
|
||||||
sysctls := config.GetLinux().GetSysctls()
|
|
||||||
specOpts = append(specOpts, customopts.WithSysctls(sysctls))
|
|
||||||
|
|
||||||
// Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile
|
|
||||||
|
|
||||||
if !c.config.DisableCgroup {
|
|
||||||
specOpts = append(specOpts, customopts.WithDefaultSandboxShares)
|
|
||||||
}
|
|
||||||
specOpts = append(specOpts, customopts.WithPodOOMScoreAdj(int(defaultSandboxOOMAdj), c.config.RestrictOOMScoreAdj))
|
|
||||||
|
|
||||||
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
|
||||||
runtimePodAnnotations) {
|
|
||||||
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
|
||||||
}
|
|
||||||
|
|
||||||
specOpts = append(specOpts,
|
|
||||||
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox),
|
|
||||||
customopts.WithAnnotation(annotations.SandboxID, id),
|
|
||||||
customopts.WithAnnotation(annotations.SandboxLogDir, config.GetLogDirectory()),
|
|
||||||
)
|
|
||||||
|
|
||||||
return runtimeSpec(id, specOpts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupSandboxFiles sets up necessary sandbox files including /dev/shm, /etc/hosts,
|
|
||||||
// /etc/resolv.conf and /etc/hostname.
|
|
||||||
func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
|
||||||
sandboxEtcHostname := c.getSandboxHostname(id)
|
|
||||||
hostname := config.GetHostname()
|
|
||||||
if hostname == "" {
|
|
||||||
var err error
|
|
||||||
hostname, err = c.os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to get hostname")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := c.os.WriteFile(sandboxEtcHostname, []byte(hostname+"\n"), 0644); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to write hostname to %q", sandboxEtcHostname)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(random-liu): Consider whether we should maintain /etc/hosts and /etc/resolv.conf in kubelet.
|
|
||||||
sandboxEtcHosts := c.getSandboxHosts(id)
|
|
||||||
if err := c.os.CopyFile(etcHosts, sandboxEtcHosts, 0644); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to generate sandbox hosts file %q", sandboxEtcHosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set DNS options. Maintain a resolv.conf for the sandbox.
|
|
||||||
var err error
|
|
||||||
resolvContent := ""
|
|
||||||
if dnsConfig := config.GetDnsConfig(); dnsConfig != nil {
|
|
||||||
resolvContent, err = parseDNSOptions(dnsConfig.Servers, dnsConfig.Searches, dnsConfig.Options)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to parse sandbox DNSConfig %+v", dnsConfig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolvPath := c.getResolvPath(id)
|
|
||||||
if resolvContent == "" {
|
|
||||||
// copy host's resolv.conf to resolvPath
|
|
||||||
err = c.os.CopyFile(resolvConfPath, resolvPath, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to copy host's resolv.conf to %q", resolvPath)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = c.os.WriteFile(resolvPath, []byte(resolvContent), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to write resolv content to %q", resolvPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup sandbox /dev/shm.
|
|
||||||
if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE {
|
|
||||||
if _, err := c.os.Stat(devShm); err != nil {
|
|
||||||
return errors.Wrapf(err, "host %q is not available for host ipc", devShm)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sandboxDevShm := c.getSandboxDevShm(id)
|
|
||||||
if err := c.os.MkdirAll(sandboxDevShm, 0700); err != nil {
|
|
||||||
return errors.Wrap(err, "failed to create sandbox shm")
|
|
||||||
}
|
|
||||||
shmproperty := fmt.Sprintf("mode=1777,size=%d", defaultShmSize)
|
|
||||||
if err := c.os.Mount("shm", sandboxDevShm, "tmpfs", uintptr(unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV), shmproperty); err != nil {
|
|
||||||
return errors.Wrap(err, "failed to mount sandbox shm")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseDNSOptions parse DNS options into resolv.conf format content,
|
|
||||||
// if none option is specified, will return empty with no error.
|
|
||||||
func parseDNSOptions(servers, searches, options []string) (string, error) {
|
|
||||||
resolvContent := ""
|
|
||||||
|
|
||||||
if len(searches) > maxDNSSearches {
|
|
||||||
return "", errors.Errorf("DNSOption.Searches has more than %d domains", maxDNSSearches)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(searches) > 0 {
|
|
||||||
resolvContent += fmt.Sprintf("search %s\n", strings.Join(searches, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(servers) > 0 {
|
|
||||||
resolvContent += fmt.Sprintf("nameserver %s\n", strings.Join(servers, "\nnameserver "))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(options) > 0 {
|
|
||||||
resolvContent += fmt.Sprintf("options %s\n", strings.Join(options, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvContent, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmountSandboxFiles unmount some sandbox files, we rely on the removal of sandbox root directory to
|
|
||||||
// remove these files. Unmount should *NOT* return error if the mount point is already unmounted.
|
|
||||||
func (c *criService) unmountSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
|
||||||
if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() != runtime.NamespaceMode_NODE {
|
|
||||||
path, err := c.os.FollowSymlinkInScope(c.getSandboxDevShm(id), "/")
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to follow symlink")
|
|
||||||
}
|
|
||||||
if err := c.os.Unmount(path); err != nil && !os.IsNotExist(err) {
|
|
||||||
return errors.Wrapf(err, "failed to unmount %q", path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupPodNetwork setups up the network for a pod
|
// setupPodNetwork setups up the network for a pod
|
||||||
func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.Sandbox) error {
|
func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.Sandbox) error {
|
||||||
var (
|
var (
|
||||||
@ -554,22 +312,12 @@ func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.
|
|||||||
return errors.New("cni config not initialized")
|
return errors.New("cni config not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := getPodCNILabels(id, config)
|
opts, err := cniNamespaceOpts(id, config)
|
||||||
|
|
||||||
// Will return an error if the bandwidth limitation has the wrong unit
|
|
||||||
// or an unreasonable valure see validateBandwidthIsReasonable()
|
|
||||||
bandWidth, err := toCNIBandWidth(config.Annotations)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to get bandwidth info from annotations")
|
return errors.Wrap(err, "get cni namespace options")
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := c.netPlugin.Setup(ctx, id,
|
result, err := c.netPlugin.Setup(ctx, id, path, opts...)
|
||||||
path,
|
|
||||||
cni.WithLabels(labels),
|
|
||||||
cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings())),
|
|
||||||
cni.WithCapabilityBandWidth(*bandWidth),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -587,11 +335,54 @@ func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.
|
|||||||
return errors.Errorf("failed to find network info for sandbox %q", id)
|
return errors.Errorf("failed to find network info for sandbox %q", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cniNamespaceOpts get CNI namespace options from sandbox config.
|
||||||
|
func cniNamespaceOpts(id string, config *runtime.PodSandboxConfig) ([]cni.NamespaceOpts, error) {
|
||||||
|
opts := []cni.NamespaceOpts{
|
||||||
|
cni.WithLabels(toCNILabels(id, config)),
|
||||||
|
}
|
||||||
|
|
||||||
|
portMappings := toCNIPortMappings(config.GetPortMappings())
|
||||||
|
if len(portMappings) > 0 {
|
||||||
|
opts = append(opts, cni.WithCapabilityPortMap(portMappings))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will return an error if the bandwidth limitation has the wrong unit
|
||||||
|
// or an unreasonable value see validateBandwidthIsReasonable()
|
||||||
|
bandWidth, err := toCNIBandWidth(config.Annotations)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if bandWidth != nil {
|
||||||
|
opts = append(opts, cni.WithCapabilityBandWidth(*bandWidth))
|
||||||
|
}
|
||||||
|
|
||||||
|
dns := toCNIDNS(config.GetDnsConfig())
|
||||||
|
if dns != nil {
|
||||||
|
opts = append(opts, cni.WithCapabilityDNS(*dns))
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCNILabels adds pod metadata into CNI labels.
|
||||||
|
func toCNILabels(id string, config *runtime.PodSandboxConfig) map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"K8S_POD_NAMESPACE": config.GetMetadata().GetNamespace(),
|
||||||
|
"K8S_POD_NAME": config.GetMetadata().GetName(),
|
||||||
|
"K8S_POD_INFRA_CONTAINER_ID": id,
|
||||||
|
"IgnoreUnknown": "1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// toCNIBandWidth converts CRI annotations to CNI bandwidth.
|
// toCNIBandWidth converts CRI annotations to CNI bandwidth.
|
||||||
func toCNIBandWidth(annotations map[string]string) (*cni.BandWidth, error) {
|
func toCNIBandWidth(annotations map[string]string) (*cni.BandWidth, error) {
|
||||||
ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations)
|
ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("reading pod bandwidth annotations: %v", err)
|
return nil, errors.Wrap(err, "reading pod bandwidth annotations")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ingress == nil && egress == nil {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bandWidth := &cni.BandWidth{}
|
bandWidth := &cni.BandWidth{}
|
||||||
@ -629,6 +420,18 @@ func toCNIPortMappings(criPortMappings []*runtime.PortMapping) []cni.PortMapping
|
|||||||
return portMappings
|
return portMappings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toCNIDNS converts CRI DNSConfig to CNI.
|
||||||
|
func toCNIDNS(dns *runtime.DNSConfig) *cni.DNS {
|
||||||
|
if dns == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &cni.DNS{
|
||||||
|
Servers: dns.GetServers(),
|
||||||
|
Searches: dns.GetSearches(),
|
||||||
|
Options: dns.GetOptions(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// selectPodIPs select an ip from the ip list. It prefers ipv4 more than ipv6
|
// selectPodIPs select an ip from the ip list. It prefers ipv4 more than ipv6
|
||||||
// and returns the additional ips
|
// and returns the additional ips
|
||||||
// TODO(random-liu): Revisit the ip order in the ipv6 beta stage. (cri#1278)
|
// TODO(random-liu): Revisit the ip order in the ipv6 beta stage. (cri#1278)
|
||||||
@ -688,6 +491,7 @@ func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig, runtime
|
|||||||
// Note: If the workload is marked untrusted but requests privileged, this can be granted, as the
|
// Note: If the workload is marked untrusted but requests privileged, this can be granted, as the
|
||||||
// runtime may support this. For example, in a virtual-machine isolated runtime, privileged
|
// runtime may support this. For example, in a virtual-machine isolated runtime, privileged
|
||||||
// is a supported option, granting the workload to access the entire guest VM instead of host.
|
// is a supported option, granting the workload to access the entire guest VM instead of host.
|
||||||
|
// TODO(windows): Deprecate this so that we don't need to handle it for windows.
|
||||||
if hostAccessingSandbox(config) {
|
if hostAccessingSandbox(config) {
|
||||||
return criconfig.Runtime{}, errors.New("untrusted workload with host access is not allowed")
|
return criconfig.Runtime{}, errors.New("untrusted workload with host access is not allowed")
|
||||||
}
|
}
|
||||||
|
298
vendor/github.com/containerd/cri/pkg/server/sandbox_run_unix.go
generated
vendored
Normal file
298
vendor/github.com/containerd/cri/pkg/server/sandbox_run_unix.go
generated
vendored
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
|
osinterface "github.com/containerd/cri/pkg/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
||||||
|
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
||||||
|
// Creates a spec Generator with the default spec.
|
||||||
|
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
||||||
|
specOpts := []oci.SpecOpts{
|
||||||
|
customopts.WithoutRunMount,
|
||||||
|
customopts.WithoutDefaultSecuritySettings,
|
||||||
|
customopts.WithRelativeRoot(relativeRootfsPath),
|
||||||
|
oci.WithEnv(imageConfig.Env),
|
||||||
|
oci.WithRootFSReadonly(),
|
||||||
|
oci.WithHostname(config.GetHostname()),
|
||||||
|
}
|
||||||
|
if imageConfig.WorkingDir != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(imageConfig.Entrypoint) == 0 && len(imageConfig.Cmd) == 0 {
|
||||||
|
// Pause image must have entrypoint or cmd.
|
||||||
|
return nil, errors.Errorf("invalid empty entrypoint and cmd in image config %+v", imageConfig)
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithProcessArgs(append(imageConfig.Entrypoint, imageConfig.Cmd...)...))
|
||||||
|
|
||||||
|
// Set cgroups parent.
|
||||||
|
if c.config.DisableCgroup {
|
||||||
|
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
||||||
|
} else {
|
||||||
|
if config.GetLinux().GetCgroupParent() != "" {
|
||||||
|
cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id)
|
||||||
|
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When cgroup parent is not set, containerd-shim will create container in a child cgroup
|
||||||
|
// of the cgroup itself is in.
|
||||||
|
// TODO(random-liu): [P2] Set default cgroup path if cgroup parent is not specified.
|
||||||
|
|
||||||
|
// Set namespace options.
|
||||||
|
var (
|
||||||
|
securityContext = config.GetLinux().GetSecurityContext()
|
||||||
|
nsOptions = securityContext.GetNamespaceOptions()
|
||||||
|
)
|
||||||
|
if nsOptions.GetNetwork() == runtime.NamespaceMode_NODE {
|
||||||
|
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.NetworkNamespace))
|
||||||
|
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.UTSNamespace))
|
||||||
|
} else {
|
||||||
|
specOpts = append(specOpts, oci.WithLinuxNamespace(
|
||||||
|
runtimespec.LinuxNamespace{
|
||||||
|
Type: runtimespec.NetworkNamespace,
|
||||||
|
Path: nsPath,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
if nsOptions.GetPid() == runtime.NamespaceMode_NODE {
|
||||||
|
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.PIDNamespace))
|
||||||
|
}
|
||||||
|
if nsOptions.GetIpc() == runtime.NamespaceMode_NODE {
|
||||||
|
specOpts = append(specOpts, customopts.WithoutNamespace(runtimespec.IPCNamespace))
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's fine to generate the spec before the sandbox /dev/shm
|
||||||
|
// is actually created.
|
||||||
|
sandboxDevShm := c.getSandboxDevShm(id)
|
||||||
|
if nsOptions.GetIpc() == runtime.NamespaceMode_NODE {
|
||||||
|
sandboxDevShm = devShm
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithMounts([]runtimespec.Mount{
|
||||||
|
{
|
||||||
|
Source: sandboxDevShm,
|
||||||
|
Destination: devShm,
|
||||||
|
Type: "bind",
|
||||||
|
Options: []string{"rbind", "ro"},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
selinuxOpt := securityContext.GetSelinuxOptions()
|
||||||
|
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
supplementalGroups := securityContext.GetSupplementalGroups()
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithSelinuxLabels(processLabel, mountLabel),
|
||||||
|
customopts.WithSupplementalGroups(supplementalGroups),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add sysctls
|
||||||
|
sysctls := config.GetLinux().GetSysctls()
|
||||||
|
specOpts = append(specOpts, customopts.WithSysctls(sysctls))
|
||||||
|
|
||||||
|
// Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile
|
||||||
|
|
||||||
|
if !c.config.DisableCgroup {
|
||||||
|
specOpts = append(specOpts, customopts.WithDefaultSandboxShares)
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, customopts.WithPodOOMScoreAdj(int(defaultSandboxOOMAdj), c.config.RestrictOOMScoreAdj))
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
||||||
|
runtimePodAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxID, id),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxLogDir, config.GetLogDirectory()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return runtimeSpec(id, specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sandboxContainerSpecOpts generates OCI spec options for
|
||||||
|
// the sandbox container.
|
||||||
|
func (c *criService) sandboxContainerSpecOpts(config *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) {
|
||||||
|
var (
|
||||||
|
securityContext = config.GetLinux().GetSecurityContext()
|
||||||
|
specOpts []oci.SpecOpts
|
||||||
|
)
|
||||||
|
seccompSpecOpts, err := generateSeccompSpecOpts(
|
||||||
|
securityContext.GetSeccompProfilePath(),
|
||||||
|
securityContext.GetPrivileged(),
|
||||||
|
c.seccompEnabled())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to generate seccomp spec opts")
|
||||||
|
}
|
||||||
|
if seccompSpecOpts != nil {
|
||||||
|
specOpts = append(specOpts, seccompSpecOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
userstr, err := generateUserString(
|
||||||
|
"",
|
||||||
|
securityContext.GetRunAsUser(),
|
||||||
|
securityContext.GetRunAsGroup(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to generate user string")
|
||||||
|
}
|
||||||
|
if userstr == "" {
|
||||||
|
// Lastly, since no user override was passed via CRI try to set via OCI
|
||||||
|
// Image
|
||||||
|
userstr = imageConfig.User
|
||||||
|
}
|
||||||
|
if userstr != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithUser(userstr))
|
||||||
|
}
|
||||||
|
return specOpts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setupSandboxFiles sets up necessary sandbox files including /dev/shm, /etc/hosts,
|
||||||
|
// /etc/resolv.conf and /etc/hostname.
|
||||||
|
func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
||||||
|
sandboxEtcHostname := c.getSandboxHostname(id)
|
||||||
|
hostname := config.GetHostname()
|
||||||
|
if hostname == "" {
|
||||||
|
var err error
|
||||||
|
hostname, err = c.os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to get hostname")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := c.os.WriteFile(sandboxEtcHostname, []byte(hostname+"\n"), 0644); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to write hostname to %q", sandboxEtcHostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(random-liu): Consider whether we should maintain /etc/hosts and /etc/resolv.conf in kubelet.
|
||||||
|
sandboxEtcHosts := c.getSandboxHosts(id)
|
||||||
|
if err := c.os.CopyFile(etcHosts, sandboxEtcHosts, 0644); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to generate sandbox hosts file %q", sandboxEtcHosts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set DNS options. Maintain a resolv.conf for the sandbox.
|
||||||
|
var err error
|
||||||
|
resolvContent := ""
|
||||||
|
if dnsConfig := config.GetDnsConfig(); dnsConfig != nil {
|
||||||
|
resolvContent, err = parseDNSOptions(dnsConfig.Servers, dnsConfig.Searches, dnsConfig.Options)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse sandbox DNSConfig %+v", dnsConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolvPath := c.getResolvPath(id)
|
||||||
|
if resolvContent == "" {
|
||||||
|
// copy host's resolv.conf to resolvPath
|
||||||
|
err = c.os.CopyFile(resolvConfPath, resolvPath, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to copy host's resolv.conf to %q", resolvPath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = c.os.WriteFile(resolvPath, []byte(resolvContent), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to write resolv content to %q", resolvPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup sandbox /dev/shm.
|
||||||
|
if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() == runtime.NamespaceMode_NODE {
|
||||||
|
if _, err := c.os.Stat(devShm); err != nil {
|
||||||
|
return errors.Wrapf(err, "host %q is not available for host ipc", devShm)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sandboxDevShm := c.getSandboxDevShm(id)
|
||||||
|
if err := c.os.MkdirAll(sandboxDevShm, 0700); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create sandbox shm")
|
||||||
|
}
|
||||||
|
shmproperty := fmt.Sprintf("mode=1777,size=%d", defaultShmSize)
|
||||||
|
if err := c.os.(osinterface.UNIX).Mount("shm", sandboxDevShm, "tmpfs", uintptr(unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV), shmproperty); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to mount sandbox shm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseDNSOptions parse DNS options into resolv.conf format content,
|
||||||
|
// if none option is specified, will return empty with no error.
|
||||||
|
func parseDNSOptions(servers, searches, options []string) (string, error) {
|
||||||
|
resolvContent := ""
|
||||||
|
|
||||||
|
if len(searches) > maxDNSSearches {
|
||||||
|
return "", errors.Errorf("DNSOption.Searches has more than %d domains", maxDNSSearches)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(searches) > 0 {
|
||||||
|
resolvContent += fmt.Sprintf("search %s\n", strings.Join(searches, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(servers) > 0 {
|
||||||
|
resolvContent += fmt.Sprintf("nameserver %s\n", strings.Join(servers, "\nnameserver "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(options) > 0 {
|
||||||
|
resolvContent += fmt.Sprintf("options %s\n", strings.Join(options, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvContent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanupSandboxFiles unmount some sandbox files, we rely on the removal of sandbox root directory to
|
||||||
|
// remove these files. Unmount should *NOT* return error if the mount point is already unmounted.
|
||||||
|
func (c *criService) cleanupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
||||||
|
if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetIpc() != runtime.NamespaceMode_NODE {
|
||||||
|
path, err := c.os.FollowSymlinkInScope(c.getSandboxDevShm(id), "/")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to follow symlink")
|
||||||
|
}
|
||||||
|
if err := c.os.(osinterface.UNIX).Unmount(path); err != nil && !os.IsNotExist(err) {
|
||||||
|
return errors.Wrapf(err, "failed to unmount %q", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// taskOpts generates task options for a (sandbox) container.
|
||||||
|
func (c *criService) taskOpts(runtimeType string) []containerd.NewTaskOpts {
|
||||||
|
// TODO(random-liu): Remove this after shim v1 is deprecated.
|
||||||
|
var taskOpts []containerd.NewTaskOpts
|
||||||
|
if c.config.NoPivot && runtimeType == plugin.RuntimeRuncV1 {
|
||||||
|
taskOpts = append(taskOpts, containerd.WithNoPivotRoot)
|
||||||
|
}
|
||||||
|
return taskOpts
|
||||||
|
}
|
91
vendor/github.com/containerd/cri/pkg/server/sandbox_run_windows.go
generated
vendored
Normal file
91
vendor/github.com/containerd/cri/pkg/server/sandbox_run_windows.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *criService) sandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
||||||
|
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
||||||
|
// Creates a spec Generator with the default spec.
|
||||||
|
specOpts := []oci.SpecOpts{
|
||||||
|
oci.WithEnv(imageConfig.Env),
|
||||||
|
oci.WithHostname(config.GetHostname()),
|
||||||
|
}
|
||||||
|
if imageConfig.WorkingDir != "" {
|
||||||
|
specOpts = append(specOpts, oci.WithProcessCwd(imageConfig.WorkingDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(imageConfig.Entrypoint) == 0 && len(imageConfig.Cmd) == 0 {
|
||||||
|
// Pause image must have entrypoint or cmd.
|
||||||
|
return nil, errors.Errorf("invalid empty entrypoint and cmd in image config %+v", imageConfig)
|
||||||
|
}
|
||||||
|
specOpts = append(specOpts, oci.WithProcessArgs(append(imageConfig.Entrypoint, imageConfig.Cmd...)...))
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
// Clear the root location since hcsshim expects it.
|
||||||
|
// NOTE: readonly rootfs doesn't work on windows.
|
||||||
|
customopts.WithoutRoot,
|
||||||
|
customopts.WithWindowsNetworkNamespace(nsPath),
|
||||||
|
)
|
||||||
|
|
||||||
|
specOpts = append(specOpts, customopts.WithWindowsDefaultSandboxShares)
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
||||||
|
runtimePodAnnotations) {
|
||||||
|
specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
specOpts = append(specOpts,
|
||||||
|
customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxID, id),
|
||||||
|
customopts.WithAnnotation(annotations.SandboxLogDir, config.GetLogDirectory()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return runtimeSpec(id, specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No sandbox container spec options for windows yet.
|
||||||
|
func (c *criService) sandboxContainerSpecOpts(config *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig) ([]oci.SpecOpts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// No sandbox files needed for windows.
|
||||||
|
func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// No sandbox files needed for windows.
|
||||||
|
func (c *criService) cleanupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// No task options needed for windows.
|
||||||
|
func (c *criService) taskOpts(runtimeType string) []containerd.NewTaskOpts {
|
||||||
|
return nil
|
||||||
|
}
|
4
vendor/github.com/containerd/cri/pkg/server/sandbox_status.go
generated
vendored
4
vendor/github.com/containerd/cri/pkg/server/sandbox_status.go
generated
vendored
@ -18,6 +18,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
goruntime "runtime"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
@ -69,7 +70,8 @@ func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandbox
|
|||||||
func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) {
|
func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) {
|
||||||
config := sandbox.Config
|
config := sandbox.Config
|
||||||
|
|
||||||
if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE {
|
if goruntime.GOOS != "windows" &&
|
||||||
|
config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE {
|
||||||
// For sandboxes using the node network we are not
|
// For sandboxes using the node network we are not
|
||||||
// responsible for reporting the IP.
|
// responsible for reporting the IP.
|
||||||
return "", nil, nil
|
return "", nil, nil
|
||||||
|
16
vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go
generated
vendored
16
vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go
generated
vendored
@ -23,7 +23,6 @@ import (
|
|||||||
eventtypes "github.com/containerd/containerd/api/events"
|
eventtypes "github.com/containerd/containerd/api/events"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
cni "github.com/containerd/go-cni"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
@ -58,8 +57,8 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.unmountSandboxFiles(id, sandbox.Config); err != nil {
|
if err := c.cleanupSandboxFiles(id, sandbox.Config); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to unmount sandbox files")
|
return nil, errors.Wrap(err, "failed to cleanup sandbox files")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only stop sandbox container when it's running or unknown.
|
// Only stop sandbox container when it's running or unknown.
|
||||||
@ -166,11 +165,12 @@ func (c *criService) teardownPodNetwork(ctx context.Context, sandbox sandboxstor
|
|||||||
path = sandbox.NetNSPath
|
path = sandbox.NetNSPath
|
||||||
config = sandbox.Config
|
config = sandbox.Config
|
||||||
)
|
)
|
||||||
labels := getPodCNILabels(id, config)
|
opts, err := cniNamespaceOpts(id, config)
|
||||||
return c.netPlugin.Remove(ctx, id,
|
if err != nil {
|
||||||
path,
|
return errors.Wrap(err, "get cni namespace options")
|
||||||
cni.WithLabels(labels),
|
}
|
||||||
cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings())))
|
|
||||||
|
return c.netPlugin.Remove(ctx, id, path, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanupUnknownSandbox cleanup stopped sandbox in unknown state.
|
// cleanupUnknownSandbox cleanup stopped sandbox in unknown state.
|
||||||
|
41
vendor/github.com/containerd/cri/pkg/server/service.go
generated
vendored
41
vendor/github.com/containerd/cri/pkg/server/service.go
generated
vendored
@ -26,10 +26,6 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
|
|
||||||
runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp"
|
|
||||||
runcsystem "github.com/opencontainers/runc/libcontainer/system"
|
|
||||||
"github.com/opencontainers/selinux/go-selinux"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -68,10 +64,6 @@ type criService struct {
|
|||||||
config criconfig.Config
|
config criconfig.Config
|
||||||
// imageFSPath is the path to image filesystem.
|
// imageFSPath is the path to image filesystem.
|
||||||
imageFSPath string
|
imageFSPath string
|
||||||
// apparmorEnabled indicates whether apparmor is enabled.
|
|
||||||
apparmorEnabled bool
|
|
||||||
// seccompEnabled indicates whether seccomp is enabled.
|
|
||||||
seccompEnabled bool
|
|
||||||
// os is an interface for all required os operations.
|
// os is an interface for all required os operations.
|
||||||
os osinterface.OS
|
os osinterface.OS
|
||||||
// sandboxStore stores all resources associated with sandboxes.
|
// sandboxStore stores all resources associated with sandboxes.
|
||||||
@ -107,8 +99,6 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||||||
c := &criService{
|
c := &criService{
|
||||||
config: config,
|
config: config,
|
||||||
client: client,
|
client: client,
|
||||||
apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor,
|
|
||||||
seccompEnabled: runcseccomp.IsEnabled(),
|
|
||||||
os: osinterface.RealOS{},
|
os: osinterface.RealOS{},
|
||||||
sandboxStore: sandboxstore.NewStore(),
|
sandboxStore: sandboxstore.NewStore(),
|
||||||
containerStore: containerstore.NewStore(),
|
containerStore: containerstore.NewStore(),
|
||||||
@ -119,20 +109,6 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||||||
initialized: atomic.NewBool(false),
|
initialized: atomic.NewBool(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
if runcsystem.RunningInUserNS() {
|
|
||||||
if !(config.DisableCgroup && !c.apparmorEnabled && config.RestrictOOMScoreAdj) {
|
|
||||||
logrus.Warn("Running containerd in a user namespace typically requires disable_cgroup, disable_apparmor, restrict_oom_score_adj set to be true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.config.EnableSelinux {
|
|
||||||
if !selinux.GetEnabled() {
|
|
||||||
logrus.Warn("Selinux is not supported")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selinux.SetDisabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
if client.SnapshotService(c.config.ContainerdConfig.Snapshotter) == nil {
|
if client.SnapshotService(c.config.ContainerdConfig.Snapshotter) == nil {
|
||||||
return nil, errors.Errorf("failed to find snapshotter %q", c.config.ContainerdConfig.Snapshotter)
|
return nil, errors.Errorf("failed to find snapshotter %q", c.config.ContainerdConfig.Snapshotter)
|
||||||
}
|
}
|
||||||
@ -140,23 +116,10 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||||||
c.imageFSPath = imageFSPath(config.ContainerdRootDir, config.ContainerdConfig.Snapshotter)
|
c.imageFSPath = imageFSPath(config.ContainerdRootDir, config.ContainerdConfig.Snapshotter)
|
||||||
logrus.Infof("Get image filesystem path %q", c.imageFSPath)
|
logrus.Infof("Get image filesystem path %q", c.imageFSPath)
|
||||||
|
|
||||||
// Pod needs to attach to atleast loopback network and a non host network,
|
if err := c.initPlatform(); err != nil {
|
||||||
// hence networkAttachCount is 2. If there are more network configs the
|
return nil, errors.Wrap(err, "initialize platform")
|
||||||
// pod will be attached to all the networks but we will only use the ip
|
|
||||||
// of the default network interface as the pod IP.
|
|
||||||
c.netPlugin, err = cni.New(cni.WithMinNetworkCount(networkAttachCount),
|
|
||||||
cni.WithPluginConfDir(config.NetworkPluginConfDir),
|
|
||||||
cni.WithPluginMaxConfNum(config.NetworkPluginMaxConfNum),
|
|
||||||
cni.WithPluginDir([]string{config.NetworkPluginBinDir}))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to initialize cni")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to load the config if it exists. Just log the error if load fails
|
|
||||||
// This is not disruptive for containerd to panic
|
|
||||||
if err := c.netPlugin.Load(cni.WithLoNetwork, cni.WithDefaultConf); err != nil {
|
|
||||||
logrus.WithError(err).Error("Failed to load cni during init, please check CRI plugin status before setting up network for pods")
|
|
||||||
}
|
|
||||||
// prepare streaming server
|
// prepare streaming server
|
||||||
c.streamServer, err = newStreamServer(c, config.StreamServerAddress, config.StreamServerPort, config.StreamIdleTimeout)
|
c.streamServer, err = newStreamServer(c, config.StreamServerAddress, config.StreamServerPort, config.StreamIdleTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
74
vendor/github.com/containerd/cri/pkg/server/service_unix.go
generated
vendored
Normal file
74
vendor/github.com/containerd/cri/pkg/server/service_unix.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
cni "github.com/containerd/go-cni"
|
||||||
|
runcsystem "github.com/opencontainers/runc/libcontainer/system"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// networkAttachCount is the minimum number of networks the PodSandbox
|
||||||
|
// attaches to
|
||||||
|
const networkAttachCount = 2
|
||||||
|
|
||||||
|
// initPlatform handles linux specific initialization for the CRI service.
|
||||||
|
func (c *criService) initPlatform() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if runcsystem.RunningInUserNS() {
|
||||||
|
if !(c.config.DisableCgroup && !c.apparmorEnabled() && c.config.RestrictOOMScoreAdj) {
|
||||||
|
logrus.Warn("Running containerd in a user namespace typically requires disable_cgroup, disable_apparmor, restrict_oom_score_adj set to be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.EnableSelinux {
|
||||||
|
if !selinux.GetEnabled() {
|
||||||
|
logrus.Warn("Selinux is not supported")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selinux.SetDisabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pod needs to attach to at least loopback network and a non host network,
|
||||||
|
// hence networkAttachCount is 2. If there are more network configs the
|
||||||
|
// pod will be attached to all the networks but we will only use the ip
|
||||||
|
// of the default network interface as the pod IP.
|
||||||
|
c.netPlugin, err = cni.New(cni.WithMinNetworkCount(networkAttachCount),
|
||||||
|
cni.WithPluginConfDir(c.config.NetworkPluginConfDir),
|
||||||
|
cni.WithPluginMaxConfNum(c.config.NetworkPluginMaxConfNum),
|
||||||
|
cni.WithPluginDir([]string{c.config.NetworkPluginBinDir}))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to initialize cni")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load the config if it exists. Just log the error if load fails
|
||||||
|
// This is not disruptive for containerd to panic
|
||||||
|
if err := c.netPlugin.Load(c.cniLoadOptions()...); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to load cni during init, please check CRI plugin status before setting up network for pods")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cniLoadOptions returns cni load options for the linux.
|
||||||
|
func (c *criService) cniLoadOptions() []cni.CNIOpt {
|
||||||
|
return []cni.CNIOpt{cni.WithLoNetwork, cni.WithDefaultConf}
|
||||||
|
}
|
58
vendor/github.com/containerd/cri/pkg/server/service_windows.go
generated
vendored
Normal file
58
vendor/github.com/containerd/cri/pkg/server/service_windows.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
cni "github.com/containerd/go-cni"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// windowsNetworkAttachCount is the minimum number of networks the PodSandbox
|
||||||
|
// attaches to
|
||||||
|
const windowsNetworkAttachCount = 1
|
||||||
|
|
||||||
|
// initPlatform handles linux specific initialization for the CRI service.
|
||||||
|
func (c *criService) initPlatform() error {
|
||||||
|
var err error
|
||||||
|
// For windows, the loopback network is added as default.
|
||||||
|
// There is no need to explicitly add one hence networkAttachCount is 1.
|
||||||
|
// If there are more network configs the pod will be attached to all the
|
||||||
|
// networks but we will only use the ip of the default network interface
|
||||||
|
// as the pod IP.
|
||||||
|
c.netPlugin, err = cni.New(cni.WithMinNetworkCount(windowsNetworkAttachCount),
|
||||||
|
cni.WithPluginConfDir(c.config.NetworkPluginConfDir),
|
||||||
|
cni.WithPluginMaxConfNum(c.config.NetworkPluginMaxConfNum),
|
||||||
|
cni.WithPluginDir([]string{c.config.NetworkPluginBinDir}))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to initialize cni")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load the config if it exists. Just log the error if load fails
|
||||||
|
// This is not disruptive for containerd to panic
|
||||||
|
if err := c.netPlugin.Load(c.cniLoadOptions()...); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to load cni during init, please check CRI plugin status before setting up network for pods")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cniLoadOptions returns cni load options for the windows.
|
||||||
|
func (c *criService) cniLoadOptions() []cni.CNIOpt {
|
||||||
|
return []cni.CNIOpt{cni.WithDefaultConf}
|
||||||
|
}
|
4
vendor/github.com/containerd/cri/pkg/server/status.go
generated
vendored
4
vendor/github.com/containerd/cri/pkg/server/status.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
|||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
cni "github.com/containerd/go-cni"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
)
|
)
|
||||||
@ -42,9 +41,8 @@ func (c *criService) Status(ctx context.Context, r *runtime.StatusRequest) (*run
|
|||||||
Type: runtime.NetworkReady,
|
Type: runtime.NetworkReady,
|
||||||
Status: true,
|
Status: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the latest cni configuration to be in sync with the latest network configuration
|
// Load the latest cni configuration to be in sync with the latest network configuration
|
||||||
if err := c.netPlugin.Load(cni.WithLoNetwork, cni.WithDefaultConf); err != nil {
|
if err := c.netPlugin.Load(c.cniLoadOptions()...); err != nil {
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to load cni configuration")
|
log.G(ctx).WithError(err).Errorf("Failed to load cni configuration")
|
||||||
}
|
}
|
||||||
// Check the status of the cni initialization
|
// Check the status of the cni initialization
|
||||||
|
4
vendor/github.com/containerd/cri/pkg/server/streaming.go
generated
vendored
4
vendor/github.com/containerd/cri/pkg/server/streaming.go
generated
vendored
@ -25,7 +25,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
|
||||||
k8snet "k8s.io/apimachinery/pkg/util/net"
|
k8snet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
@ -156,7 +155,8 @@ func (s *streamRuntime) PortForward(podSandboxID string, port int32, stream io.R
|
|||||||
if port <= 0 || port > math.MaxUint16 {
|
if port <= 0 || port > math.MaxUint16 {
|
||||||
return errors.Errorf("invalid port %d", port)
|
return errors.Errorf("invalid port %d", port)
|
||||||
}
|
}
|
||||||
return s.c.portForward(context.Background(), podSandboxID, port, stream)
|
ctx := ctrdutil.NamespacedContext()
|
||||||
|
return s.c.portForward(ctx, podSandboxID, port, stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each
|
// handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each
|
||||||
|
3
vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go
generated
vendored
3
vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
cni "github.com/containerd/go-cni"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
@ -73,7 +72,7 @@ func (c *criService) UpdateRuntimeConfig(ctx context.Context, r *runtime.UpdateR
|
|||||||
if err := c.netPlugin.Status(); err == nil {
|
if err := c.netPlugin.Status(); err == nil {
|
||||||
log.G(ctx).Infof("Network plugin is ready, skip generating cni config from template %q", confTemplate)
|
log.G(ctx).Infof("Network plugin is ready, skip generating cni config from template %q", confTemplate)
|
||||||
return &runtime.UpdateRuntimeConfigResponse{}, nil
|
return &runtime.UpdateRuntimeConfigResponse{}, nil
|
||||||
} else if err := c.netPlugin.Load(cni.WithLoNetwork, cni.WithDefaultConf); err == nil {
|
} else if err := c.netPlugin.Load(c.cniLoadOptions()...); err == nil {
|
||||||
log.G(ctx).Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate)
|
log.G(ctx).Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate)
|
||||||
return &runtime.UpdateRuntimeConfigResponse{}, nil
|
return &runtime.UpdateRuntimeConfigResponse{}, nil
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/containerd/cri/vendor.conf
generated
vendored
19
vendor/github.com/containerd/cri/vendor.conf
generated
vendored
@ -5,11 +5,12 @@ github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
|||||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||||
|
|
||||||
# containerd dependencies
|
# containerd dependencies
|
||||||
go.etcd.io/bbolt 2eb7227adea1d5cf85f0bc2a82b7059b13c2fa68
|
go.opencensus.io v0.22.0
|
||||||
google.golang.org/grpc 25c4f928eaa6d96443009bd842389fb4fa48664e # v1.20.1
|
go.etcd.io/bbolt v1.3.3
|
||||||
|
google.golang.org/grpc 6eaf6f47437a6b4e2153a190160ef39a92c7eceb # v1.23.0
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
golang.org/x/sys 4c4f7f33c9ed00de01c4c741d2177abfcfe19307 https://github.com/golang/sys
|
golang.org/x/sys fb81701db80f1745f51259b1f286de3fe2ec80c8 https://github.com/golang/sys # TODO(windows): update this in containerd/containerd
|
||||||
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||||
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
||||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||||
@ -25,6 +26,9 @@ github.com/opencontainers/runc f4982d86f7fde0b6f953cc62ccc4022c519a10a9 # v1.0.0
|
|||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
||||||
|
github.com/imdario/mergo v0.3.7
|
||||||
|
github.com/hashicorp/golang-lru v0.5.3
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/golang/protobuf v1.2.0
|
github.com/golang/protobuf v1.2.0
|
||||||
@ -37,17 +41,16 @@ github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
|||||||
github.com/coreos/go-systemd v14
|
github.com/coreos/go-systemd v14
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
||||||
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
github.com/containerd/go-runc 9007c2405372fe28918845901a3276c0915689a1
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
||||||
github.com/containerd/containerd d4802a64f9737f02db3426751f380d97fc878dec
|
github.com/containerd/containerd ed16170c4c399c57f25d6aa1e97b345ed6ab96cb
|
||||||
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
||||||
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
|
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
|
||||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
github.com/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
|
github.com/Microsoft/hcsshim c088f411aaf3585d8dffc9deb4289ffa32854497 # TODO(windows): update this in containerd/containerd
|
||||||
github.com/Microsoft/go-winio v0.4.14
|
github.com/Microsoft/go-winio v0.4.14
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/imdario/mergo v0.3.7
|
|
||||||
|
|
||||||
# kubernetes dependencies
|
# kubernetes dependencies
|
||||||
sigs.k8s.io/yaml v1.1.0
|
sigs.k8s.io/yaml v1.1.0
|
||||||
@ -78,4 +81,4 @@ github.com/davecgh/go-spew v1.1.1
|
|||||||
# cni dependencies
|
# cni dependencies
|
||||||
github.com/containernetworking/plugins v0.7.6
|
github.com/containernetworking/plugins v0.7.6
|
||||||
github.com/containernetworking/cni v0.7.1
|
github.com/containernetworking/cni v0.7.1
|
||||||
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
github.com/containerd/go-cni 0d360c50b10b350b6bb23863fd4dfb1c232b01c9
|
||||||
|
8
vendor/github.com/containerd/go-cni/namespace_opts.go
generated
vendored
8
vendor/github.com/containerd/go-cni/namespace_opts.go
generated
vendored
@ -42,6 +42,14 @@ func WithCapabilityBandWidth(bandWidth BandWidth) NamespaceOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithCapabilityDNS adds support for dns
|
||||||
|
func WithCapabilityDNS(dns DNS) NamespaceOpts {
|
||||||
|
return func(c *Namespace) error {
|
||||||
|
c.capabilityArgs["dns"] = dns
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func WithCapability(name string, capability interface{}) NamespaceOpts {
|
func WithCapability(name string, capability interface{}) NamespaceOpts {
|
||||||
return func(c *Namespace) error {
|
return func(c *Namespace) error {
|
||||||
c.capabilityArgs[name] = capability
|
c.capabilityArgs[name] = capability
|
||||||
|
10
vendor/github.com/containerd/go-cni/types.go
generated
vendored
10
vendor/github.com/containerd/go-cni/types.go
generated
vendored
@ -53,3 +53,13 @@ type BandWidth struct {
|
|||||||
EgressRate uint64
|
EgressRate uint64
|
||||||
EgressBurst uint64
|
EgressBurst uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DNS defines the dns config
|
||||||
|
type DNS struct {
|
||||||
|
// List of DNS servers of the cluster.
|
||||||
|
Servers []string
|
||||||
|
// List of DNS search domains of the cluster.
|
||||||
|
Searches []string
|
||||||
|
// List of DNS options.
|
||||||
|
Options []string
|
||||||
|
}
|
||||||
|
198
vendor/golang.org/x/sys/windows/registry/key.go
generated
vendored
Normal file
198
vendor/golang.org/x/sys/windows/registry/key.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
// Package registry provides access to the Windows registry.
|
||||||
|
//
|
||||||
|
// Here is a simple example, opening a registry key and reading a string value from it.
|
||||||
|
//
|
||||||
|
// k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
// defer k.Close()
|
||||||
|
//
|
||||||
|
// s, _, err := k.GetStringValue("SystemRoot")
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
// fmt.Printf("Windows system root is %q\n", s)
|
||||||
|
//
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Registry key security and access rights.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878.aspx
|
||||||
|
// for details.
|
||||||
|
ALL_ACCESS = 0xf003f
|
||||||
|
CREATE_LINK = 0x00020
|
||||||
|
CREATE_SUB_KEY = 0x00004
|
||||||
|
ENUMERATE_SUB_KEYS = 0x00008
|
||||||
|
EXECUTE = 0x20019
|
||||||
|
NOTIFY = 0x00010
|
||||||
|
QUERY_VALUE = 0x00001
|
||||||
|
READ = 0x20019
|
||||||
|
SET_VALUE = 0x00002
|
||||||
|
WOW64_32KEY = 0x00200
|
||||||
|
WOW64_64KEY = 0x00100
|
||||||
|
WRITE = 0x20006
|
||||||
|
)
|
||||||
|
|
||||||
|
// Key is a handle to an open Windows registry key.
|
||||||
|
// Keys can be obtained by calling OpenKey; there are
|
||||||
|
// also some predefined root keys such as CURRENT_USER.
|
||||||
|
// Keys can be used directly in the Windows API.
|
||||||
|
type Key syscall.Handle
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Windows defines some predefined root keys that are always open.
|
||||||
|
// An application can use these keys as entry points to the registry.
|
||||||
|
// Normally these keys are used in OpenKey to open new keys,
|
||||||
|
// but they can also be used anywhere a Key is required.
|
||||||
|
CLASSES_ROOT = Key(syscall.HKEY_CLASSES_ROOT)
|
||||||
|
CURRENT_USER = Key(syscall.HKEY_CURRENT_USER)
|
||||||
|
LOCAL_MACHINE = Key(syscall.HKEY_LOCAL_MACHINE)
|
||||||
|
USERS = Key(syscall.HKEY_USERS)
|
||||||
|
CURRENT_CONFIG = Key(syscall.HKEY_CURRENT_CONFIG)
|
||||||
|
PERFORMANCE_DATA = Key(syscall.HKEY_PERFORMANCE_DATA)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Close closes open key k.
|
||||||
|
func (k Key) Close() error {
|
||||||
|
return syscall.RegCloseKey(syscall.Handle(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenKey opens a new key with path name relative to key k.
|
||||||
|
// It accepts any open key, including CURRENT_USER and others,
|
||||||
|
// and returns the new key and an error.
|
||||||
|
// The access parameter specifies desired access rights to the
|
||||||
|
// key to be opened.
|
||||||
|
func OpenKey(k Key, path string, access uint32) (Key, error) {
|
||||||
|
p, err := syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var subkey syscall.Handle
|
||||||
|
err = syscall.RegOpenKeyEx(syscall.Handle(k), p, 0, access, &subkey)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return Key(subkey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenRemoteKey opens a predefined registry key on another
|
||||||
|
// computer pcname. The key to be opened is specified by k, but
|
||||||
|
// can only be one of LOCAL_MACHINE, PERFORMANCE_DATA or USERS.
|
||||||
|
// If pcname is "", OpenRemoteKey returns local computer key.
|
||||||
|
func OpenRemoteKey(pcname string, k Key) (Key, error) {
|
||||||
|
var err error
|
||||||
|
var p *uint16
|
||||||
|
if pcname != "" {
|
||||||
|
p, err = syscall.UTF16PtrFromString(`\\` + pcname)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var remoteKey syscall.Handle
|
||||||
|
err = regConnectRegistry(p, syscall.Handle(k), &remoteKey)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return Key(remoteKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSubKeyNames returns the names of subkeys of key k.
|
||||||
|
// The parameter n controls the number of returned names,
|
||||||
|
// analogous to the way os.File.Readdirnames works.
|
||||||
|
func (k Key) ReadSubKeyNames(n int) ([]string, error) {
|
||||||
|
names := make([]string, 0)
|
||||||
|
// Registry key size limit is 255 bytes and described there:
|
||||||
|
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
||||||
|
buf := make([]uint16, 256) //plus extra room for terminating zero byte
|
||||||
|
loopItems:
|
||||||
|
for i := uint32(0); ; i++ {
|
||||||
|
if n > 0 {
|
||||||
|
if len(names) == n {
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err == syscall.ERROR_MORE_DATA {
|
||||||
|
// Double buffer size and try again.
|
||||||
|
l = uint32(2 * len(buf))
|
||||||
|
buf = make([]uint16, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == _ERROR_NO_MORE_ITEMS {
|
||||||
|
break loopItems
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
|
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||||
|
}
|
||||||
|
if n > len(names) {
|
||||||
|
return names, io.EOF
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKey creates a key named path under open key k.
|
||||||
|
// CreateKey returns the new key and a boolean flag that reports
|
||||||
|
// whether the key already existed.
|
||||||
|
// The access parameter specifies the access rights for the key
|
||||||
|
// to be created.
|
||||||
|
func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) {
|
||||||
|
var h syscall.Handle
|
||||||
|
var d uint32
|
||||||
|
err = regCreateKeyEx(syscall.Handle(k), syscall.StringToUTF16Ptr(path),
|
||||||
|
0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, err
|
||||||
|
}
|
||||||
|
return Key(h), d == _REG_OPENED_EXISTING_KEY, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteKey deletes the subkey path of key k and its values.
|
||||||
|
func DeleteKey(k Key, path string) error {
|
||||||
|
return regDeleteKey(syscall.Handle(k), syscall.StringToUTF16Ptr(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// A KeyInfo describes the statistics of a key. It is returned by Stat.
|
||||||
|
type KeyInfo struct {
|
||||||
|
SubKeyCount uint32
|
||||||
|
MaxSubKeyLen uint32 // size of the key's subkey with the longest name, in Unicode characters, not including the terminating zero byte
|
||||||
|
ValueCount uint32
|
||||||
|
MaxValueNameLen uint32 // size of the key's longest value name, in Unicode characters, not including the terminating zero byte
|
||||||
|
MaxValueLen uint32 // longest data component among the key's values, in bytes
|
||||||
|
lastWriteTime syscall.Filetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModTime returns the key's last write time.
|
||||||
|
func (ki *KeyInfo) ModTime() time.Time {
|
||||||
|
return time.Unix(0, ki.lastWriteTime.Nanoseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat retrieves information about the open key k.
|
||||||
|
func (k Key) Stat() (*KeyInfo, error) {
|
||||||
|
var ki KeyInfo
|
||||||
|
err := syscall.RegQueryInfoKey(syscall.Handle(k), nil, nil, nil,
|
||||||
|
&ki.SubKeyCount, &ki.MaxSubKeyLen, nil, &ki.ValueCount,
|
||||||
|
&ki.MaxValueNameLen, &ki.MaxValueLen, nil, &ki.lastWriteTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ki, nil
|
||||||
|
}
|
9
vendor/golang.org/x/sys/windows/registry/mksyscall.go
generated
vendored
Normal file
9
vendor/golang.org/x/sys/windows/registry/mksyscall.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build generate
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
|
32
vendor/golang.org/x/sys/windows/registry/syscall.go
generated
vendored
Normal file
32
vendor/golang.org/x/sys/windows/registry/syscall.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const (
|
||||||
|
_REG_OPTION_NON_VOLATILE = 0
|
||||||
|
|
||||||
|
_REG_CREATED_NEW_KEY = 1
|
||||||
|
_REG_OPENED_EXISTING_KEY = 2
|
||||||
|
|
||||||
|
_ERROR_NO_MORE_ITEMS syscall.Errno = 259
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadRegLoadMUIString() error {
|
||||||
|
return procRegLoadMUIStringW.Find()
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
||||||
|
//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
|
||||||
|
//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
|
||||||
|
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
||||||
|
//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
|
||||||
|
//sys regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW
|
||||||
|
//sys regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) = advapi32.RegConnectRegistryW
|
||||||
|
|
||||||
|
//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
|
387
vendor/golang.org/x/sys/windows/registry/value.go
generated
vendored
Normal file
387
vendor/golang.org/x/sys/windows/registry/value.go
generated
vendored
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Registry value types.
|
||||||
|
NONE = 0
|
||||||
|
SZ = 1
|
||||||
|
EXPAND_SZ = 2
|
||||||
|
BINARY = 3
|
||||||
|
DWORD = 4
|
||||||
|
DWORD_BIG_ENDIAN = 5
|
||||||
|
LINK = 6
|
||||||
|
MULTI_SZ = 7
|
||||||
|
RESOURCE_LIST = 8
|
||||||
|
FULL_RESOURCE_DESCRIPTOR = 9
|
||||||
|
RESOURCE_REQUIREMENTS_LIST = 10
|
||||||
|
QWORD = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrShortBuffer is returned when the buffer was too short for the operation.
|
||||||
|
ErrShortBuffer = syscall.ERROR_MORE_DATA
|
||||||
|
|
||||||
|
// ErrNotExist is returned when a registry key or value does not exist.
|
||||||
|
ErrNotExist = syscall.ERROR_FILE_NOT_FOUND
|
||||||
|
|
||||||
|
// ErrUnexpectedType is returned by Get*Value when the value's type was unexpected.
|
||||||
|
ErrUnexpectedType = errors.New("unexpected key value type")
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetValue retrieves the type and data for the specified value associated
|
||||||
|
// with an open key k. It fills up buffer buf and returns the retrieved
|
||||||
|
// byte count n. If buf is too small to fit the stored value it returns
|
||||||
|
// ErrShortBuffer error along with the required buffer size n.
|
||||||
|
// If no buffer is provided, it returns true and actual buffer size n.
|
||||||
|
// If no buffer is provided, GetValue returns the value's type only.
|
||||||
|
// If the value does not exist, the error returned is ErrNotExist.
|
||||||
|
//
|
||||||
|
// GetValue is a low level function. If value's type is known, use the appropriate
|
||||||
|
// Get*Value function instead.
|
||||||
|
func (k Key) GetValue(name string, buf []byte) (n int, valtype uint32, err error) {
|
||||||
|
pname, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
var pbuf *byte
|
||||||
|
if len(buf) > 0 {
|
||||||
|
pbuf = (*byte)(unsafe.Pointer(&buf[0]))
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
err = syscall.RegQueryValueEx(syscall.Handle(k), pname, nil, &valtype, pbuf, &l)
|
||||||
|
if err != nil {
|
||||||
|
return int(l), valtype, err
|
||||||
|
}
|
||||||
|
return int(l), valtype, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) getValue(name string, buf []byte) (data []byte, valtype uint32, err error) {
|
||||||
|
p, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
var t uint32
|
||||||
|
n := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err = syscall.RegQueryValueEx(syscall.Handle(k), p, nil, &t, (*byte)(unsafe.Pointer(&buf[0])), &n)
|
||||||
|
if err == nil {
|
||||||
|
return buf[:n], t, nil
|
||||||
|
}
|
||||||
|
if err != syscall.ERROR_MORE_DATA {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(buf)) {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
buf = make([]byte, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringValue retrieves the string value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetStringValue returns ErrNotExist.
|
||||||
|
// If value is not SZ or EXPAND_SZ, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetStringValue(name string) (val string, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return "", typ, err2
|
||||||
|
}
|
||||||
|
switch typ {
|
||||||
|
case SZ, EXPAND_SZ:
|
||||||
|
default:
|
||||||
|
return "", typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return "", typ, nil
|
||||||
|
}
|
||||||
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
|
||||||
|
return syscall.UTF16ToString(u), typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMUIStringValue retrieves the localized string value for
|
||||||
|
// the specified value name associated with an open key k.
|
||||||
|
// If the value name doesn't exist or the localized string value
|
||||||
|
// can't be resolved, GetMUIStringValue returns ErrNotExist.
|
||||||
|
// GetMUIStringValue panics if the system doesn't support
|
||||||
|
// regLoadMUIString; use LoadRegLoadMUIString to check if
|
||||||
|
// regLoadMUIString is supported before calling this function.
|
||||||
|
func (k Key) GetMUIStringValue(name string) (string, error) {
|
||||||
|
pname, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]uint16, 1024)
|
||||||
|
var buflen uint32
|
||||||
|
var pdir *uint16
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path
|
||||||
|
|
||||||
|
// Try to resolve the string value using the system directory as
|
||||||
|
// a DLL search path; this assumes the string value is of the form
|
||||||
|
// @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320.
|
||||||
|
|
||||||
|
// This approach works with tzres.dll but may have to be revised
|
||||||
|
// in the future to allow callers to provide custom search paths.
|
||||||
|
|
||||||
|
var s string
|
||||||
|
s, err = ExpandString("%SystemRoot%\\system32\\")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pdir, err = syscall.UTF16PtrFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed
|
||||||
|
if buflen <= uint32(len(buf)) {
|
||||||
|
break // Buffer not growing, assume race; break
|
||||||
|
}
|
||||||
|
buf = make([]uint16, buflen)
|
||||||
|
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return syscall.UTF16ToString(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandString expands environment-variable strings and replaces
|
||||||
|
// them with the values defined for the current user.
|
||||||
|
// Use ExpandString to expand EXPAND_SZ strings.
|
||||||
|
func ExpandString(value string) (string, error) {
|
||||||
|
if value == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
p, err := syscall.UTF16PtrFromString(value)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
r := make([]uint16, 100)
|
||||||
|
for {
|
||||||
|
n, err := expandEnvironmentStrings(p, &r[0], uint32(len(r)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if n <= uint32(len(r)) {
|
||||||
|
u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
|
||||||
|
return syscall.UTF16ToString(u), nil
|
||||||
|
}
|
||||||
|
r = make([]uint16, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringsValue retrieves the []string value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetStringsValue returns ErrNotExist.
|
||||||
|
// If value is not MULTI_SZ, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, typ, err2
|
||||||
|
}
|
||||||
|
if typ != MULTI_SZ {
|
||||||
|
return nil, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, typ, nil
|
||||||
|
}
|
||||||
|
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
|
||||||
|
if len(p) == 0 {
|
||||||
|
return nil, typ, nil
|
||||||
|
}
|
||||||
|
if p[len(p)-1] == 0 {
|
||||||
|
p = p[:len(p)-1] // remove terminating null
|
||||||
|
}
|
||||||
|
val = make([]string, 0, 5)
|
||||||
|
from := 0
|
||||||
|
for i, c := range p {
|
||||||
|
if c == 0 {
|
||||||
|
val = append(val, string(utf16.Decode(p[from:i])))
|
||||||
|
from = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val, typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIntegerValue retrieves the integer value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetIntegerValue returns ErrNotExist.
|
||||||
|
// If value is not DWORD or QWORD, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetIntegerValue(name string) (val uint64, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 8))
|
||||||
|
if err2 != nil {
|
||||||
|
return 0, typ, err2
|
||||||
|
}
|
||||||
|
switch typ {
|
||||||
|
case DWORD:
|
||||||
|
if len(data) != 4 {
|
||||||
|
return 0, typ, errors.New("DWORD value is not 4 bytes long")
|
||||||
|
}
|
||||||
|
var val32 uint32
|
||||||
|
copy((*[4]byte)(unsafe.Pointer(&val32))[:], data)
|
||||||
|
return uint64(val32), DWORD, nil
|
||||||
|
case QWORD:
|
||||||
|
if len(data) != 8 {
|
||||||
|
return 0, typ, errors.New("QWORD value is not 8 bytes long")
|
||||||
|
}
|
||||||
|
copy((*[8]byte)(unsafe.Pointer(&val))[:], data)
|
||||||
|
return val, QWORD, nil
|
||||||
|
default:
|
||||||
|
return 0, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBinaryValue retrieves the binary value for the specified
|
||||||
|
// value name associated with an open key k. It also returns the value's type.
|
||||||
|
// If value does not exist, GetBinaryValue returns ErrNotExist.
|
||||||
|
// If value is not BINARY, it will return the correct value
|
||||||
|
// type and ErrUnexpectedType.
|
||||||
|
func (k Key) GetBinaryValue(name string) (val []byte, valtype uint32, err error) {
|
||||||
|
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, typ, err2
|
||||||
|
}
|
||||||
|
if typ != BINARY {
|
||||||
|
return nil, typ, ErrUnexpectedType
|
||||||
|
}
|
||||||
|
return data, typ, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) setValue(name string, valtype uint32, data []byte) error {
|
||||||
|
p, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return regSetValueEx(syscall.Handle(k), p, 0, valtype, nil, 0)
|
||||||
|
}
|
||||||
|
return regSetValueEx(syscall.Handle(k), p, 0, valtype, &data[0], uint32(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDWordValue sets the data and type of a name value
|
||||||
|
// under key k to value and DWORD.
|
||||||
|
func (k Key) SetDWordValue(name string, value uint32) error {
|
||||||
|
return k.setValue(name, DWORD, (*[4]byte)(unsafe.Pointer(&value))[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetQWordValue sets the data and type of a name value
|
||||||
|
// under key k to value and QWORD.
|
||||||
|
func (k Key) SetQWordValue(name string, value uint64) error {
|
||||||
|
return k.setValue(name, QWORD, (*[8]byte)(unsafe.Pointer(&value))[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) setStringValue(name string, valtype uint32, value string) error {
|
||||||
|
v, err := syscall.UTF16FromString(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
|
return k.setValue(name, valtype, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringValue sets the data and type of a name value
|
||||||
|
// under key k to value and SZ. The value must not contain a zero byte.
|
||||||
|
func (k Key) SetStringValue(name, value string) error {
|
||||||
|
return k.setStringValue(name, SZ, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExpandStringValue sets the data and type of a name value
|
||||||
|
// under key k to value and EXPAND_SZ. The value must not contain a zero byte.
|
||||||
|
func (k Key) SetExpandStringValue(name, value string) error {
|
||||||
|
return k.setStringValue(name, EXPAND_SZ, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringsValue sets the data and type of a name value
|
||||||
|
// under key k to value and MULTI_SZ. The value strings
|
||||||
|
// must not contain a zero byte.
|
||||||
|
func (k Key) SetStringsValue(name string, value []string) error {
|
||||||
|
ss := ""
|
||||||
|
for _, s := range value {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == 0 {
|
||||||
|
return errors.New("string cannot have 0 inside")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss += s + "\x00"
|
||||||
|
}
|
||||||
|
v := utf16.Encode([]rune(ss + "\x00"))
|
||||||
|
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||||
|
return k.setValue(name, MULTI_SZ, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBinaryValue sets the data and type of a name value
|
||||||
|
// under key k to value and BINARY.
|
||||||
|
func (k Key) SetBinaryValue(name string, value []byte) error {
|
||||||
|
return k.setValue(name, BINARY, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValue removes a named value from the key k.
|
||||||
|
func (k Key) DeleteValue(name string) error {
|
||||||
|
return regDeleteValue(syscall.Handle(k), syscall.StringToUTF16Ptr(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadValueNames returns the value names of key k.
|
||||||
|
// The parameter n controls the number of returned names,
|
||||||
|
// analogous to the way os.File.Readdirnames works.
|
||||||
|
func (k Key) ReadValueNames(n int) ([]string, error) {
|
||||||
|
ki, err := k.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
names := make([]string, 0, ki.ValueCount)
|
||||||
|
buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character
|
||||||
|
loopItems:
|
||||||
|
for i := uint32(0); ; i++ {
|
||||||
|
if n > 0 {
|
||||||
|
if len(names) == n {
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := uint32(len(buf))
|
||||||
|
for {
|
||||||
|
err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err == syscall.ERROR_MORE_DATA {
|
||||||
|
// Double buffer size and try again.
|
||||||
|
l = uint32(2 * len(buf))
|
||||||
|
buf = make([]uint16, l)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == _ERROR_NO_MORE_ITEMS {
|
||||||
|
break loopItems
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
|
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||||
|
}
|
||||||
|
if n > len(names) {
|
||||||
|
return names, io.EOF
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
120
vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
generated
vendored
Normal file
120
vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Code generated by 'go generate'; DO NOT EDIT.
|
||||||
|
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ unsafe.Pointer
|
||||||
|
|
||||||
|
// Do the interface allocations only once for common
|
||||||
|
// Errno values.
|
||||||
|
const (
|
||||||
|
errnoERROR_IO_PENDING = 997
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case errnoERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
}
|
||||||
|
// TODO: add more here, after collecting data on the common
|
||||||
|
// error values see on Windows. (perhaps when running
|
||||||
|
// all.bat?)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||||
|
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
||||||
|
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||||
|
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||||
|
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||||
|
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||||
|
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||||
|
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegDeleteKeyW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result)))
|
||||||
|
if r0 != 0 {
|
||||||
|
regerrno = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
||||||
|
n = uint32(r0)
|
||||||
|
if n == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user