Browse Source

Network allocator

Andrea Luzzardi 12 years ago
parent
commit
797bb6e75b
2 changed files with 90 additions and 0 deletions
  1. 63 0
      network.go
  2. 27 0
      network_test.go

+ 63 - 0
network.go

@@ -3,6 +3,7 @@ package docker
 import (
 	"bytes"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"math/rand"
 	"net"
@@ -118,3 +119,65 @@ func allocateNetwork() (*NetworkInterface, error) {
 	}
 	return iface, nil
 }
+
+type NetworkAllocator struct {
+	iface string
+	queue chan (net.IP)
+}
+
+func (alloc *NetworkAllocator) Acquire() (net.IP, error) {
+	select {
+	case ip := <-alloc.queue:
+		return ip, nil
+	default:
+		return net.IP{}, errors.New("No more IP addresses available")
+	}
+	return net.IP{}, nil
+}
+
+func (alloc *NetworkAllocator) Release(ip net.IP) error {
+	select {
+	case alloc.queue <- ip:
+		return nil
+	default:
+		return errors.New("Too many IP addresses have been released")
+	}
+	return nil
+}
+
+func (alloc *NetworkAllocator) PopulateFromNetwork(network *net.IPNet) error {
+	firstIP, _ := networkRange(network)
+	size, err := networkSize(network.Mask)
+	if err != nil {
+		return err
+	}
+	// The queue size should be the network size - 3
+	// -1 for the network address, -1 for the broadcast address and
+	// -1 for the gateway address
+	alloc.queue = make(chan net.IP, size-3)
+	for i := int32(1); i < size-1; i++ {
+		ipNum, err := ipToInt(firstIP)
+		if err != nil {
+			return err
+		}
+		ip, err := intToIp(ipNum + int32(i))
+		if err != nil {
+			return err
+		}
+		// Discard the network IP (that's the host IP address)
+		if ip.Equal(network.IP) {
+			continue
+		}
+		alloc.Release(ip)
+	}
+	return nil
+}
+
+func (alloc *NetworkAllocator) PopulateFromInterface(iface string) error {
+	addr, err := getBridgeAddr(iface)
+	if err != nil {
+		return err
+	}
+	network := addr.(*net.IPNet)
+	return alloc.PopulateFromNetwork(network)
+}

+ 27 - 0
network_test.go

@@ -99,3 +99,30 @@ func TestConversion(t *testing.T) {
 		t.Error(conv.String())
 	}
 }
+
+func TestNetworkAllocator(t *testing.T) {
+	alloc := NetworkAllocator{}
+	_, n, _ := net.ParseCIDR("127.0.0.1/29")
+	alloc.PopulateFromNetwork(n)
+	var lastIP net.IP
+	for i := 0; i < 5; i++ {
+		ip, err := alloc.Acquire()
+		if err != nil {
+			t.Fatal(err)
+		}
+		lastIP = ip
+	}
+	ip, err := alloc.Acquire()
+	if err == nil {
+		t.Fatal("There shouldn't be any IP addresses at this point")
+	}
+	// Release 1 IP
+	alloc.Release(lastIP)
+	ip, err = alloc.Acquire()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !ip.Equal(lastIP) {
+		t.Fatal(ip.String())
+	}
+}