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:
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)
|
||||
|
||||
|
||||
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):
|
||||
"""Representation of an allocation pool in a Neutron subnet."""
|
||||
|
||||
@ -76,10 +42,6 @@ class IPAllocationPool(model_base.BASEV2, model_base.HasId):
|
||||
nullable=True)
|
||||
first_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):
|
||||
return "%s - %s" % (self.first_ip, self.last_ip)
|
||||
|
@ -13,12 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_db import exception as db_exc
|
||||
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 import exceptions as ipam_exc
|
||||
|
||||
# Database operations for Neutron's DB-backed IPAM driver
|
||||
|
||||
@ -69,7 +66,7 @@ class IpamSubnetManager(object):
|
||||
neutron_subnet_id=neutron_subnet_id).delete()
|
||||
|
||||
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
|
||||
persist data on the database.
|
||||
@ -83,11 +80,6 @@ class IpamSubnetManager(object):
|
||||
first_ip=pool_start,
|
||||
last_ip=pool_end)
|
||||
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
|
||||
|
||||
def delete_allocation_pools(self, session):
|
||||
@ -104,104 +96,6 @@ class IpamSubnetManager(object):
|
||||
db_models.IpamAllocationPool).filter_by(
|
||||
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):
|
||||
"""Validate that the IP address on the subnet is not in use."""
|
||||
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
|
||||
|
||||
|
||||
# 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
|
||||
# models_v2.IPAllocationPool. This level of data redundancy could be tolerated
|
||||
# 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)
|
||||
first_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):
|
||||
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
|
||||
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
|
||||
@ -72,7 +69,7 @@ class NeutronDbSubnet(ipam_base.Subnet):
|
||||
subnet_request.gateway_ip)
|
||||
else:
|
||||
pools = subnet_request.allocation_pools
|
||||
# Create IPAM allocation pools and availability ranges
|
||||
# Create IPAM allocation pools
|
||||
cls.create_allocation_pools(subnet_manager, session, pools,
|
||||
subnet_request.subnet_cidr)
|
||||
|
||||
@ -208,9 +205,8 @@ class NeutronDbSubnet(ipam_base.Subnet):
|
||||
|
||||
def deallocate(self, address):
|
||||
# This is almost a no-op because the Neutron DB IPAM driver does not
|
||||
# delete IPAllocation objects, neither rebuilds availability ranges
|
||||
# at every deallocation. The only operation it performs is to delete
|
||||
# an IPRequest entry.
|
||||
# delete IPAllocation objects at every deallocation. The only operation
|
||||
# it performs is to delete an IPRequest entry.
|
||||
session = self._context.session
|
||||
|
||||
count = self.subnet_manager.delete_allocation(
|
||||
|
@ -76,10 +76,6 @@ class IPAllocationFailed(exceptions.NeutronException):
|
||||
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):
|
||||
def __init__(self, message=None):
|
||||
self.message = message
|
||||
|
@ -21,7 +21,6 @@ import testtools
|
||||
from neutron import context
|
||||
from neutron.db import db_base_plugin_v2 as base_plugin
|
||||
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
|
||||
|
||||
|
||||
@ -67,13 +66,6 @@ class IpamTestCase(testlib_api.SqlTestCase):
|
||||
actual = self.result_set_to_dicts(result_set, keys)
|
||||
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):
|
||||
result_set = self.cxt.session.query(models_v2.IPAllocationPool).all()
|
||||
keys = ['first_ip', 'last_ip', 'subnet_id']
|
||||
|
@ -13,16 +13,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy.orm import exc as orm_exc
|
||||
|
||||
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_models
|
||||
from neutron.ipam import exceptions as ipam_exc
|
||||
from neutron.tests.unit import testlib_api
|
||||
|
||||
|
||||
@ -61,122 +56,19 @@ class TestIpamSubnetManager(testlib_api.SqlTestCase):
|
||||
'non-existent')
|
||||
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):
|
||||
self.assertTrue(
|
||||
any(pool == (db_pool.first_ip, db_pool.last_ip) for pool in pools))
|
||||
|
||||
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).\
|
||||
filter_by(ipam_subnet_id=self.ipam_subnet_id).first()
|
||||
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):
|
||||
self.assertTrue(self.subnet_manager.check_unique_allocation(
|
||||
self.ctx.session, self.subnet_ip))
|
||||
|
Loading…
Reference in New Issue
Block a user