libnetwork/service_windows.go
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() {
}