Revision 3e7c63f8
b/snf-cyclades-app/synnefo/db/pools/__init__.py | ||
---|---|---|
27 | 27 |
""" |
28 | 28 |
def __init__(self, pool_table): |
29 | 29 |
self.pool_table = pool_table |
30 |
|
|
30 |
self.pool_size = pool_table.size |
|
31 | 31 |
if pool_table.available_map: |
32 | 32 |
self.available = _bitarray_from_string(pool_table.available_map) |
33 | 33 |
self.reserved = _bitarray_from_string(pool_table.reserved_map) |
34 | 34 |
else: |
35 |
size = self.pool_table.size |
|
36 |
padding = find_padding(size) |
|
37 |
size = size + padding |
|
38 |
self.pool_size = size |
|
39 |
self.available = self._create_empty_pool() |
|
40 |
self.reserved = self._create_empty_pool() |
|
41 |
for i in xrange(0, padding): |
|
42 |
self._reserve(size - i - 1, external=True) |
|
43 |
|
|
44 |
def _create_empty_pool(self): |
|
45 |
assert(self.pool_size % 8 == 0) |
|
46 |
ba = bitarray(self.pool_size) |
|
35 |
self.available = self._create_empty_pool(self.pool_size) |
|
36 |
self.reserved = self._create_empty_pool(self.pool_size) |
|
37 |
self.add_padding(self.pool_size) |
|
38 |
|
|
39 |
def _create_empty_pool(self, size): |
|
40 |
ba = bitarray(size) |
|
47 | 41 |
ba.setall(AVAILABLE) |
48 | 42 |
return ba |
49 | 43 |
|
44 |
def add_padding(self, pool_size): |
|
45 |
bits = find_padding(pool_size) |
|
46 |
self.available.extend([AVAILABLE] * bits) |
|
47 |
self.reserved.extend([UNAVAILABLE] * bits) |
|
48 |
|
|
49 |
def cut_padding(self, pool_size): |
|
50 |
bits = find_padding(pool_size) |
|
51 |
self.available = self.available[:-bits] |
|
52 |
self.reserved = self.reserved[:-bits] |
|
53 |
|
|
50 | 54 |
@property |
51 | 55 |
def pool(self): |
52 | 56 |
return (self.available & self.reserved) |
... | ... | |
57 | 61 |
raise EmptyPool |
58 | 62 |
# Get the first available index |
59 | 63 |
index = int(self.pool.index(AVAILABLE)) |
64 |
assert(index < self.pool_size) |
|
60 | 65 |
self._reserve(index) |
61 | 66 |
return self.index_to_value(index) |
62 | 67 |
|
... | ... | |
85 | 90 |
return not self.pool.any() |
86 | 91 |
|
87 | 92 |
def size(self): |
93 |
"""Return the size of the bitarray(original size + padding).""" |
|
88 | 94 |
return self.pool.length() |
89 | 95 |
|
90 | 96 |
def _reserve(self, index, external=False): |
... | ... | |
106 | 112 |
return self.pool.count(UNAVAILABLE) |
107 | 113 |
|
108 | 114 |
def count_reserved(self): |
109 |
return self.reserved.count(UNAVAILABLE) |
|
115 |
return self.reserved[:self.pool_size].count(UNAVAILABLE)
|
|
110 | 116 |
|
111 | 117 |
def count_unreserved(self): |
112 |
return self.size() - self.count_reserved()
|
|
118 |
return self.pool_size - self.count_reserved()
|
|
113 | 119 |
|
114 | 120 |
def is_available(self, value, index=False): |
115 | 121 |
if not index: |
... | ... | |
126 | 132 |
return self.reserved[idx] == UNAVAILABLE |
127 | 133 |
|
128 | 134 |
def to_01(self): |
129 |
return self.pool.to01() |
|
135 |
return self.pool[:self.pool_size].to01()
|
|
130 | 136 |
|
131 | 137 |
def to_map(self): |
132 | 138 |
return self.to_01().replace("0", "X").replace("1", ".") |
133 | 139 |
|
140 |
def extend(self, bits_num): |
|
141 |
assert(bits_num >= 0) |
|
142 |
self.resize(bits_num) |
|
143 |
|
|
144 |
def shrink(self, bits_num): |
|
145 |
assert(bits_num >= 0) |
|
146 |
size = self.pool_size |
|
147 |
tmp = self.available[(size - bits_num): size] |
|
148 |
if tmp.count(UNAVAILABLE): |
|
149 |
raise Exception("Can not shrink. In use") |
|
150 |
self.resize(-bits_num) |
|
151 |
|
|
152 |
def resize(self, bits_num): |
|
153 |
if bits_num == 0: |
|
154 |
return |
|
155 |
# Cut old padding |
|
156 |
self.cut_padding(self.pool_size) |
|
157 |
# Do the resize |
|
158 |
if bits_num > 0: |
|
159 |
self.available.extend([AVAILABLE] * bits_num) |
|
160 |
self.reserved.extend([AVAILABLE] * bits_num) |
|
161 |
else: |
|
162 |
self.available = self.available[:bits_num] |
|
163 |
self.reserved = self.reserved[:bits_num] |
|
164 |
# Add new padding |
|
165 |
self.pool_size = self.pool_size + bits_num |
|
166 |
self.add_padding(self.pool_size) |
|
167 |
self.pool_table.size = self.pool_size |
|
168 |
|
|
134 | 169 |
def index_to_value(self, index): |
135 | 170 |
raise NotImplementedError |
136 | 171 |
|
... | ... | |
183 | 218 |
do_init = False if pool_table.available_map else True |
184 | 219 |
super(MacPrefixPool, self).__init__(pool_table) |
185 | 220 |
if do_init: |
186 |
for i in xrange(1, self.size()):
|
|
221 |
for i in xrange(1, self.pool_size):
|
|
187 | 222 |
if not self.validate_mac(self.index_to_value(i)): |
188 | 223 |
self._reserve(i, external=True) |
189 | 224 |
# Reserve the first mac-prefix for public-networks |
... | ... | |
221 | 256 |
self._reserve(0, external=True) |
222 | 257 |
if gateway: |
223 | 258 |
self.reserve(gateway, external=True) |
224 |
self._reserve(self.size() - 1, external=True)
|
|
259 |
self._reserve(self.pool_size - 1, external=True)
|
|
225 | 260 |
|
226 | 261 |
def value_to_index(self, value): |
227 | 262 |
addr = ipaddr.IPAddress(value) |
b/snf-cyclades-app/synnefo/db/pools/tests.py | ||
---|---|---|
1 | 1 |
import sys |
2 | 2 |
from synnefo.db.pools import (PoolManager, EmptyPool, BridgePool, |
3 | 3 |
MacPrefixPool, IPPool) |
4 |
from bitarray import bitarray |
|
4 | 5 |
|
5 | 6 |
# Use backported unittest functionality if Python < 2.7 |
6 | 7 |
try: |
... | ... | |
34 | 35 |
def test_created_pool(self): |
35 | 36 |
obj = DummyObject(42) |
36 | 37 |
pool = DummyPool(obj) |
37 |
self.assertEqual(pool.to_01(), '1' * 42 + '0' * 6) |
|
38 |
self.assertEqual(pool.to_map(), '.' * 42 + 'X' * 6) |
|
38 |
self.assertEqual(pool.to_01(), '1' * 42) |
|
39 |
self.assertEqual(pool.to_map(), '.' * 42) |
|
40 |
self.assertEqual(pool.available, bitarray('1' * 42 + '0' * 6)) |
|
41 |
self.assertEqual(pool.reserved, bitarray('1' * 42 + '0' * 6)) |
|
39 | 42 |
|
40 | 43 |
def test_save_pool(self): |
41 | 44 |
obj = DummyObject(42) |
... | ... | |
89 | 92 |
pool.put(0) |
90 | 93 |
self.assertEqual(pool.get(), 1) |
91 | 94 |
|
95 |
def test_extend_pool(self): |
|
96 |
obj = DummyObject(42) |
|
97 |
pool = DummyPool(obj) |
|
98 |
pool.extend(7) |
|
99 |
self.assertEqual(pool.to_01(), '1' * 49) |
|
100 |
self.assertEqual(pool.to_map(), '.' * 49) |
|
101 |
self.assertEqual(pool.available, bitarray('1' * 49 + '0' * 7)) |
|
102 |
self.assertEqual(pool.reserved, bitarray('1' * 49 + '0' * 7)) |
|
103 |
|
|
104 |
def test_shrink_pool(self): |
|
105 |
obj = DummyObject(42) |
|
106 |
pool = DummyPool(obj) |
|
107 |
pool.shrink(3) |
|
108 |
self.assertEqual(pool.to_01(), '1' * 39) |
|
109 |
self.assertEqual(pool.to_map(), '.' * 39) |
|
110 |
self.assertEqual(pool.available, bitarray('1' * 39 + '0' * 1)) |
|
111 |
self.assertEqual(pool.reserved, bitarray('1' * 39 + '0' * 1)) |
|
112 |
|
|
92 | 113 |
|
93 | 114 |
class BridgePoolTestCase(unittest.TestCase): |
94 | 115 |
def test_bridge_conversion(self): |
... | ... | |
96 | 117 |
obj.base = "bridge" |
97 | 118 |
pool = BridgePool(obj) |
98 | 119 |
for i in range(0, 13): |
99 |
self.assertEqual("bridge" + str(i), pool.get()) |
|
120 |
self.assertEqual("bridge" + str(i + 1), pool.get())
|
|
100 | 121 |
pool.put("bridge2") |
101 | 122 |
pool.put("bridge6") |
102 | 123 |
self.assertEqual("bridge2", pool.get()) |
b/snf-cyclades-app/synnefo/logic/management/commands/pool-modify.py | ||
---|---|---|
49 | 49 |
help="Type of pool" |
50 | 50 |
), |
51 | 51 |
make_option('--offset', dest='offset'), |
52 |
make_option('--size', dest='size'), |
|
52 | 53 |
make_option('--base', dest='base'), |
53 | 54 |
make_option('--add-reserved', dest='add-reserved', |
54 | 55 |
help="Comma-seperated list of values to reserve"), |
... | ... | |
90 | 91 |
if base: |
91 | 92 |
pool_row.base = base |
92 | 93 |
|
94 |
# Save now, to avoid conflict with resizing pool.save() |
|
93 | 95 |
pool_row.save() |
96 |
|
|
97 |
if size: |
|
98 |
try: |
|
99 |
size = int(size) |
|
100 |
except ValueError: |
|
101 |
raise CommandError("Invalid size") |
|
102 |
pool = pool_row.get_pool() |
|
103 |
self.resize_pool(pool, pool_row.size, size) |
|
104 |
pool.save() |
|
105 |
|
|
106 |
def resize_pool(self, pool, old_size, new_size): |
|
107 |
if new_size == old_size: |
|
108 |
return |
|
109 |
elif new_size > old_size: |
|
110 |
pool.extend(new_size - old_size) |
|
111 |
else: |
|
112 |
pool.shrink(old_size - new_size) |
|
113 |
pool.save() |
b/snf-cyclades-app/synnefo/logic/management/commands/pool-show.py | ||
---|---|---|
81 | 81 |
|
82 | 82 |
step = (type_ == 'bridge') and 64 or 80 |
83 | 83 |
print_map('Pool', pool.to_map(), step, self.stdout) |
84 |
print_map('Reserved', bitarray_to_map(pool.reserved), step, self.stdout) |
|
84 |
print_map('Reserved', bitarray_to_map(pool.reserved[:pool_row.size]), step, self.stdout)
|
|
85 | 85 |
|
86 | 86 |
|
87 | 87 |
def print_map(name, pool_map, step, out): |
Also available in: Unified diff