from ganeti import errors
+
+def _ComputeIpv4NumHosts(network_size):
+ """Derives the number of hosts in an IPv4 network from the size.
+
+ """
+ return 2 ** (32 - network_size)
+
+
IPV4_NETWORK_MIN_SIZE = 30
-IPV4_NETWORK_MIN_NUM_HOSTS = 2 ** (32 - IPV4_NETWORK_MIN_SIZE)
+# FIXME: This limit is for performance reasons. Remove when refactoring
+# for performance tuning was successful.
+IPV4_NETWORK_MAX_SIZE = 16
+IPV4_NETWORK_MIN_NUM_HOSTS = _ComputeIpv4NumHosts(IPV4_NETWORK_MIN_SIZE)
+IPV4_NETWORK_MAX_NUM_HOSTS = _ComputeIpv4NumHosts(IPV4_NETWORK_MAX_SIZE)
class AddressPool(object):
self.net = network
self.network = ipaddr.IPNetwork(self.net.network)
+ if self.network.numhosts > IPV4_NETWORK_MAX_NUM_HOSTS:
+ raise errors.AddressPoolError("A big network with %s host(s) is currently"
+ " not supported. please specify at most a"
+ " /%s network" %
+ (str(self.network.numhosts),
+ IPV4_NETWORK_MAX_SIZE))
+
if self.network.numhosts < IPV4_NETWORK_MIN_NUM_HOSTS:
raise errors.AddressPoolError("A network with only %s host(s) is too"
" small, please specify at least a /%s"
def Validate(self):
assert len(self.reservations) == self._GetSize()
assert len(self.ext_reservations) == self._GetSize()
- all_res = self.reservations & self.ext_reservations
- assert not all_res.any()
if self.gateway is not None:
assert self.gateway in self.network
if self.network6 and self.gateway6:
- assert self.gateway6 in self.network6
+ assert self.gateway6 in self.network6 or self.gateway6.is_link_local
return True
"""
return self.all_reservations.to01().replace("1", "X").replace("0", ".")
- def IsReserved(self, address):
+ def IsReserved(self, address, external=False):
"""Checks if the given IP is reserved.
"""
idx = self._GetAddrIndex(address)
- return self.all_reservations[idx]
+ if external:
+ return self.ext_reservations[idx]
+ else:
+ return self.reservations[idx]
def Reserve(self, address, external=False):
"""Mark an address as used.
"""
- if self.IsReserved(address):
- raise errors.AddressPoolError("%s is already reserved" % address)
+ if self.IsReserved(address, external):
+ if external:
+ msg = "IP %s is already externally reserved" % address
+ else:
+ msg = "IP %s is already used by an instance" % address
+ raise errors.AddressPoolError(msg)
+
self._Mark(address, external=external)
def Release(self, address, external=False):
"""Release a given address reservation.
"""
+ if not self.IsReserved(address, external):
+ if external:
+ msg = "IP %s is not externally reserved" % address
+ else:
+ msg = "IP %s is not used by an instance" % address
+ raise errors.AddressPoolError(msg)
+
self._Mark(address, value=False, external=external)
def GetFreeAddress(self):