neutron/neutron/db/segments_db.py

194 lines
7.6 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.api.definitions import segment as segment_def
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib.db import api as db_api
from neutron_lib.plugins.ml2 import api as ml2_api
from oslo_log import log as logging
from oslo_utils import uuidutils
from neutron.objects import base as base_obj
from neutron.objects import network as network_obj
from neutron.services.segments import exceptions as segments_exceptions
LOG = logging.getLogger(__name__)
NETWORK_TYPE = segment_def.NETWORK_TYPE
PHYSICAL_NETWORK = segment_def.PHYSICAL_NETWORK
SEGMENTATION_ID = segment_def.SEGMENTATION_ID
NETWORK_ID = 'network_id'
def _make_segment_dict(obj):
"""Make a segment dictionary out of an object."""
return {'id': obj.id,
NETWORK_TYPE: obj.network_type,
PHYSICAL_NETWORK: obj.physical_network,
SEGMENTATION_ID: obj.segmentation_id,
NETWORK_ID: obj.network_id}
def add_network_segment(context, network_id, segment, segment_index=0,
is_dynamic=False):
with db_api.CONTEXT_WRITER.using(context):
netseg_obj = network_obj.NetworkSegment(
context, 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)
netseg_obj.create()
registry.notify(resources.SEGMENT,
events.PRECOMMIT_CREATE,
trigger=add_network_segment,
context=context,
segment=netseg_obj)
segment['id'] = netseg_obj.id
LOG.info("Added segment %(id)s of type %(network_type)s for network "
"%(network_id)s",
{'id': netseg_obj.id,
'network_type': netseg_obj.network_type,
'network_id': netseg_obj.network_id})
def update_network_segment(context, segment_id, segmentation_id):
with db_api.CONTEXT_WRITER.using(context):
netseg_obj = network_obj.NetworkSegment.get_object(context,
id=segment_id)
if not netseg_obj:
raise segments_exceptions.SegmentNotFound(segment_id=segment_id)
netseg_obj[ml2_api.SEGMENTATION_ID] = segmentation_id
netseg_obj.update()
LOG.info("Updated segment %(id)s, segmentation_id: %(segmentation_id)s)",
{'id': segment_id, 'segmentation_id': segmentation_id})
def get_network_segments(context, network_id, filter_dynamic=False):
return get_networks_segments(
context, [network_id], filter_dynamic)[network_id]
def get_networks_segments(context, network_ids, filter_dynamic=False):
if not network_ids:
return {}
with db_api.CONTEXT_READER.using(context):
filters = {
'network_id': network_ids,
}
if filter_dynamic is not None:
filters['is_dynamic'] = filter_dynamic
objs = network_obj.NetworkSegment.get_objects(context, **filters)
result = {net_id: [] for net_id in network_ids}
for record in objs:
result[record.network_id].append(_make_segment_dict(record))
return result
def get_segment_by_id(context, segment_id):
with db_api.CONTEXT_READER.using(context):
net_obj = network_obj.NetworkSegment.get_object(context, id=segment_id)
if net_obj:
return _make_segment_dict(net_obj)
def get_dynamic_segment(context, network_id, physical_network=None,
segmentation_id=None):
"""Return a dynamic segment for the filters provided if one exists."""
with db_api.CONTEXT_READER.using(context):
filters = {
'network_id': network_id,
'is_dynamic': True,
}
if physical_network:
filters['physical_network'] = physical_network
if segmentation_id:
filters['segmentation_id'] = segmentation_id
pager = base_obj.Pager(limit=1)
objs = network_obj.NetworkSegment.get_objects(
context, _pager=pager, **filters)
if objs:
return _make_segment_dict(objs[0])
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})
def delete_network_segment(context, segment_id):
"""Release a dynamic segment for the params provided if one exists."""
with db_api.CONTEXT_WRITER.using(context):
network_obj.NetworkSegment.delete_objects(context, id=segment_id)
def network_segments_exist_in_range(context, network_type, physical_network,
segment_range=None):
"""Check whether one or more network segments exist in a range."""
with db_api.CONTEXT_READER.using(context):
filters = {
'network_type': network_type,
'physical_network': physical_network,
}
segment_objs = network_obj.NetworkSegment.get_objects(
context, **filters)
if segment_range:
minimum_id = segment_range['minimum']
maximum_id = segment_range['maximum']
segment_objs = [
segment for segment in segment_objs if
minimum_id <= segment.segmentation_id <= maximum_id]
return len(segment_objs) > 0
def min_max_actual_segments_in_range(context, network_type, physical_network,
segment_range=None):
"""Return the minimum and maximum segmentation IDs used in a network
segment range
"""
with db_api.CONTEXT_READER.using(context):
filters = {
'network_type': network_type,
'physical_network': physical_network,
}
pager = base_obj.Pager()
# (NOTE) True means ASC, False is DESC
pager.sorts = [('segmentation_id', True)]
segment_objs = network_obj.NetworkSegment.get_objects(
context, _pager=pager, **filters)
if segment_range:
minimum_id = segment_range['minimum']
maximum_id = segment_range['maximum']
segment_objs = [
segment for segment in segment_objs if
minimum_id <= segment.segmentation_id <= maximum_id]
if segment_objs:
return (segment_objs[0].segmentation_id,
segment_objs[-1].segmentation_id)
else:
LOG.debug("No existing segment found for "
"Network type:%(network_type)s, "
"Physical network:%(physical_network)s",
{'network_type': network_type,
'physical_network': physical_network})
return None, None