Merge lp:~santhoshkumar/network-service/melange_framework into lp:~rajarammallya/network-service/melange_framework
- melange_framework
- Merge into melange_framework
Proposed by
Santhosh Kumar Muniraj
Status: | Merged |
---|---|
Merged at revision: | 34 |
Proposed branch: | lp:~santhoshkumar/network-service/melange_framework |
Merge into: | lp:~rajarammallya/network-service/melange_framework |
Diff against target: |
765 lines (+365/-230) 4 files modified
melange/ipam/models.py (+20/-25) melange/ipam/service.py (+76/-41) tests/unit/test_ipam_models.py (+20/-3) tests/unit/test_service.py (+249/-161) |
To merge this branch: | bzr merge lp:~santhoshkumar/network-service/melange_framework |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rajaram Mallya | Approve | ||
Review via email:
|
Commit message
Description of the change
* Policy can eager load ip_rules
* Exposed API for index, create and show of Policies.
To post a comment you must log in.
- 31. By Rajaram Mallya
-
Vinkesh/
Rajaram| cleaned up test_extensions
Revision history for this message

Rajaram Mallya (rajarammallya) : | # |
review:
Approve
- 32. By Rajaram Mallya
-
merge from: Santhosh/Vinkesh | Exposed API for ip_block policy resource
- 33. By Rajaram Mallya
-
Vinkesh/
Rajaram| added extensions to app - 34. By Rajaram Mallya
-
Rajaram/Deepak| Merge changes from Santosh branch of Iprange rules and nat controller split
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'melange/ipam/models.py' |
2 | --- melange/ipam/models.py 2011-06-02 13:24:42 +0000 |
3 | +++ melange/ipam/models.py 2011-06-06 04:56:28 +0000 |
4 | @@ -127,13 +127,8 @@ |
5 | def allowed_by_policy(cls, ip_block, policy, address): |
6 | return policy == None or policy.allows(ip_block.cidr, address) |
7 | |
8 | - def policy(self, eager_load_rules=False): |
9 | - policy = Policy.find_by_id(self.policy_id) |
10 | - if policy == None: |
11 | - return None |
12 | - if eager_load_rules: |
13 | - policy.eager_load() |
14 | - return policy |
15 | + def policy(self): |
16 | + return Policy.find_by_id(self.policy_id) |
17 | |
18 | def allocate_ip(self, port_id=None, address=None): |
19 | candidate_ip = None |
20 | @@ -162,7 +157,7 @@ |
21 | raise AddressDoesNotBelongError( |
22 | "Address does not belong to IpBlock") |
23 | |
24 | - policy = self.policy(eager_load_rules=True) |
25 | + policy = self.policy() |
26 | if not IpBlock.allowed_by_policy(self, policy, address): |
27 | raise AddressDisallowedByPolicyError( |
28 | "Block policy does not allow this address") |
29 | @@ -172,7 +167,7 @@ |
30 | def _generate_ip(self, allocated_addresses): |
31 | #TODO: very inefficient way to generate ips, |
32 | #will look at better algos for this |
33 | - policy = self.policy(eager_load_rules=True) |
34 | + policy = self.policy() |
35 | for ip in IPNetwork(self.cidr): |
36 | if IpBlock.allowed_by_policy(self, policy, str(ip)) and (str(ip) |
37 | not in allocated_addresses): |
38 | @@ -271,24 +266,24 @@ |
39 | def find_by_name(cls, name): |
40 | return db_api.find_by(Policy, name=name) |
41 | |
42 | - def ip_rules(self): |
43 | - if hasattr(self, 'ip_range_rules'): |
44 | - return self.ip_range_rules |
45 | - return self._find_ip_range_rules() |
46 | + def create_unusable_range(self, attributes): |
47 | + attributes['policy_id'] = self.id |
48 | + ip_range = IpRange.create(attributes) |
49 | + if hasattr(self, '_unusable_ip_ranges'): |
50 | + self._unusable_ip_ranges.append(ip_range) |
51 | + return ip_range |
52 | + |
53 | + def unusable_ip_ranges(self): |
54 | + if not hasattr(self, '_unusable_ip_ranges'): |
55 | + self._load_unusable_ip_ranges() |
56 | + return self._unusable_ip_ranges |
57 | |
58 | def allows(self, cidr, address): |
59 | - return not any(ip_rule.contains(cidr, address) |
60 | - for ip_rule in self.ip_rules()) |
61 | - |
62 | - def eager_load(self): |
63 | - self._load_ip_range_rules() |
64 | - return self |
65 | - |
66 | - def _load_ip_range_rules(self): |
67 | - self.ip_range_rules = self._find_ip_range_rules() |
68 | - |
69 | - def _find_ip_range_rules(self): |
70 | - return IpRange.find_all_by_policy(self.id).all() |
71 | + return not any(ip_range.contains(cidr, address) |
72 | + for ip_range in self.unusable_ip_ranges()) |
73 | + |
74 | + def _load_unusable_ip_ranges(self): |
75 | + self._unusable_ip_ranges = IpRange.find_all_by_policy(self.id).all() |
76 | |
77 | def data_fields(self): |
78 | return ['id', 'name'] |
79 | |
80 | === modified file 'melange/ipam/service.py' |
81 | --- melange/ipam/service.py 2011-06-03 05:46:27 +0000 |
82 | +++ melange/ipam/service.py 2011-06-06 04:56:28 +0000 |
83 | @@ -49,6 +49,15 @@ |
84 | def _get_optionals(self, params, *args): |
85 | return [params.get(key, None) for key in args] |
86 | |
87 | + def _parse_ips(self, addresses): |
88 | + return [IpBlock.find_or_allocate_ip(address["ip_block_id"], |
89 | + address["ip_address"]) |
90 | + for address in json.loads(addresses)] |
91 | + |
92 | + def _get_addresses(self, ips): |
93 | + return self._json_response( |
94 | + dict(ip_addresses=[ip_address.data() for ip_address in ips])) |
95 | + |
96 | |
97 | class IpBlockController(BaseController): |
98 | |
99 | @@ -100,46 +109,63 @@ |
100 | ip_address.restore() |
101 | |
102 | |
103 | -class NatController(BaseController): |
104 | - |
105 | - def create_locals(self, request, ip_block_id, address): |
106 | - global_ip = IpBlock.find_or_allocate_ip(ip_block_id, address) |
107 | - local_ips = self._parse_ips(request.params["ip_addresses"]) |
108 | - global_ip.add_inside_locals(local_ips) |
109 | - |
110 | - def create_globals(self, request, ip_block_id, address): |
111 | +class InsideGlobalsController(BaseController): |
112 | + |
113 | + def create(self, request, ip_block_id, address): |
114 | local_ip = IpBlock.find_or_allocate_ip(ip_block_id, address) |
115 | global_ips = self._parse_ips(request.params["ip_addresses"]) |
116 | local_ip.add_inside_globals(global_ips) |
117 | |
118 | - def show_globals(self, request, ip_block_id, address): |
119 | + def index(self, request, ip_block_id, address): |
120 | ip = IpBlock.find(ip_block_id).find_allocated_ip(address) |
121 | return self._get_addresses(ip.inside_globals( |
122 | **self._extract_limits(request.params))) |
123 | |
124 | - def show_locals(self, request, ip_block_id, address): |
125 | - ip = IpBlock.find(ip_block_id).find_allocated_ip(address) |
126 | - return self._get_addresses(ip.inside_locals( |
127 | - **self._extract_limits(request.params))) |
128 | - |
129 | - def delete_globals(self, request, ip_block_id, address, |
130 | - inside_global_address=None): |
131 | + def delete(self, request, ip_block_id, address, |
132 | + inside_global_address=None): |
133 | local_ip = IpBlock.find(ip_block_id).find_allocated_ip(address) |
134 | local_ip.remove_inside_globals(inside_global_address) |
135 | |
136 | - def delete_locals(self, request, ip_block_id, address, |
137 | - inside_local_address=None): |
138 | + |
139 | +class InsideLocalsController(BaseController): |
140 | + |
141 | + def create(self, request, ip_block_id, address): |
142 | + global_ip = IpBlock.find_or_allocate_ip(ip_block_id, address) |
143 | + local_ips = self._parse_ips(request.params["ip_addresses"]) |
144 | + global_ip.add_inside_locals(local_ips) |
145 | + |
146 | + def index(self, request, ip_block_id, address): |
147 | + ip = IpBlock.find(ip_block_id).find_allocated_ip(address) |
148 | + return self._get_addresses(ip.inside_locals( |
149 | + **self._extract_limits(request.params))) |
150 | + |
151 | + def delete(self, request, ip_block_id, address, |
152 | + inside_local_address=None): |
153 | global_ip = IpBlock.find(ip_block_id).find_allocated_ip(address) |
154 | global_ip.remove_inside_locals(inside_local_address) |
155 | |
156 | - def _get_addresses(self, ips): |
157 | - return self._json_response( |
158 | - dict(ip_addresses=[ip_address.data() for ip_address in ips])) |
159 | - |
160 | - def _parse_ips(self, addresses): |
161 | - return [IpBlock.find_or_allocate_ip(address["ip_block_id"], |
162 | - address["ip_address"]) |
163 | - for address in json.loads(addresses)] |
164 | + |
165 | +class PoliciesController(BaseController): |
166 | + |
167 | + def index(self, request): |
168 | + policies = Policy.find_all() |
169 | + return self._json_response(body=dict( |
170 | + policies=[policy.data() for policy in policies])) |
171 | + |
172 | + def show(self, request, id): |
173 | + return self._json_response(Policy.find(id).data()) |
174 | + |
175 | + def create(self, request): |
176 | + policy = Policy.create(request.params) |
177 | + return self._json_response(policy.data(), status=201) |
178 | + |
179 | + |
180 | +class UnusableIpRangesController(BaseController): |
181 | + |
182 | + def create(self, request, policy_id): |
183 | + policy = Policy.find(policy_id) |
184 | + ip_range = policy.create_unusable_range(request.params.copy()) |
185 | + return self._json_response(ip_range.data(), status=201) |
186 | |
187 | |
188 | class PoliciesController(BaseController): |
189 | @@ -163,32 +189,37 @@ |
190 | mapper = routes.Mapper() |
191 | ip_block_controller = IpBlockController() |
192 | ip_address_controller = IpAddressController() |
193 | - nat_controller = NatController() |
194 | + inside_globals_controller = InsideGlobalsController() |
195 | + inside_locals_controller = InsideLocalsController() |
196 | mapper.resource("ip_block", "/ipam/ip_blocks", |
197 | controller=ip_block_controller) |
198 | mapper.resource("policy", "/ipam/policies", |
199 | controller=PoliciesController()) |
200 | |
201 | - with mapper.submapper(controller=nat_controller, |
202 | + with mapper.submapper(controller=inside_globals_controller, |
203 | path_prefix="/ipam/ip_blocks/{ip_block_id}/" |
204 | "ip_addresses/{address:.+?}/") as submap: |
205 | - submap.connect("inside_locals", action="create_locals", |
206 | - conditions=dict(method=["POST"])) |
207 | - submap.connect("inside_globals", action="create_globals", |
208 | - conditions=dict(method=["POST"])) |
209 | - submap.connect("inside_globals", action="show_globals", |
210 | - conditions=dict(method=["GET"])) |
211 | - submap.connect("inside_locals", action="show_locals", |
212 | - conditions=dict(method=["GET"])) |
213 | - submap.connect("inside_globals", action="delete_globals", |
214 | - conditions=dict(method=["DELETE"])) |
215 | - submap.connect("inside_locals", action="delete_locals", |
216 | + submap.connect("inside_globals", action="create", |
217 | + conditions=dict(method=["POST"])) |
218 | + submap.connect("inside_globals", action="index", |
219 | + conditions=dict(method=["GET"])) |
220 | + submap.connect("inside_globals", action="delete", |
221 | conditions=dict(method=["DELETE"])) |
222 | submap.connect("inside_globals/{inside_global_address:.+?}", |
223 | - action="delete_globals", |
224 | + action="delete", |
225 | conditions=dict(method=["DELETE"])) |
226 | + |
227 | + with mapper.submapper(controller=inside_locals_controller, |
228 | + path_prefix="/ipam/ip_blocks/{ip_block_id}/" |
229 | + "ip_addresses/{address:.+?}/") as submap: |
230 | + submap.connect("inside_locals", action="create", |
231 | + conditions=dict(method=["POST"])) |
232 | + submap.connect("inside_locals", action="index", |
233 | + conditions=dict(method=["GET"])) |
234 | submap.connect("inside_locals/{inside_local_address:.+?}", |
235 | - action="delete_locals", |
236 | + action="delete", |
237 | + conditions=dict(method=["DELETE"])) |
238 | + submap.connect("inside_locals", action="delete", |
239 | conditions=dict(method=["DELETE"])) |
240 | |
241 | mapper.connect("/ipam/ip_blocks/{ip_block_id}/" |
242 | @@ -207,6 +238,10 @@ |
243 | controller=ip_address_controller, |
244 | parent_resource=dict(member_name="ip_block", |
245 | collection_name="/ipam/ip_blocks")) |
246 | + mapper.resource("unusable_ip_range", "unusable_ip_ranges", |
247 | + controller=UnusableIpRangesController(), |
248 | + parent_resource=dict(member_name="policy", |
249 | + collection_name="/ipam/policies")) |
250 | mapper.connect("/", controller=ip_block_controller, action="version") |
251 | super(API, self).__init__(mapper) |
252 | |
253 | |
254 | === modified file 'tests/unit/test_ipam_models.py' |
255 | --- tests/unit/test_ipam_models.py 2011-06-02 13:24:42 +0000 |
256 | +++ tests/unit/test_ipam_models.py 2011-06-06 04:56:28 +0000 |
257 | @@ -430,14 +430,14 @@ |
258 | self.assertFalse(policy.allows("10.0.0.0/29", "10.0.0.4")) |
259 | self.assertTrue(policy.allows("10.0.0.0/29", "10.0.0.6")) |
260 | |
261 | - def test_ip_rules_for_policy(self): |
262 | + def test_unusable_ip_ranges_for_policy(self): |
263 | policy = Policy.create({'name': "blah"}) |
264 | ip_range1 = IpRange.create({'offset': 0, 'length': 2, |
265 | 'policy_id': policy.id}) |
266 | ip_range2 = IpRange.create({'offset': 3, 'length': 2, |
267 | 'policy_id': policy.id}) |
268 | |
269 | - self.assertEqual(policy.ip_rules(), [ip_range1, ip_range2]) |
270 | + self.assertEqual(policy.unusable_ip_ranges(), [ip_range1, ip_range2]) |
271 | |
272 | def test_data(self): |
273 | policy_data = {'name': 'Infrastructure'} |
274 | @@ -454,6 +454,23 @@ |
275 | |
276 | self.assertEqual(policies, [policy1, policy2]) |
277 | |
278 | + def test_create_unusable_ip_range(self): |
279 | + policy = Policy.create({'name': "BLAH"}) |
280 | + |
281 | + ip_range = policy.create_unusable_range({'offset': 1, 'length': 2}) |
282 | + |
283 | + self.assertEqual(ip_range, |
284 | + IpRange.find_all_by_policy(policy.id).first()) |
285 | + self.assertEqual(ip_range.offset, 1) |
286 | + self.assertEqual(ip_range.length, 2) |
287 | + |
288 | + def test_unusable_ip_ranges_include_newly_created_ip_ranges(self): |
289 | + policy = Policy.create({'name': "BLAH"}) |
290 | + policy.unusable_ip_ranges() |
291 | + ip_range = policy.create_unusable_range({'offset': 1, 'length': 2}) |
292 | + |
293 | + self.assertTrue(ip_range in policy.unusable_ip_ranges()) |
294 | + |
295 | |
296 | class TestIpRange(BaseTest): |
297 | |
298 | @@ -461,7 +478,7 @@ |
299 | policy = Policy.create({'name': 'blah'}) |
300 | IpRange.create({'offset': 3, 'length': 10, 'policy_id': policy.id}) |
301 | |
302 | - ip_range = policy.ip_rules()[0] |
303 | + ip_range = policy.unusable_ip_ranges()[0] |
304 | |
305 | self.assertEqual(ip_range.offset, 3) |
306 | self.assertEqual(ip_range.length, 10) |
307 | |
308 | === modified file 'tests/unit/test_service.py' |
309 | --- tests/unit/test_service.py 2011-06-03 05:46:27 +0000 |
310 | +++ tests/unit/test_service.py 2011-06-06 04:56:28 +0000 |
311 | @@ -21,9 +21,9 @@ |
312 | |
313 | from tests.unit import BaseTest |
314 | from melange.common import config |
315 | -from melange.ipam.models import IpBlock, IpAddress, Policy |
316 | from melange.ipam import models |
317 | from melange.db import session |
318 | +from melange.ipam.models import IpBlock, IpAddress, Policy, IpRange |
319 | |
320 | |
321 | class TestController(BaseTest): |
322 | @@ -246,112 +246,9 @@ |
323 | self.assertEqual(ip_addresses, [ip.address for ip in ips]) |
324 | |
325 | |
326 | -class TestIpNatController(TestController): |
327 | - |
328 | - def test_create_inside_local_nat(self): |
329 | - global_block, = _create_blocks("169.1.1.1/32") |
330 | - local_block1, = _create_blocks("10.1.1.1/32") |
331 | - local_block2, = _create_blocks("10.0.0.1/32") |
332 | - |
333 | - url = "/ipam/ip_blocks/%s/ip_addresses/169.1.1.1/inside_locals" |
334 | - json_data = [ |
335 | - {'ip_block_id': local_block1.id, 'ip_address': "10.1.1.1"}, |
336 | - {'ip_block_id': local_block2.id, 'ip_address': "10.0.0.1"}, |
337 | - ] |
338 | - request_data = {'ip_addresses': json.dumps(json_data)} |
339 | - response = self.app.post(url % global_block.id, request_data) |
340 | - |
341 | - self.assertEqual(response.status, "200 OK") |
342 | - ips = global_block.find_allocated_ip("169.1.1.1").inside_locals() |
343 | - inside_locals = [ip.address for ip in ips] |
344 | - |
345 | - self.assertEqual(len(inside_locals), 2) |
346 | - self.assertTrue("10.1.1.1" in inside_locals) |
347 | - self.assertTrue("10.0.0.1" in inside_locals) |
348 | - local_ip = IpAddress.find_by_block_and_address(local_block1.id, |
349 | - "10.1.1.1") |
350 | - self.assertEqual(local_ip.inside_globals()[0].address, "169.1.1.1") |
351 | - |
352 | - def test_create_inside_global_nat(self): |
353 | - global_block, local_block = _create_blocks('192.1.1.1/32', |
354 | - '10.1.1.1/32') |
355 | - global_ip = global_block.allocate_ip() |
356 | - local_ip = local_block.allocate_ip() |
357 | - |
358 | - response = self.app.post("/ipam/ip_blocks/%s/ip_addresses/%s/" |
359 | - "inside_globals" |
360 | - % (local_block.id, local_ip.address), |
361 | - {"ip_addresses": json.dumps( |
362 | - [{"ip_block_id": global_block.id, |
363 | - "ip_address": global_ip.address}])}) |
364 | - |
365 | - self.assertEqual(response.status, "200 OK") |
366 | - |
367 | - self.assertEqual(len(local_ip.inside_globals()), 1) |
368 | - self.assertEqual(global_ip.id, local_ip.inside_globals()[0].id) |
369 | - self.assertEqual(local_ip.id, global_ip.inside_locals()[0].id) |
370 | - |
371 | - def test_delete_inside_globals(self): |
372 | - global_block, local_block = _create_blocks('192.1.1.1/32', |
373 | - '10.1.1.1/32') |
374 | - global_ip = global_block.allocate_ip() |
375 | - local_ip = local_block.allocate_ip() |
376 | - local_ip.add_inside_globals([global_ip]) |
377 | - |
378 | - response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
379 | - "inside_globals" |
380 | - % (local_block.id, local_ip.address)) |
381 | - |
382 | - self.assertEqual(response.status, "200 OK") |
383 | - self.assertEqual(local_ip.inside_globals(), []) |
384 | - |
385 | - def test_delete_inside_global_for_specific_address(self): |
386 | - global_block, local_block = _create_blocks('192.1.1.1/28', |
387 | - '10.1.1.1/28') |
388 | - global_ips, = _allocate_ips((global_block, 3)) |
389 | - local_ip = local_block.allocate_ip() |
390 | - local_ip.add_inside_globals(global_ips) |
391 | - |
392 | - response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
393 | - "inside_globals/%s" |
394 | - % (local_block.id, local_ip.address, |
395 | - global_ips[1].address)) |
396 | - |
397 | - globals_left = [ip.address for ip in local_ip.inside_globals()] |
398 | - self.assertEqual(globals_left, [global_ips[0].address, |
399 | - global_ips[2].address]) |
400 | - |
401 | - def test_delete_inside_local_for_specific_address(self): |
402 | - global_block, local_block = _create_blocks('192.1.1.1/28', |
403 | - '10.1.1.1/28') |
404 | - local_ips, = _allocate_ips((local_block, 3)) |
405 | - global_ip = global_block.allocate_ip() |
406 | - global_ip.add_inside_locals(local_ips) |
407 | - |
408 | - response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
409 | - "inside_locals/%s" |
410 | - % (global_block.id, global_ip.address, |
411 | - local_ips[1].address)) |
412 | - |
413 | - locals_left = [ip.address for ip in global_ip.inside_locals()] |
414 | - self.assertEqual(locals_left, [local_ips[0].address, |
415 | - local_ips[2].address]) |
416 | - |
417 | - def test_delete_inside_locals(self): |
418 | - global_block, local_block = _create_blocks('192.1.1.1/32', |
419 | - '10.1.1.1/32') |
420 | - global_ip = global_block.allocate_ip() |
421 | - local_ip = local_block.allocate_ip() |
422 | - global_ip.add_inside_locals([local_ip]) |
423 | - |
424 | - response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
425 | - "inside_locals" |
426 | - % (global_block.id, global_ip.address)) |
427 | - |
428 | - self.assertEqual(response.status, "200 OK") |
429 | - self.assertEqual(global_ip.inside_locals(), []) |
430 | - |
431 | - def test_show_inside_globals(self): |
432 | +class TestInsideGlobalsController(TestController): |
433 | + |
434 | + def test_index(self): |
435 | local_block, global_block_1, global_block_2 =\ |
436 | _create_blocks("10.1.1.1/30", |
437 | "192.1.1.1/30", |
438 | @@ -370,7 +267,7 @@ |
439 | {'ip_addresses': _data_of(global_ip_1, |
440 | global_ip_2)}) |
441 | |
442 | - def test_show_inside_globals_with_pagination(self): |
443 | + def test_index_with_pagination(self): |
444 | local_block, global_block = _create_blocks("10.1.1.1/8", |
445 | "192.1.1.1/8") |
446 | [local_ip], global_ips = _allocate_ips((local_block, 1), |
447 | @@ -386,7 +283,110 @@ |
448 | {'ip_addresses': _data_of(global_ips[2], |
449 | global_ips[3])}) |
450 | |
451 | - def test_show_inside_locals_with_pagination(self): |
452 | + def test_index_for_nonexistent_block(self): |
453 | + non_existant_block_id = 12122 |
454 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_globals" |
455 | + response = self.app.get(url % (non_existant_block_id, |
456 | + "10.1.1.2"), |
457 | + status='*') |
458 | + |
459 | + self.assertErrorResponse(response, "404 Not Found", |
460 | + "IpBlock Not Found") |
461 | + |
462 | + def test_index_for_nonexistent_address(self): |
463 | + ip_block, = _create_blocks("191.1.1.1/10") |
464 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_globals" |
465 | + response = self.app.get(url % (ip_block.id, '10.1.1.2'), |
466 | + status='*') |
467 | + |
468 | + self.assertErrorResponse(response, "404 Not Found", |
469 | + "IpAddress Not Found") |
470 | + |
471 | + def test_create(self): |
472 | + global_block, local_block = _create_blocks('192.1.1.1/32', |
473 | + '10.1.1.1/32') |
474 | + global_ip = global_block.allocate_ip() |
475 | + local_ip = local_block.allocate_ip() |
476 | + |
477 | + response = self.app.post("/ipam/ip_blocks/%s/ip_addresses/%s/" |
478 | + "inside_globals" |
479 | + % (local_block.id, local_ip.address), |
480 | + {"ip_addresses": json.dumps( |
481 | + [{"ip_block_id": global_block.id, |
482 | + "ip_address": global_ip.address}])}) |
483 | + |
484 | + self.assertEqual(response.status, "200 OK") |
485 | + |
486 | + self.assertEqual(len(local_ip.inside_globals()), 1) |
487 | + self.assertEqual(global_ip.id, local_ip.inside_globals()[0].id) |
488 | + self.assertEqual(local_ip.id, global_ip.inside_locals()[0].id) |
489 | + |
490 | + def test_delete(self): |
491 | + global_block, local_block = _create_blocks('192.1.1.1/32', |
492 | + '10.1.1.1/32') |
493 | + global_ip = global_block.allocate_ip() |
494 | + local_ip = local_block.allocate_ip() |
495 | + local_ip.add_inside_globals([global_ip]) |
496 | + |
497 | + response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
498 | + "inside_globals" |
499 | + % (local_block.id, local_ip.address)) |
500 | + |
501 | + self.assertEqual(response.status, "200 OK") |
502 | + self.assertEqual(local_ip.inside_globals(), []) |
503 | + |
504 | + def test_delete_for_specific_address(self): |
505 | + global_block, local_block = _create_blocks('192.1.1.1/28', |
506 | + '10.1.1.1/28') |
507 | + global_ips, = _allocate_ips((global_block, 3)) |
508 | + local_ip = local_block.allocate_ip() |
509 | + local_ip.add_inside_globals(global_ips) |
510 | + |
511 | + response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
512 | + "inside_globals/%s" |
513 | + % (local_block.id, local_ip.address, |
514 | + global_ips[1].address)) |
515 | + |
516 | + globals_left = [ip.address for ip in local_ip.inside_globals()] |
517 | + self.assertEqual(globals_left, [global_ips[0].address, |
518 | + global_ips[2].address]) |
519 | + |
520 | + def test_delete_for_nonexistent_block(self): |
521 | + non_existant_block_id = 12122 |
522 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_globals" |
523 | + response = self.app.delete(url % (non_existant_block_id, |
524 | + '10.1.1.2'), status='*') |
525 | + |
526 | + self.assertErrorResponse(response, "404 Not Found", |
527 | + "IpBlock Not Found") |
528 | + |
529 | + def test_delete_for_nonexistent_address(self): |
530 | + ip_block, = _create_blocks("191.1.1.1/10") |
531 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_globals" |
532 | + response = self.app.delete(url % (ip_block.id, '10.1.1.2'), |
533 | + status='*') |
534 | + |
535 | + self.assertErrorResponse(response, "404 Not Found", |
536 | + "IpAddress Not Found") |
537 | + |
538 | + |
539 | +class TestInsideLocalsController(TestController): |
540 | + |
541 | + def test_index(self): |
542 | + global_block, local_block = _create_blocks("192.1.1.1/8", |
543 | + "10.1.1.1/8") |
544 | + [global_ip], local_ips = _allocate_ips((global_block, 1), |
545 | + (local_block, 5)) |
546 | + global_ip.add_inside_locals(local_ips) |
547 | + |
548 | + response = self.app.get("/ipam/ip_blocks/%s/ip_addresses/%s/" |
549 | + "inside_locals" |
550 | + % (global_block.id, global_ip.address)) |
551 | + |
552 | + self.assertEqual(response.json, |
553 | + {'ip_addresses': _data_of(*local_ips)}) |
554 | + |
555 | + def test_index_with_pagination(self): |
556 | global_block, local_block = _create_blocks("192.1.1.1/8", |
557 | "10.1.1.1/8") |
558 | [global_ip], local_ips = _allocate_ips((global_block, 1), |
559 | @@ -403,60 +403,144 @@ |
560 | {'ip_addresses': _data_of(local_ips[2], |
561 | local_ips[3])}) |
562 | |
563 | - def test_show_inside_locals(self): |
564 | - global_block, local_block = _create_blocks("192.1.1.1/8", |
565 | - "10.1.1.1/8") |
566 | - [global_ip], local_ips = _allocate_ips((global_block, 1), |
567 | - (local_block, 5)) |
568 | + def test_index_for_nonexistent_block(self): |
569 | + non_existant_block_id = 12122 |
570 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_locals" |
571 | + response = self.app.get(url % (non_existant_block_id, |
572 | + "10.1.1.2"), |
573 | + status='*') |
574 | + |
575 | + self.assertErrorResponse(response, "404 Not Found", |
576 | + "IpBlock Not Found") |
577 | + |
578 | + def test_index_for_nonexistent_address(self): |
579 | + ip_block, = _create_blocks("191.1.1.1/10") |
580 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_locals" |
581 | + response = self.app.get(url % (ip_block.id, '10.1.1.2'), |
582 | + status='*') |
583 | + |
584 | + self.assertErrorResponse(response, "404 Not Found", |
585 | + "IpAddress Not Found") |
586 | + |
587 | + def test_create(self): |
588 | + global_block, = _create_blocks("169.1.1.1/32") |
589 | + local_block1, = _create_blocks("10.1.1.1/32") |
590 | + local_block2, = _create_blocks("10.0.0.1/32") |
591 | + |
592 | + url = "/ipam/ip_blocks/%s/ip_addresses/169.1.1.1/inside_locals" |
593 | + json_data = [ |
594 | + {'ip_block_id': local_block1.id, 'ip_address': "10.1.1.1"}, |
595 | + {'ip_block_id': local_block2.id, 'ip_address': "10.0.0.1"}, |
596 | + ] |
597 | + request_data = {'ip_addresses': json.dumps(json_data)} |
598 | + response = self.app.post(url % global_block.id, request_data) |
599 | + |
600 | + self.assertEqual(response.status, "200 OK") |
601 | + ips = global_block.find_allocated_ip("169.1.1.1").inside_locals() |
602 | + inside_locals = [ip.address for ip in ips] |
603 | + |
604 | + self.assertEqual(len(inside_locals), 2) |
605 | + self.assertTrue("10.1.1.1" in inside_locals) |
606 | + self.assertTrue("10.0.0.1" in inside_locals) |
607 | + local_ip = IpAddress.find_by_block_and_address(local_block1.id, |
608 | + "10.1.1.1") |
609 | + self.assertEqual(local_ip.inside_globals()[0].address, "169.1.1.1") |
610 | + |
611 | + def test_delete_for_specific_address(self): |
612 | + global_block, local_block = _create_blocks('192.1.1.1/28', |
613 | + '10.1.1.1/28') |
614 | + local_ips, = _allocate_ips((local_block, 3)) |
615 | + global_ip = global_block.allocate_ip() |
616 | global_ip.add_inside_locals(local_ips) |
617 | |
618 | - response = self.app.get("/ipam/ip_blocks/%s/ip_addresses/%s/" |
619 | - "inside_locals" |
620 | - % (global_block.id, global_ip.address)) |
621 | - |
622 | - self.assertEqual(response.json, |
623 | - {'ip_addresses': _data_of(*local_ips)}) |
624 | - |
625 | - def test_show_nats_for_nonexistent_block(self): |
626 | - for action in ["inside_locals", "inside_globals"]: |
627 | - non_existant_block_id = 12122 |
628 | - url = "/ipam/ip_blocks/%s/ip_addresses/%s/%s" |
629 | - response = self.app.get(url % (non_existant_block_id, |
630 | - "10.1.1.2", action), |
631 | - status='*') |
632 | - |
633 | - self.assertErrorResponse(response, "404 Not Found", |
634 | - "IpBlock Not Found") |
635 | - |
636 | - def test_show_nats_for_nonexistent_address(self): |
637 | - for action in ["inside_locals", "inside_globals"]: |
638 | - ip_block, = _create_blocks("191.1.1.1/10") |
639 | - url = "/ipam/ip_blocks/%s/ip_addresses/%s/%s" |
640 | - response = self.app.get(url % (ip_block.id, '10.1.1.2', action), |
641 | - status='*') |
642 | - |
643 | - self.assertErrorResponse(response, "404 Not Found", |
644 | - "IpAddress Not Found") |
645 | - |
646 | - def test_delete_nats_for_nonexistent_block(self): |
647 | - for action in ["inside_locals", "inside_globals"]: |
648 | - non_existant_block_id = 12122 |
649 | - url = "/ipam/ip_blocks/%s/ip_addresses/%s/%s" |
650 | - response = self.app.delete(url % (non_existant_block_id, |
651 | - '10.1.1.2', action), status='*') |
652 | - |
653 | - self.assertErrorResponse(response, "404 Not Found", |
654 | - "IpBlock Not Found") |
655 | - |
656 | - def test_delete_nats_for_nonexistent_address(self): |
657 | - for action in ["inside_locals", "inside_globals"]: |
658 | - ip_block, = _create_blocks("191.1.1.1/10") |
659 | - url = "/ipam/ip_blocks/%s/ip_addresses/%s/%s" |
660 | - response = self.app.delete(url % (ip_block.id, '10.1.1.2', action), |
661 | - status='*') |
662 | - |
663 | - self.assertErrorResponse(response, "404 Not Found", |
664 | - "IpAddress Not Found") |
665 | + response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
666 | + "inside_locals/%s" |
667 | + % (global_block.id, global_ip.address, |
668 | + local_ips[1].address)) |
669 | + |
670 | + locals_left = [ip.address for ip in global_ip.inside_locals()] |
671 | + self.assertEqual(locals_left, [local_ips[0].address, |
672 | + local_ips[2].address]) |
673 | + |
674 | + def test_delete(self): |
675 | + global_block, local_block = _create_blocks('192.1.1.1/32', |
676 | + '10.1.1.1/32') |
677 | + global_ip = global_block.allocate_ip() |
678 | + local_ip = local_block.allocate_ip() |
679 | + global_ip.add_inside_locals([local_ip]) |
680 | + |
681 | + response = self.app.delete("/ipam/ip_blocks/%s/ip_addresses/%s/" |
682 | + "inside_locals" |
683 | + % (global_block.id, global_ip.address)) |
684 | + |
685 | + self.assertEqual(response.status, "200 OK") |
686 | + self.assertEqual(global_ip.inside_locals(), []) |
687 | + |
688 | + def test_delete_for_nonexistent_block(self): |
689 | + non_existant_block_id = 12122 |
690 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_locals" |
691 | + response = self.app.delete(url % (non_existant_block_id, |
692 | + '10.1.1.2'), status='*') |
693 | + |
694 | + self.assertErrorResponse(response, "404 Not Found", |
695 | + "IpBlock Not Found") |
696 | + |
697 | + def test_delete_for_nonexistent_address(self): |
698 | + ip_block, = _create_blocks("191.1.1.1/10") |
699 | + url = "/ipam/ip_blocks/%s/ip_addresses/%s/inside_locals" |
700 | + response = self.app.delete(url % (ip_block.id, '10.1.1.2'), |
701 | + status='*') |
702 | + |
703 | + self.assertErrorResponse(response, "404 Not Found", |
704 | + "IpAddress Not Found") |
705 | + |
706 | + |
707 | +class TestPoliciesController(TestController): |
708 | + |
709 | + def test_create(self): |
710 | + response = self.app.post("/ipam/policies", {'name': "ServiceNet"}) |
711 | + |
712 | + self.assertEqual(response.status, "201 Created") |
713 | + self.assertEqual(response.json['name'], "ServiceNet") |
714 | + |
715 | + def test_index(self): |
716 | + _create_policy("PublicNet") |
717 | + _create_policy("DedicatedServiceNet") |
718 | + |
719 | + response = self.app.get("/ipam/policies") |
720 | + |
721 | + self.assertEqual(response.status, "200 OK") |
722 | + response_policies = response.json['policies'] |
723 | + policies = Policy.find_all() |
724 | + self.assertEqual(len(policies), 2) |
725 | + self.assertEqual(response_policies, _data_of(*policies)) |
726 | + |
727 | + def test_show_when_requested_policy_exists(self): |
728 | + policy = _create_policy("DRAC") |
729 | + |
730 | + response = self.app.get("/ipam/policies/%s" % policy.id) |
731 | + |
732 | + self.assertEqual(response.status, "200 OK") |
733 | + self.assertEqual(response.json, policy.data()) |
734 | + |
735 | + def test_show_when_requested_policy_does_not_exist(self): |
736 | + response = self.app.get("/ipam/policies/invalid_id", status="*") |
737 | + |
738 | + self.assertErrorResponse(response, "404 Not Found", |
739 | + "Policy Not Found") |
740 | + |
741 | + |
742 | +class TestUnusableIpRangesController(TestController): |
743 | + |
744 | + def test_create(self): |
745 | + policy = _create_policy("ServiceNet") |
746 | + |
747 | + response = self.app.post("/ipam/policies/%s/unusable_ip_ranges" |
748 | + % policy.id, {'offset': 1, 'length': 2}) |
749 | + |
750 | + unusable_range = IpRange.find_all_by_policy(policy.id).first() |
751 | + self.assertEqual(response.status, "201 Created") |
752 | + self.assertEqual(response.json, unusable_range.data()) |
753 | |
754 | |
755 | class TestPoliciesController(TestController): |
756 | @@ -503,5 +587,9 @@ |
757 | return [IpBlock.create({"cidr": cidr}) for cidr in args] |
758 | |
759 | |
760 | +def _create_policy(name): |
761 | + return Policy.create({"name": name}) |
762 | + |
763 | + |
764 | def _data_of(*args): |
765 | return [model.data() for model in args] |