Skip to content

Commit

Permalink
Make sure that there's a way of creating a subnet without a gateway
Browse files Browse the repository at this point in the history
Fixes bug 1028646
You can use null for gateway ip.

Change-Id: I969112ad46efa22203db40106d4e35dce1757165
  • Loading branch information
Nachi Ueno committed Aug 13, 2012
1 parent f3b6441 commit 795711f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 9 deletions.
10 changes: 8 additions & 2 deletions quantum/api/v2/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ def _validate_ip_address(data, valid_values=None):
return msg


def _validate_ip_address_or_none(data, valid_values=None):
if data is None:
return None
return _validate_ip_address(data, valid_values)


def _validate_subnet(data, valid_values=None):
try:
netaddr.IPNetwork(data)
Expand Down Expand Up @@ -103,7 +109,6 @@ def convert_to_boolean(data):
msg = _("%s is not boolean") % data
raise q_exc.InvalidInput(error_message=msg)


HEX_ELEM = '[0-9A-Fa-f]'
UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}',
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
Expand All @@ -117,6 +122,7 @@ def convert_to_boolean(data):
'type:values': _validate_values,
'type:mac_address': _validate_mac_address,
'type:ip_address': _validate_ip_address,
'type:ip_address_or_none': _validate_ip_address_or_none,
'type:subnet': _validate_subnet,
'type:regex': _validate_regex}

Expand Down Expand Up @@ -226,7 +232,7 @@ def convert_to_boolean(data):
'is_visible': True},
'gateway_ip': {'allow_post': True, 'allow_put': True,
'default': ATTR_NOT_SPECIFIED,
'validate': {'type:ip_address': None},
'validate': {'type:ip_address_or_none': None},
'is_visible': True},
#TODO(salvatore-orlando): Enable PUT on allocation_pools
'allocation_pools': {'allow_post': True, 'allow_put': False,
Expand Down
12 changes: 8 additions & 4 deletions quantum/db/db_base_plugin_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,9 @@ def _validate_allocation_pools(self, ip_pools, gateway_ip, subnet_cidr):
"and gateway ip")
ip_ranges = ip_pools[:]
# Treat gw as IPset as well
ip_ranges.append(gateway_ip)
ip_sets.append(netaddr.IPSet([gateway_ip]))
if gateway_ip:
ip_ranges.append(gateway_ip)
ip_sets.append(netaddr.IPSet([gateway_ip]))
# Use integer cursors as an efficient way for implementing
# comparison and avoiding comparing the same pair twice
for l_cursor in range(len(ip_sets)):
Expand All @@ -593,11 +594,12 @@ def _allocate_pools_for_subnet(self, context, subnet):

pools = []
if subnet['allocation_pools'] == attributes.ATTR_NOT_SPECIFIED:
# Auto allocate the pool around gateway
gw_ip = int(netaddr.IPAddress(subnet['gateway_ip']))
# Auto allocate the pool around gateway_ip
net = netaddr.IPNetwork(subnet['cidr'])
first_ip = net.first + 1
last_ip = net.last - 1
gw_ip = int(netaddr.IPAddress(subnet['gateway_ip'] or net.last))

if gw_ip > first_ip:
pools.append({'start': str(netaddr.IPAddress(first_ip)),
'end': str(netaddr.IPAddress(gw_ip - 1))})
Expand Down Expand Up @@ -657,6 +659,8 @@ def _make_subnet_dict(self, subnet, fields=None):
for pool in subnet['allocation_pools']],
'gateway_ip': subnet['gateway_ip'],
'enable_dhcp': subnet['enable_dhcp']}
if subnet['gateway_ip']:
res['gateway_ip'] = subnet['gateway_ip']
return self._fields(res, fields)

def _make_port_dict(self, port, fields=None):
Expand Down
33 changes: 30 additions & 3 deletions quantum/tests/unit/test_db_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import webob.exc

import quantum
from quantum.api.v2 import attributes
from quantum.api.v2.attributes import ATTR_NOT_SPECIFIED
from quantum.api.v2.router import APIRouter
from quantum.common import config
from quantum.common import exceptions as q_exc
Expand Down Expand Up @@ -140,12 +142,16 @@ def _create_subnet(self, fmt, net_id, cidr,
'cidr': cidr,
'ip_version': 4,
'tenant_id': self._tenant_id}}
for arg in ('gateway_ip', 'allocation_pools',
for arg in ('allocation_pools',
'ip_version', 'tenant_id',
'enable_dhcp'):
# Arg must be present and not null (but can be false)
if arg in kwargs and kwargs[arg] is not None:
data['subnet'][arg] = kwargs[arg]

if kwargs.get('gateway_ip', ATTR_NOT_SPECIFIED) != ATTR_NOT_SPECIFIED:
data['subnet']['gateway_ip'] = kwargs['gateway_ip']

subnet_req = self.new_create_request('subnets', data, fmt)
if (kwargs.get('set_context') and 'tenant_id' in kwargs):
# create a specific auth context for this request
Expand Down Expand Up @@ -241,7 +247,7 @@ def network(self, name='net1',

@contextlib.contextmanager
def subnet(self, network=None,
gateway_ip=None,
gateway_ip=ATTR_NOT_SPECIFIED,
cidr='10.0.0.0/24',
fmt='json',
ip_version=4,
Expand Down Expand Up @@ -725,7 +731,7 @@ def test_requested_subnet_id_v4_and_v6(self):
net_id=net_id,
cidr='2607:f0d0:1002:51::0/124',
ip_version=6,
gateway_ip=None)
gateway_ip=ATTR_NOT_SPECIFIED)
subnet2 = self.deserialize(fmt, res)
kwargs = {"fixed_ips":
[{'subnet_id': subnet['subnet']['id']},
Expand Down Expand Up @@ -1220,6 +1226,27 @@ def test_create_subnet_with_allocation_pool(self):
cidr=cidr,
allocation_pools=allocation_pools)

def test_create_subnet_with_none_gateway(self):
cidr = '10.0.0.0/24'
self._test_create_subnet(gateway_ip=None,
cidr=cidr)

def test_create_subnet_with_none_gateway_fully_allocated(self):
cidr = '10.0.0.0/24'
allocation_pools = [{'start': '10.0.0.1',
'end': '10.0.0.254'}]
self._test_create_subnet(gateway_ip=None,
cidr=cidr,
allocation_pools=allocation_pools)

def test_create_subnet_with_none_gateway_allocation_pool(self):
cidr = '10.0.0.0/24'
allocation_pools = [{'start': '10.0.0.2',
'end': '10.0.0.100'}]
self._test_create_subnet(gateway_ip=None,
cidr=cidr,
allocation_pools=allocation_pools)

def test_create_subnet_with_v6_allocation_pool(self):
gateway_ip = 'fe80::1'
cidr = 'fe80::0/80'
Expand Down

0 comments on commit 795711f

Please sign in to comment.