Merge lp:~mpontillo/maas/fix-1552719 into lp:~maas-committers/maas/trunk

Proposed by Mike Pontillo
Status: Merged
Approved by: Andres Rodriguez
Approved revision: no longer in the source branch.
Merged at revision: 4769
Proposed branch: lp:~mpontillo/maas/fix-1552719
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 114 lines (+63/-7)
2 files modified
src/provisioningserver/utils/network.py (+11/-5)
src/provisioningserver/utils/tests/test_network.py (+52/-2)
To merge this branch: bzr merge lp:~mpontillo/maas/fix-1552719
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+288742@code.launchpad.net

Commit message

Fix bug #1552719: Handle /32 and /128 IP ranges appropriately.

Drive-by fix to remove unused inefficiency field. (it has been removed from the new designs)

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/utils/network.py'
2--- src/provisioningserver/utils/network.py 2016-03-07 23:20:52 +0000
3+++ src/provisioningserver/utils/network.py 2016-03-11 08:43:04 +0000
4@@ -191,8 +191,6 @@
5 "usage": self.usage_percentage,
6 "usage_string": self.usage_percentage_string,
7 "available_string": self.available_percentage_string,
8- # XXX LJ 20151004: determine the right calculation, and do it.
9- "inefficiency_string": "TBD",
10 }
11 if include_ranges:
12 data["ranges"] = self.ranges.render_json()
13@@ -254,7 +252,12 @@
14 unused_ranges = []
15 if type(outer_range) == IPNetwork:
16 # Skip the network address, if this is a network
17- start = outer_range.first + 1
18+ if outer_range.version == 4 and outer_range.prefixlen == 32:
19+ start = outer_range.first
20+ elif outer_range.version == 6 and outer_range.prefixlen == 128:
21+ start = outer_range.first
22+ else:
23+ start = outer_range.first + 1
24 else:
25 # Otherwise, assume the first address is the start of the range
26 start = outer_range.first
27@@ -271,8 +274,11 @@
28 make_iprange(candidate_start, candidate_end, comment))
29 candidate_start = used_range.last + 1
30 # Skip the broadcast address, if this is an IPv4 network
31- if type(outer_range) == IPNetwork and outer_range.version == 4:
32- candidate_end = outer_range.last - 1
33+ if type(outer_range) == IPNetwork:
34+ if outer_range.version == 4 and outer_range.prefixlen != 32:
35+ candidate_end = outer_range.last - 1
36+ else:
37+ candidate_end = outer_range.last
38 else:
39 candidate_end = outer_range.last
40 # Check if there is a gap between the last used range and the end
41
42=== modified file 'src/provisioningserver/utils/tests/test_network.py'
43--- src/provisioningserver/utils/tests/test_network.py 2016-03-08 18:50:36 +0000
44+++ src/provisioningserver/utils/tests/test_network.py 2016-03-11 08:43:04 +0000
45@@ -720,7 +720,6 @@
46 self.assertThat(json['usage'], Equals(float(4) / float(254)))
47 self.assertThat(json['usage_string'], Equals("2%"))
48 self.assertThat(json['available_string'], Equals("98%"))
49- self.assertThat(json['inefficiency_string'], Equals("TBD"))
50 self.assertThat(json, Not(Contains("ranges")))
51
52 def test__statistics_are_accurate_and_ranges_are_returned_if_desired(self):
53@@ -734,10 +733,61 @@
54 self.assertThat(json['usage'], Equals(float(4) / float(254)))
55 self.assertThat(json['usage_string'], Equals('2%'))
56 self.assertThat(json['available_string'], Equals("98%"))
57- self.assertThat(json['inefficiency_string'], Equals("TBD"))
58 self.assertThat(json, Contains('ranges'))
59 self.assertThat(json['ranges'], Equals(stats.ranges.render_json()))
60
61+ def test__statistics_are_accurate_for_full_slash_32(self):
62+ s = MAASIPSet(['10.0.0.1'])
63+ u = s.get_full_range('10.0.0.1/32')
64+ stats = IPRangeStatistics(u)
65+ json = stats.render_json()
66+ self.assertThat(json['num_available'], Equals(0))
67+ self.assertThat(json['largest_available'], Equals(0))
68+ self.assertThat(json['num_unavailable'], Equals(1))
69+ self.assertThat(json['usage'], Equals(float(1) / float(1)))
70+ self.assertThat(json['usage_string'], Equals("100%"))
71+ self.assertThat(json['available_string'], Equals("0%"))
72+ self.assertThat(json, Not(Contains("ranges")))
73+
74+ def test__statistics_are_accurate_for_empty_slash_32(self):
75+ s = MAASIPSet([])
76+ u = s.get_full_range('10.0.0.1/32')
77+ stats = IPRangeStatistics(u)
78+ json = stats.render_json()
79+ self.assertThat(json['num_available'], Equals(1))
80+ self.assertThat(json['largest_available'], Equals(1))
81+ self.assertThat(json['num_unavailable'], Equals(0))
82+ self.assertThat(json['usage'], Equals(float(0) / float(1)))
83+ self.assertThat(json['usage_string'], Equals("0%"))
84+ self.assertThat(json['available_string'], Equals("100%"))
85+ self.assertThat(json, Not(Contains("ranges")))
86+
87+ def test__statistics_are_accurate_for_full_slash_128(self):
88+ s = MAASIPSet(['2001:db8::1'])
89+ u = s.get_full_range('2001:db8::1/128')
90+ stats = IPRangeStatistics(u)
91+ json = stats.render_json()
92+ self.assertThat(json['num_available'], Equals(0))
93+ self.assertThat(json['largest_available'], Equals(0))
94+ self.assertThat(json['num_unavailable'], Equals(1))
95+ self.assertThat(json['usage'], Equals(float(1) / float(1)))
96+ self.assertThat(json['usage_string'], Equals("100%"))
97+ self.assertThat(json['available_string'], Equals("0%"))
98+ self.assertThat(json, Not(Contains("ranges")))
99+
100+ def test__statistics_are_accurate_for_empty_slash_128(self):
101+ s = MAASIPSet([])
102+ u = s.get_full_range('2001:db8::1/128')
103+ stats = IPRangeStatistics(u)
104+ json = stats.render_json()
105+ self.assertThat(json['num_available'], Equals(1))
106+ self.assertThat(json['largest_available'], Equals(1))
107+ self.assertThat(json['num_unavailable'], Equals(0))
108+ self.assertThat(json['usage'], Equals(float(0) / float(1)))
109+ self.assertThat(json['usage_string'], Equals("0%"))
110+ self.assertThat(json['available_string'], Equals("100%"))
111+ self.assertThat(json, Not(Contains("ranges")))
112+
113
114 class TestParseInteger(MAASTestCase):
115