Revision a27f9450
b/lib/network.py | ||
---|---|---|
29 | 29 |
|
30 | 30 |
from ganeti import errors |
31 | 31 |
|
32 |
|
|
32 | 33 |
class AddressPool(object): |
33 | 34 |
"""Address pool class, wrapping an objects.Network object |
34 | 35 |
|
... | ... | |
36 | 37 |
L{objects.Network} objects. |
37 | 38 |
|
38 | 39 |
""" |
40 |
FREE = bitarray('0') |
|
41 |
RESERVED = bitarray('1') |
|
39 | 42 |
def __init__(self, network): |
40 | 43 |
"""Initialize a new IPv4 address pool from an objects.Network object |
41 | 44 |
|
... | ... | |
63 | 66 |
self.reservations = bitarray(self.net.reservations) |
64 | 67 |
else: |
65 | 68 |
self.reservations = bitarray(self.network.numhosts) |
69 |
# pylint: disable=E1103 |
|
66 | 70 |
self.reservations.setall(False) |
67 | 71 |
|
68 | 72 |
if self.net.ext_reservations: |
69 | 73 |
self.ext_reservations = bitarray(self.net.ext_reservations) |
70 | 74 |
else: |
71 | 75 |
self.ext_reservations = bitarray(self.network.numhosts) |
76 |
# pylint: disable=E1103 |
|
72 | 77 |
self.ext_reservations.setall(False) |
73 | 78 |
|
74 | 79 |
assert len(self.reservations) == self.network.numhosts |
75 | 80 |
assert len(self.ext_reservations) == self.network.numhosts |
76 | 81 |
|
77 |
def _Contains(self, address):
|
|
82 |
def Contains(self, address): |
|
78 | 83 |
if address is None: |
79 | 84 |
return False |
80 | 85 |
addr = ipaddr.IPAddress(address) |
... | ... | |
90 | 95 |
|
91 | 96 |
return int(addr) - int(self.network.network) |
92 | 97 |
|
93 |
def _Update(self):
|
|
98 |
def Update(self): |
|
94 | 99 |
"""Write address pools back to the network object""" |
100 |
# pylint: disable=E1103 |
|
95 | 101 |
self.net.ext_reservations = self.ext_reservations.to01() |
96 | 102 |
self.net.reservations = self.reservations.to01() |
97 | 103 |
|
... | ... | |
101 | 107 |
self.ext_reservations[idx] = value |
102 | 108 |
else: |
103 | 109 |
self.reservations[idx] = value |
104 |
self._Update()
|
|
110 |
self.Update() |
|
105 | 111 |
|
106 | 112 |
def _GetSize(self): |
107 |
return 2**(32 - self.network.prefixlen)
|
|
113 |
return 2 ** (32 - self.network.prefixlen)
|
|
108 | 114 |
|
109 | 115 |
@property |
110 | 116 |
def all_reservations(self): |
... | ... | |
115 | 121 |
assert self.net.family == 4 |
116 | 122 |
assert len(self.reservations) == self._GetSize() |
117 | 123 |
assert len(self.ext_reservations) == self._GetSize() |
118 |
assert not (self.reservations & self.ext_reservations).any() |
|
124 |
all_res = self.reservations & self.ext_reservations |
|
125 |
assert not all_res.any() |
|
119 | 126 |
|
120 | 127 |
if self.gateway is not None: |
121 | 128 |
assert self.net.family == self.gateway.version |
... | ... | |
168 | 175 |
return address |
169 | 176 |
|
170 | 177 |
def GenerateFree(self): |
171 |
"""A generator for free addresses.""" |
|
172 |
def _iter_free(): |
|
173 |
for idx in self.all_reservations.search("0", 64): |
|
174 |
yield str(self.network[idx]) |
|
178 |
"""Returns the first free address of the network if any or |
|
179 |
raises an error if it is full. |
|
175 | 180 |
|
176 |
return _iter_free().next |
|
181 |
""" |
|
182 |
if self.IsFull(): |
|
183 |
raise errors.AddressPoolError("%s is full" % self.network) |
|
184 |
[idx] = self.all_reservations.search(self.FREE, 1) |
|
185 |
return str(self.network[idx]) |
|
177 | 186 |
|
178 | 187 |
def GetExternalReservations(self): |
179 | 188 |
"""Returns a list of all externally reserved addresses""" |
180 |
idxs = self.ext_reservations.search("1") |
|
189 |
# pylint: disable=E1103 |
|
190 |
idxs = self.ext_reservations.search(self.RESERVED) |
|
181 | 191 |
return [str(self.network[idx]) for idx in idxs] |
182 | 192 |
|
183 | 193 |
@classmethod |
... | ... | |
188 | 198 |
|
189 | 199 |
""" |
190 | 200 |
obj = cls(net) |
191 |
obj._Update()
|
|
201 |
obj.Update() |
|
192 | 202 |
for ip in [obj.network[0], obj.network[-1]]: |
193 | 203 |
obj.Reserve(ip, external=True) |
194 | 204 |
if obj.net.gateway is not None: |
Also available in: Unified diff