import sqlalchemy as sa
from sqlalchemy import sql
-from neutron.common import exceptions as exc
from neutron.db import api as db_api
from neutron.db import model_base
+from neutron.openstack.common.gettextutils import _LE
from neutron.openstack.common import log
from neutron.plugins.common import constants as p_const
-from neutron.plugins.ml2 import driver_api as api
-from neutron.plugins.ml2.drivers import helpers
from neutron.plugins.ml2.drivers import type_tunnel
LOG = log.getLogger(__name__)
return "<GreTunnelEndpoint(%s)>" % self.ip_address
-class GreTypeDriver(helpers.TypeDriverHelper, type_tunnel.TunnelTypeDriver):
+class GreTypeDriver(type_tunnel.TunnelTypeDriver):
def __init__(self):
super(GreTypeDriver, self).__init__(GreAllocation)
return p_const.TYPE_GRE
def initialize(self):
- self.gre_id_ranges = []
- self._parse_tunnel_ranges(
- cfg.CONF.ml2_type_gre.tunnel_id_ranges,
- self.gre_id_ranges,
- p_const.TYPE_GRE
- )
- self._sync_gre_allocations()
-
- def reserve_provider_segment(self, session, segment):
- if self.is_partial_segment(segment):
- alloc = self.allocate_partially_specified_segment(session)
- if not alloc:
- raise exc.NoNetworkAvailable
- else:
- segmentation_id = segment.get(api.SEGMENTATION_ID)
- alloc = self.allocate_fully_specified_segment(
- session, gre_id=segmentation_id)
- if not alloc:
- raise exc.TunnelIdInUse(tunnel_id=segmentation_id)
- return {api.NETWORK_TYPE: p_const.TYPE_GRE,
- api.PHYSICAL_NETWORK: None,
- api.SEGMENTATION_ID: alloc.gre_id}
-
- def allocate_tenant_segment(self, session):
- alloc = self.allocate_partially_specified_segment(session)
- if not alloc:
- return
- return {api.NETWORK_TYPE: p_const.TYPE_GRE,
- api.PHYSICAL_NETWORK: None,
- api.SEGMENTATION_ID: alloc.gre_id}
-
- def release_segment(self, session, segment):
- gre_id = segment[api.SEGMENTATION_ID]
-
- inside = any(lo <= gre_id <= hi for lo, hi in self.gre_id_ranges)
+ self._initialize(cfg.CONF.ml2_type_gre.tunnel_id_ranges)
- with session.begin(subtransactions=True):
- query = session.query(GreAllocation).filter_by(gre_id=gre_id)
- if inside:
- count = query.update({"allocated": False})
- if count:
- LOG.debug("Releasing gre tunnel %s to pool", gre_id)
- else:
- count = query.delete()
- if count:
- LOG.debug("Releasing gre tunnel %s outside pool", gre_id)
-
- if not count:
- LOG.warning(_("gre_id %s not found"), gre_id)
-
- def _sync_gre_allocations(self):
- """Synchronize gre_allocations table with configured tunnel ranges."""
+ def sync_allocations(self):
# determine current configured allocatable gres
gre_ids = set()
- for gre_id_range in self.gre_id_ranges:
+ for gre_id_range in self.tunnel_ranges:
tun_min, tun_max = gre_id_range
if tun_max + 1 - tun_min > 1000000:
- LOG.error(_("Skipping unreasonable gre ID range "
+ LOG.error(_LE("Skipping unreasonable gre ID range "
"%(tun_min)s:%(tun_max)s"),
{'tun_min': tun_min, 'tun_max': tun_max})
else:
# it's not allocatable, so check if its allocated
if not alloc.allocated:
# it's not, so remove it from table
- LOG.debug(_("Removing tunnel %s from pool"),
- alloc.gre_id)
+ LOG.debug("Removing tunnel %s from pool", alloc.gre_id)
session.delete(alloc)
# add missing allocatable tunnels to table
alloc = GreAllocation(gre_id=gre_id)
session.add(alloc)
- def get_gre_allocation(self, session, gre_id):
- return session.query(GreAllocation).filter_by(gre_id=gre_id).first()
-
def get_endpoints(self):
"""Get every gre endpoints from database."""
- LOG.debug(_("get_gre_endpoints() called"))
+ LOG.debug("get_gre_endpoints() called")
session = db_api.get_session()
with session.begin(subtransactions=True):
for gre_endpoint in gre_endpoints]
def add_endpoint(self, ip):
- LOG.debug(_("add_gre_endpoint() called for ip %s"), ip)
+ LOG.debug("add_gre_endpoint() called for ip %s", ip)
session = db_api.get_session()
try:
gre_endpoint = GreEndpoints(ip_address=ip)
# License for the specific language governing permissions and limitations
# under the License.
import abc
-import six
from neutron.common import exceptions as exc
from neutron.common import topics
+from neutron.openstack.common.gettextutils import _LW
from neutron.openstack.common import log
from neutron.plugins.ml2 import driver_api as api
+from neutron.plugins.ml2.drivers import helpers
LOG = log.getLogger(__name__)
TUNNEL = 'tunnel'
-@six.add_metaclass(abc.ABCMeta)
-class TunnelTypeDriver(api.TypeDriver):
+class TunnelTypeDriver(helpers.TypeDriverHelper):
"""Define stable abstract interface for ML2 type drivers.
tunnel type networks rely on tunnel endpoints. This class defines abstract
methods to manage these endpoints.
"""
+ def __init__(self, model):
+ super(TunnelTypeDriver, self).__init__(model)
+ self.segmentation_key = iter(self.primary_keys).next()
+
+ @abc.abstractmethod
+ def sync_allocations(self):
+ """Synchronize type_driver allocation table with configured ranges."""
+
@abc.abstractmethod
def add_endpoint(self, ip):
"""Register the endpoint in the type_driver database.
"""
pass
+ def _initialize(self, raw_tunnel_ranges):
+ self.tunnel_ranges = []
+ self._parse_tunnel_ranges(raw_tunnel_ranges,
+ self.tunnel_ranges,
+ self.get_type())
+ self.sync_allocations()
+
def _parse_tunnel_ranges(self, tunnel_ranges, current_range, tunnel_type):
for entry in tunnel_ranges:
entry = entry.strip()
{'key': key, 'tunnel': segment.get(api.NETWORK_TYPE)})
raise exc.InvalidInput(error_message=msg)
+ def reserve_provider_segment(self, session, segment):
+ if self.is_partial_segment(segment):
+ alloc = self.allocate_partially_specified_segment(session)
+ if not alloc:
+ raise exc.NoNetworkAvailable
+ else:
+ segmentation_id = segment.get(api.SEGMENTATION_ID)
+ alloc = self.allocate_fully_specified_segment(
+ session, **{self.segmentation_key: segmentation_id})
+ if not alloc:
+ raise exc.TunnelIdInUse(tunnel_id=segmentation_id)
+ return {api.NETWORK_TYPE: self.get_type(),
+ api.PHYSICAL_NETWORK: None,
+ api.SEGMENTATION_ID: getattr(alloc, self.segmentation_key)}
+
+ def allocate_tenant_segment(self, session):
+ alloc = self.allocate_partially_specified_segment(session)
+ if not alloc:
+ return
+ return {api.NETWORK_TYPE: self.get_type(),
+ api.PHYSICAL_NETWORK: None,
+ api.SEGMENTATION_ID: getattr(alloc, self.segmentation_key)}
+
+ def release_segment(self, session, segment):
+ tunnel_id = segment[api.SEGMENTATION_ID]
+
+ inside = any(lo <= tunnel_id <= hi for lo, hi in self.tunnel_ranges)
+
+ info = {'type': self.get_type(), 'id': tunnel_id}
+ with session.begin(subtransactions=True):
+ query = (session.query(self.model).
+ filter_by(**{self.segmentation_key: tunnel_id}))
+ if inside:
+ count = query.update({"allocated": False})
+ if count:
+ LOG.debug("Releasing %(type)s tunnel %(id)s to pool",
+ info)
+ else:
+ count = query.delete()
+ if count:
+ LOG.debug("Releasing %(type)s tunnel %(id)s outside pool",
+ info)
+
+ if not count:
+ LOG.warning(_LW("%(type)s tunnel %(id)s not found"), info)
+
+ def get_allocation(self, session, tunnel_id):
+ return (session.query(self.model).
+ filter_by(**{self.segmentation_key: tunnel_id}).
+ first())
+
class TunnelRpcCallbackMixin(object):
from oslo.config import cfg
from oslo.db import exception as db_exc
+from six import moves
import sqlalchemy as sa
from sqlalchemy import sql
-from neutron.common import exceptions as exc
from neutron.db import api as db_api
from neutron.db import model_base
+from neutron.openstack.common.gettextutils import _LE
from neutron.openstack.common import log
from neutron.plugins.common import constants as p_const
-from neutron.plugins.ml2 import driver_api as api
-from neutron.plugins.ml2.drivers import helpers
from neutron.plugins.ml2.drivers import type_tunnel
LOG = log.getLogger(__name__)
return "<VxlanTunnelEndpoint(%s)>" % self.ip_address
-class VxlanTypeDriver(helpers.TypeDriverHelper, type_tunnel.TunnelTypeDriver):
+class VxlanTypeDriver(type_tunnel.TunnelTypeDriver):
def __init__(self):
super(VxlanTypeDriver, self).__init__(VxlanAllocation)
return p_const.TYPE_VXLAN
def initialize(self):
- self.vxlan_vni_ranges = []
- self._parse_tunnel_ranges(
- cfg.CONF.ml2_type_vxlan.vni_ranges,
- self.vxlan_vni_ranges,
- p_const.TYPE_VXLAN
- )
- self._sync_vxlan_allocations()
-
- def reserve_provider_segment(self, session, segment):
- if self.is_partial_segment(segment):
- alloc = self.allocate_partially_specified_segment(session)
- if not alloc:
- raise exc.NoNetworkAvailable
- else:
- segmentation_id = segment.get(api.SEGMENTATION_ID)
- alloc = self.allocate_fully_specified_segment(
- session, vxlan_vni=segmentation_id)
- if not alloc:
- raise exc.TunnelIdInUse(tunnel_id=segmentation_id)
- return {api.NETWORK_TYPE: p_const.TYPE_VXLAN,
- api.PHYSICAL_NETWORK: None,
- api.SEGMENTATION_ID: alloc.vxlan_vni}
-
- def allocate_tenant_segment(self, session):
- alloc = self.allocate_partially_specified_segment(session)
- if not alloc:
- return
- return {api.NETWORK_TYPE: p_const.TYPE_VXLAN,
- api.PHYSICAL_NETWORK: None,
- api.SEGMENTATION_ID: alloc.vxlan_vni}
-
- def release_segment(self, session, segment):
- vxlan_vni = segment[api.SEGMENTATION_ID]
-
- inside = any(lo <= vxlan_vni <= hi for lo, hi in self.vxlan_vni_ranges)
+ self._initialize(cfg.CONF.ml2_type_vxlan.vni_ranges)
- with session.begin(subtransactions=True):
- query = (session.query(VxlanAllocation).
- filter_by(vxlan_vni=vxlan_vni))
- if inside:
- count = query.update({"allocated": False})
- if count:
- LOG.debug("Releasing vxlan tunnel %s to pool",
- vxlan_vni)
- else:
- count = query.delete()
- if count:
- LOG.debug("Releasing vxlan tunnel %s outside pool",
- vxlan_vni)
-
- if not count:
- LOG.warning(_("vxlan_vni %s not found"), vxlan_vni)
-
- def _sync_vxlan_allocations(self):
- """
- Synchronize vxlan_allocations table with configured tunnel ranges.
- """
+ def sync_allocations(self):
# determine current configured allocatable vnis
vxlan_vnis = set()
- for tun_min, tun_max in self.vxlan_vni_ranges:
+ for tun_min, tun_max in self.tunnel_ranges:
if tun_max + 1 - tun_min > MAX_VXLAN_VNI:
- LOG.error(_("Skipping unreasonable VXLAN VNI range "
- "%(tun_min)s:%(tun_max)s"),
+ LOG.error(_LE("Skipping unreasonable VXLAN VNI range "
+ "%(tun_min)s:%(tun_max)s"),
{'tun_min': tun_min, 'tun_max': tun_max})
else:
- vxlan_vnis |= set(xrange(tun_min, tun_max + 1))
+ vxlan_vnis |= set(moves.xrange(tun_min, tun_max + 1))
session = db_api.get_session()
with session.begin(subtransactions=True):
for vni in vni_list]
session.execute(VxlanAllocation.__table__.insert(), bulk)
- def get_vxlan_allocation(self, session, vxlan_vni):
- with session.begin(subtransactions=True):
- return session.query(VxlanAllocation).filter_by(
- vxlan_vni=vxlan_vni).first()
-
def get_endpoints(self):
"""Get every vxlan endpoints from database."""
def setUp(self):
super(GreTypeTest, self).setUp()
self.driver = type_gre.GreTypeDriver()
- self.driver.gre_id_ranges = TUNNEL_RANGES
- self.driver._sync_gre_allocations()
+ self.driver.tunnel_ranges = TUNNEL_RANGES
+ self.driver.sync_allocations()
self.session = db.get_session()
def test_validate_provider_segment(self):
def test_sync_tunnel_allocations(self):
self.assertIsNone(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN - 1))
- )
+ self.driver.get_allocation(self.session, (TUN_MIN - 1)))
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MIN)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN + 1)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MIN + 1)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX - 1)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MAX - 1)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MAX)).allocated)
self.assertIsNone(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX + 1))
- )
+ self.driver.get_allocation(self.session, (TUN_MAX + 1)))
- self.driver.gre_id_ranges = UPDATED_TUNNEL_RANGES
- self.driver._sync_gre_allocations()
+ self.driver.tunnel_ranges = UPDATED_TUNNEL_RANGES
+ self.driver.sync_allocations()
self.assertIsNone(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN + 5 - 1))
- )
+ self.driver.get_allocation(self.session, (TUN_MIN + 5 - 1)))
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN + 5)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MIN + 5)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MIN + 5 + 1)).allocated
- )
+ self.driver.get_allocation(self.session,
+ (TUN_MIN + 5 + 1)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX + 5 - 1)).allocated
- )
+ self.driver.get_allocation(self.session,
+ (TUN_MAX + 5 - 1)).allocated)
self.assertFalse(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX + 5)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MAX + 5)).allocated)
self.assertIsNone(
- self.driver.get_gre_allocation(self.session,
- (TUN_MAX + 5 + 1))
- )
+ self.driver.get_allocation(self.session, (TUN_MAX + 5 + 1)))
def test_partial_segment_is_partial_segment(self):
segment = {api.NETWORK_TYPE: 'gre',
api.PHYSICAL_NETWORK: None,
api.SEGMENTATION_ID: 101}
observed = self.driver.reserve_provider_segment(self.session, segment)
- alloc = self.driver.get_gre_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertTrue(alloc.allocated)
with testtools.ExpectedException(exc.TunnelIdInUse):
self.driver.reserve_provider_segment(self.session, segment)
self.driver.release_segment(self.session, segment)
- alloc = self.driver.get_gre_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertFalse(alloc.allocated)
segment[api.SEGMENTATION_ID] = 1000
observed = self.driver.reserve_provider_segment(self.session, segment)
- alloc = self.driver.get_gre_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertTrue(alloc.allocated)
self.driver.release_segment(self.session, segment)
- alloc = self.driver.get_gre_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertIsNone(alloc)
def test_reserve_provider_segment(self):
def setUp(self):
super(GreTypeMultiRangeTest, self).setUp()
self.driver = type_gre.GreTypeDriver()
- self.driver.gre_id_ranges = self.TUNNEL_MULTI_RANGES
- self.driver._sync_gre_allocations()
+ self.driver.tunnel_ranges = self.TUNNEL_MULTI_RANGES
+ self.driver.sync_allocations()
self.session = db.get_session()
def test_release_segment(self):
for key in (self.TUN_MIN0, self.TUN_MAX0,
self.TUN_MIN1, self.TUN_MAX1):
- alloc = self.driver.get_gre_allocation(self.session, key)
+ alloc = self.driver.get_allocation(self.session, key)
self.assertFalse(alloc.allocated)
def setUp(self):
super(VxlanTypeTest, self).setUp()
self.driver = type_vxlan.VxlanTypeDriver()
- self.driver.vxlan_vni_ranges = TUNNEL_RANGES
- self.driver._sync_vxlan_allocations()
+ self.driver.tunnel_ranges = TUNNEL_RANGES
+ self.driver.sync_allocations()
self.session = db.get_session()
def test_vxlan_tunnel_type(self):
def test_sync_tunnel_allocations(self):
self.assertIsNone(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MIN - 1))
- )
+ self.driver.get_allocation(self.session, (TUN_MIN - 1)))
self.assertFalse(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MIN)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MIN)).allocated)
self.assertFalse(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MIN + 1)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MIN + 1)).allocated)
self.assertFalse(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MAX - 1)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MAX - 1)).allocated)
self.assertFalse(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MAX)).allocated
- )
+ self.driver.get_allocation(self.session, (TUN_MAX)).allocated)
self.assertIsNone(
- self.driver.get_vxlan_allocation(self.session,
- (TUN_MAX + 1))
- )
-
- self.driver.vxlan_vni_ranges = UPDATED_TUNNEL_RANGES
- self.driver._sync_vxlan_allocations()
-
- self.assertIsNone(self.driver.
- get_vxlan_allocation(self.session,
- (TUN_MIN + 5 - 1)))
- self.assertFalse(self.driver.
- get_vxlan_allocation(self.session, (TUN_MIN + 5)).
- allocated)
- self.assertFalse(self.driver.
- get_vxlan_allocation(self.session, (TUN_MIN + 5 + 1)).
- allocated)
- self.assertFalse(self.driver.
- get_vxlan_allocation(self.session, (TUN_MAX + 5 - 1)).
- allocated)
- self.assertFalse(self.driver.
- get_vxlan_allocation(self.session, (TUN_MAX + 5)).
- allocated)
- self.assertIsNone(self.driver.
- get_vxlan_allocation(self.session,
- (TUN_MAX + 5 + 1)))
+ self.driver.get_allocation(self.session, (TUN_MAX + 1)))
+
+ self.driver.tunnel_ranges = UPDATED_TUNNEL_RANGES
+ self.driver.sync_allocations()
+
+ self.assertIsNone(
+ self.driver.get_allocation(self.session, (TUN_MIN + 5 - 1)))
+ self.assertFalse(
+ self.driver.get_allocation(self.session, (TUN_MIN + 5)).allocated)
+ self.assertFalse(
+ self.driver.get_allocation(self.session,
+ (TUN_MIN + 5 + 1)).allocated)
+ self.assertFalse(
+ self.driver.get_allocation(self.session,
+ (TUN_MAX + 5 - 1)).allocated)
+ self.assertFalse(
+ self.driver.get_allocation(self.session, (TUN_MAX + 5)).allocated)
+ self.assertIsNone(
+ self.driver.get_allocation(self.session, (TUN_MAX + 5 + 1)))
def test_partial_segment_is_partial_segment(self):
segment = {api.NETWORK_TYPE: 'vxlan',
api.PHYSICAL_NETWORK: None,
api.SEGMENTATION_ID: 101}
observed = self.driver.reserve_provider_segment(self.session, segment)
- alloc = self.driver.get_vxlan_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertTrue(alloc.allocated)
with testtools.ExpectedException(exc.TunnelIdInUse):
self.driver.reserve_provider_segment(self.session, segment)
self.driver.release_segment(self.session, segment)
- alloc = self.driver.get_vxlan_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertFalse(alloc.allocated)
segment[api.SEGMENTATION_ID] = 1000
observed = self.driver.reserve_provider_segment(self.session, segment)
- alloc = self.driver.get_vxlan_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertTrue(alloc.allocated)
self.driver.release_segment(self.session, segment)
- alloc = self.driver.get_vxlan_allocation(self.session,
- observed[api.SEGMENTATION_ID])
+ alloc = self.driver.get_allocation(self.session,
+ observed[api.SEGMENTATION_ID])
self.assertIsNone(alloc)
def test_reserve_provider_segment(self):
def setUp(self):
super(VxlanTypeMultiRangeTest, self).setUp()
self.driver = type_vxlan.VxlanTypeDriver()
- self.driver.vxlan_vni_ranges = self.TUNNEL_MULTI_RANGES
- self.driver._sync_vxlan_allocations()
+ self.driver.tunnel_ranges = self.TUNNEL_MULTI_RANGES
+ self.driver.sync_allocations()
self.session = db.get_session()
def test_release_segment(self):
for key in (self.TUN_MIN0, self.TUN_MAX0,
self.TUN_MIN1, self.TUN_MAX1):
- alloc = self.driver.get_vxlan_allocation(self.session, key)
+ alloc = self.driver.get_allocation(self.session, key)
self.assertFalse(alloc.allocated)