Merge lp:~santhoshkumar/network-service/melange_framework into lp:~rajarammallya/network-service/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
Reviewer Review Type Date Requested Status
Rajaram Mallya Approve
Review via email: mp+63237@code.launchpad.net

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]

Subscribers

People subscribed via source and target branches