Check manually-assigned addresses with IPAM to see if they clash
This commit is contained in:
1 parent
26dc83dbc2
commit
647b755b64
5 files changed
+35
-19
No files matched your search
+2
-2
@@ -215,9 +215,9 @@ func (alloc *Allocator) Lookup(ident string, r address.Range) (address.Address,
|
||||
}
|
||||
|
||||
// Claim an address that we think we should own (Sync)
|
||||
func (alloc *Allocator) Claim(ident string, addr address.Address) error {
|
||||
func (alloc *Allocator) Claim(ident string, addr address.Address, reclaim bool) error {
|
||||
resultChan := make(chan error)
|
||||
op := &claim{resultChan: resultChan, ident: ident, addr: addr}
|
||||
op := &claim{resultChan: resultChan, ident: ident, addr: addr, reclaim: reclaim}
|
||||
alloc.doOperation(op, &alloc.pendingClaims)
|
||||
return <-resultChan
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ func TestAllocatorClaim(t *testing.T) {
|
||||
addr1, _ := address.ParseIP(testAddr1)
|
||||
|
||||
// First claim should trigger "dunno, I'm going to wait"
|
||||
err := alloc.Claim(container3, addr1)
|
||||
err := alloc.Claim(container3, addr1, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Do one allocate to ensure paxos is all done
|
||||
@@ -152,23 +152,23 @@ func TestAllocatorClaim(t *testing.T) {
|
||||
addrx, err := allocs[0].Allocate(container1, subnet, nil)
|
||||
|
||||
// Now try the claim again
|
||||
err = alloc.Claim(container3, addr1)
|
||||
err = alloc.Claim(container3, addr1, true)
|
||||
require.NoError(t, err)
|
||||
// Check we get this address back if we try an allocate
|
||||
addr3, _ := alloc.Allocate(container3, subnet, nil)
|
||||
require.Equal(t, testAddr1, addr3.String(), "address")
|
||||
// one more claim should still work
|
||||
err = alloc.Claim(container3, addr1)
|
||||
err = alloc.Claim(container3, addr1, true)
|
||||
require.NoError(t, err)
|
||||
// claim for a different container should fail
|
||||
err = alloc.Claim(container1, addr1)
|
||||
err = alloc.Claim(container1, addr1, true)
|
||||
require.Error(t, err)
|
||||
// claiming the address allocated on the other peer should fail
|
||||
err = alloc.Claim(container1, addrx)
|
||||
err = alloc.Claim(container1, addrx, true)
|
||||
require.Error(t, err, "claiming address allocated on other peer should fail")
|
||||
// Check an address outside of our universe
|
||||
addr2, _ := address.ParseIP(testAddr2)
|
||||
err = alloc.Claim(container1, addr2)
|
||||
err = alloc.Claim(container1, addr2, true)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ func TestAllocatorFuzz(t *testing.T) {
|
||||
addressIndex := rand.Int31n(int32(subnet.Size()))
|
||||
alloc := allocs[allocIndex]
|
||||
addr := address.Add(subnet.Start, address.Offset(addressIndex))
|
||||
err := alloc.Claim(name, addr)
|
||||
err := alloc.Claim(name, addr, true)
|
||||
if err == nil {
|
||||
noteAllocation(allocIndex, name, addr)
|
||||
}
|
||||
|
||||
+18
-6
@@ -12,6 +12,7 @@ type claim struct {
|
||||
resultChan chan<- error
|
||||
ident string
|
||||
addr address.Address
|
||||
reclaim bool
|
||||
}
|
||||
|
||||
func (c *claim) sendResult(result error) {
|
||||
@@ -20,6 +21,7 @@ func (c *claim) sendResult(result error) {
|
||||
c.resultChan <- result
|
||||
close(c.resultChan)
|
||||
c.resultChan = nil
|
||||
return
|
||||
}
|
||||
if result != nil {
|
||||
common.Log.Errorln("[allocator] " + result.Error())
|
||||
@@ -30,7 +32,9 @@ func (c *claim) sendResult(result error) {
|
||||
func (c *claim) Try(alloc *Allocator) bool {
|
||||
if !alloc.ring.Contains(c.addr) {
|
||||
// Address not within our universe; assume user knows what they are doing
|
||||
alloc.infof("Ignored address %s claimed by %s - not in our universe", c.addr, c.ident)
|
||||
if c.reclaim {
|
||||
alloc.infof("Ignored address %s claimed by %s - not in our universe", c.addr, c.ident)
|
||||
}
|
||||
c.sendResult(nil)
|
||||
return true
|
||||
}
|
||||
@@ -40,15 +44,23 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
// success
|
||||
case router.UnknownPeerName:
|
||||
// If our ring doesn't know, it must be empty.
|
||||
alloc.infof("Claim %s for %s: address allocator still initializing; will try later.", c.addr, c.ident)
|
||||
c.sendResult(nil) // don't make the caller wait
|
||||
if c.reclaim {
|
||||
alloc.infof("Claim %s for %s: address allocator still initializing; will try later.", c.addr, c.ident)
|
||||
c.sendResult(nil) // don't make the caller wait
|
||||
} else {
|
||||
c.sendResult(fmt.Errorf("%s is in the range %s, but the allocator is not initialized yet", c.addr, alloc.universe.AsCIDRString()))
|
||||
}
|
||||
return false
|
||||
default:
|
||||
alloc.debugf("requesting address %s from other peer %s", c.addr, owner)
|
||||
err := alloc.sendSpaceRequest(owner, address.NewRange(c.addr, 1))
|
||||
if err != nil { // can't speak to owner right now; figure it out later
|
||||
alloc.infof("Claim %s for %s: %s; will try later.", c.addr, c.ident, err)
|
||||
c.sendResult(nil)
|
||||
if err != nil { // can't speak to owner right now
|
||||
if c.reclaim { // don't hold up launch; figure it out later
|
||||
alloc.infof("Claim %s for %s: %s; will try later.", c.addr, c.ident, err)
|
||||
c.sendResult(nil)
|
||||
} else { // just tell the user they can't do this.
|
||||
c.DeniedBy(alloc, owner)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+2
-1
@@ -22,10 +22,11 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
||||
vars := mux.Vars(r)
|
||||
ident := vars["id"]
|
||||
ipStr := vars["ip"]
|
||||
reclaim := r.FormValue("reclaim") == "true"
|
||||
if ip, err := address.ParseIP(ipStr); err != nil {
|
||||
badRequest(w, err)
|
||||
return
|
||||
} else if err := alloc.Claim(ident, ip); err != nil {
|
||||
} else if err := alloc.Claim(ident, ip, reclaim); err != nil {
|
||||
badRequest(w, fmt.Errorf("Unable to claim: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -812,10 +812,10 @@ delete_dns_fqdn() {
|
||||
|
||||
# Claim addresses for a container in IPAM. Expects to be called from
|
||||
# with_container_addresses.
|
||||
ipam_claim() {
|
||||
ipam_reclaim() {
|
||||
for CIDR in $3 ; do
|
||||
# NB: CONTAINER_IP is the IP of the weave container; it is set by wait_for_status.
|
||||
http_call_ip $CONTAINER_IP $HTTP_PORT PUT /ip/$1/${CIDR%/*}
|
||||
http_call_ip $CONTAINER_IP $HTTP_PORT PUT /ip/$1/${CIDR%/*}?reclaim=true
|
||||
done
|
||||
}
|
||||
|
||||
@@ -862,6 +862,9 @@ ipam_cidrs() {
|
||||
else
|
||||
# This is a plain IP address; warn if it clashes but carry on
|
||||
command_exists netcheck && netcheck --ignore-iface=$BRIDGE $1 || true
|
||||
if container_ip $CONTAINER_NAME 2>/dev/null ; then
|
||||
http_call_ip $CONTAINER_IP $HTTP_PORT PUT /ip/$CONTAINER_ID/${1%/*} >&2
|
||||
fi
|
||||
ALL_CIDRS="$ALL_CIDRS $1"
|
||||
fi
|
||||
shift 1
|
||||
@@ -1091,7 +1094,7 @@ launch_router() {
|
||||
wait_for_status $CONTAINER_NAME $HTTP_PORT
|
||||
if [ -n "$IPRANGE" ] ; then
|
||||
# Tell the newly-started weave IP allocator about existing weave IPs
|
||||
with_container_addresses ipam_claim weave:expose $(docker ps -q --no-trunc)
|
||||
with_container_addresses ipam_reclaim weave:expose $(docker ps -q --no-trunc)
|
||||
fi
|
||||
if [ -n "$DNS_PORT_MAPPING" ] ; then
|
||||
# Tell the newly-started weaveDNS about existing weave IPs
|
||||
|
||||
Reference in new issue
Block a user