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)
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}',
'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}
'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,
"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)):
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))})
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):
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
'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
@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,
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']},
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'