neutron/neutron/db/segments_db.py
Nurmatov Mamatisa 2d97f3edb2 use payloads for SEGMENT events
This patch switches over to payload style of callbacks for the remaining
SEGMENT based callback events. Unit tests are also updated as needed
to handle the switch.

NeutronLibImpact

Change-Id: I3624228238babc64fe02bf0cc56eb0c1f6d35e73
2021-05-05 15:17:50 +03:00

195 lines
7.7 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.publish(resources.SEGMENT,
events.PRECOMMIT_CREATE,
add_network_segment,
payload=events.DBEventPayload(
context, resource_id=netseg_obj.id,
states=(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