| ... | ... |
@@ -105,7 +105,7 @@ github.com/docker/containerd 9048e5e50717ea4497b757314bad98ea3763c145 |
| 105 | 105 |
github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 |
| 106 | 106 |
|
| 107 | 107 |
# cluster |
| 108 |
-github.com/docker/swarmkit 78685cfc94de06f21d65d0d30b6f61e80d250c45 |
|
| 108 |
+github.com/docker/swarmkit 78db8a5fed39c637dcd136b9e16c29f135b41c94 |
|
| 109 | 109 |
github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2 |
| 110 | 110 |
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a |
| 111 | 111 |
github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e |
| ... | ... |
@@ -164,7 +164,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
|
| 164 | 164 |
|
| 165 | 165 |
var allocatedServices []*api.Service |
| 166 | 166 |
for _, s := range services {
|
| 167 |
- if nc.nwkAllocator.IsServiceAllocated(s, networkallocator.OnInit) {
|
|
| 167 |
+ if !nc.nwkAllocator.ServiceNeedsAllocation(s, networkallocator.OnInit) {
|
|
| 168 | 168 |
continue |
| 169 | 169 |
} |
| 170 | 170 |
|
| ... | ... |
@@ -317,7 +317,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
|
| 317 | 317 |
break |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 |
- if nc.nwkAllocator.IsServiceAllocated(s) {
|
|
| 320 |
+ if !nc.nwkAllocator.ServiceNeedsAllocation(s) {
|
|
| 321 | 321 |
break |
| 322 | 322 |
} |
| 323 | 323 |
|
| ... | ... |
@@ -345,7 +345,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
|
| 345 | 345 |
break |
| 346 | 346 |
} |
| 347 | 347 |
|
| 348 |
- if nc.nwkAllocator.IsServiceAllocated(s) {
|
|
| 348 |
+ if !nc.nwkAllocator.ServiceNeedsAllocation(s) {
|
|
| 349 | 349 |
if nc.nwkAllocator.PortsAllocatedInHostPublishMode(s) {
|
| 350 | 350 |
break |
| 351 | 351 |
} |
| ... | ... |
@@ -544,7 +544,7 @@ func taskReadyForNetworkVote(t *api.Task, s *api.Service, nc *networkContext) bo |
| 544 | 544 |
// network configured or service endpoints have been |
| 545 | 545 |
// allocated. |
| 546 | 546 |
return (len(t.Networks) == 0 || nc.nwkAllocator.IsTaskAllocated(t)) && |
| 547 |
- (s == nil || nc.nwkAllocator.IsServiceAllocated(s)) |
|
| 547 |
+ (s == nil || !nc.nwkAllocator.ServiceNeedsAllocation(s)) |
|
| 548 | 548 |
} |
| 549 | 549 |
|
| 550 | 550 |
func taskUpdateNetworks(t *api.Task, networks []*api.NetworkAttachment) {
|
| ... | ... |
@@ -886,7 +886,7 @@ func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
|
| 886 | 886 |
return |
| 887 | 887 |
} |
| 888 | 888 |
|
| 889 |
- if !nc.nwkAllocator.IsServiceAllocated(s) {
|
|
| 889 |
+ if nc.nwkAllocator.ServiceNeedsAllocation(s) {
|
|
| 890 | 890 |
err = fmt.Errorf("service %s to which this task %s belongs has pending allocations", s.ID, t.ID)
|
| 891 | 891 |
return |
| 892 | 892 |
} |
| ... | ... |
@@ -1000,7 +1000,7 @@ func (a *Allocator) procUnallocatedServices(ctx context.Context) {
|
| 1000 | 1000 |
nc := a.netCtx |
| 1001 | 1001 |
var allocatedServices []*api.Service |
| 1002 | 1002 |
for _, s := range nc.unallocatedServices {
|
| 1003 |
- if !nc.nwkAllocator.IsServiceAllocated(s) {
|
|
| 1003 |
+ if nc.nwkAllocator.ServiceNeedsAllocation(s) {
|
|
| 1004 | 1004 |
if err := a.allocateService(ctx, s); err != nil {
|
| 1005 | 1005 |
log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated service %s", s.ID)
|
| 1006 | 1006 |
continue |
| ... | ... |
@@ -186,19 +186,34 @@ func (na *NetworkAllocator) ServiceAllocate(s *api.Service) (err error) {
|
| 186 | 186 |
return |
| 187 | 187 |
} |
| 188 | 188 |
|
| 189 |
- // First allocate VIPs for all the pre-populated endpoint attachments |
|
| 190 |
- for _, eAttach := range s.Endpoint.VirtualIPs {
|
|
| 191 |
- if err = na.allocateVIP(eAttach); err != nil {
|
|
| 192 |
- return |
|
| 193 |
- } |
|
| 194 |
- } |
|
| 195 |
- |
|
| 196 | 189 |
// Always prefer NetworkAttachmentConfig in the TaskSpec |
| 197 | 190 |
specNetworks := s.Spec.Task.Networks |
| 198 | 191 |
if len(specNetworks) == 0 && s != nil && len(s.Spec.Networks) != 0 {
|
| 199 | 192 |
specNetworks = s.Spec.Networks |
| 200 | 193 |
} |
| 201 | 194 |
|
| 195 |
+ // Allocate VIPs for all the pre-populated endpoint attachments |
|
| 196 |
+ eVIPs := s.Endpoint.VirtualIPs[:0] |
|
| 197 |
+ for _, eAttach := range s.Endpoint.VirtualIPs {
|
|
| 198 |
+ match := false |
|
| 199 |
+ for _, nAttach := range specNetworks {
|
|
| 200 |
+ if nAttach.Target == eAttach.NetworkID {
|
|
| 201 |
+ match = true |
|
| 202 |
+ if err = na.allocateVIP(eAttach); err != nil {
|
|
| 203 |
+ return |
|
| 204 |
+ } |
|
| 205 |
+ eVIPs = append(eVIPs, eAttach) |
|
| 206 |
+ break |
|
| 207 |
+ } |
|
| 208 |
+ } |
|
| 209 |
+ //If the network of the VIP is not part of the service spec, |
|
| 210 |
+ //deallocate the vip |
|
| 211 |
+ if !match {
|
|
| 212 |
+ na.deallocateVIP(eAttach) |
|
| 213 |
+ } |
|
| 214 |
+ } |
|
| 215 |
+ s.Endpoint.VirtualIPs = eVIPs |
|
| 216 |
+ |
|
| 202 | 217 |
outer: |
| 203 | 218 |
for _, nAttach := range specNetworks {
|
| 204 | 219 |
for _, vip := range s.Endpoint.VirtualIPs {
|
| ... | ... |
@@ -215,7 +230,11 @@ outer: |
| 215 | 215 |
s.Endpoint.VirtualIPs = append(s.Endpoint.VirtualIPs, vip) |
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 |
- na.services[s.ID] = struct{}{}
|
|
| 218 |
+ if len(s.Endpoint.VirtualIPs) > 0 {
|
|
| 219 |
+ na.services[s.ID] = struct{}{}
|
|
| 220 |
+ } else {
|
|
| 221 |
+ delete(na.services, s.ID) |
|
| 222 |
+ } |
|
| 219 | 223 |
return |
| 220 | 224 |
} |
| 221 | 225 |
|
| ... | ... |
@@ -300,41 +319,79 @@ func OnInit(options *ServiceAllocationOpts) {
|
| 300 | 300 |
options.OnInit = true |
| 301 | 301 |
} |
| 302 | 302 |
|
| 303 |
-// IsServiceAllocated returns if the passed service has its network resources allocated or not. |
|
| 304 |
-// init bool indicates if the func is called during allocator initialization stage. |
|
| 305 |
-func (na *NetworkAllocator) IsServiceAllocated(s *api.Service, flags ...func(*ServiceAllocationOpts)) bool {
|
|
| 303 |
+// ServiceNeedsAllocation returns true if the passed service needs to have network resources allocated/updated. |
|
| 304 |
+func (na *NetworkAllocator) ServiceNeedsAllocation(s *api.Service, flags ...func(*ServiceAllocationOpts)) bool {
|
|
| 306 | 305 |
var options ServiceAllocationOpts |
| 307 |
- |
|
| 308 | 306 |
for _, flag := range flags {
|
| 309 | 307 |
flag(&options) |
| 310 | 308 |
} |
| 311 | 309 |
|
| 310 |
+ // Always prefer NetworkAttachmentConfig in the TaskSpec |
|
| 311 |
+ specNetworks := s.Spec.Task.Networks |
|
| 312 |
+ if len(specNetworks) == 0 && len(s.Spec.Networks) != 0 {
|
|
| 313 |
+ specNetworks = s.Spec.Networks |
|
| 314 |
+ } |
|
| 315 |
+ |
|
| 312 | 316 |
// If endpoint mode is VIP and allocator does not have the |
| 313 |
- // service in VIP allocated set then it is not allocated. |
|
| 314 |
- if (len(s.Spec.Task.Networks) != 0 || len(s.Spec.Networks) != 0) && |
|
| 317 |
+ // service in VIP allocated set then it needs to be allocated. |
|
| 318 |
+ if len(specNetworks) != 0 && |
|
| 315 | 319 |
(s.Spec.Endpoint == nil || |
| 316 | 320 |
s.Spec.Endpoint.Mode == api.ResolutionModeVirtualIP) {
|
| 321 |
+ |
|
| 317 | 322 |
if _, ok := na.services[s.ID]; !ok {
|
| 318 |
- return false |
|
| 323 |
+ return true |
|
| 324 |
+ } |
|
| 325 |
+ |
|
| 326 |
+ if s.Endpoint == nil || len(s.Endpoint.VirtualIPs) == 0 {
|
|
| 327 |
+ return true |
|
| 328 |
+ } |
|
| 329 |
+ |
|
| 330 |
+ for _, net := range specNetworks {
|
|
| 331 |
+ match := false |
|
| 332 |
+ for _, vip := range s.Endpoint.VirtualIPs {
|
|
| 333 |
+ if vip.NetworkID == net.Target {
|
|
| 334 |
+ match = true |
|
| 335 |
+ break |
|
| 336 |
+ } |
|
| 337 |
+ } |
|
| 338 |
+ if !match {
|
|
| 339 |
+ return true |
|
| 340 |
+ } |
|
| 341 |
+ } |
|
| 342 |
+ } |
|
| 343 |
+ |
|
| 344 |
+ //If the spec no longer has networks attached and has a vip allocated |
|
| 345 |
+ //from previous spec the service needs to updated |
|
| 346 |
+ if s.Endpoint != nil {
|
|
| 347 |
+ for _, vip := range s.Endpoint.VirtualIPs {
|
|
| 348 |
+ match := false |
|
| 349 |
+ for _, net := range specNetworks {
|
|
| 350 |
+ if vip.NetworkID == net.Target {
|
|
| 351 |
+ match = true |
|
| 352 |
+ break |
|
| 353 |
+ } |
|
| 354 |
+ } |
|
| 355 |
+ if !match {
|
|
| 356 |
+ return true |
|
| 357 |
+ } |
|
| 319 | 358 |
} |
| 320 | 359 |
} |
| 321 | 360 |
|
| 322 | 361 |
// If the endpoint mode is DNSRR and allocator has the service |
| 323 |
- // in VIP allocated set then we return not allocated to make |
|
| 362 |
+ // in VIP allocated set then we return to be allocated to make |
|
| 324 | 363 |
// sure the allocator triggers networkallocator to free up the |
| 325 | 364 |
// resources if any. |
| 326 | 365 |
if s.Spec.Endpoint != nil && s.Spec.Endpoint.Mode == api.ResolutionModeDNSRoundRobin {
|
| 327 | 366 |
if _, ok := na.services[s.ID]; ok {
|
| 328 |
- return false |
|
| 367 |
+ return true |
|
| 329 | 368 |
} |
| 330 | 369 |
} |
| 331 | 370 |
|
| 332 | 371 |
if (s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0) || |
| 333 | 372 |
(s.Endpoint != nil && len(s.Endpoint.Ports) != 0) {
|
| 334 |
- return na.portAllocator.isPortsAllocatedOnInit(s, options.OnInit) |
|
| 373 |
+ return !na.portAllocator.isPortsAllocatedOnInit(s, options.OnInit) |
|
| 335 | 374 |
} |
| 336 |
- |
|
| 337 |
- return true |
|
| 375 |
+ return false |
|
| 338 | 376 |
} |
| 339 | 377 |
|
| 340 | 378 |
// IsNodeAllocated returns if the passed node has its network resources allocated or not. |