implementation for bug 1008180
implement the database models for the v2 db plugin base to store dns + additional routes also handles the dns/route remote/update Change-Id: I06c585b47668ee963324a5064e40a24471da28c4
This commit is contained in:
parent
635c5bd48d
commit
ba371d90d2
@ -238,12 +238,12 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'allocation_pools': {'allow_post': True, 'allow_put': False,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True},
|
||||
'dns_namesevers': {'allow_post': True, 'allow_put': True,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'is_visible': False},
|
||||
'additional_host_routes': {'allow_post': True, 'allow_put': True,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'is_visible': False},
|
||||
'dns_nameservers': {'allow_post': True, 'allow_put': True,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True},
|
||||
'host_routes': {'allow_post': True, 'allow_put': True,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'is_visible': True},
|
||||
|
@ -41,6 +41,8 @@ FAULT_MAP = {exceptions.NotFound: webob.exc.HTTPNotFound,
|
||||
exceptions.OutOfBoundsAllocationPool: webob.exc.HTTPBadRequest,
|
||||
exceptions.InvalidAllocationPool: webob.exc.HTTPBadRequest,
|
||||
exceptions.InvalidSharedSetting: webob.exc.HTTPConflict,
|
||||
exceptions.HostRoutesExhausted: webob.exc.HTTPBadRequest,
|
||||
exceptions.DNSNameServersExhausted: webob.exc.HTTPBadRequest,
|
||||
}
|
||||
|
||||
QUOTAS = quota.QUOTAS
|
||||
|
@ -45,6 +45,8 @@ core_opts = [
|
||||
cfg.StrOpt('base_mac', default="fa:16:3e:00:00:00"),
|
||||
cfg.IntOpt('mac_generation_retries', default=16),
|
||||
cfg.BoolOpt('allow_bulk', default=True),
|
||||
cfg.IntOpt('max_dns_nameservers', default=5),
|
||||
cfg.IntOpt('max_subnet_host_routes', default=20),
|
||||
]
|
||||
|
||||
# Register the configuration options
|
||||
|
@ -100,6 +100,18 @@ class MacAddressInUse(InUse):
|
||||
"The mac address %(mac)s is in use.")
|
||||
|
||||
|
||||
class HostRoutesExhausted(QuantumException):
|
||||
# NOTE(xchenum): probably make sense to use quota exceeded exception?
|
||||
message = _("Unable to complete operation for %(subnet_id)s. "
|
||||
"The number of host routes exceeds the limit %(quota).")
|
||||
|
||||
|
||||
class DNSNameServersExhausted(QuantumException):
|
||||
# NOTE(xchenum): probably make sense to use quota exceeded exception?
|
||||
message = _("Unable to complete operation for %(subnet_id)s. "
|
||||
"The number of DNS nameservers exceeds the limit %(quota).")
|
||||
|
||||
|
||||
class IpAddressInUse(InUse):
|
||||
message = _("Unable to complete operation for network %(net_id)s. "
|
||||
"The IP address %(ip_address)s is in use.")
|
||||
|
@ -125,6 +125,20 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
raise q_exc.PortNotFound(port_id=id)
|
||||
return port
|
||||
|
||||
def _get_dns_by_subnet(self, context, subnet_id):
|
||||
try:
|
||||
dns_qry = context.session.query(models_v2.DNSNameServer)
|
||||
return dns_qry.filter_by(subnet_id=subnet_id).all()
|
||||
except exc.NoResultFound:
|
||||
return []
|
||||
|
||||
def _get_route_by_subnet(self, context, subnet_id):
|
||||
try:
|
||||
route_qry = context.session.query(models_v2.Route)
|
||||
return route_qry.filter_by(subnet_id=subnet_id).all()
|
||||
except exc.NoResultFound:
|
||||
return []
|
||||
|
||||
def _fields(self, resource, fields):
|
||||
if fields:
|
||||
return dict(((key, item) for key, item in resource.iteritems()
|
||||
@ -588,6 +602,18 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
pool_2=r_range,
|
||||
subnet_cidr=subnet_cidr)
|
||||
|
||||
def _validate_host_route(self, route):
|
||||
try:
|
||||
netaddr.IPNetwork(route['destination'])
|
||||
netaddr.IPAddress(route['nexthop'])
|
||||
except netaddr.core.AddrFormatError:
|
||||
err_msg = ("invalid route: %s" % (str(route)))
|
||||
raise q_exc.InvalidInput(error_message=err_msg)
|
||||
except ValueError:
|
||||
# netaddr.IPAddress would raise this
|
||||
err_msg = ("invalid route: %s" % (str(route)))
|
||||
raise q_exc.InvalidInput(error_message=err_msg)
|
||||
|
||||
def _allocate_pools_for_subnet(self, context, subnet):
|
||||
"""Create IP allocation pools for a given subnet
|
||||
|
||||
@ -663,9 +689,16 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
'end': pool['last_ip']}
|
||||
for pool in subnet['allocation_pools']],
|
||||
'gateway_ip': subnet['gateway_ip'],
|
||||
'enable_dhcp': subnet['enable_dhcp']}
|
||||
'enable_dhcp': subnet['enable_dhcp'],
|
||||
'dns_nameservers': [dns['address']
|
||||
for dns in subnet['dns_nameservers']],
|
||||
'host_routes': [{'destination': route['destination'],
|
||||
'nexthop': route['nexthop']}
|
||||
for route in subnet['routes']],
|
||||
}
|
||||
if subnet['gateway_ip']:
|
||||
res['gateway_ip'] = subnet['gateway_ip']
|
||||
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _make_port_dict(self, port, fields=None):
|
||||
@ -755,8 +788,37 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
def create_subnet_bulk(self, context, subnets):
|
||||
return self._create_bulk('subnet', context, subnets)
|
||||
|
||||
def _validate_subnet(self, s):
|
||||
"""a subroutine to validate a subnet spec"""
|
||||
# check if the number of DNS nameserver exceeds the quota
|
||||
if 'dns_nameservers' in s and \
|
||||
s['dns_nameservers'] != attributes.ATTR_NOT_SPECIFIED:
|
||||
if len(s['dns_nameservers']) > cfg.CONF.max_dns_nameservers:
|
||||
raise q_exc.DNSNameServersExhausted(
|
||||
subnet_id=id,
|
||||
quota=cfg.CONF.max_dns_nameservers)
|
||||
for dns in s['dns_nameservers']:
|
||||
try:
|
||||
netaddr.IPAddress(dns)
|
||||
except Exception:
|
||||
raise q_exc.InvalidInput(
|
||||
error_message=("error parsing dns address %s" % dns))
|
||||
|
||||
# check if the number of host routes exceeds the quota
|
||||
if 'host_routes' in s and \
|
||||
s['host_routes'] != attributes.ATTR_NOT_SPECIFIED:
|
||||
if len(s['host_routes']) > cfg.CONF.max_subnet_host_routes:
|
||||
raise q_exc.HostRoutesExhausted(
|
||||
subnet_id=id,
|
||||
quota=cfg.CONF.max_subnet_host_routes)
|
||||
# check if the routes are all valid
|
||||
for rt in s['host_routes']:
|
||||
self._validate_host_route(rt)
|
||||
|
||||
def create_subnet(self, context, subnet):
|
||||
s = subnet['subnet']
|
||||
self._validate_subnet(s)
|
||||
|
||||
net = netaddr.IPNetwork(s['cidr'])
|
||||
if s['gateway_ip'] == attributes.ATTR_NOT_SPECIFIED:
|
||||
s['gateway_ip'] = str(netaddr.IPAddress(net.first + 1))
|
||||
@ -771,10 +833,25 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
network_id=s['network_id'],
|
||||
ip_version=s['ip_version'],
|
||||
cidr=s['cidr'],
|
||||
gateway_ip=s['gateway_ip'],
|
||||
enable_dhcp=s['enable_dhcp'])
|
||||
context.session.add(subnet)
|
||||
enable_dhcp=s['enable_dhcp'],
|
||||
gateway_ip=s['gateway_ip'])
|
||||
|
||||
# perform allocate pools first, since it might raise an error
|
||||
pools = self._allocate_pools_for_subnet(context, s)
|
||||
|
||||
context.session.add(subnet)
|
||||
if s['dns_nameservers'] != attributes.ATTR_NOT_SPECIFIED:
|
||||
for addr in s['dns_nameservers']:
|
||||
ns = models_v2.DNSNameServer(address=addr,
|
||||
subnet_id=subnet.id)
|
||||
context.session.add(ns)
|
||||
|
||||
if s['host_routes'] != attributes.ATTR_NOT_SPECIFIED:
|
||||
for rt in s['host_routes']:
|
||||
route = models_v2.Route(subnet_id=subnet.id,
|
||||
destination=rt['destination'],
|
||||
nexthop=rt['nexthop'])
|
||||
context.session.add(route)
|
||||
for pool in pools:
|
||||
ip_pool = models_v2.IPAllocationPool(subnet=subnet,
|
||||
first_ip=pool['start'],
|
||||
@ -785,11 +862,60 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
first_ip=pool['start'],
|
||||
last_ip=pool['end'])
|
||||
context.session.add(ip_range)
|
||||
|
||||
return self._make_subnet_dict(subnet)
|
||||
|
||||
def update_subnet(self, context, id, subnet):
|
||||
"""Update the subnet with new info. The change however will not be
|
||||
realized until the client renew the dns lease or we support
|
||||
gratuitous DHCP offers"""
|
||||
|
||||
s = subnet['subnet']
|
||||
self._validate_subnet(s)
|
||||
|
||||
with context.session.begin():
|
||||
if "dns_nameservers" in s:
|
||||
old_dns_list = self._get_dns_by_subnet(context, id)
|
||||
|
||||
new_dns_addr_set = set(s["dns_nameservers"])
|
||||
old_dns_addr_set = set([dns['address']
|
||||
for dns in old_dns_list])
|
||||
|
||||
for dns_addr in old_dns_addr_set - new_dns_addr_set:
|
||||
for dns in old_dns_list:
|
||||
if dns['address'] == dns_addr:
|
||||
context.session.delete(dns)
|
||||
for dns_addr in new_dns_addr_set - old_dns_addr_set:
|
||||
dns = models_v2.DNSNameServer(
|
||||
address=dns_addr,
|
||||
subnet_id=id)
|
||||
context.session.add(dns)
|
||||
del s["dns_nameservers"]
|
||||
|
||||
def _combine(ht):
|
||||
return ht['destination'] + "_" + ht['nexthop']
|
||||
|
||||
if "host_routes" in s:
|
||||
old_route_list = self._get_route_by_subnet(context, id)
|
||||
|
||||
new_route_set = set([_combine(route)
|
||||
for route in s['host_routes']])
|
||||
|
||||
old_route_set = set([_combine(route)
|
||||
for route in old_route_list])
|
||||
|
||||
for route_str in old_route_set - new_route_set:
|
||||
for route in old_route_list:
|
||||
if _combine(route) == route_str:
|
||||
context.session.delete(route)
|
||||
for route_str in new_route_set - old_route_set:
|
||||
route = models_v2.Route(
|
||||
destination=route_str.partition("_")[0],
|
||||
nexthop=route_str.partition("_")[2],
|
||||
subnet_id=id)
|
||||
context.session.add(route)
|
||||
del s["host_routes"]
|
||||
|
||||
subnet = self._get_subnet(context, id)
|
||||
subnet.update(s)
|
||||
return self._make_subnet_dict(subnet)
|
||||
@ -802,6 +928,7 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
allocated = allocated_qry.filter_by(subnet_id=id).all()
|
||||
if allocated:
|
||||
raise q_exc.SubnetInUse(subnet_id=id)
|
||||
|
||||
context.session.delete(subnet)
|
||||
|
||||
def get_subnet(self, context, id, fields=None, verbose=None):
|
||||
|
@ -98,6 +98,25 @@ class Port(model_base.BASEV2, HasId, HasTenant):
|
||||
device_id = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
|
||||
class DNSNameServer(model_base.BASEV2):
|
||||
"""Internal representation of a DNS nameserver."""
|
||||
address = sa.Column(sa.String(128), nullable=False, primary_key=True)
|
||||
subnet_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('subnets.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
|
||||
|
||||
class Route(model_base.BASEV2):
|
||||
"""Represents a route for a subnet or port."""
|
||||
destination = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
||||
nexthop = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
||||
subnet_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('subnets.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
|
||||
|
||||
class Subnet(model_base.BASEV2, HasId, HasTenant):
|
||||
"""Represents a quantum subnet.
|
||||
|
||||
@ -113,10 +132,12 @@ class Subnet(model_base.BASEV2, HasId, HasTenant):
|
||||
backref='subnet',
|
||||
lazy="dynamic")
|
||||
enable_dhcp = sa.Column(sa.Boolean())
|
||||
|
||||
#TODO(danwent):
|
||||
# - dns_namservers
|
||||
# - additional_routes
|
||||
dns_nameservers = orm.relationship(DNSNameServer,
|
||||
backref='subnet',
|
||||
cascade='delete')
|
||||
routes = orm.relationship(Route,
|
||||
backref='subnet',
|
||||
cascade='delete')
|
||||
|
||||
|
||||
class Network(model_base.BASEV2, HasId, HasTenant):
|
||||
|
@ -73,6 +73,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
# Update the plugin
|
||||
cfg.CONF.set_override('core_plugin', plugin)
|
||||
cfg.CONF.set_override('base_mac', "12:34:56:78:90:ab")
|
||||
cfg.CONF.max_dns_nameservers = 2
|
||||
cfg.CONF.max_subnet_host_routes = 2
|
||||
self.api = APIRouter()
|
||||
|
||||
def _is_native_bulk_supported():
|
||||
@ -179,7 +181,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
'tenant_id': self._tenant_id}}
|
||||
for arg in ('allocation_pools',
|
||||
'ip_version', 'tenant_id',
|
||||
'enable_dhcp'):
|
||||
'enable_dhcp', 'allocation_pools',
|
||||
'dns_nameservers', 'host_routes'):
|
||||
# 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]
|
||||
@ -258,7 +261,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
return self._create_bulk(fmt, number, 'port', base_data, **kwargs)
|
||||
|
||||
def _make_subnet(self, fmt, network, gateway, cidr,
|
||||
allocation_pools=None, ip_version=4, enable_dhcp=True):
|
||||
allocation_pools=None, ip_version=4, enable_dhcp=True,
|
||||
dns_nameservers=None, host_routes=None):
|
||||
res = self._create_subnet(fmt,
|
||||
net_id=network['network']['id'],
|
||||
cidr=cidr,
|
||||
@ -266,7 +270,9 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
tenant_id=network['network']['tenant_id'],
|
||||
allocation_pools=allocation_pools,
|
||||
ip_version=ip_version,
|
||||
enable_dhcp=enable_dhcp)
|
||||
enable_dhcp=enable_dhcp,
|
||||
dns_nameservers=dns_nameservers,
|
||||
host_routes=host_routes)
|
||||
# Things can go wrong - raise HTTP exc with res code only
|
||||
# so it can be caught by unit tests
|
||||
if res.status_int >= 400:
|
||||
@ -330,7 +336,9 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
fmt='json',
|
||||
ip_version=4,
|
||||
allocation_pools=None,
|
||||
enable_dhcp=True):
|
||||
enable_dhcp=True,
|
||||
dns_nameservers=None,
|
||||
host_routes=None):
|
||||
# TODO(anyone) DRY this
|
||||
# NOTE(salvatore-orlando): we can pass the network object
|
||||
# to gen function anyway, and then avoid the repetition
|
||||
@ -342,7 +350,9 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
cidr,
|
||||
allocation_pools,
|
||||
ip_version,
|
||||
enable_dhcp)
|
||||
enable_dhcp,
|
||||
dns_nameservers,
|
||||
host_routes)
|
||||
yield subnet
|
||||
self._delete('subnets', subnet['subnet']['id'])
|
||||
else:
|
||||
@ -352,7 +362,9 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
||||
cidr,
|
||||
allocation_pools,
|
||||
ip_version,
|
||||
enable_dhcp)
|
||||
enable_dhcp,
|
||||
dns_nameservers,
|
||||
host_routes)
|
||||
yield subnet
|
||||
self._delete('subnets', subnet['subnet']['id'])
|
||||
|
||||
@ -1717,3 +1729,177 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase):
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 422)
|
||||
|
||||
def test_create_subnet_with_one_dns(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
allocation_pools = [{'start': '10.0.0.2',
|
||||
'end': '10.0.0.100'}]
|
||||
dns_nameservers = ['1.2.3.4']
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr,
|
||||
allocation_pools=allocation_pools,
|
||||
dns_nameservers=dns_nameservers)
|
||||
|
||||
def test_create_subnet_with_two_dns(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
allocation_pools = [{'start': '10.0.0.2',
|
||||
'end': '10.0.0.100'}]
|
||||
dns_nameservers = ['1.2.3.4', '4.3.2.1']
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr,
|
||||
allocation_pools=allocation_pools,
|
||||
dns_nameservers=dns_nameservers)
|
||||
|
||||
def test_create_subnet_with_too_many_dns(self):
|
||||
with self.network() as network:
|
||||
dns_list = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
|
||||
data = {'subnet': {'network_id': network['network']['id'],
|
||||
'cidr': '10.0.2.0/24',
|
||||
'ip_version': 4,
|
||||
'tenant_id': network['network']['tenant_id'],
|
||||
'gateway_ip': '10.0.0.1',
|
||||
'dns_nameservers': dns_list}}
|
||||
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 400)
|
||||
|
||||
def test_create_subnet_with_one_host_route(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
allocation_pools = [{'start': '10.0.0.2',
|
||||
'end': '10.0.0.100'}]
|
||||
host_routes = [{'destination': '135.207.0.0/16',
|
||||
'nexthop': '1.2.3.4'}]
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr,
|
||||
allocation_pools=allocation_pools,
|
||||
host_routes=host_routes)
|
||||
|
||||
def test_create_subnet_with_two_host_routes(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
allocation_pools = [{'start': '10.0.0.2',
|
||||
'end': '10.0.0.100'}]
|
||||
host_routes = [{'destination': '135.207.0.0/16',
|
||||
'nexthop': '1.2.3.4'},
|
||||
{'destination': '12.0.0.0/8',
|
||||
'nexthop': '4.3.2.1'}]
|
||||
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr,
|
||||
allocation_pools=allocation_pools,
|
||||
host_routes=host_routes)
|
||||
|
||||
def test_create_subnet_with_too_many_routes(self):
|
||||
with self.network() as network:
|
||||
host_routes = [{'destination': '135.207.0.0/16',
|
||||
'nexthop': '1.2.3.4'},
|
||||
{'destination': '12.0.0.0/8',
|
||||
'nexthop': '4.3.2.1'},
|
||||
{'destination': '141.212.0.0/16',
|
||||
'nexthop': '2.2.2.2'}]
|
||||
|
||||
data = {'subnet': {'network_id': network['network']['id'],
|
||||
'cidr': '10.0.2.0/24',
|
||||
'ip_version': 4,
|
||||
'tenant_id': network['network']['tenant_id'],
|
||||
'gateway_ip': '10.0.0.1',
|
||||
'host_routes': host_routes}}
|
||||
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 400)
|
||||
|
||||
def test_update_subnet_dns(self):
|
||||
with self.subnet() as subnet:
|
||||
data = {'subnet': {'dns_nameservers': ['11.0.0.1']}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
res = self.deserialize('json', req.get_response(self.api))
|
||||
self.assertEqual(res['subnet']['dns_nameservers'],
|
||||
data['subnet']['dns_nameservers'])
|
||||
|
||||
def test_update_subnet_dns_with_too_many_entries(self):
|
||||
with self.subnet() as subnet:
|
||||
dns_list = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
|
||||
data = {'subnet': {'dns_nameservers': dns_list}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 400)
|
||||
|
||||
def test_update_subnet_route(self):
|
||||
with self.subnet() as subnet:
|
||||
data = {'subnet': {'host_routes':
|
||||
[{'destination': '12.0.0.0/8', 'nexthop': '1.2.3.4'}]}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
res = self.deserialize('json', req.get_response(self.api))
|
||||
self.assertEqual(res['subnet']['host_routes'],
|
||||
data['subnet']['host_routes'])
|
||||
|
||||
def test_update_subnet_route_with_too_many_entries(self):
|
||||
with self.subnet() as subnet:
|
||||
data = {'subnet': {'host_routes': [
|
||||
{'destination': '12.0.0.0/8', 'nexthop': '1.2.3.4'},
|
||||
{'destination': '13.0.0.0/8', 'nexthop': '1.2.3.5'},
|
||||
{'destination': '14.0.0.0/8', 'nexthop': '1.2.3.6'}]}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 400)
|
||||
|
||||
def test_delete_subnet_with_dns(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
fmt = 'json'
|
||||
dns_nameservers = ['1.2.3.4']
|
||||
# Create new network
|
||||
res = self._create_network(fmt=fmt, name='net',
|
||||
admin_status_up=True)
|
||||
network = self.deserialize(fmt, res)
|
||||
subnet = self._make_subnet(fmt, network, gateway_ip,
|
||||
cidr, ip_version=4,
|
||||
dns_nameservers=dns_nameservers)
|
||||
req = self.new_delete_request('subnets', subnet['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 204)
|
||||
|
||||
def test_delete_subnet_with_route(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
fmt = 'json'
|
||||
host_routes = [{'destination': '135.207.0.0/16',
|
||||
'nexthop': '1.2.3.4'}]
|
||||
# Create new network
|
||||
res = self._create_network(fmt=fmt, name='net',
|
||||
admin_status_up=True)
|
||||
network = self.deserialize(fmt, res)
|
||||
subnet = self._make_subnet(fmt, network, gateway_ip,
|
||||
cidr, ip_version=4,
|
||||
host_routes=host_routes)
|
||||
req = self.new_delete_request('subnets', subnet['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 204)
|
||||
|
||||
def test_delete_subnet_with_dns_and_route(self):
|
||||
gateway_ip = '10.0.0.1'
|
||||
cidr = '10.0.0.0/24'
|
||||
fmt = 'json'
|
||||
dns_nameservers = ['1.2.3.4']
|
||||
host_routes = [{'destination': '135.207.0.0/16',
|
||||
'nexthop': '1.2.3.4'}]
|
||||
# Create new network
|
||||
res = self._create_network(fmt=fmt, name='net',
|
||||
admin_status_up=True)
|
||||
network = self.deserialize(fmt, res)
|
||||
subnet = self._make_subnet(fmt, network, gateway_ip,
|
||||
cidr, ip_version=4,
|
||||
dns_nameservers=dns_nameservers,
|
||||
host_routes=host_routes)
|
||||
req = self.new_delete_request('subnets', subnet['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 204)
|
||||
|
Loading…
Reference in New Issue
Block a user