Allow CIDRs with non-zero masked portions
Allow users to specify CIDRs with bits other than zeros in the masked portion of the subnet. e.g. 192.168.1.5/24 is accepted and converted to 192.168.1.0/24. Closes-Bug: #1204173 Change-Id: I7ddff41e6988feb6e2a87e40a4d99db7174415b1
This commit is contained in:
parent
d263b44cd7
commit
ee4ef3ee00
@ -291,7 +291,7 @@ def _validate_subnet(data, valid_values=None):
|
||||
msg = None
|
||||
try:
|
||||
net = netaddr.IPNetwork(_validate_no_whitespace(data))
|
||||
if ('/' not in data or net.network != net.ip):
|
||||
if '/' not in data:
|
||||
msg = _("'%(data)s' isn't a recognized IP subnet cidr,"
|
||||
" '%(cidr)s' is recommended") % {"data": data,
|
||||
"cidr": net.cidr}
|
||||
|
@ -1062,8 +1062,11 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
|
||||
def create_subnet(self, context, subnet):
|
||||
|
||||
net = netaddr.IPNetwork(subnet['subnet']['cidr'])
|
||||
# turn the CIDR into a proper subnet
|
||||
subnet['subnet']['cidr'] = '%s/%s' % (net.network, net.prefixlen)
|
||||
|
||||
s = subnet['subnet']
|
||||
net = netaddr.IPNetwork(s['cidr'])
|
||||
|
||||
if s['gateway_ip'] is attributes.ATTR_NOT_SPECIFIED:
|
||||
s['gateway_ip'] = str(netaddr.IPAddress(net.first + 1))
|
||||
|
@ -459,13 +459,11 @@ class TestAttributes(base.BaseTestCase):
|
||||
"cidr": "10.0.2.0/32"}
|
||||
self.assertEqual(msg, error)
|
||||
|
||||
# Invalid - IPv4 with final octets
|
||||
cidr = "192.168.1.1/24"
|
||||
msg = validator(cidr, None)
|
||||
error = _("'%(data)s' isn't a recognized IP subnet cidr,"
|
||||
" '%(cidr)s' is recommended") % {"data": cidr,
|
||||
"cidr": "192.168.1.0/24"}
|
||||
self.assertEqual(msg, error)
|
||||
# Valid - IPv4 with non-zero masked bits is ok
|
||||
for i in range(1, 255):
|
||||
cidr = "192.168.1.%s/24" % i
|
||||
msg = validator(cidr, None)
|
||||
self.assertIsNone(msg)
|
||||
|
||||
# Invalid - IPv6 without final octets, missing mask
|
||||
cidr = "fe80::"
|
||||
|
@ -2503,16 +2503,26 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
device_owner='fake_owner',
|
||||
set_context=False)
|
||||
|
||||
def test_create_subnet_bad_cidr(self):
|
||||
with self.network() as network:
|
||||
data = {'subnet': {'network_id': network['network']['id'],
|
||||
'cidr': '10.0.2.5/24',
|
||||
'ip_version': 4,
|
||||
'tenant_id': network['network']['tenant_id']}}
|
||||
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPBadRequest.code)
|
||||
def test_create_subnet_nonzero_cidr(self):
|
||||
with contextlib.nested(
|
||||
self.subnet(cidr='10.129.122.5/8'),
|
||||
self.subnet(cidr='11.129.122.5/15'),
|
||||
self.subnet(cidr='12.129.122.5/16'),
|
||||
self.subnet(cidr='13.129.122.5/18'),
|
||||
self.subnet(cidr='14.129.122.5/22'),
|
||||
self.subnet(cidr='15.129.122.5/24'),
|
||||
self.subnet(cidr='16.129.122.5/28'),
|
||||
self.subnet(cidr='17.129.122.5/32')
|
||||
) as subs:
|
||||
# the API should accept and correct these for users
|
||||
self.assertEqual(subs[0]['subnet']['cidr'], '10.0.0.0/8')
|
||||
self.assertEqual(subs[1]['subnet']['cidr'], '11.128.0.0/15')
|
||||
self.assertEqual(subs[2]['subnet']['cidr'], '12.129.0.0/16')
|
||||
self.assertEqual(subs[3]['subnet']['cidr'], '13.129.64.0/18')
|
||||
self.assertEqual(subs[4]['subnet']['cidr'], '14.129.120.0/22')
|
||||
self.assertEqual(subs[5]['subnet']['cidr'], '15.129.122.0/24')
|
||||
self.assertEqual(subs[6]['subnet']['cidr'], '16.129.122.0/28')
|
||||
self.assertEqual(subs[7]['subnet']['cidr'], '17.129.122.5/32')
|
||||
|
||||
def test_create_subnet_bad_ip_version(self):
|
||||
with self.network() as network:
|
||||
|
Loading…
Reference in New Issue
Block a user