dotcloud/docker

View on GitHub
libnetwork/service_windows.go

Summary

Maintainability
B
4 hrs
Test Coverage
package libnetwork

import (
    "context"
    "net"

    "github.com/Microsoft/hcsshim"
    "github.com/containerd/log"
)

type policyLists struct {
    ilb *hcsshim.PolicyList
    elb *hcsshim.PolicyList
}

var lbPolicylistMap = make(map[*loadBalancer]*policyLists)

func (n *Network) addLBBackend(ip net.IP, lb *loadBalancer) {
    if len(lb.vip) == 0 {
        return
    }

    vip := lb.vip
    ingressPorts := lb.service.ingressPorts

    lb.Lock()
    defer lb.Unlock()
    // find the load balancer IP for the network.
    var sourceVIP string
    for _, e := range n.Endpoints() {
        epInfo := e.Info()
        if epInfo == nil {
            continue
        }
        if epInfo.LoadBalancer() {
            sourceVIP = epInfo.Iface().Address().IP.String()
            break
        }
    }

    if sourceVIP == "" {
        log.G(context.TODO()).Errorf("Failed to find load balancer IP for network %s", n.Name())
        return
    }

    var endpoints []hcsshim.HNSEndpoint

    for eid, be := range lb.backEnds {
        if be.disabled {
            continue
        }
        // Call HNS to get back ID (GUID) corresponding to the endpoint.
        hnsEndpoint, err := hcsshim.GetHNSEndpointByName(eid)
        if err != nil {
            log.G(context.TODO()).Errorf("Failed to find HNS ID for endpoint %v: %v", eid, err)
            return
        }

        endpoints = append(endpoints, *hnsEndpoint)
    }

    if policies, ok := lbPolicylistMap[lb]; ok {

        if policies.ilb != nil {
            policies.ilb.Delete()
            policies.ilb = nil
        }

        if policies.elb != nil {
            policies.elb.Delete()
            policies.elb = nil
        }
        delete(lbPolicylistMap, lb)
    }

    ilbPolicy, err := hcsshim.AddLoadBalancer(endpoints, true, sourceVIP, vip.String(), 0, 0, 0)
    if err != nil {
        log.G(context.TODO()).Errorf("Failed to add ILB policy for service %s (%s) with endpoints %v using load balancer IP %s on network %s: %v",
            lb.service.name, vip.String(), endpoints, sourceVIP, n.Name(), err)
        return
    }

    lbPolicylistMap[lb] = &policyLists{
        ilb: ilbPolicy,
    }

    publishedPorts := make(map[uint32]uint32)

    for i, port := range ingressPorts {
        protocol := uint16(6)

        // Skip already published port
        if publishedPorts[port.PublishedPort] == port.TargetPort {
            continue
        }

        if port.Protocol == ProtocolUDP {
            protocol = 17
        }

        // check if already has udp matching to add wild card publishing
        for j := i + 1; j < len(ingressPorts); j++ {
            if ingressPorts[j].TargetPort == port.TargetPort &&
                ingressPorts[j].PublishedPort == port.PublishedPort {
                protocol = 0
            }
        }

        publishedPorts[port.PublishedPort] = port.TargetPort

        lbPolicylistMap[lb].elb, err = hcsshim.AddLoadBalancer(endpoints, false, sourceVIP, "", protocol, uint16(port.TargetPort), uint16(port.PublishedPort))
        if err != nil {
            log.G(context.TODO()).Errorf("Failed to add ELB policy for service %s (ip:%s target port:%v published port:%v) with endpoints %v using load balancer IP %s on network %s: %v",
                lb.service.name, vip.String(), uint16(port.TargetPort), uint16(port.PublishedPort), endpoints, sourceVIP, n.Name(), err)
            return
        }
    }
}

func (n *Network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullRemove bool) {
    if len(lb.vip) == 0 {
        return
    }

    if numEnabledBackends(lb) > 0 {
        // Reprogram HNS (actually VFP) with the existing backends.
        n.addLBBackend(ip, lb)
    } else {
        lb.Lock()
        defer lb.Unlock()
        log.G(context.TODO()).Debugf("No more backends for service %s (ip:%s).  Removing all policies", lb.service.name, lb.vip.String())

        if policyLists, ok := lbPolicylistMap[lb]; ok {
            if policyLists.ilb != nil {
                if _, err := policyLists.ilb.Delete(); err != nil {
                    log.G(context.TODO()).Errorf("Failed to remove HNS ILB policylist %s: %s", policyLists.ilb.ID, err)
                }
                policyLists.ilb = nil
            }

            if policyLists.elb != nil {
                if _, err := policyLists.elb.Delete(); err != nil {
                    log.G(context.TODO()).Errorf("Failed to remove HNS ELB policylist %s: %s", policyLists.elb.ID, err)
                }
                policyLists.elb = nil
            }
            delete(lbPolicylistMap, lb)

        } else {
            log.G(context.TODO()).Errorf("Failed to find policies for service %s (%s)", lb.service.name, lb.vip.String())
        }
    }
}

func numEnabledBackends(lb *loadBalancer) int {
    nEnabled := 0
    for _, be := range lb.backEnds {
        if !be.disabled {
            nEnabled++
        }
    }
    return nEnabled
}

func (sb *Sandbox) populateLoadBalancers(ep *Endpoint) {
}

func arrangeIngressFilterRule() {
}