Remove availability range code and model
These models are effectively obsolete [1] and should've been removed in a previous patch [2] but some of it was left behind. [1] https://review.openstack.org/#/c/292207 [2] https://review.openstack.org/#/c/303638 Change-Id: Ib381c24f37e787b4912e28d98ec77473c0448c2b Related-Bug: #1543094 Closes-Bug: #1620746
This commit is contained in:

committed by
Carl Baldwin

parent
1cf8e5ab5a
commit
774792681d
@@ -1 +1 @@
|
|||||||
2e0d7a8a1586
|
5c85685d616d
|
||||||
|
@@ -0,0 +1,24 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Remove availability ranges."""
|
||||||
|
|
||||||
|
revision = '5c85685d616d'
|
||||||
|
down_revision = '2e0d7a8a1586'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.drop_table('ipavailabilityranges')
|
||||||
|
op.drop_table('ipamavailabilityranges')
|
@@ -34,40 +34,6 @@ _deprecate._moved_global('HasId', new_module=model_base)
|
|||||||
_deprecate._moved_global('HasStatusDescription', new_module=model_base)
|
_deprecate._moved_global('HasStatusDescription', new_module=model_base)
|
||||||
|
|
||||||
|
|
||||||
class IPAvailabilityRange(model_base.BASEV2):
|
|
||||||
"""Internal representation of available IPs for Neutron subnets.
|
|
||||||
|
|
||||||
Allocation - first entry from the range will be allocated.
|
|
||||||
If the first entry is equal to the last entry then this row
|
|
||||||
will be deleted.
|
|
||||||
Recycling ips involves reading the IPAllocationPool and IPAllocation tables
|
|
||||||
and inserting ranges representing available ips. This happens after the
|
|
||||||
final allocation is pulled from this table and a new ip allocation is
|
|
||||||
requested. Any contiguous ranges of available ips will be inserted as a
|
|
||||||
single range.
|
|
||||||
"""
|
|
||||||
|
|
||||||
allocation_pool_id = sa.Column(sa.String(36),
|
|
||||||
sa.ForeignKey('ipallocationpools.id',
|
|
||||||
ondelete="CASCADE"),
|
|
||||||
nullable=False,
|
|
||||||
primary_key=True)
|
|
||||||
first_ip = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
|
||||||
last_ip = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
|
||||||
__table_args__ = (
|
|
||||||
sa.UniqueConstraint(
|
|
||||||
first_ip, allocation_pool_id,
|
|
||||||
name='uniq_ipavailabilityranges0first_ip0allocation_pool_id'),
|
|
||||||
sa.UniqueConstraint(
|
|
||||||
last_ip, allocation_pool_id,
|
|
||||||
name='uniq_ipavailabilityranges0last_ip0allocation_pool_id'),
|
|
||||||
model_base.BASEV2.__table_args__
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "%s - %s" % (self.first_ip, self.last_ip)
|
|
||||||
|
|
||||||
|
|
||||||
class IPAllocationPool(model_base.BASEV2, model_base.HasId):
|
class IPAllocationPool(model_base.BASEV2, model_base.HasId):
|
||||||
"""Representation of an allocation pool in a Neutron subnet."""
|
"""Representation of an allocation pool in a Neutron subnet."""
|
||||||
|
|
||||||
@@ -76,10 +42,6 @@ class IPAllocationPool(model_base.BASEV2, model_base.HasId):
|
|||||||
nullable=True)
|
nullable=True)
|
||||||
first_ip = sa.Column(sa.String(64), nullable=False)
|
first_ip = sa.Column(sa.String(64), nullable=False)
|
||||||
last_ip = sa.Column(sa.String(64), nullable=False)
|
last_ip = sa.Column(sa.String(64), nullable=False)
|
||||||
available_ranges = orm.relationship(IPAvailabilityRange,
|
|
||||||
backref='ipallocationpool',
|
|
||||||
lazy="select",
|
|
||||||
cascade='all, delete-orphan')
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s - %s" % (self.first_ip, self.last_ip)
|
return "%s - %s" % (self.first_ip, self.last_ip)
|
||||||
|
@@ -13,12 +13,9 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_db import exception as db_exc
|
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from sqlalchemy.orm import exc as orm_exc
|
|
||||||
|
|
||||||
from neutron.ipam.drivers.neutrondb_ipam import db_models
|
from neutron.ipam.drivers.neutrondb_ipam import db_models
|
||||||
from neutron.ipam import exceptions as ipam_exc
|
|
||||||
|
|
||||||
# Database operations for Neutron's DB-backed IPAM driver
|
# Database operations for Neutron's DB-backed IPAM driver
|
||||||
|
|
||||||
@@ -69,7 +66,7 @@ class IpamSubnetManager(object):
|
|||||||
neutron_subnet_id=neutron_subnet_id).delete()
|
neutron_subnet_id=neutron_subnet_id).delete()
|
||||||
|
|
||||||
def create_pool(self, session, pool_start, pool_end):
|
def create_pool(self, session, pool_start, pool_end):
|
||||||
"""Create an allocation pool and availability ranges for the subnet.
|
"""Create an allocation pool for the subnet.
|
||||||
|
|
||||||
This method does not perform any validation on parameters; it simply
|
This method does not perform any validation on parameters; it simply
|
||||||
persist data on the database.
|
persist data on the database.
|
||||||
@@ -83,11 +80,6 @@ class IpamSubnetManager(object):
|
|||||||
first_ip=pool_start,
|
first_ip=pool_start,
|
||||||
last_ip=pool_end)
|
last_ip=pool_end)
|
||||||
session.add(ip_pool)
|
session.add(ip_pool)
|
||||||
ip_range = db_models.IpamAvailabilityRange(
|
|
||||||
allocation_pool=ip_pool,
|
|
||||||
first_ip=pool_start,
|
|
||||||
last_ip=pool_end)
|
|
||||||
session.add(ip_range)
|
|
||||||
return ip_pool
|
return ip_pool
|
||||||
|
|
||||||
def delete_allocation_pools(self, session):
|
def delete_allocation_pools(self, session):
|
||||||
@@ -104,104 +96,6 @@ class IpamSubnetManager(object):
|
|||||||
db_models.IpamAllocationPool).filter_by(
|
db_models.IpamAllocationPool).filter_by(
|
||||||
ipam_subnet_id=self._ipam_subnet_id)
|
ipam_subnet_id=self._ipam_subnet_id)
|
||||||
|
|
||||||
def _range_query(self, session):
|
|
||||||
return session.query(
|
|
||||||
db_models.IpamAvailabilityRange).join(
|
|
||||||
db_models.IpamAllocationPool).filter_by(
|
|
||||||
ipam_subnet_id=self._ipam_subnet_id)
|
|
||||||
|
|
||||||
def get_first_range(self, session):
|
|
||||||
"""Return the first availability range for the subnet
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:return: first available range as instance of
|
|
||||||
neutron.ipam.drivers.neutrondb_ipam.db_models.IpamAvailabilityRange
|
|
||||||
"""
|
|
||||||
return self._range_query(session).first()
|
|
||||||
|
|
||||||
def list_ranges_by_subnet_id(self, session):
|
|
||||||
"""Return availability ranges for a given ipam subnet
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:return: list of availability ranges as instances of
|
|
||||||
neutron.ipam.drivers.neutrondb_ipam.db_models.IpamAvailabilityRange
|
|
||||||
"""
|
|
||||||
return self._range_query(session)
|
|
||||||
|
|
||||||
def list_ranges_by_allocation_pool(self, session, allocation_pool_id):
|
|
||||||
"""Return availability ranges for a given pool.
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:param allocation_pool_id: allocation pool identifier
|
|
||||||
:return: list of availability ranges as instances of
|
|
||||||
neutron.ipam.drivers.neutrondb_ipam.db_models.IpamAvailabilityRange
|
|
||||||
"""
|
|
||||||
return session.query(
|
|
||||||
db_models.IpamAvailabilityRange).join(
|
|
||||||
db_models.IpamAllocationPool).filter_by(
|
|
||||||
id=allocation_pool_id)
|
|
||||||
|
|
||||||
def update_range(self, session, db_range, first_ip=None, last_ip=None):
|
|
||||||
"""Updates db_range to have new first_ip and last_ip.
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:param db_range: IpamAvailabilityRange db object
|
|
||||||
:param first_ip: first ip address in range
|
|
||||||
:param last_ip: last ip address in range
|
|
||||||
:return: count of updated rows
|
|
||||||
"""
|
|
||||||
opts = {}
|
|
||||||
if first_ip:
|
|
||||||
opts['first_ip'] = str(first_ip)
|
|
||||||
if last_ip:
|
|
||||||
opts['last_ip'] = str(last_ip)
|
|
||||||
if not opts:
|
|
||||||
raise ipam_exc.IpamAvailabilityRangeNoChanges()
|
|
||||||
try:
|
|
||||||
return session.query(
|
|
||||||
db_models.IpamAvailabilityRange).filter_by(
|
|
||||||
allocation_pool_id=db_range.allocation_pool_id).filter_by(
|
|
||||||
first_ip=db_range.first_ip).filter_by(
|
|
||||||
last_ip=db_range.last_ip).update(opts)
|
|
||||||
except orm_exc.ObjectDeletedError:
|
|
||||||
raise db_exc.RetryRequest(ipam_exc.IPAllocationFailed())
|
|
||||||
|
|
||||||
def delete_range(self, session, db_range):
|
|
||||||
"""Return count of deleted ranges
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:param db_range: IpamAvailabilityRange db object
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return session.query(
|
|
||||||
db_models.IpamAvailabilityRange).filter_by(
|
|
||||||
allocation_pool_id=db_range.allocation_pool_id).filter_by(
|
|
||||||
first_ip=db_range.first_ip).filter_by(
|
|
||||||
last_ip=db_range.last_ip).delete()
|
|
||||||
except orm_exc.ObjectDeletedError:
|
|
||||||
raise db_exc.RetryRequest(ipam_exc.IPAllocationFailed())
|
|
||||||
|
|
||||||
def create_range(self, session, allocation_pool_id,
|
|
||||||
range_start, range_end):
|
|
||||||
"""Create an availability range for a given pool.
|
|
||||||
|
|
||||||
This method does not perform any validation on parameters; it simply
|
|
||||||
persist data on the database.
|
|
||||||
|
|
||||||
:param session: database session
|
|
||||||
:param allocation_pool_id: allocation pool identifier
|
|
||||||
:param range_start: first ip address in the range
|
|
||||||
:param range_end: last ip address in the range
|
|
||||||
:return: the newly created availability range as an instance of
|
|
||||||
neutron.ipam.drivers.neutrondb_ipam.db_models.IpamAvailabilityRange
|
|
||||||
"""
|
|
||||||
new_ip_range = db_models.IpamAvailabilityRange(
|
|
||||||
allocation_pool_id=allocation_pool_id,
|
|
||||||
first_ip=range_start,
|
|
||||||
last_ip=range_end)
|
|
||||||
session.add(new_ip_range)
|
|
||||||
return new_ip_range
|
|
||||||
|
|
||||||
def check_unique_allocation(self, session, ip_address):
|
def check_unique_allocation(self, session, ip_address):
|
||||||
"""Validate that the IP address on the subnet is not in use."""
|
"""Validate that the IP address on the subnet is not in use."""
|
||||||
iprequest = session.query(db_models.IpamAllocation).filter_by(
|
iprequest = session.query(db_models.IpamAllocation).filter_by(
|
||||||
|
@@ -21,40 +21,6 @@ from sqlalchemy import orm as sa_orm
|
|||||||
# Database models used by the neutron DB IPAM driver
|
# Database models used by the neutron DB IPAM driver
|
||||||
|
|
||||||
|
|
||||||
# NOTE(salv-orlando): This is meant to replace the class
|
|
||||||
# neutron.db.models_v2.IPAvailabilityRange.
|
|
||||||
class IpamAvailabilityRange(model_base.BASEV2):
|
|
||||||
"""Internal representation of available IPs for Neutron subnets.
|
|
||||||
|
|
||||||
Allocation - first entry from the range will be allocated.
|
|
||||||
If the first entry is equal to the last entry then this row
|
|
||||||
will be deleted.
|
|
||||||
Recycling ips involves reading the IPAllocationPool and IPAllocation tables
|
|
||||||
and inserting ranges representing available ips. This happens after the
|
|
||||||
final allocation is pulled from this table and a new ip allocation is
|
|
||||||
requested. Any contiguous ranges of available ips will be inserted as a
|
|
||||||
single range.
|
|
||||||
"""
|
|
||||||
|
|
||||||
allocation_pool_id = sa.Column(sa.String(36),
|
|
||||||
sa.ForeignKey('ipamallocationpools.id',
|
|
||||||
ondelete="CASCADE"),
|
|
||||||
nullable=False,
|
|
||||||
primary_key=True)
|
|
||||||
first_ip = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
|
||||||
last_ip = sa.Column(sa.String(64), nullable=False, primary_key=True)
|
|
||||||
__table_args__ = (
|
|
||||||
sa.Index('ix_ipamavailabilityranges_first_ip_allocation_pool_id',
|
|
||||||
'first_ip', 'allocation_pool_id'),
|
|
||||||
sa.Index('ix_ipamavailabilityranges_last_ip_allocation_pool_id',
|
|
||||||
'last_ip', 'allocation_pool_id'),
|
|
||||||
model_base.BASEV2.__table_args__
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "%s - %s" % (self.first_ip, self.last_ip)
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE(salv-orlando): The following data model creates redundancy with
|
# NOTE(salv-orlando): The following data model creates redundancy with
|
||||||
# models_v2.IPAllocationPool. This level of data redundancy could be tolerated
|
# models_v2.IPAllocationPool. This level of data redundancy could be tolerated
|
||||||
# considering that the following model is specific to the IPAM driver logic.
|
# considering that the following model is specific to the IPAM driver logic.
|
||||||
@@ -72,10 +38,6 @@ class IpamAllocationPool(model_base.BASEV2, model_base.HasId):
|
|||||||
nullable=False)
|
nullable=False)
|
||||||
first_ip = sa.Column(sa.String(64), nullable=False)
|
first_ip = sa.Column(sa.String(64), nullable=False)
|
||||||
last_ip = sa.Column(sa.String(64), nullable=False)
|
last_ip = sa.Column(sa.String(64), nullable=False)
|
||||||
available_ranges = sa_orm.relationship(IpamAvailabilityRange,
|
|
||||||
backref='allocation_pool',
|
|
||||||
lazy="joined",
|
|
||||||
cascade='all, delete-orphan')
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s - %s" % (self.first_ip, self.last_ip)
|
return "%s - %s" % (self.first_ip, self.last_ip)
|
||||||
|
@@ -39,9 +39,6 @@ class NeutronDbSubnet(ipam_base.Subnet):
|
|||||||
|
|
||||||
This class implements the strategy for IP address allocation and
|
This class implements the strategy for IP address allocation and
|
||||||
deallocation for the Neutron DB IPAM driver.
|
deallocation for the Neutron DB IPAM driver.
|
||||||
Allocation for IP addresses is based on the concept of availability
|
|
||||||
ranges, which were already used in Neutron's DB base class for handling
|
|
||||||
IPAM operations.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -72,7 +69,7 @@ class NeutronDbSubnet(ipam_base.Subnet):
|
|||||||
subnet_request.gateway_ip)
|
subnet_request.gateway_ip)
|
||||||
else:
|
else:
|
||||||
pools = subnet_request.allocation_pools
|
pools = subnet_request.allocation_pools
|
||||||
# Create IPAM allocation pools and availability ranges
|
# Create IPAM allocation pools
|
||||||
cls.create_allocation_pools(subnet_manager, session, pools,
|
cls.create_allocation_pools(subnet_manager, session, pools,
|
||||||
subnet_request.subnet_cidr)
|
subnet_request.subnet_cidr)
|
||||||
|
|
||||||
@@ -208,9 +205,8 @@ class NeutronDbSubnet(ipam_base.Subnet):
|
|||||||
|
|
||||||
def deallocate(self, address):
|
def deallocate(self, address):
|
||||||
# This is almost a no-op because the Neutron DB IPAM driver does not
|
# This is almost a no-op because the Neutron DB IPAM driver does not
|
||||||
# delete IPAllocation objects, neither rebuilds availability ranges
|
# delete IPAllocation objects at every deallocation. The only operation
|
||||||
# at every deallocation. The only operation it performs is to delete
|
# it performs is to delete an IPRequest entry.
|
||||||
# an IPRequest entry.
|
|
||||||
session = self._context.session
|
session = self._context.session
|
||||||
|
|
||||||
count = self.subnet_manager.delete_allocation(
|
count = self.subnet_manager.delete_allocation(
|
||||||
|
@@ -76,10 +76,6 @@ class IPAllocationFailed(exceptions.NeutronException):
|
|||||||
message = _("IP allocation failed. Try again later.")
|
message = _("IP allocation failed. Try again later.")
|
||||||
|
|
||||||
|
|
||||||
class IpamAvailabilityRangeNoChanges(exceptions.NeutronException):
|
|
||||||
message = _("New value for first_ip or last_ip has to be specified.")
|
|
||||||
|
|
||||||
|
|
||||||
class IpamValueInvalid(exceptions.Conflict):
|
class IpamValueInvalid(exceptions.Conflict):
|
||||||
def __init__(self, message=None):
|
def __init__(self, message=None):
|
||||||
self.message = message
|
self.message = message
|
||||||
|
@@ -21,7 +21,6 @@ import testtools
|
|||||||
from neutron import context
|
from neutron import context
|
||||||
from neutron.db import db_base_plugin_v2 as base_plugin
|
from neutron.db import db_base_plugin_v2 as base_plugin
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.ipam.drivers.neutrondb_ipam import db_models as ipam_models
|
|
||||||
from neutron.tests.unit import testlib_api
|
from neutron.tests.unit import testlib_api
|
||||||
|
|
||||||
|
|
||||||
@@ -67,13 +66,6 @@ class IpamTestCase(testlib_api.SqlTestCase):
|
|||||||
actual = self.result_set_to_dicts(result_set, keys)
|
actual = self.result_set_to_dicts(result_set, keys)
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def assert_ip_avail_range_matches(self, expected):
|
|
||||||
result_set = self.cxt.session.query(
|
|
||||||
ipam_models.IpamAvailabilityRange).all()
|
|
||||||
keys = ['first_ip', 'last_ip']
|
|
||||||
actual = self.result_set_to_dicts(result_set, keys)
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def assert_ip_alloc_pool_matches(self, expected):
|
def assert_ip_alloc_pool_matches(self, expected):
|
||||||
result_set = self.cxt.session.query(models_v2.IPAllocationPool).all()
|
result_set = self.cxt.session.query(models_v2.IPAllocationPool).all()
|
||||||
keys = ['first_ip', 'last_ip', 'subnet_id']
|
keys = ['first_ip', 'last_ip', 'subnet_id']
|
||||||
|
@@ -13,16 +13,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from sqlalchemy.orm import exc as orm_exc
|
|
||||||
|
|
||||||
from neutron import context
|
from neutron import context
|
||||||
from neutron.db import api as ndb_api
|
|
||||||
from neutron.ipam.drivers.neutrondb_ipam import db_api
|
from neutron.ipam.drivers.neutrondb_ipam import db_api
|
||||||
from neutron.ipam.drivers.neutrondb_ipam import db_models
|
from neutron.ipam.drivers.neutrondb_ipam import db_models
|
||||||
from neutron.ipam import exceptions as ipam_exc
|
|
||||||
from neutron.tests.unit import testlib_api
|
from neutron.tests.unit import testlib_api
|
||||||
|
|
||||||
|
|
||||||
@@ -61,122 +56,19 @@ class TestIpamSubnetManager(testlib_api.SqlTestCase):
|
|||||||
'non-existent')
|
'non-existent')
|
||||||
self.assertEqual(0, count)
|
self.assertEqual(0, count)
|
||||||
|
|
||||||
def _create_pools(self, pools):
|
|
||||||
db_pools = []
|
|
||||||
for pool in pools:
|
|
||||||
db_pool = self.subnet_manager.create_pool(self.ctx.session,
|
|
||||||
pool[0],
|
|
||||||
pool[1])
|
|
||||||
db_pools.append(db_pool)
|
|
||||||
return db_pools
|
|
||||||
|
|
||||||
def _validate_ips(self, pools, db_pool):
|
def _validate_ips(self, pools, db_pool):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
any(pool == (db_pool.first_ip, db_pool.last_ip) for pool in pools))
|
any(pool == (db_pool.first_ip, db_pool.last_ip) for pool in pools))
|
||||||
|
|
||||||
def test_create_pool(self):
|
def test_create_pool(self):
|
||||||
db_pools = self._create_pools([self.single_pool])
|
self.subnet_manager.create_pool(self.ctx.session,
|
||||||
|
self.single_pool[0],
|
||||||
|
self.single_pool[1])
|
||||||
|
|
||||||
ipam_pool = self.ctx.session.query(db_models.IpamAllocationPool).\
|
ipam_pool = self.ctx.session.query(db_models.IpamAllocationPool).\
|
||||||
filter_by(ipam_subnet_id=self.ipam_subnet_id).first()
|
filter_by(ipam_subnet_id=self.ipam_subnet_id).first()
|
||||||
self._validate_ips([self.single_pool], ipam_pool)
|
self._validate_ips([self.single_pool], ipam_pool)
|
||||||
|
|
||||||
range = self.ctx.session.query(db_models.IpamAvailabilityRange).\
|
|
||||||
filter_by(allocation_pool_id=db_pools[0].id).first()
|
|
||||||
self._validate_ips([self.single_pool], range)
|
|
||||||
|
|
||||||
def test_get_first_range(self):
|
|
||||||
self._create_pools(self.multi_pool)
|
|
||||||
range = self.subnet_manager.get_first_range(self.ctx.session)
|
|
||||||
self._validate_ips(self.multi_pool, range)
|
|
||||||
|
|
||||||
def test_list_ranges_by_subnet_id(self):
|
|
||||||
self._create_pools(self.multi_pool)
|
|
||||||
|
|
||||||
db_ranges = self.subnet_manager.list_ranges_by_subnet_id(
|
|
||||||
self.ctx.session).all()
|
|
||||||
self.assertEqual(2, len(db_ranges))
|
|
||||||
self.assertEqual(db_models.IpamAvailabilityRange, type(db_ranges[0]))
|
|
||||||
|
|
||||||
def test_list_ranges_by_allocation_pool(self):
|
|
||||||
db_pools = self._create_pools([self.single_pool])
|
|
||||||
# generate ids for allocation pools on flush
|
|
||||||
self.ctx.session.flush()
|
|
||||||
db_ranges = self.subnet_manager.list_ranges_by_allocation_pool(
|
|
||||||
self.ctx.session,
|
|
||||||
db_pools[0].id).all()
|
|
||||||
self.assertEqual(1, len(db_ranges))
|
|
||||||
self.assertEqual(db_models.IpamAvailabilityRange, type(db_ranges[0]))
|
|
||||||
self._validate_ips([self.single_pool], db_ranges[0])
|
|
||||||
|
|
||||||
def test_create_range(self):
|
|
||||||
self._create_pools([self.single_pool])
|
|
||||||
pool = self.ctx.session.query(db_models.IpamAllocationPool).\
|
|
||||||
filter_by(ipam_subnet_id=self.ipam_subnet_id).first()
|
|
||||||
self._validate_ips([self.single_pool], pool)
|
|
||||||
allocation_pool_id = pool.id
|
|
||||||
|
|
||||||
# delete the range
|
|
||||||
db_range = self.subnet_manager.list_ranges_by_allocation_pool(
|
|
||||||
self.ctx.session,
|
|
||||||
pool.id).first()
|
|
||||||
self._validate_ips([self.single_pool], db_range)
|
|
||||||
self.ctx.session.delete(db_range)
|
|
||||||
|
|
||||||
# create a new range
|
|
||||||
range_start = '1.2.3.5'
|
|
||||||
range_end = '1.2.3.9'
|
|
||||||
new_range = self.subnet_manager.create_range(self.ctx.session,
|
|
||||||
allocation_pool_id,
|
|
||||||
range_start,
|
|
||||||
range_end)
|
|
||||||
self.assertEqual(range_start, new_range.first_ip)
|
|
||||||
self.assertEqual(range_end, new_range.last_ip)
|
|
||||||
|
|
||||||
def test_update_range(self):
|
|
||||||
self._create_pools([self.single_pool])
|
|
||||||
db_range = self.subnet_manager.get_first_range(self.ctx.session)
|
|
||||||
updated_count = self.subnet_manager.update_range(self.ctx.session,
|
|
||||||
db_range,
|
|
||||||
first_ip='1.2.3.6',
|
|
||||||
last_ip='1.2.3.8')
|
|
||||||
self.assertEqual(1, updated_count)
|
|
||||||
|
|
||||||
def test_update_range_no_new_values(self):
|
|
||||||
self._create_pools([self.single_pool])
|
|
||||||
db_range = self.subnet_manager.get_first_range(self.ctx.session)
|
|
||||||
self.assertRaises(ipam_exc.IpamAvailabilityRangeNoChanges,
|
|
||||||
self.subnet_manager.update_range,
|
|
||||||
self.ctx.session, db_range)
|
|
||||||
|
|
||||||
def test_update_range_reraise_error(self):
|
|
||||||
session = mock.Mock()
|
|
||||||
session.query.side_effect = orm_exc.ObjectDeletedError(None, None)
|
|
||||||
|
|
||||||
@ndb_api.retry_db_errors
|
|
||||||
def go():
|
|
||||||
self.subnet_manager.update_range(session, mock.Mock(),
|
|
||||||
first_ip='1.2.3.5')
|
|
||||||
|
|
||||||
self.assertRaises(ipam_exc.IPAllocationFailed, go)
|
|
||||||
|
|
||||||
def test_delete_range(self):
|
|
||||||
self._create_pools([self.single_pool])
|
|
||||||
db_range = self.subnet_manager.get_first_range(self.ctx.session)
|
|
||||||
deleted_count = self.subnet_manager.delete_range(self.ctx.session,
|
|
||||||
db_range)
|
|
||||||
self.assertEqual(1, deleted_count)
|
|
||||||
|
|
||||||
def test_delete_range_reraise_error(self):
|
|
||||||
session = mock.Mock()
|
|
||||||
session.query.side_effect = orm_exc.ObjectDeletedError(None, None)
|
|
||||||
|
|
||||||
@ndb_api.retry_db_errors
|
|
||||||
def go():
|
|
||||||
self.subnet_manager.delete_range(session, mock.Mock())
|
|
||||||
|
|
||||||
self.assertRaises(ipam_exc.IPAllocationFailed, go)
|
|
||||||
|
|
||||||
def test_check_unique_allocation(self):
|
def test_check_unique_allocation(self):
|
||||||
self.assertTrue(self.subnet_manager.check_unique_allocation(
|
self.assertTrue(self.subnet_manager.check_unique_allocation(
|
||||||
self.ctx.session, self.subnet_ip))
|
self.ctx.session, self.subnet_ip))
|
||||||
|
Reference in New Issue
Block a user