Fixes in the Service Discovery areas
Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
| ... | ... |
@@ -26,7 +26,7 @@ github.com/imdario/mergo 0.2.1 |
| 26 | 26 |
golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 |
| 27 | 27 |
|
| 28 | 28 |
#get libnetwork packages |
| 29 |
-github.com/docker/libnetwork f4a15a0890383619ad797b3bd2481cc6f46a978d |
|
| 29 |
+github.com/docker/libnetwork 6426d1e66f33c0b0c8bb135b7ee547447f54d043 |
|
| 30 | 30 |
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 31 | 31 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 32 | 32 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -165,13 +165,13 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
| 165 | 165 |
a.networkDB.SetKey(added) |
| 166 | 166 |
} |
| 167 | 167 |
|
| 168 |
- key, tag, err := c.getPrimaryKeyTag(subsysGossip) |
|
| 168 |
+ key, _, err := c.getPrimaryKeyTag(subsysGossip) |
|
| 169 | 169 |
if err != nil {
|
| 170 | 170 |
return err |
| 171 | 171 |
} |
| 172 | 172 |
a.networkDB.SetPrimaryKey(key) |
| 173 | 173 |
|
| 174 |
- key, tag, err = c.getPrimaryKeyTag(subsysIPSec) |
|
| 174 |
+ key, tag, err := c.getPrimaryKeyTag(subsysIPSec) |
|
| 175 | 175 |
if err != nil {
|
| 176 | 176 |
return err |
| 177 | 177 |
} |
| ... | ... |
@@ -648,13 +648,13 @@ func (ep *endpoint) addServiceInfoToCluster(sb *sandbox) error {
|
| 648 | 648 |
TaskAliases: ep.myAliases, |
| 649 | 649 |
EndpointIP: ep.Iface().Address().IP.String(), |
| 650 | 650 |
}) |
| 651 |
- |
|
| 652 | 651 |
if err != nil {
|
| 653 | 652 |
return err |
| 654 | 653 |
} |
| 655 | 654 |
|
| 656 | 655 |
if agent != nil {
|
| 657 | 656 |
if err := agent.networkDB.CreateEntry(libnetworkEPTable, n.ID(), ep.ID(), buf); err != nil {
|
| 657 |
+ logrus.Warnf("addServiceInfoToCluster NetworkDB CreateEntry failed for %s %s err:%s", ep.id, n.id, err)
|
|
| 658 | 658 |
return err |
| 659 | 659 |
} |
| 660 | 660 |
} |
| ... | ... |
@@ -686,6 +686,13 @@ func (ep *endpoint) deleteServiceInfoFromCluster(sb *sandbox, method string) err |
| 686 | 686 |
name = ep.MyAliases()[0] |
| 687 | 687 |
} |
| 688 | 688 |
|
| 689 |
+ if agent != nil {
|
|
| 690 |
+ // First delete from networkDB then locally |
|
| 691 |
+ if err := agent.networkDB.DeleteEntry(libnetworkEPTable, n.ID(), ep.ID()); err != nil {
|
|
| 692 |
+ logrus.Warnf("deleteServiceInfoFromCluster NetworkDB DeleteEntry failed for %s %s err:%s", ep.id, n.id, err)
|
|
| 693 |
+ } |
|
| 694 |
+ } |
|
| 695 |
+ |
|
| 689 | 696 |
if ep.Iface().Address() != nil {
|
| 690 | 697 |
if ep.svcID != "" {
|
| 691 | 698 |
// This is a task part of a service |
| ... | ... |
@@ -693,7 +700,7 @@ func (ep *endpoint) deleteServiceInfoFromCluster(sb *sandbox, method string) err |
| 693 | 693 |
if n.ingress {
|
| 694 | 694 |
ingressPorts = ep.ingressPorts |
| 695 | 695 |
} |
| 696 |
- if err := c.rmServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster"); err != nil {
|
|
| 696 |
+ if err := c.rmServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster", true); err != nil {
|
|
| 697 | 697 |
return err |
| 698 | 698 |
} |
| 699 | 699 |
} else {
|
| ... | ... |
@@ -704,12 +711,6 @@ func (ep *endpoint) deleteServiceInfoFromCluster(sb *sandbox, method string) err |
| 704 | 704 |
} |
| 705 | 705 |
} |
| 706 | 706 |
|
| 707 |
- if agent != nil {
|
|
| 708 |
- if err := agent.networkDB.DeleteEntry(libnetworkEPTable, n.ID(), ep.ID()); err != nil {
|
|
| 709 |
- return err |
|
| 710 |
- } |
|
| 711 |
- } |
|
| 712 |
- |
|
| 713 | 707 |
logrus.Debugf("deleteServiceInfoFromCluster from %s END for %s %s", method, ep.svcName, ep.ID())
|
| 714 | 708 |
|
| 715 | 709 |
return nil |
| ... | ... |
@@ -883,7 +884,7 @@ func (c *controller) handleEpTableEvent(ev events.Event) {
|
| 883 | 883 |
} |
| 884 | 884 |
|
| 885 | 885 |
if isAdd {
|
| 886 |
- logrus.Debugf("handleEpTableEvent ADD %s R:%v", isAdd, eid, epRec)
|
|
| 886 |
+ logrus.Debugf("handleEpTableEvent ADD %s R:%v", eid, epRec)
|
|
| 887 | 887 |
if svcID != "" {
|
| 888 | 888 |
// This is a remote task part of a service |
| 889 | 889 |
if err := c.addServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent"); err != nil {
|
| ... | ... |
@@ -897,10 +898,10 @@ func (c *controller) handleEpTableEvent(ev events.Event) {
|
| 897 | 897 |
} |
| 898 | 898 |
} |
| 899 | 899 |
} else {
|
| 900 |
- logrus.Debugf("handleEpTableEvent DEL %s R:%v", isAdd, eid, epRec)
|
|
| 900 |
+ logrus.Debugf("handleEpTableEvent DEL %s R:%v", eid, epRec)
|
|
| 901 | 901 |
if svcID != "" {
|
| 902 | 902 |
// This is a remote task part of a service |
| 903 |
- if err := c.rmServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent"); err != nil {
|
|
| 903 |
+ if err := c.rmServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent", true); err != nil {
|
|
| 904 | 904 |
logrus.Errorf("failed removing service binding for %s epRec:%v err:%s", eid, epRec, err)
|
| 905 | 905 |
return |
| 906 | 906 |
} |
| ... | ... |
@@ -10,24 +10,26 @@ import ( |
| 10 | 10 |
type SetMatrix interface {
|
| 11 | 11 |
// Get returns the members of the set for a specific key as a slice. |
| 12 | 12 |
Get(key string) ([]interface{}, bool)
|
| 13 |
- // Contains is used to verify is an element is in a set for a specific key |
|
| 13 |
+ // Contains is used to verify if an element is in a set for a specific key |
|
| 14 | 14 |
// returns true if the element is in the set |
| 15 | 15 |
// returns true if there is a set for the key |
| 16 | 16 |
Contains(key string, value interface{}) (bool, bool)
|
| 17 |
- // Insert inserts the mapping between the IP and the endpoint identifier |
|
| 18 |
- // returns true if the mapping was not present, false otherwise |
|
| 19 |
- // returns also the number of endpoints associated to the IP |
|
| 17 |
+ // Insert inserts the value in the set of a key |
|
| 18 |
+ // returns true if the value is inserted (was not already in the set), false otherwise |
|
| 19 |
+ // returns also the length of the set for the key |
|
| 20 | 20 |
Insert(key string, value interface{}) (bool, int)
|
| 21 |
- // Remove removes the mapping between the IP and the endpoint identifier |
|
| 22 |
- // returns true if the mapping was deleted, false otherwise |
|
| 23 |
- // returns also the number of endpoints associated to the IP |
|
| 21 |
+ // Remove removes the value in the set for a specific key |
|
| 22 |
+ // returns true if the value is deleted, false otherwise |
|
| 23 |
+ // returns also the length of the set for the key |
|
| 24 | 24 |
Remove(key string, value interface{}) (bool, int)
|
| 25 |
- // Cardinality returns the number of elements in the set of a specfic key |
|
| 26 |
- // returns false if the key is not in the map |
|
| 25 |
+ // Cardinality returns the number of elements in the set for a key |
|
| 26 |
+ // returns false if the set is not present |
|
| 27 | 27 |
Cardinality(key string) (int, bool) |
| 28 | 28 |
// String returns the string version of the set, empty otherwise |
| 29 |
- // returns false if the key is not in the map |
|
| 29 |
+ // returns false if the set is not present |
|
| 30 | 30 |
String(key string) (string, bool) |
| 31 |
+ // Returns all the keys in the map |
|
| 32 |
+ Keys() []string |
|
| 31 | 33 |
} |
| 32 | 34 |
|
| 33 | 35 |
type setMatrix struct {
|
| ... | ... |
@@ -121,3 +123,13 @@ func (s *setMatrix) String(key string) (string, bool) {
|
| 121 | 121 |
} |
| 122 | 122 |
return set.String(), ok |
| 123 | 123 |
} |
| 124 |
+ |
|
| 125 |
+func (s *setMatrix) Keys() []string {
|
|
| 126 |
+ s.Lock() |
|
| 127 |
+ defer s.Unlock() |
|
| 128 |
+ keys := make([]string, 0, len(s.matrix)) |
|
| 129 |
+ for k := range s.matrix {
|
|
| 130 |
+ keys = append(keys, k) |
|
| 131 |
+ } |
|
| 132 |
+ return keys |
|
| 133 |
+} |
| ... | ... |
@@ -1014,7 +1014,7 @@ func (c *controller) NetworkByID(id string) (Network, error) {
|
| 1014 | 1014 |
} |
| 1015 | 1015 |
|
| 1016 | 1016 |
// NewSandbox creates a new sandbox for the passed container id |
| 1017 |
-func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (sBox Sandbox, err error) {
|
|
| 1017 |
+func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (Sandbox, error) {
|
|
| 1018 | 1018 |
if containerID == "" {
|
| 1019 | 1019 |
return nil, types.BadRequestErrorf("invalid container ID")
|
| 1020 | 1020 |
} |
| ... | ... |
@@ -1054,7 +1054,6 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s |
| 1054 | 1054 |
extDNS: []extDNSEntry{},
|
| 1055 | 1055 |
} |
| 1056 | 1056 |
} |
| 1057 |
- sBox = sb |
|
| 1058 | 1057 |
|
| 1059 | 1058 |
heap.Init(&sb.endpoints) |
| 1060 | 1059 |
|
| ... | ... |
@@ -1073,6 +1072,8 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s |
| 1073 | 1073 |
sb.id = "ingress_sbox" |
| 1074 | 1074 |
} |
| 1075 | 1075 |
c.Unlock() |
| 1076 |
+ |
|
| 1077 |
+ var err error |
|
| 1076 | 1078 |
defer func() {
|
| 1077 | 1079 |
if err != nil {
|
| 1078 | 1080 |
c.Lock() |
| ... | ... |
@@ -670,7 +670,7 @@ func (n *network) initSandbox(restore bool) error {
|
| 670 | 670 |
// In the restore case network sandbox already exist; but we don't know |
| 671 | 671 |
// what epoch number it was created with. It has to be retrieved by |
| 672 | 672 |
// searching the net namespaces. |
| 673 |
- key := "" |
|
| 673 |
+ var key string |
|
| 674 | 674 |
if restore {
|
| 675 | 675 |
key = osl.GenerateKey("-" + n.id)
|
| 676 | 676 |
} else {
|
| ... | ... |
@@ -872,15 +872,10 @@ func (n *network) Value() []byte {
|
| 872 | 872 |
netJSON = append(netJSON, sj) |
| 873 | 873 |
} |
| 874 | 874 |
|
| 875 |
- b, err := json.Marshal(netJSON) |
|
| 876 |
- if err != nil {
|
|
| 877 |
- return []byte{}
|
|
| 878 |
- } |
|
| 879 |
- |
|
| 880 | 875 |
m["secure"] = n.secure |
| 881 | 876 |
m["subnets"] = netJSON |
| 882 | 877 |
m["mtu"] = n.mtu |
| 883 |
- b, err = json.Marshal(m) |
|
| 878 |
+ b, err := json.Marshal(m) |
|
| 884 | 879 |
if err != nil {
|
| 885 | 880 |
return []byte{}
|
| 886 | 881 |
} |
| ... | ... |
@@ -457,7 +457,7 @@ func (n *network) initSandbox(restore bool) error {
|
| 457 | 457 |
// In the restore case network sandbox already exist; but we don't know |
| 458 | 458 |
// what epoch number it was created with. It has to be retrieved by |
| 459 | 459 |
// searching the net namespaces. |
| 460 |
- key := "" |
|
| 460 |
+ var key string |
|
| 461 | 461 |
if restore {
|
| 462 | 462 |
key = osl.GenerateKey("-" + n.id)
|
| 463 | 463 |
} else {
|
| ... | ... |
@@ -570,15 +570,10 @@ func (n *network) Value() []byte {
|
| 570 | 570 |
netJSON = append(netJSON, sj) |
| 571 | 571 |
} |
| 572 | 572 |
|
| 573 |
- b, err := json.Marshal(netJSON) |
|
| 574 |
- if err != nil {
|
|
| 575 |
- return []byte{}
|
|
| 576 |
- } |
|
| 577 |
- |
|
| 578 | 573 |
m["secure"] = n.secure |
| 579 | 574 |
m["subnets"] = netJSON |
| 580 | 575 |
m["mtu"] = n.mtu |
| 581 |
- b, err = json.Marshal(m) |
|
| 576 |
+ b, err := json.Marshal(m) |
|
| 582 | 577 |
if err != nil {
|
| 583 | 578 |
return []byte{}
|
| 584 | 579 |
} |
| ... | ... |
@@ -324,6 +324,9 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 324 | 324 |
} |
| 325 | 325 |
|
| 326 | 326 |
n, err := d.getNetwork(id) |
| 327 |
+ if err != nil {
|
|
| 328 |
+ return err |
|
| 329 |
+ } |
|
| 327 | 330 |
n.created = true |
| 328 | 331 |
return d.storeUpdate(config) |
| 329 | 332 |
} |
| ... | ... |
@@ -530,7 +533,13 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 530 | 530 |
} |
| 531 | 531 |
|
| 532 | 532 |
epOption, err := parseEndpointOptions(epOptions) |
| 533 |
+ if err != nil {
|
|
| 534 |
+ return err |
|
| 535 |
+ } |
|
| 533 | 536 |
epConnectivity, err := parseEndpointConnectivity(epOptions) |
| 537 |
+ if err != nil {
|
|
| 538 |
+ return err |
|
| 539 |
+ } |
|
| 534 | 540 |
|
| 535 | 541 |
macAddress := ifInfo.MacAddress() |
| 536 | 542 |
// Use the macaddress if it was provided |
| ... | ... |
@@ -232,9 +232,12 @@ func (ep *hnsEndpoint) MarshalJSON() ([]byte, error) {
|
| 232 | 232 |
epMap["Type"] = ep.Type |
| 233 | 233 |
epMap["profileID"] = ep.profileID |
| 234 | 234 |
epMap["MacAddress"] = ep.macAddress.String() |
| 235 |
- epMap["Addr"] = ep.addr.String() |
|
| 236 |
- epMap["gateway"] = ep.gateway.String() |
|
| 237 |
- |
|
| 235 |
+ if ep.addr.IP != nil {
|
|
| 236 |
+ epMap["Addr"] = ep.addr.String() |
|
| 237 |
+ } |
|
| 238 |
+ if ep.gateway != nil {
|
|
| 239 |
+ epMap["gateway"] = ep.gateway.String() |
|
| 240 |
+ } |
|
| 238 | 241 |
epMap["epOption"] = ep.epOption |
| 239 | 242 |
epMap["epConnectivity"] = ep.epConnectivity |
| 240 | 243 |
epMap["PortMapping"] = ep.portMapping |
| ... | ... |
@@ -251,7 +254,6 @@ func (ep *hnsEndpoint) UnmarshalJSON(b []byte) error {
|
| 251 | 251 |
if err = json.Unmarshal(b, &epMap); err != nil {
|
| 252 | 252 |
return fmt.Errorf("Failed to unmarshal to endpoint: %v", err)
|
| 253 | 253 |
} |
| 254 |
- |
|
| 255 | 254 |
if v, ok := epMap["MacAddress"]; ok {
|
| 256 | 255 |
if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
|
| 257 | 256 |
return types.InternalErrorf("failed to decode endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
| ... | ... |
@@ -262,7 +264,9 @@ func (ep *hnsEndpoint) UnmarshalJSON(b []byte) error {
|
| 262 | 262 |
return types.InternalErrorf("failed to decode endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
| 263 | 263 |
} |
| 264 | 264 |
} |
| 265 |
- |
|
| 265 |
+ if v, ok := epMap["gateway"]; ok {
|
|
| 266 |
+ ep.gateway = net.ParseIP(v.(string)) |
|
| 267 |
+ } |
|
| 266 | 268 |
ep.id = epMap["id"].(string) |
| 267 | 269 |
ep.Type = epMap["Type"].(string) |
| 268 | 270 |
ep.nid = epMap["nid"].(string) |
| ... | ... |
@@ -92,12 +92,20 @@ type EndpointWalker func(ep Endpoint) bool |
| 92 | 92 |
// Its an indication to defer PTR queries also to that external server. |
| 93 | 93 |
type ipInfo struct {
|
| 94 | 94 |
name string |
| 95 |
+ serviceID string |
|
| 95 | 96 |
extResolver bool |
| 96 | 97 |
} |
| 97 | 98 |
|
| 99 |
+// svcMapEntry is the body of the element into the svcMap |
|
| 100 |
+// The ip is a string because the SetMatrix does not accept non hashable values |
|
| 101 |
+type svcMapEntry struct {
|
|
| 102 |
+ ip string |
|
| 103 |
+ serviceID string |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 98 | 106 |
type svcInfo struct {
|
| 99 |
- svcMap map[string][]net.IP |
|
| 100 |
- svcIPv6Map map[string][]net.IP |
|
| 107 |
+ svcMap common.SetMatrix |
|
| 108 |
+ svcIPv6Map common.SetMatrix |
|
| 101 | 109 |
ipMap common.SetMatrix |
| 102 | 110 |
service map[string][]servicePorts |
| 103 | 111 |
} |
| ... | ... |
@@ -933,6 +941,9 @@ func (n *network) delete(force bool) error {
|
| 933 | 933 |
id := n.id |
| 934 | 934 |
n.Unlock() |
| 935 | 935 |
|
| 936 |
+ c.networkLocker.Lock(id) |
|
| 937 |
+ defer c.networkLocker.Unlock(id) |
|
| 938 |
+ |
|
| 936 | 939 |
n, err := c.getNetworkFromStore(id) |
| 937 | 940 |
if err != nil {
|
| 938 | 941 |
return &UnknownNetworkError{name: name, id: id}
|
| ... | ... |
@@ -991,12 +1002,6 @@ func (n *network) delete(force bool) error {
|
| 991 | 991 |
|
| 992 | 992 |
c.cleanupServiceBindings(n.ID()) |
| 993 | 993 |
|
| 994 |
- // The network had been left, the service discovery can be cleaned up |
|
| 995 |
- c.Lock() |
|
| 996 |
- logrus.Debugf("network %s delete, clean svcRecords", n.id)
|
|
| 997 |
- delete(c.svcRecords, n.id) |
|
| 998 |
- c.Unlock() |
|
| 999 |
- |
|
| 1000 | 994 |
removeFromStore: |
| 1001 | 995 |
// deleteFromStore performs an atomic delete operation and the |
| 1002 | 996 |
// network.epCnt will help prevent any possible |
| ... | ... |
@@ -1070,6 +1075,9 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi |
| 1070 | 1070 |
ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}}
|
| 1071 | 1071 |
ep.id = stringid.GenerateRandomID() |
| 1072 | 1072 |
|
| 1073 |
+ n.ctrlr.networkLocker.Lock(n.id) |
|
| 1074 |
+ defer n.ctrlr.networkLocker.Unlock(n.id) |
|
| 1075 |
+ |
|
| 1073 | 1076 |
// Initialize ep.network with a possibly stale copy of n. We need this to get network from |
| 1074 | 1077 |
// store. But once we get it from store we will have the most uptodate copy possibly. |
| 1075 | 1078 |
ep.network = n |
| ... | ... |
@@ -1228,75 +1236,77 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool |
| 1228 | 1228 |
ipv6 = iface.AddressIPv6().IP |
| 1229 | 1229 |
} |
| 1230 | 1230 |
|
| 1231 |
+ serviceID := ep.svcID |
|
| 1232 |
+ if serviceID == "" {
|
|
| 1233 |
+ serviceID = ep.ID() |
|
| 1234 |
+ } |
|
| 1231 | 1235 |
if isAdd {
|
| 1232 | 1236 |
// If anonymous endpoint has an alias use the first alias |
| 1233 | 1237 |
// for ip->name mapping. Not having the reverse mapping |
| 1234 | 1238 |
// breaks some apps |
| 1235 | 1239 |
if ep.isAnonymous() {
|
| 1236 | 1240 |
if len(myAliases) > 0 {
|
| 1237 |
- n.addSvcRecords(ep.ID(), myAliases[0], iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1241 |
+ n.addSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1238 | 1242 |
} |
| 1239 | 1243 |
} else {
|
| 1240 |
- n.addSvcRecords(ep.ID(), epName, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1244 |
+ n.addSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1241 | 1245 |
} |
| 1242 | 1246 |
for _, alias := range myAliases {
|
| 1243 |
- n.addSvcRecords(ep.ID(), alias, iface.Address().IP, ipv6, false, "updateSvcRecord") |
|
| 1247 |
+ n.addSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") |
|
| 1244 | 1248 |
} |
| 1245 | 1249 |
} else {
|
| 1246 | 1250 |
if ep.isAnonymous() {
|
| 1247 | 1251 |
if len(myAliases) > 0 {
|
| 1248 |
- n.deleteSvcRecords(ep.ID(), myAliases[0], iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1252 |
+ n.deleteSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1249 | 1253 |
} |
| 1250 | 1254 |
} else {
|
| 1251 |
- n.deleteSvcRecords(ep.ID(), epName, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1255 |
+ n.deleteSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") |
|
| 1252 | 1256 |
} |
| 1253 | 1257 |
for _, alias := range myAliases {
|
| 1254 |
- n.deleteSvcRecords(ep.ID(), alias, iface.Address().IP, ipv6, false, "updateSvcRecord") |
|
| 1258 |
+ n.deleteSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") |
|
| 1255 | 1259 |
} |
| 1256 | 1260 |
} |
| 1257 | 1261 |
} |
| 1258 | 1262 |
} |
| 1259 | 1263 |
|
| 1260 |
-func addIPToName(ipMap common.SetMatrix, name string, ip net.IP) {
|
|
| 1264 |
+func addIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1261 | 1265 |
reverseIP := netutils.ReverseIP(ip.String()) |
| 1262 | 1266 |
ipMap.Insert(reverseIP, ipInfo{
|
| 1263 |
- name: name, |
|
| 1267 |
+ name: name, |
|
| 1268 |
+ serviceID: serviceID, |
|
| 1264 | 1269 |
}) |
| 1265 | 1270 |
} |
| 1266 | 1271 |
|
| 1267 |
-func addNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) {
|
|
| 1268 |
- ipList := svcMap[name] |
|
| 1269 |
- for _, ip := range ipList {
|
|
| 1270 |
- if ip.Equal(epIP) {
|
|
| 1271 |
- return |
|
| 1272 |
- } |
|
| 1273 |
- } |
|
| 1274 |
- svcMap[name] = append(svcMap[name], epIP) |
|
| 1272 |
+func delIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1273 |
+ reverseIP := netutils.ReverseIP(ip.String()) |
|
| 1274 |
+ ipMap.Remove(reverseIP, ipInfo{
|
|
| 1275 |
+ name: name, |
|
| 1276 |
+ serviceID: serviceID, |
|
| 1277 |
+ }) |
|
| 1275 | 1278 |
} |
| 1276 | 1279 |
|
| 1277 |
-func delNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) {
|
|
| 1278 |
- ipList := svcMap[name] |
|
| 1279 |
- for i, ip := range ipList {
|
|
| 1280 |
- if ip.Equal(epIP) {
|
|
| 1281 |
- ipList = append(ipList[:i], ipList[i+1:]...) |
|
| 1282 |
- break |
|
| 1283 |
- } |
|
| 1284 |
- } |
|
| 1285 |
- svcMap[name] = ipList |
|
| 1280 |
+func addNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1281 |
+ svcMap.Insert(name, svcMapEntry{
|
|
| 1282 |
+ ip: epIP.String(), |
|
| 1283 |
+ serviceID: serviceID, |
|
| 1284 |
+ }) |
|
| 1285 |
+} |
|
| 1286 | 1286 |
|
| 1287 |
- if len(ipList) == 0 {
|
|
| 1288 |
- delete(svcMap, name) |
|
| 1289 |
- } |
|
| 1287 |
+func delNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1288 |
+ svcMap.Remove(name, svcMapEntry{
|
|
| 1289 |
+ ip: epIP.String(), |
|
| 1290 |
+ serviceID: serviceID, |
|
| 1291 |
+ }) |
|
| 1290 | 1292 |
} |
| 1291 | 1293 |
|
| 1292 |
-func (n *network) addSvcRecords(eID, name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) {
|
|
| 1294 |
+func (n *network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP, ipMapUpdate bool, method string) {
|
|
| 1293 | 1295 |
// Do not add service names for ingress network as this is a |
| 1294 | 1296 |
// routing only network |
| 1295 | 1297 |
if n.ingress {
|
| 1296 | 1298 |
return |
| 1297 | 1299 |
} |
| 1298 | 1300 |
|
| 1299 |
- logrus.Debugf("%s (%s).addSvcRecords(%s, %s, %s, %t) %s", eID, n.ID()[0:7], name, epIP, epIPv6, ipMapUpdate, method)
|
|
| 1301 |
+ logrus.Debugf("%s (%s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, n.ID()[0:7], name, epIP, epIPv6, ipMapUpdate, method, serviceID)
|
|
| 1300 | 1302 |
|
| 1301 | 1303 |
c := n.getController() |
| 1302 | 1304 |
c.Lock() |
| ... | ... |
@@ -1305,34 +1315,34 @@ func (n *network) addSvcRecords(eID, name string, epIP net.IP, epIPv6 net.IP, ip |
| 1305 | 1305 |
sr, ok := c.svcRecords[n.ID()] |
| 1306 | 1306 |
if !ok {
|
| 1307 | 1307 |
sr = svcInfo{
|
| 1308 |
- svcMap: make(map[string][]net.IP), |
|
| 1309 |
- svcIPv6Map: make(map[string][]net.IP), |
|
| 1308 |
+ svcMap: common.NewSetMatrix(), |
|
| 1309 |
+ svcIPv6Map: common.NewSetMatrix(), |
|
| 1310 | 1310 |
ipMap: common.NewSetMatrix(), |
| 1311 | 1311 |
} |
| 1312 | 1312 |
c.svcRecords[n.ID()] = sr |
| 1313 | 1313 |
} |
| 1314 | 1314 |
|
| 1315 | 1315 |
if ipMapUpdate {
|
| 1316 |
- addIPToName(sr.ipMap, name, epIP) |
|
| 1316 |
+ addIPToName(sr.ipMap, name, serviceID, epIP) |
|
| 1317 | 1317 |
if epIPv6 != nil {
|
| 1318 |
- addIPToName(sr.ipMap, name, epIPv6) |
|
| 1318 |
+ addIPToName(sr.ipMap, name, serviceID, epIPv6) |
|
| 1319 | 1319 |
} |
| 1320 | 1320 |
} |
| 1321 | 1321 |
|
| 1322 |
- addNameToIP(sr.svcMap, name, epIP) |
|
| 1322 |
+ addNameToIP(sr.svcMap, name, serviceID, epIP) |
|
| 1323 | 1323 |
if epIPv6 != nil {
|
| 1324 |
- addNameToIP(sr.svcIPv6Map, name, epIPv6) |
|
| 1324 |
+ addNameToIP(sr.svcIPv6Map, name, serviceID, epIPv6) |
|
| 1325 | 1325 |
} |
| 1326 | 1326 |
} |
| 1327 | 1327 |
|
| 1328 |
-func (n *network) deleteSvcRecords(eID, name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) {
|
|
| 1328 |
+func (n *network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) {
|
|
| 1329 | 1329 |
// Do not delete service names from ingress network as this is a |
| 1330 | 1330 |
// routing only network |
| 1331 | 1331 |
if n.ingress {
|
| 1332 | 1332 |
return |
| 1333 | 1333 |
} |
| 1334 | 1334 |
|
| 1335 |
- logrus.Debugf("%s (%s).deleteSvcRecords(%s, %s, %s, %t) %s", eID, n.ID()[0:7], name, epIP, epIPv6, ipMapUpdate, method)
|
|
| 1335 |
+ logrus.Debugf("%s (%s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, n.ID()[0:7], name, epIP, epIPv6, ipMapUpdate, method, serviceID)
|
|
| 1336 | 1336 |
|
| 1337 | 1337 |
c := n.getController() |
| 1338 | 1338 |
c.Lock() |
| ... | ... |
@@ -1344,21 +1354,17 @@ func (n *network) deleteSvcRecords(eID, name string, epIP net.IP, epIPv6 net.IP, |
| 1344 | 1344 |
} |
| 1345 | 1345 |
|
| 1346 | 1346 |
if ipMapUpdate {
|
| 1347 |
- sr.ipMap.Remove(netutils.ReverseIP(epIP.String()), ipInfo{
|
|
| 1348 |
- name: name, |
|
| 1349 |
- }) |
|
| 1347 |
+ delIPToName(sr.ipMap, name, serviceID, epIP) |
|
| 1350 | 1348 |
|
| 1351 | 1349 |
if epIPv6 != nil {
|
| 1352 |
- sr.ipMap.Remove(netutils.ReverseIP(epIPv6.String()), ipInfo{
|
|
| 1353 |
- name: name, |
|
| 1354 |
- }) |
|
| 1350 |
+ delIPToName(sr.ipMap, name, serviceID, epIPv6) |
|
| 1355 | 1351 |
} |
| 1356 | 1352 |
} |
| 1357 | 1353 |
|
| 1358 |
- delNameToIP(sr.svcMap, name, epIP) |
|
| 1354 |
+ delNameToIP(sr.svcMap, name, serviceID, epIP) |
|
| 1359 | 1355 |
|
| 1360 | 1356 |
if epIPv6 != nil {
|
| 1361 |
- delNameToIP(sr.svcIPv6Map, name, epIPv6) |
|
| 1357 |
+ delNameToIP(sr.svcIPv6Map, name, serviceID, epIPv6) |
|
| 1362 | 1358 |
} |
| 1363 | 1359 |
} |
| 1364 | 1360 |
|
| ... | ... |
@@ -1376,19 +1382,31 @@ func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
| 1376 | 1376 |
|
| 1377 | 1377 |
n.ctrlr.Lock() |
| 1378 | 1378 |
defer n.ctrlr.Unlock() |
| 1379 |
- sr, _ := n.ctrlr.svcRecords[n.id] |
|
| 1379 |
+ sr, ok := n.ctrlr.svcRecords[n.id] |
|
| 1380 |
+ if !ok || sr.svcMap == nil {
|
|
| 1381 |
+ return nil |
|
| 1382 |
+ } |
|
| 1380 | 1383 |
|
| 1381 |
- for h, ip := range sr.svcMap {
|
|
| 1382 |
- if strings.Split(h, ".")[0] == epName {
|
|
| 1384 |
+ svcMapKeys := sr.svcMap.Keys() |
|
| 1385 |
+ // Loop on service names on this network |
|
| 1386 |
+ for _, k := range svcMapKeys {
|
|
| 1387 |
+ if strings.Split(k, ".")[0] == epName {
|
|
| 1388 |
+ continue |
|
| 1389 |
+ } |
|
| 1390 |
+ // Get all the IPs associated to this service |
|
| 1391 |
+ mapEntryList, ok := sr.svcMap.Get(k) |
|
| 1392 |
+ if !ok {
|
|
| 1393 |
+ // The key got deleted |
|
| 1383 | 1394 |
continue |
| 1384 | 1395 |
} |
| 1385 |
- if len(ip) == 0 {
|
|
| 1386 |
- logrus.Warnf("Found empty list of IP addresses for service %s on network %s (%s)", h, n.name, n.id)
|
|
| 1396 |
+ if len(mapEntryList) == 0 {
|
|
| 1397 |
+ logrus.Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id)
|
|
| 1387 | 1398 |
continue |
| 1388 | 1399 |
} |
| 1400 |
+ |
|
| 1389 | 1401 |
recs = append(recs, etchosts.Record{
|
| 1390 |
- Hosts: h, |
|
| 1391 |
- IP: ip[0].String(), |
|
| 1402 |
+ Hosts: k, |
|
| 1403 |
+ IP: mapEntryList[0].(svcMapEntry).ip, |
|
| 1392 | 1404 |
}) |
| 1393 | 1405 |
} |
| 1394 | 1406 |
|
| ... | ... |
@@ -1845,8 +1863,7 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
|
| 1845 | 1845 |
} |
| 1846 | 1846 |
|
| 1847 | 1847 |
req = strings.TrimSuffix(req, ".") |
| 1848 |
- var ip []net.IP |
|
| 1849 |
- ip, ok = sr.svcMap[req] |
|
| 1848 |
+ ipSet, ok := sr.svcMap.Get(req) |
|
| 1850 | 1849 |
|
| 1851 | 1850 |
if ipType == types.IPv6 {
|
| 1852 | 1851 |
// If the name resolved to v4 address then its a valid name in |
| ... | ... |
@@ -1856,13 +1873,20 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
|
| 1856 | 1856 |
if ok && n.enableIPv6 == false {
|
| 1857 | 1857 |
ipv6Miss = true |
| 1858 | 1858 |
} |
| 1859 |
- ip = sr.svcIPv6Map[req] |
|
| 1859 |
+ ipSet, ok = sr.svcIPv6Map.Get(req) |
|
| 1860 | 1860 |
} |
| 1861 | 1861 |
|
| 1862 |
- if ip != nil {
|
|
| 1863 |
- ipLocal := make([]net.IP, len(ip)) |
|
| 1864 |
- copy(ipLocal, ip) |
|
| 1865 |
- return ipLocal, false |
|
| 1862 |
+ if ok && len(ipSet) > 0 {
|
|
| 1863 |
+ // this map is to avoid IP duplicates, this can happen during a transition period where 2 services are using the same IP |
|
| 1864 |
+ noDup := make(map[string]bool) |
|
| 1865 |
+ var ipLocal []net.IP |
|
| 1866 |
+ for _, ip := range ipSet {
|
|
| 1867 |
+ if _, dup := noDup[ip.(svcMapEntry).ip]; !dup {
|
|
| 1868 |
+ noDup[ip.(svcMapEntry).ip] = true |
|
| 1869 |
+ ipLocal = append(ipLocal, net.ParseIP(ip.(svcMapEntry).ip)) |
|
| 1870 |
+ } |
|
| 1871 |
+ } |
|
| 1872 |
+ return ipLocal, ok |
|
| 1866 | 1873 |
} |
| 1867 | 1874 |
|
| 1868 | 1875 |
return nil, ipv6Miss |
| ... | ... |
@@ -1904,7 +1928,7 @@ func (n *network) ResolveIP(ip string) string {
|
| 1904 | 1904 |
return "" |
| 1905 | 1905 |
} |
| 1906 | 1906 |
// NOTE it is possible to have more than one element in the Set, this will happen |
| 1907 |
- // because of interleave of diffent events from differnt sources (local container create vs |
|
| 1907 |
+ // because of interleave of different events from different sources (local container create vs |
|
| 1908 | 1908 |
// network db notifications) |
| 1909 | 1909 |
// In such cases the resolution will be based on the first element of the set, and can vary |
| 1910 | 1910 |
// during the system stabilitation |
| ... | ... |
@@ -629,6 +629,10 @@ func (sb *sandbox) SetKey(basePath string) error {
|
| 629 | 629 |
} |
| 630 | 630 |
|
| 631 | 631 |
sb.Lock() |
| 632 |
+ if sb.inDelete {
|
|
| 633 |
+ sb.Unlock() |
|
| 634 |
+ return types.ForbiddenErrorf("failed to SetKey: sandbox %q delete in progress", sb.id)
|
|
| 635 |
+ } |
|
| 632 | 636 |
oldosSbox := sb.osSbox |
| 633 | 637 |
sb.Unlock() |
| 634 | 638 |
|
| ... | ... |
@@ -85,14 +85,8 @@ type loadBalancer struct {
|
| 85 | 85 |
|
| 86 | 86 |
// Map of backend IPs backing this loadbalancer on this |
| 87 | 87 |
// network. It is keyed with endpoint ID. |
| 88 |
- backEnds map[string]loadBalancerBackend |
|
| 88 |
+ backEnds map[string]net.IP |
|
| 89 | 89 |
|
| 90 | 90 |
// Back pointer to service to which the loadbalancer belongs. |
| 91 | 91 |
service *service |
| 92 | 92 |
} |
| 93 |
- |
|
| 94 |
-type loadBalancerBackend struct {
|
|
| 95 |
- ip net.IP |
|
| 96 |
- containerName string |
|
| 97 |
- taskAliases []string |
|
| 98 |
-} |
| ... | ... |
@@ -15,29 +15,35 @@ func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, contain |
| 15 | 15 |
return err |
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 |
- logrus.Debugf("addEndpointNameResolution %s %s add_service:%t", eID, svcName, addService)
|
|
| 18 |
+ logrus.Debugf("addEndpointNameResolution %s %s add_service:%t sAliases:%v tAliases:%v", eID, svcName, addService, serviceAliases, taskAliases)
|
|
| 19 | 19 |
|
| 20 | 20 |
// Add container resolution mappings |
| 21 | 21 |
c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method) |
| 22 | 22 |
|
| 23 |
+ serviceID := svcID |
|
| 24 |
+ if serviceID == "" {
|
|
| 25 |
+ // This is the case of a normal container not part of a service |
|
| 26 |
+ serviceID = eID |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 23 | 29 |
// Add endpoint IP to special "tasks.svc_name" so that the applications have access to DNS RR. |
| 24 |
- n.(*network).addSvcRecords(eID, "tasks."+svcName, ip, nil, false, method) |
|
| 30 |
+ n.(*network).addSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method) |
|
| 25 | 31 |
for _, alias := range serviceAliases {
|
| 26 |
- n.(*network).addSvcRecords(eID, "tasks."+alias, ip, nil, false, method) |
|
| 32 |
+ n.(*network).addSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method) |
|
| 27 | 33 |
} |
| 28 | 34 |
|
| 29 | 35 |
// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR |
| 30 | 36 |
if len(vip) == 0 {
|
| 31 |
- n.(*network).addSvcRecords(eID, svcName, ip, nil, false, method) |
|
| 37 |
+ n.(*network).addSvcRecords(eID, svcName, serviceID, ip, nil, false, method) |
|
| 32 | 38 |
for _, alias := range serviceAliases {
|
| 33 |
- n.(*network).addSvcRecords(eID, alias, ip, nil, false, method) |
|
| 39 |
+ n.(*network).addSvcRecords(eID, alias, serviceID, ip, nil, false, method) |
|
| 34 | 40 |
} |
| 35 | 41 |
} |
| 36 | 42 |
|
| 37 | 43 |
if addService && len(vip) != 0 {
|
| 38 |
- n.(*network).addSvcRecords(eID, svcName, vip, nil, false, method) |
|
| 44 |
+ n.(*network).addSvcRecords(eID, svcName, serviceID, vip, nil, false, method) |
|
| 39 | 45 |
for _, alias := range serviceAliases {
|
| 40 |
- n.(*network).addSvcRecords(eID, alias, vip, nil, false, method) |
|
| 46 |
+ n.(*network).addSvcRecords(eID, alias, serviceID, vip, nil, false, method) |
|
| 41 | 47 |
} |
| 42 | 48 |
} |
| 43 | 49 |
|
| ... | ... |
@@ -52,11 +58,11 @@ func (c *controller) addContainerNameResolution(nID, eID, containerName string, |
| 52 | 52 |
logrus.Debugf("addContainerNameResolution %s %s", eID, containerName)
|
| 53 | 53 |
|
| 54 | 54 |
// Add resolution for container name |
| 55 |
- n.(*network).addSvcRecords(eID, containerName, ip, nil, true, method) |
|
| 55 |
+ n.(*network).addSvcRecords(eID, containerName, eID, ip, nil, true, method) |
|
| 56 | 56 |
|
| 57 | 57 |
// Add resolution for taskaliases |
| 58 | 58 |
for _, alias := range taskAliases {
|
| 59 |
- n.(*network).addSvcRecords(eID, alias, ip, nil, true, method) |
|
| 59 |
+ n.(*network).addSvcRecords(eID, alias, eID, ip, nil, true, method) |
|
| 60 | 60 |
} |
| 61 | 61 |
|
| 62 | 62 |
return nil |
| ... | ... |
@@ -68,32 +74,38 @@ func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, cont |
| 68 | 68 |
return err |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
- logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t", eID, svcName, rmService, multipleEntries)
|
|
| 71 |
+ logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t sAliases:%v tAliases:%v", eID, svcName, rmService, multipleEntries, serviceAliases, taskAliases)
|
|
| 72 | 72 |
|
| 73 | 73 |
// Delete container resolution mappings |
| 74 | 74 |
c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method) |
| 75 | 75 |
|
| 76 |
+ serviceID := svcID |
|
| 77 |
+ if serviceID == "" {
|
|
| 78 |
+ // This is the case of a normal container not part of a service |
|
| 79 |
+ serviceID = eID |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 76 | 82 |
// Delete the special "tasks.svc_name" backend record. |
| 77 | 83 |
if !multipleEntries {
|
| 78 |
- n.(*network).deleteSvcRecords(eID, "tasks."+svcName, ip, nil, false, method) |
|
| 84 |
+ n.(*network).deleteSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method) |
|
| 79 | 85 |
for _, alias := range serviceAliases {
|
| 80 |
- n.(*network).deleteSvcRecords(eID, "tasks."+alias, ip, nil, false, method) |
|
| 86 |
+ n.(*network).deleteSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method) |
|
| 81 | 87 |
} |
| 82 | 88 |
} |
| 83 | 89 |
|
| 84 | 90 |
// If we are doing DNS RR delete the endpoint IP from DNS record right away. |
| 85 | 91 |
if !multipleEntries && len(vip) == 0 {
|
| 86 |
- n.(*network).deleteSvcRecords(eID, svcName, ip, nil, false, method) |
|
| 92 |
+ n.(*network).deleteSvcRecords(eID, svcName, serviceID, ip, nil, false, method) |
|
| 87 | 93 |
for _, alias := range serviceAliases {
|
| 88 |
- n.(*network).deleteSvcRecords(eID, alias, ip, nil, false, method) |
|
| 94 |
+ n.(*network).deleteSvcRecords(eID, alias, serviceID, ip, nil, false, method) |
|
| 89 | 95 |
} |
| 90 | 96 |
} |
| 91 | 97 |
|
| 92 | 98 |
// Remove the DNS record for VIP only if we are removing the service |
| 93 | 99 |
if rmService && len(vip) != 0 && !multipleEntries {
|
| 94 |
- n.(*network).deleteSvcRecords(eID, svcName, vip, nil, false, method) |
|
| 100 |
+ n.(*network).deleteSvcRecords(eID, svcName, serviceID, vip, nil, false, method) |
|
| 95 | 101 |
for _, alias := range serviceAliases {
|
| 96 |
- n.(*network).deleteSvcRecords(eID, alias, vip, nil, false, method) |
|
| 102 |
+ n.(*network).deleteSvcRecords(eID, alias, serviceID, vip, nil, false, method) |
|
| 97 | 103 |
} |
| 98 | 104 |
} |
| 99 | 105 |
|
| ... | ... |
@@ -108,11 +120,11 @@ func (c *controller) delContainerNameResolution(nID, eID, containerName string, |
| 108 | 108 |
logrus.Debugf("delContainerNameResolution %s %s", eID, containerName)
|
| 109 | 109 |
|
| 110 | 110 |
// Delete resolution for container name |
| 111 |
- n.(*network).deleteSvcRecords(eID, containerName, ip, nil, true, method) |
|
| 111 |
+ n.(*network).deleteSvcRecords(eID, containerName, eID, ip, nil, true, method) |
|
| 112 | 112 |
|
| 113 | 113 |
// Delete resolution for taskaliases |
| 114 | 114 |
for _, alias := range taskAliases {
|
| 115 |
- n.(*network).deleteSvcRecords(eID, alias, ip, nil, true, method) |
|
| 115 |
+ n.(*network).deleteSvcRecords(eID, alias, eID, ip, nil, true, method) |
|
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
return nil |
| ... | ... |
@@ -152,6 +164,7 @@ func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int |
| 152 | 152 |
func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
| 153 | 153 |
var cleanupFuncs []func() |
| 154 | 154 |
|
| 155 |
+ logrus.Debugf("cleanupServiceBindings for %s", cleanupNID)
|
|
| 155 | 156 |
c.Lock() |
| 156 | 157 |
services := make([]*service, 0, len(c.serviceBindings)) |
| 157 | 158 |
for _, s := range c.serviceBindings {
|
| ... | ... |
@@ -171,16 +184,27 @@ func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
| 171 | 171 |
continue |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 |
- for eid, be := range lb.backEnds {
|
|
| 174 |
+ // The network is being deleted, erase all the associated service discovery records |
|
| 175 |
+ // TODO(fcrisciani) separate the Load Balancer from the Service discovery, this operation |
|
| 176 |
+ // can be done safely here, but the rmServiceBinding is still keeping consistency in the |
|
| 177 |
+ // data structures that are tracking the endpoint to IP mapping. |
|
| 178 |
+ c.Lock() |
|
| 179 |
+ logrus.Debugf("cleanupServiceBindings erasing the svcRecords for %s", nid)
|
|
| 180 |
+ delete(c.svcRecords, nid) |
|
| 181 |
+ c.Unlock() |
|
| 182 |
+ |
|
| 183 |
+ for eid, ip := range lb.backEnds {
|
|
| 184 |
+ epID := eid |
|
| 185 |
+ epIP := ip |
|
| 175 | 186 |
service := s |
| 176 | 187 |
loadBalancer := lb |
| 177 | 188 |
networkID := nid |
| 178 |
- epID := eid |
|
| 179 |
- epIP := be.ip |
|
| 180 |
- |
|
| 181 | 189 |
cleanupFuncs = append(cleanupFuncs, func() {
|
| 182 |
- if err := c.rmServiceBinding(service.name, service.id, networkID, epID, be.containerName, loadBalancer.vip, |
|
| 183 |
- service.ingressPorts, service.aliases, be.taskAliases, epIP, "cleanupServiceBindings"); err != nil {
|
|
| 190 |
+ // ContainerName and taskAliases are not available here, this is still fine because the Service discovery |
|
| 191 |
+ // cleanup already happened before. The only thing that rmServiceBinding is still doing here a part from the Load |
|
| 192 |
+ // Balancer bookeeping, is to keep consistent the mapping of endpoint to IP. |
|
| 193 |
+ if err := c.rmServiceBinding(service.name, service.id, networkID, epID, "", loadBalancer.vip, |
|
| 194 |
+ service.ingressPorts, service.aliases, []string{}, epIP, "cleanupServiceBindings", false); err != nil {
|
|
| 184 | 195 |
logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
|
| 185 | 196 |
service.id, networkID, epID, err) |
| 186 | 197 |
} |
| ... | ... |
@@ -228,8 +252,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s |
| 228 | 228 |
} |
| 229 | 229 |
s.Unlock() |
| 230 | 230 |
} |
| 231 |
- logrus.Debugf("addServiceBinding from %s START for %s %s", method, svcName, eID)
|
|
| 232 |
- |
|
| 231 |
+ logrus.Debugf("addServiceBinding from %s START for %s %s p:%p nid:%s skey:%v", method, svcName, eID, s, nID, skey)
|
|
| 233 | 232 |
defer s.Unlock() |
| 234 | 233 |
|
| 235 | 234 |
lb, ok := s.loadBalancers[nID] |
| ... | ... |
@@ -242,7 +265,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s |
| 242 | 242 |
lb = &loadBalancer{
|
| 243 | 243 |
vip: vip, |
| 244 | 244 |
fwMark: fwMarkCtr, |
| 245 |
- backEnds: make(map[string]loadBalancerBackend), |
|
| 245 |
+ backEnds: make(map[string]net.IP), |
|
| 246 | 246 |
service: s, |
| 247 | 247 |
} |
| 248 | 248 |
|
| ... | ... |
@@ -253,9 +276,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s |
| 253 | 253 |
addService = true |
| 254 | 254 |
} |
| 255 | 255 |
|
| 256 |
- lb.backEnds[eID] = loadBalancerBackend{ip: ip,
|
|
| 257 |
- containerName: containerName, |
|
| 258 |
- taskAliases: taskAliases} |
|
| 256 |
+ lb.backEnds[eID] = ip |
|
| 259 | 257 |
|
| 260 | 258 |
ok, entries := s.assignIPToEndpoint(ip.String(), eID) |
| 261 | 259 |
if !ok || entries > 1 {
|
| ... | ... |
@@ -277,7 +298,7 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s |
| 277 | 277 |
return nil |
| 278 | 278 |
} |
| 279 | 279 |
|
| 280 |
-func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string) error {
|
|
| 280 |
+func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string, deleteSvcRecords bool) error {
|
|
| 281 | 281 |
|
| 282 | 282 |
var rmService bool |
| 283 | 283 |
|
| ... | ... |
@@ -294,7 +315,6 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st |
| 294 | 294 |
c.Lock() |
| 295 | 295 |
s, ok := c.serviceBindings[skey] |
| 296 | 296 |
c.Unlock() |
| 297 |
- logrus.Debugf("rmServiceBinding from %s START for %s %s", method, svcName, eID)
|
|
| 298 | 297 |
if !ok {
|
| 299 | 298 |
logrus.Warnf("rmServiceBinding %s %s %s aborted c.serviceBindings[skey] !ok", method, svcName, eID)
|
| 300 | 299 |
return nil |
| ... | ... |
@@ -302,6 +322,7 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st |
| 302 | 302 |
|
| 303 | 303 |
s.Lock() |
| 304 | 304 |
defer s.Unlock() |
| 305 |
+ logrus.Debugf("rmServiceBinding from %s START for %s %s p:%p nid:%s sKey:%v deleteSvc:%t", method, svcName, eID, s, nID, skey, deleteSvcRecords)
|
|
| 305 | 306 |
lb, ok := s.loadBalancers[nID] |
| 306 | 307 |
if !ok {
|
| 307 | 308 |
logrus.Warnf("rmServiceBinding %s %s %s aborted s.loadBalancers[nid] !ok", method, svcName, eID)
|
| ... | ... |
@@ -322,17 +343,7 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st |
| 322 | 322 |
rmService = true |
| 323 | 323 |
|
| 324 | 324 |
delete(s.loadBalancers, nID) |
| 325 |
- } |
|
| 326 |
- |
|
| 327 |
- if len(s.loadBalancers) == 0 {
|
|
| 328 |
- // All loadbalancers for the service removed. Time to |
|
| 329 |
- // remove the service itself. |
|
| 330 |
- c.Lock() |
|
| 331 |
- |
|
| 332 |
- // Mark the object as deleted so that the add won't use it wrongly |
|
| 333 |
- s.deleted = true |
|
| 334 |
- delete(c.serviceBindings, skey) |
|
| 335 |
- c.Unlock() |
|
| 325 |
+ logrus.Debugf("rmServiceBinding %s delete %s, p:%p in loadbalancers len:%d", eID, nID, lb, len(s.loadBalancers))
|
|
| 336 | 326 |
} |
| 337 | 327 |
|
| 338 | 328 |
ok, entries := s.removeIPToEndpoint(ip.String(), eID) |
| ... | ... |
@@ -348,7 +359,22 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st |
| 348 | 348 |
} |
| 349 | 349 |
|
| 350 | 350 |
// Delete the name resolutions |
| 351 |
- c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding") |
|
| 351 |
+ if deleteSvcRecords {
|
|
| 352 |
+ c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding") |
|
| 353 |
+ } |
|
| 354 |
+ |
|
| 355 |
+ if len(s.loadBalancers) == 0 {
|
|
| 356 |
+ // All loadbalancers for the service removed. Time to |
|
| 357 |
+ // remove the service itself. |
|
| 358 |
+ c.Lock() |
|
| 359 |
+ |
|
| 360 |
+ // Mark the object as deleted so that the add won't use it wrongly |
|
| 361 |
+ s.deleted = true |
|
| 362 |
+ // NOTE The delete from the serviceBindings map has to be the last operation else we are allowing a race between this service |
|
| 363 |
+ // that is getting deleted and a new service that will be created if the entry is not anymore there |
|
| 364 |
+ delete(c.serviceBindings, skey) |
|
| 365 |
+ c.Unlock() |
|
| 366 |
+ } |
|
| 352 | 367 |
|
| 353 | 368 |
logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
|
| 354 | 369 |
return nil |
| ... | ... |
@@ -102,8 +102,8 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
|
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
lb.service.Lock() |
| 105 |
- for _, l := range lb.backEnds {
|
|
| 106 |
- sb.addLBBackend(l.ip, lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, gwIP, n.ingress) |
|
| 105 |
+ for _, ip := range lb.backEnds {
|
|
| 106 |
+ sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, gwIP, n.ingress) |
|
| 107 | 107 |
} |
| 108 | 108 |
lb.service.Unlock() |
| 109 | 109 |
} |
| ... | ... |
@@ -520,7 +520,7 @@ func writePortsToFile(ports []*PortConfig) (string, error) {
|
| 520 | 520 |
} |
| 521 | 521 |
defer f.Close() |
| 522 | 522 |
|
| 523 |
- buf, err := proto.Marshal(&EndpointRecord{
|
|
| 523 |
+ buf, _ := proto.Marshal(&EndpointRecord{
|
|
| 524 | 524 |
IngressPorts: ports, |
| 525 | 525 |
}) |
| 526 | 526 |
|