neutron/neutron/db/segments_db.py

155 lines
5.8 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 neutron_lib.db import model_base
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.callbacks import events
from neutron.callbacks import registry
from neutron.callbacks import resources
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(context, network_id, segment, segment_index=0,
is_dynamic=False):
with context.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
)
context.session.add(record)
registry.notify(resources.SEGMENT,
events.PRECOMMIT_CREATE,
trigger=add_network_segment,
context=context,
segment=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())