123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906 |
- //go:build windows
- // Shim for the Host Network Service (HNS) to manage networking for
- // Windows Server containers and Hyper-V containers. This module
- // is a basic libnetwork driver that passes all the calls to HNS
- // It implements the 4 networking modes supported by HNS L2Bridge,
- // L2Tunnel, NAT and Transparent(DHCP)
- //
- // The network are stored in memory and docker daemon ensures discovering
- // and loading these networks on startup
- package windows
- import (
- "context"
- "encoding/json"
- "fmt"
- "net"
- "strconv"
- "strings"
- "sync"
- "github.com/Microsoft/hcsshim"
- "github.com/containerd/log"
- "github.com/docker/docker/libnetwork/datastore"
- "github.com/docker/docker/libnetwork/driverapi"
- "github.com/docker/docker/libnetwork/netlabel"
- "github.com/docker/docker/libnetwork/portmapper"
- "github.com/docker/docker/libnetwork/scope"
- "github.com/docker/docker/libnetwork/types"
- )
- // networkConfiguration for network specific configuration
- type networkConfiguration struct {
- ID string
- Type string
- Name string
- HnsID string
- RDID string
- VLAN uint
- VSID uint
- DNSServers string
- MacPools []hcsshim.MacPool
- DNSSuffix string
- SourceMac string
- NetworkAdapterName string
- dbIndex uint64
- dbExists bool
- DisableGatewayDNS bool
- EnableOutboundNat bool
- OutboundNatExceptions []string
- }
- // endpointConfiguration represents the user specified configuration for the sandbox endpoint
- type endpointOption struct {
- MacAddress net.HardwareAddr
- QosPolicies []types.QosPolicy
- DNSServers []string
- DisableDNS bool
- DisableICC bool
- }
- // EndpointConnectivity stores the port bindings and exposed ports that the user has specified in epOptions.
- type EndpointConnectivity struct {
- PortBindings []types.PortBinding
- ExposedPorts []types.TransportPort
- }
- type hnsEndpoint struct {
- id string
- nid string
- profileID string
- Type string
- // Note: Currently, the sandboxID is the same as the containerID since windows does
- // not expose the sandboxID.
- // In the future, windows will support a proper sandboxID that is different
- // than the containerID.
- // Therefore, we are using sandboxID now, so that we won't have to change this code
- // when windows properly supports a sandboxID.
- sandboxID string
- macAddress net.HardwareAddr
- epOption *endpointOption // User specified parameters
- epConnectivity *EndpointConnectivity // User specified parameters
- portMapping []types.PortBinding // Operation port bindings
- addr *net.IPNet
- gateway net.IP
- dbIndex uint64
- dbExists bool
- }
- type hnsNetwork struct {
- id string
- created bool
- config *networkConfiguration
- endpoints map[string]*hnsEndpoint // key: endpoint id
- driver *driver // The network's driver
- portMapper *portmapper.PortMapper
- sync.Mutex
- }
- type driver struct {
- name string
- networks map[string]*hnsNetwork
- store *datastore.Store
- sync.Mutex
- }
- const (
- errNotFound = "HNS failed with error : The object identifier does not represent a valid object. "
- )
- var builtinLocalDrivers = map[string]struct{}{
- "transparent": {},
- "l2bridge": {},
- "l2tunnel": {},
- "nat": {},
- "internal": {},
- "private": {},
- "ics": {},
- }
- // IsBuiltinLocalDriver validates if network-type is a builtin local-scoped driver
- func IsBuiltinLocalDriver(networkType string) bool {
- _, ok := builtinLocalDrivers[networkType]
- return ok
- }
- // New constructs a new bridge driver
- func newDriver(networkType string) *driver {
- return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
- }
- // GetInit returns an initializer for the given network type
- func RegisterBuiltinLocalDrivers(r driverapi.Registerer, driverConfig func(string) map[string]interface{}) error {
- for networkType := range builtinLocalDrivers {
- d := newDriver(networkType)
- err := d.initStore(driverConfig(networkType))
- if err != nil {
- return fmt.Errorf("failed to initialize %q driver: %w", networkType, err)
- }
- err = r.RegisterDriver(networkType, d, driverapi.Capability{
- DataScope: scope.Local,
- ConnectivityScope: scope.Local,
- })
- if err != nil {
- return fmt.Errorf("failed to register %q driver: %w", networkType, err)
- }
- }
- return nil
- }
- func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
- d.Lock()
- defer d.Unlock()
- if nw, ok := d.networks[id]; ok {
- return nw, nil
- }
- return nil, types.NotFoundErrorf("network not found: %s", id)
- }
- func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
- n.Lock()
- defer n.Unlock()
- if ep, ok := n.endpoints[eid]; ok {
- return ep, nil
- }
- return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
- }
- func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
- config := &networkConfiguration{Type: d.name}
- for label, value := range genericOptions {
- switch label {
- case NetworkName:
- config.Name = value
- case HNSID:
- config.HnsID = value
- case RoutingDomain:
- config.RDID = value
- case Interface:
- config.NetworkAdapterName = value
- case DNSSuffix:
- config.DNSSuffix = value
- case DNSServers:
- config.DNSServers = value
- case DisableGatewayDNS:
- b, err := strconv.ParseBool(value)
- if err != nil {
- return nil, err
- }
- config.DisableGatewayDNS = b
- case MacPool:
- config.MacPools = make([]hcsshim.MacPool, 0)
- s := strings.Split(value, ",")
- if len(s)%2 != 0 {
- return nil, types.InvalidParameterErrorf("invalid mac pool. You must specify both a start range and an end range")
- }
- for i := 0; i < len(s)-1; i += 2 {
- config.MacPools = append(config.MacPools, hcsshim.MacPool{
- StartMacAddress: s[i],
- EndMacAddress: s[i+1],
- })
- }
- case VLAN:
- vlan, err := strconv.ParseUint(value, 10, 32)
- if err != nil {
- return nil, err
- }
- config.VLAN = uint(vlan)
- case VSID:
- vsid, err := strconv.ParseUint(value, 10, 32)
- if err != nil {
- return nil, err
- }
- config.VSID = uint(vsid)
- case EnableOutboundNat:
- b, err := strconv.ParseBool(value)
- if err != nil {
- return nil, err
- }
- config.EnableOutboundNat = b
- case OutboundNatExceptions:
- s := strings.Split(value, ",")
- config.OutboundNatExceptions = s
- }
- }
- config.ID = id
- config.Type = d.name
- return config, nil
- }
- func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
- if len(ipamV6Data) > 0 {
- return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
- }
- if len(ipamV4Data) == 0 {
- return types.InvalidParameterErrorf("network %s requires ipv4 configuration", id)
- }
- return nil
- }
- func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
- }
- func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
- return "", nil
- }
- func (d *driver) createNetwork(config *networkConfiguration) *hnsNetwork {
- network := &hnsNetwork{
- id: config.ID,
- endpoints: make(map[string]*hnsEndpoint),
- config: config,
- driver: d,
- portMapper: portmapper.New(),
- }
- d.Lock()
- d.networks[config.ID] = network
- d.Unlock()
- return network
- }
- // Create a new network
- func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
- if _, err := d.getNetwork(id); err == nil {
- return types.ForbiddenErrorf("network %s exists", id)
- }
- genData, ok := option[netlabel.GenericData].(map[string]string)
- if !ok {
- return fmt.Errorf("Unknown generic data option")
- }
- // Parse and validate the config. It should not conflict with existing networks' config
- config, err := d.parseNetworkOptions(id, genData)
- if err != nil {
- return err
- }
- err = config.processIPAM(id, ipV4Data, ipV6Data)
- if err != nil {
- return err
- }
- n := d.createNetwork(config)
- // A non blank hnsid indicates that the network was discovered
- // from HNS. No need to call HNS if this network was discovered
- // from HNS
- if config.HnsID == "" {
- subnets := []hcsshim.Subnet{}
- for _, ipData := range ipV4Data {
- subnet := hcsshim.Subnet{
- AddressPrefix: ipData.Pool.String(),
- }
- if ipData.Gateway != nil {
- subnet.GatewayAddress = ipData.Gateway.IP.String()
- }
- subnets = append(subnets, subnet)
- }
- network := &hcsshim.HNSNetwork{
- Name: config.Name,
- Type: d.name,
- Subnets: subnets,
- DNSServerList: config.DNSServers,
- DNSSuffix: config.DNSSuffix,
- MacPools: config.MacPools,
- SourceMac: config.SourceMac,
- NetworkAdapterName: config.NetworkAdapterName,
- }
- if config.VLAN != 0 {
- vlanPolicy, err := json.Marshal(hcsshim.VlanPolicy{
- Type: "VLAN",
- VLAN: config.VLAN,
- })
- if err != nil {
- return err
- }
- network.Policies = append(network.Policies, vlanPolicy)
- }
- if config.VSID != 0 {
- vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
- Type: "VSID",
- VSID: config.VSID,
- })
- if err != nil {
- return err
- }
- network.Policies = append(network.Policies, vsidPolicy)
- }
- if network.Name == "" {
- network.Name = id
- }
- configurationb, err := json.Marshal(network)
- if err != nil {
- return err
- }
- configuration := string(configurationb)
- log.G(context.TODO()).Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
- hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
- if err != nil {
- return err
- }
- config.HnsID = hnsresponse.Id
- genData[HNSID] = config.HnsID
- n.created = true
- defer func() {
- if err != nil {
- d.DeleteNetwork(n.id)
- }
- }()
- hnsIPv4Data := make([]driverapi.IPAMData, len(hnsresponse.Subnets))
- for i, subnet := range hnsresponse.Subnets {
- var gwIP, subnetIP *net.IPNet
- // The gateway returned from HNS is an IPAddress.
- // We need to convert it to an IPNet to use as the Gateway of driverapi.IPAMData struct
- gwCIDR := subnet.GatewayAddress + "/32"
- _, gwIP, err = net.ParseCIDR(gwCIDR)
- if err != nil {
- return err
- }
- hnsIPv4Data[i].Gateway = gwIP
- _, subnetIP, err = net.ParseCIDR(subnet.AddressPrefix)
- if err != nil {
- return err
- }
- hnsIPv4Data[i].Pool = subnetIP
- }
- nInfo.UpdateIpamConfig(hnsIPv4Data)
- } else {
- // Delete any stale HNS endpoints for this network.
- if endpoints, err := hcsshim.HNSListEndpointRequest(); err == nil {
- for _, ep := range endpoints {
- if ep.VirtualNetwork == config.HnsID {
- log.G(context.TODO()).Infof("Removing stale HNS endpoint %s", ep.Id)
- _, err = hcsshim.HNSEndpointRequest("DELETE", ep.Id, "")
- if err != nil {
- log.G(context.TODO()).Warnf("Error removing HNS endpoint %s", ep.Id)
- }
- }
- }
- } else {
- log.G(context.TODO()).Warnf("Error listing HNS endpoints for network %s", config.HnsID)
- }
- n.created = true
- }
- return d.storeUpdate(config)
- }
- func (d *driver) DeleteNetwork(nid string) error {
- n, err := d.getNetwork(nid)
- if err != nil {
- return types.InternalMaskableErrorf("%s", err)
- }
- n.Lock()
- config := n.config
- n.Unlock()
- if n.created {
- _, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
- if err != nil && err.Error() != errNotFound {
- return types.ForbiddenErrorf(err.Error())
- }
- }
- d.Lock()
- delete(d.networks, nid)
- d.Unlock()
- // delele endpoints belong to this network
- for _, ep := range n.endpoints {
- if err := d.storeDelete(ep); err != nil {
- log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
- }
- }
- return d.storeDelete(config)
- }
- func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error) {
- var qps []json.RawMessage
- // Enumerate through the qos policies specified by the user and convert
- // them into the internal structure matching the JSON blob that can be
- // understood by the HCS.
- for _, elem := range qosPolicies {
- encodedPolicy, err := json.Marshal(hcsshim.QosPolicy{
- Type: "QOS",
- MaximumOutgoingBandwidthInBytes: elem.MaxEgressBandwidth,
- })
- if err != nil {
- return nil, err
- }
- qps = append(qps, encodedPolicy)
- }
- return qps, nil
- }
- // ConvertPortBindings converts PortBindings to JSON for HNS request
- func ConvertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
- var pbs []json.RawMessage
- // Enumerate through the port bindings specified by the user and convert
- // them into the internal structure matching the JSON blob that can be
- // understood by the HCS.
- for _, elem := range portBindings {
- proto := strings.ToUpper(elem.Proto.String())
- if proto != "TCP" && proto != "UDP" {
- return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
- }
- if elem.HostPort != elem.HostPortEnd {
- return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
- }
- if len(elem.HostIP) != 0 && !elem.HostIP.IsUnspecified() {
- return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
- }
- encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
- Type: "NAT",
- ExternalPort: elem.HostPort,
- InternalPort: elem.Port,
- Protocol: elem.Proto.String(),
- ExternalPortReserved: true,
- })
- if err != nil {
- return nil, err
- }
- pbs = append(pbs, encodedPolicy)
- }
- return pbs, nil
- }
- // ParsePortBindingPolicies parses HNS endpoint response message to PortBindings
- func ParsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
- var bindings []types.PortBinding
- hcsPolicy := &hcsshim.NatPolicy{}
- for _, elem := range policies {
- if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
- continue
- }
- binding := types.PortBinding{
- HostPort: hcsPolicy.ExternalPort,
- HostPortEnd: hcsPolicy.ExternalPort,
- Port: hcsPolicy.InternalPort,
- Proto: types.ParseProtocol(hcsPolicy.Protocol),
- HostIP: net.IPv4(0, 0, 0, 0),
- }
- bindings = append(bindings, binding)
- }
- return bindings, nil
- }
- func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
- if epOptions == nil {
- return nil, nil
- }
- ec := &endpointOption{}
- if opt, ok := epOptions[netlabel.MacAddress]; ok {
- if mac, ok := opt.(net.HardwareAddr); ok {
- ec.MacAddress = mac
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- if opt, ok := epOptions[QosPolicies]; ok {
- if policies, ok := opt.([]types.QosPolicy); ok {
- ec.QosPolicies = policies
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- if opt, ok := epOptions[netlabel.DNSServers]; ok {
- if dns, ok := opt.([]string); ok {
- ec.DNSServers = dns
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- if opt, ok := epOptions[DisableICC]; ok {
- if disableICC, ok := opt.(bool); ok {
- ec.DisableICC = disableICC
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- if opt, ok := epOptions[DisableDNS]; ok {
- if disableDNS, ok := opt.(bool); ok {
- ec.DisableDNS = disableDNS
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- return ec, nil
- }
- // ParseEndpointConnectivity parses options passed to CreateEndpoint, specifically port bindings, and store in a endpointConnectivity object.
- func ParseEndpointConnectivity(epOptions map[string]interface{}) (*EndpointConnectivity, error) {
- if epOptions == nil {
- return nil, nil
- }
- ec := &EndpointConnectivity{}
- if opt, ok := epOptions[netlabel.PortMap]; ok {
- if bs, ok := opt.([]types.PortBinding); ok {
- ec.PortBindings = bs
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
- if ports, ok := opt.([]types.TransportPort); ok {
- ec.ExposedPorts = ports
- } else {
- return nil, fmt.Errorf("Invalid endpoint configuration")
- }
- }
- return ec, nil
- }
- func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
- n, err := d.getNetwork(nid)
- if err != nil {
- return err
- }
- // Check if endpoint id is good and retrieve corresponding endpoint
- ep, err := n.getEndpoint(eid)
- if err == nil && ep != nil {
- return driverapi.ErrEndpointExists(eid)
- }
- endpointStruct := &hcsshim.HNSEndpoint{
- VirtualNetwork: n.config.HnsID,
- }
- epOption, err := parseEndpointOptions(epOptions)
- if err != nil {
- return err
- }
- epConnectivity, err := ParseEndpointConnectivity(epOptions)
- if err != nil {
- return err
- }
- macAddress := ifInfo.MacAddress()
- // Use the macaddress if it was provided
- if macAddress != nil {
- endpointStruct.MacAddress = strings.ReplaceAll(macAddress.String(), ":", "-")
- }
- portMapping := epConnectivity.PortBindings
- if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
- ip := net.IPv4(0, 0, 0, 0)
- if ifInfo.Address() != nil {
- ip = ifInfo.Address().IP
- }
- portMapping, err = AllocatePorts(n.portMapper, portMapping, ip)
- if err != nil {
- return err
- }
- defer func() {
- if err != nil {
- ReleasePorts(n.portMapper, portMapping)
- }
- }()
- }
- endpointStruct.Policies, err = ConvertPortBindings(portMapping)
- if err != nil {
- return err
- }
- qosPolicies, err := convertQosPolicies(epOption.QosPolicies)
- if err != nil {
- return err
- }
- endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...)
- if ifInfo.Address() != nil {
- endpointStruct.IPAddress = ifInfo.Address().IP
- }
- endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
- // overwrite the ep DisableDNS option if DisableGatewayDNS was set to true during the network creation option
- if n.config.DisableGatewayDNS {
- log.G(context.TODO()).Debugf("n.config.DisableGatewayDNS[%v] overwrites epOption.DisableDNS[%v]", n.config.DisableGatewayDNS, epOption.DisableDNS)
- epOption.DisableDNS = n.config.DisableGatewayDNS
- }
- if n.driver.name == "nat" && !epOption.DisableDNS {
- endpointStruct.EnableInternalDNS = true
- log.G(context.TODO()).Debugf("endpointStruct.EnableInternalDNS =[%v]", endpointStruct.EnableInternalDNS)
- }
- endpointStruct.DisableICC = epOption.DisableICC
- // Inherit OutboundNat policy from the network
- if n.config.EnableOutboundNat {
- outboundNatPolicy, err := json.Marshal(hcsshim.OutboundNatPolicy{
- Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
- Exceptions: n.config.OutboundNatExceptions,
- })
- if err != nil {
- return err
- }
- endpointStruct.Policies = append(endpointStruct.Policies, outboundNatPolicy)
- }
- configurationb, err := json.Marshal(endpointStruct)
- if err != nil {
- return err
- }
- hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
- if err != nil {
- return err
- }
- mac, err := net.ParseMAC(hnsresponse.MacAddress)
- if err != nil {
- return err
- }
- // TODO For now the ip mask is not in the info generated by HNS
- endpoint := &hnsEndpoint{
- id: eid,
- nid: n.id,
- Type: d.name,
- addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
- macAddress: mac,
- }
- if hnsresponse.GatewayAddress != "" {
- endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress)
- }
- endpoint.profileID = hnsresponse.Id
- endpoint.epConnectivity = epConnectivity
- endpoint.epOption = epOption
- endpoint.portMapping, err = ParsePortBindingPolicies(hnsresponse.Policies)
- if err != nil {
- hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
- return err
- }
- n.Lock()
- n.endpoints[eid] = endpoint
- n.Unlock()
- if ifInfo.Address() == nil {
- ifInfo.SetIPAddress(endpoint.addr)
- }
- if macAddress == nil {
- ifInfo.SetMacAddress(endpoint.macAddress)
- }
- if err = d.storeUpdate(endpoint); err != nil {
- log.G(context.TODO()).Errorf("Failed to save endpoint %.7s to store: %v", endpoint.id, err)
- }
- return nil
- }
- func (d *driver) DeleteEndpoint(nid, eid string) error {
- n, err := d.getNetwork(nid)
- if err != nil {
- return types.InternalMaskableErrorf("%s", err)
- }
- ep, err := n.getEndpoint(eid)
- if err != nil {
- return err
- }
- if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
- ReleasePorts(n.portMapper, ep.portMapping)
- }
- n.Lock()
- delete(n.endpoints, eid)
- n.Unlock()
- _, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
- if err != nil && err.Error() != errNotFound {
- return err
- }
- if err := d.storeDelete(ep); err != nil {
- log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
- }
- return nil
- }
- func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
- network, err := d.getNetwork(nid)
- if err != nil {
- return nil, err
- }
- ep, err := network.getEndpoint(eid)
- if err != nil {
- return nil, err
- }
- data := make(map[string]interface{}, 1)
- if network.driver.name == "nat" {
- data["AllowUnqualifiedDNSQuery"] = true
- }
- data["hnsid"] = ep.profileID
- if ep.epConnectivity.ExposedPorts != nil {
- // Return a copy of the config data
- epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts))
- for _, tp := range ep.epConnectivity.ExposedPorts {
- epc = append(epc, tp.GetCopy())
- }
- data[netlabel.ExposedPorts] = epc
- }
- if ep.portMapping != nil {
- // Return a copy of the operational data
- pmc := make([]types.PortBinding, 0, len(ep.portMapping))
- for _, pm := range ep.portMapping {
- pmc = append(pmc, pm.GetCopy())
- }
- data[netlabel.PortMap] = pmc
- }
- if len(ep.macAddress) != 0 {
- data[netlabel.MacAddress] = ep.macAddress
- }
- return data, nil
- }
- // Join method is invoked when a Sandbox is attached to an endpoint.
- func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
- network, err := d.getNetwork(nid)
- if err != nil {
- return err
- }
- // Ensure that the endpoint exists
- endpoint, err := network.getEndpoint(eid)
- if err != nil {
- return err
- }
- err = jinfo.SetGateway(endpoint.gateway)
- if err != nil {
- return err
- }
- endpoint.sandboxID = sboxKey
- err = hcsshim.HotAttachEndpoint(endpoint.sandboxID, endpoint.profileID)
- if err != nil {
- // If container doesn't exists in hcs, do not throw error for hot add/remove
- if err != hcsshim.ErrComputeSystemDoesNotExist {
- return err
- }
- }
- jinfo.DisableGatewayService()
- return nil
- }
- // Leave method is invoked when a Sandbox detaches from an endpoint.
- func (d *driver) Leave(nid, eid string) error {
- network, err := d.getNetwork(nid)
- if err != nil {
- return types.InternalMaskableErrorf("%s", err)
- }
- // Ensure that the endpoint exists
- endpoint, err := network.getEndpoint(eid)
- if err != nil {
- return err
- }
- err = hcsshim.HotDetachEndpoint(endpoint.sandboxID, endpoint.profileID)
- if err != nil {
- // If container doesn't exists in hcs, do not throw error for hot add/remove
- if err != hcsshim.ErrComputeSystemDoesNotExist {
- return err
- }
- }
- return nil
- }
- func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
- return nil
- }
- func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
- return nil
- }
- func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
- return nil, types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) NetworkFree(id string) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) Type() string {
- return d.name
- }
- func (d *driver) IsBuiltIn() bool {
- return true
- }
|