1080620e5a
A warning could be found in SQLAlchemy, if handling empty WHERE IN clauses. This is found at neutron.db.segments_db.get_networks_segments To avoid it, just return empty dict in such case. Change-Id: I3cf727dede1d5909aeefbf852332818164ad3777 Closes-bug: #1586816
147 lines
5.4 KiB
Python
147 lines
5.4 KiB
Python
# 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.
|
|
|
|
from oslo_log import log as logging
|
|
from oslo_utils import uuidutils
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.orm import exc
|
|
|
|
from neutron._i18n import _LI
|
|
from neutron.db import model_base
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
"""
|
|
Some standalone plugins need a DB table to store provider
|
|
network information. Initially there was no such table,
|
|
but in Mitaka the ML2 NetworkSegment table was promoted here.
|
|
"""
|
|
|
|
|
|
class NetworkSegment(model_base.BASEV2, model_base.HasId):
|
|
"""Represent persistent state of a network segment.
|
|
|
|
A network segment is a portion of a neutron network with a
|
|
specific physical realization. A neutron network can consist of
|
|
one or more segments.
|
|
"""
|
|
|
|
network_id = sa.Column(sa.String(36),
|
|
sa.ForeignKey('networks.id', ondelete="CASCADE"),
|
|
nullable=False)
|
|
network_type = sa.Column(sa.String(32), nullable=False)
|
|
physical_network = sa.Column(sa.String(64))
|
|
segmentation_id = sa.Column(sa.Integer)
|
|
is_dynamic = sa.Column(sa.Boolean, default=False, nullable=False,
|
|
server_default=sa.sql.false())
|
|
segment_index = sa.Column(sa.Integer, nullable=False, server_default='0')
|
|
|
|
|
|
NETWORK_TYPE = NetworkSegment.network_type.name
|
|
PHYSICAL_NETWORK = NetworkSegment.physical_network.name
|
|
SEGMENTATION_ID = NetworkSegment.segmentation_id.name
|
|
|
|
|
|
def _make_segment_dict(record):
|
|
"""Make a segment dictionary out of a DB record."""
|
|
return {'id': record.id,
|
|
NETWORK_TYPE: record.network_type,
|
|
PHYSICAL_NETWORK: record.physical_network,
|
|
SEGMENTATION_ID: record.segmentation_id}
|
|
|
|
|
|
def add_network_segment(session, network_id, segment, segment_index=0,
|
|
is_dynamic=False):
|
|
with session.begin(subtransactions=True):
|
|
record = NetworkSegment(
|
|
id=uuidutils.generate_uuid(),
|
|
network_id=network_id,
|
|
network_type=segment.get(NETWORK_TYPE),
|
|
physical_network=segment.get(PHYSICAL_NETWORK),
|
|
segmentation_id=segment.get(SEGMENTATION_ID),
|
|
segment_index=segment_index,
|
|
is_dynamic=is_dynamic
|
|
)
|
|
session.add(record)
|
|
segment['id'] = record.id
|
|
LOG.info(_LI("Added segment %(id)s of type %(network_type)s for network "
|
|
"%(network_id)s"),
|
|
{'id': record.id,
|
|
'network_type': record.network_type,
|
|
'network_id': record.network_id})
|
|
|
|
|
|
def get_network_segments(session, network_id, filter_dynamic=False):
|
|
return get_networks_segments(
|
|
session, [network_id], filter_dynamic)[network_id]
|
|
|
|
|
|
def get_networks_segments(session, network_ids, filter_dynamic=False):
|
|
if not network_ids:
|
|
return {}
|
|
|
|
with session.begin(subtransactions=True):
|
|
query = (session.query(NetworkSegment).
|
|
filter(NetworkSegment.network_id.in_(network_ids)).
|
|
order_by(NetworkSegment.segment_index))
|
|
if filter_dynamic is not None:
|
|
query = query.filter_by(is_dynamic=filter_dynamic)
|
|
records = query.all()
|
|
result = {net_id: [] for net_id in network_ids}
|
|
for record in records:
|
|
result[record.network_id].append(_make_segment_dict(record))
|
|
return result
|
|
|
|
|
|
def get_segment_by_id(session, segment_id):
|
|
with session.begin(subtransactions=True):
|
|
try:
|
|
record = (session.query(NetworkSegment).
|
|
filter_by(id=segment_id).
|
|
one())
|
|
return _make_segment_dict(record)
|
|
except exc.NoResultFound:
|
|
return
|
|
|
|
|
|
def get_dynamic_segment(session, network_id, physical_network=None,
|
|
segmentation_id=None):
|
|
"""Return a dynamic segment for the filters provided if one exists."""
|
|
with session.begin(subtransactions=True):
|
|
query = (session.query(NetworkSegment).
|
|
filter_by(network_id=network_id, is_dynamic=True))
|
|
if physical_network:
|
|
query = query.filter_by(physical_network=physical_network)
|
|
if segmentation_id:
|
|
query = query.filter_by(segmentation_id=segmentation_id)
|
|
record = query.first()
|
|
|
|
if record:
|
|
return _make_segment_dict(record)
|
|
else:
|
|
LOG.debug("No dynamic segment found for "
|
|
"Network:%(network_id)s, "
|
|
"Physical network:%(physnet)s, "
|
|
"segmentation_id:%(segmentation_id)s",
|
|
{'network_id': network_id,
|
|
'physnet': physical_network,
|
|
'segmentation_id': segmentation_id})
|
|
return None
|
|
|
|
|
|
def delete_network_segment(session, segment_id):
|
|
"""Release a dynamic segment for the params provided if one exists."""
|
|
with session.begin(subtransactions=True):
|
|
(session.query(NetworkSegment).
|
|
filter_by(id=segment_id).delete())
|