Browse code

Network allocator

Andrea Luzzardi authored on 2013/02/26 03:45:23
Showing 2 changed files
... ...
@@ -3,6 +3,7 @@ package docker
3 3
 import (
4 4
 	"bytes"
5 5
 	"encoding/binary"
6
+	"errors"
6 7
 	"fmt"
7 8
 	"math/rand"
8 9
 	"net"
... ...
@@ -118,3 +119,65 @@ func allocateNetwork() (*NetworkInterface, error) {
118 118
 	}
119 119
 	return iface, nil
120 120
 }
121
+
122
+type NetworkAllocator struct {
123
+	iface string
124
+	queue chan (net.IP)
125
+}
126
+
127
+func (alloc *NetworkAllocator) Acquire() (net.IP, error) {
128
+	select {
129
+	case ip := <-alloc.queue:
130
+		return ip, nil
131
+	default:
132
+		return net.IP{}, errors.New("No more IP addresses available")
133
+	}
134
+	return net.IP{}, nil
135
+}
136
+
137
+func (alloc *NetworkAllocator) Release(ip net.IP) error {
138
+	select {
139
+	case alloc.queue <- ip:
140
+		return nil
141
+	default:
142
+		return errors.New("Too many IP addresses have been released")
143
+	}
144
+	return nil
145
+}
146
+
147
+func (alloc *NetworkAllocator) PopulateFromNetwork(network *net.IPNet) error {
148
+	firstIP, _ := networkRange(network)
149
+	size, err := networkSize(network.Mask)
150
+	if err != nil {
151
+		return err
152
+	}
153
+	// The queue size should be the network size - 3
154
+	// -1 for the network address, -1 for the broadcast address and
155
+	// -1 for the gateway address
156
+	alloc.queue = make(chan net.IP, size-3)
157
+	for i := int32(1); i < size-1; i++ {
158
+		ipNum, err := ipToInt(firstIP)
159
+		if err != nil {
160
+			return err
161
+		}
162
+		ip, err := intToIp(ipNum + int32(i))
163
+		if err != nil {
164
+			return err
165
+		}
166
+		// Discard the network IP (that's the host IP address)
167
+		if ip.Equal(network.IP) {
168
+			continue
169
+		}
170
+		alloc.Release(ip)
171
+	}
172
+	return nil
173
+}
174
+
175
+func (alloc *NetworkAllocator) PopulateFromInterface(iface string) error {
176
+	addr, err := getBridgeAddr(iface)
177
+	if err != nil {
178
+		return err
179
+	}
180
+	network := addr.(*net.IPNet)
181
+	return alloc.PopulateFromNetwork(network)
182
+}
... ...
@@ -99,3 +99,30 @@ func TestConversion(t *testing.T) {
99 99
 		t.Error(conv.String())
100 100
 	}
101 101
 }
102
+
103
+func TestNetworkAllocator(t *testing.T) {
104
+	alloc := NetworkAllocator{}
105
+	_, n, _ := net.ParseCIDR("127.0.0.1/29")
106
+	alloc.PopulateFromNetwork(n)
107
+	var lastIP net.IP
108
+	for i := 0; i < 5; i++ {
109
+		ip, err := alloc.Acquire()
110
+		if err != nil {
111
+			t.Fatal(err)
112
+		}
113
+		lastIP = ip
114
+	}
115
+	ip, err := alloc.Acquire()
116
+	if err == nil {
117
+		t.Fatal("There shouldn't be any IP addresses at this point")
118
+	}
119
+	// Release 1 IP
120
+	alloc.Release(lastIP)
121
+	ip, err = alloc.Acquire()
122
+	if err != nil {
123
+		t.Fatal(err)
124
+	}
125
+	if !ip.Equal(lastIP) {
126
+		t.Fatal(ip.String())
127
+	}
128
+}