* Module name changed to `github.com/rajch/weave` * Added environment variable `CHECKPOINT_DISABLE=1` to default manifests, to bypass weaveworks telemetry
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package ipam
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/rajch/weave/api"
|
|
"github.com/rajch/weave/net/address"
|
|
)
|
|
|
|
type allocateResult struct {
|
|
addr address.Address
|
|
err error
|
|
}
|
|
|
|
type allocate struct {
|
|
resultChan chan<- allocateResult
|
|
ident string // a container ID, something like "weave:expose", or api.NoContainerID
|
|
r address.CIDR // Subnet we are trying to allocate within
|
|
isContainer bool // true if ident is a container ID
|
|
hasBeenCancelled func() bool
|
|
}
|
|
|
|
// Try returns true if the request is completed, false if pending
|
|
func (g *allocate) Try(alloc *Allocator) bool {
|
|
if g.hasBeenCancelled() {
|
|
g.Cancel()
|
|
return true
|
|
}
|
|
|
|
if addrs := alloc.ownedInRange(g.ident, g.r.Range()); len(addrs) > 0 {
|
|
// If we had heard that this container died, resurrect it
|
|
delete(alloc.dead, g.ident) // delete is no-op if key not in map
|
|
g.resultChan <- allocateResult{addrs[0].Addr, nil}
|
|
return true
|
|
}
|
|
|
|
if !alloc.universe.Range().Overlaps(g.r.Range()) {
|
|
g.resultChan <- allocateResult{err: fmt.Errorf("range %s out of bounds: %s", g.r, alloc.universe)}
|
|
return true
|
|
}
|
|
|
|
alloc.establishRing()
|
|
|
|
if ok, addr := alloc.space.Allocate(g.r.HostRange()); ok {
|
|
// If caller hasn't supplied a unique ID, file it under the IP address
|
|
// which lets the caller then release the address using DELETE /ip/address
|
|
if g.ident == api.NoContainerID {
|
|
g.ident = addr.String()
|
|
}
|
|
alloc.debugln("Allocated", addr, "for", g.ident, "in", g.r)
|
|
alloc.addOwned(g.ident, address.MakeCIDR(g.r, addr), g.isContainer)
|
|
g.resultChan <- allocateResult{addr, nil}
|
|
return true
|
|
}
|
|
|
|
// out of space
|
|
donors := alloc.ring.ChoosePeersToAskForSpace(g.r.Addr, g.r.Range().End)
|
|
for _, donor := range donors {
|
|
if err := alloc.sendSpaceRequest(donor, g.r.Range()); err != nil {
|
|
alloc.debugln("Problem asking peer", donor, "for space:", err)
|
|
} else {
|
|
alloc.debugln("Decided to ask peer", donor, "for space in range", g.r)
|
|
break
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (g *allocate) Cancel() {
|
|
g.resultChan <- allocateResult{err: &errorCancelled{"Allocate", g.ident}}
|
|
}
|
|
|
|
func (g *allocate) ForContainer(ident string) bool {
|
|
return g.ident == ident
|
|
}
|