Kaynağa Gözat

Finalize core changes with new package

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
Michael Crosby 11 yıl önce
ebeveyn
işleme
ea5b3e193b

+ 11 - 2
network.go

@@ -60,10 +60,13 @@ func CreateBridgeIface(config *DaemonConfig) error {
 
 	var ifaceAddr string
 	if len(config.BridgeIp) != 0 {
-		_, _, err := net.ParseCIDR(config.BridgeIp)
+		_, dockerNetwork, err := net.ParseCIDR(config.BridgeIp)
 		if err != nil {
 			return err
 		}
+		if err := ipallocator.RegisterNetwork(dockerNetwork, nameservers); err != nil {
+			return err
+		}
 		ifaceAddr = config.BridgeIp
 	} else {
 		for _, addr := range addrs {
@@ -534,6 +537,7 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
 		return manager, nil
 	}
 
+	var network *net.IPNet
 	addr, err := getIfaceAddr(config.BridgeIface)
 	if err != nil {
 		// If the iface is not found, try to create it
@@ -544,8 +548,13 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
 		if err != nil {
 			return nil, err
 		}
+		network = addr.(*net.IPNet)
+	} else {
+		network = addr.(*net.IPNet)
+		if err := ipallocator.RegisterExistingNetwork(network); err != nil {
+			return nil, err
+		}
 	}
-	network := addr.(*net.IPNet)
 
 	// Configure iptables for link support
 	if config.EnableIptables {

+ 59 - 9
networkdriver/ipallocator/allocator.go

@@ -21,12 +21,16 @@ var (
 	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
 	ErrNoAvailableIPs                 = errors.New("no available ip addresses on network")
 	ErrIPAlreadyAllocated             = errors.New("ip already allocated")
+	ErrNetworkNotRegistered           = errors.New("network not registered")
 
 	lock         = sync.Mutex{}
 	allocatedIPs = networkSet{}
 	availableIPS = networkSet{}
 )
 
+// RegisterNetwork registers a new network with the allocator
+// and validates that it contains a valid ip that does not overlap
+// with existing routes and nameservers
 func RegisterNetwork(network *net.IPNet, nameservers []string) error {
 	lock.Lock()
 	defer lock.Unlock()
@@ -47,19 +51,36 @@ func RegisterNetwork(network *net.IPNet, nameservers []string) error {
 	if err := checkNameserverOverlaps(nameservers, network); err != nil {
 		return err
 	}
+	return RegisterExistingNetwork(network)
+}
 
+// RegisterExistingNetwork registers an exising network created
+// for use with the allocator but does not perform any validation
+func RegisterExistingNetwork(network *net.IPNet) error {
 	n := newIPNet(network)
 
-	allocatedIPs[n] = &iPSet{}
-	availableIPS[n] = &iPSet{}
+	if _, exists := allocatedIPs[n]; !exists {
+		allocatedIPs[n] = &iPSet{}
+	}
+	if _, exists := availableIPS[n]; !exists {
+		availableIPS[n] = &iPSet{}
+	}
 
 	return nil
 }
 
+// RequestIP requests an available ip from the given network.  It
+// will return the next available ip if the ip provided is nil.  If the
+// ip provided is not nil it will validate that the provided ip is available
+// for use or return an error
 func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
 	lock.Lock()
 	defer lock.Unlock()
 
+	if !networkExists(network) {
+		return nil, ErrNetworkNotRegistered
+	}
+
 	if ip == nil {
 		next, err := getNextIp(network)
 		if err != nil {
@@ -74,18 +95,21 @@ func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
 	return ip, nil
 }
 
+// ReleaseIP adds the provided ip back into the pool of
+// available ips to be returned for use.
 func ReleaseIP(network *net.IPNet, ip *net.IP) error {
 	lock.Lock()
 	defer lock.Unlock()
 
+	if !networkExists(network) {
+		return ErrNetworkNotRegistered
+	}
+
 	var (
-		first, _  = networkRange(network)
-		base      = ipToInt(&first)
 		n         = newIPNet(network)
 		existing  = allocatedIPs[n]
 		available = availableIPS[n]
-		i         = ipToInt(ip)
-		pos       = i - base
+		pos       = getPosition(network, ip)
 	)
 
 	existing.Remove(int(pos))
@@ -94,6 +118,19 @@ func ReleaseIP(network *net.IPNet, ip *net.IP) error {
 	return nil
 }
 
+// convert the ip into the position in the subnet.  Only
+// position are saved in the set
+func getPosition(network *net.IPNet, ip *net.IP) int32 {
+	var (
+		first, _ = networkRange(network)
+		base     = ipToInt(&first)
+		i        = ipToInt(ip)
+	)
+	return i - base
+}
+
+// return an available ip if one is currently available.  If not,
+// return the next available ip for the nextwork
 func getNextIp(network *net.IPNet) (*net.IP, error) {
 	var (
 		n         = newIPNet(network)
@@ -134,11 +171,18 @@ func getNextIp(network *net.IPNet) (*net.IP, error) {
 }
 
 func registerIP(network *net.IPNet, ip *net.IP) error {
-	existing := allocatedIPs[newIPNet(network)]
-	// checking position not ip
-	if existing.Exists(int(ipToInt(ip))) {
+	var (
+		n         = newIPNet(network)
+		existing  = allocatedIPs[n]
+		available = availableIPS[n]
+		pos       = getPosition(network, ip)
+	)
+
+	if existing.Exists(int(pos)) {
 		return ErrIPAlreadyAllocated
 	}
+	available.Remove(int(pos))
+
 	return nil
 }
 
@@ -241,3 +285,9 @@ func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
 	}
 	return nil
 }
+
+func networkExists(network *net.IPNet) bool {
+	n := newIPNet(network)
+	_, exists := allocatedIPs[n]
+	return exists
+}

+ 2 - 0
networkdriver/ipallocator/allocator_test.go

@@ -386,6 +386,8 @@ func TestIPAllocator(t *testing.T) {
 	// 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
 	//                       ↑
 
+	// Reordered these because the new set will always return the
+	// lowest ips first and not in the order that they were released
 	assertIPEquals(t, &expectedIPs[2], newIPs[0])
 	assertIPEquals(t, &expectedIPs[3], newIPs[1])
 	assertIPEquals(t, &expectedIPs[4], newIPs[2])