Integrate NetworkSegment OVO
This patch integrates the NetworkSegment Oslo-Versioned Object. Change-Id: Ie1569578fca45f3a705fbac44204a3d1e7bea7fe Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db
This commit is contained in:
parent
143a6e8546
commit
d26b96b7a2
|
@ -43,6 +43,7 @@ from neutron.extensions import ip_allocation as ipa
|
|||
from neutron.extensions import segment
|
||||
from neutron.ipam import exceptions as ipam_exceptions
|
||||
from neutron.ipam import utils as ipam_utils
|
||||
from neutron.objects import network as network_obj
|
||||
from neutron.objects import subnet as subnet_obj
|
||||
from neutron.services.segments import exceptions as segment_exc
|
||||
|
||||
|
@ -334,10 +335,8 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
|||
network_id=network_id)
|
||||
|
||||
if segment_id:
|
||||
query = context.session.query(segment_model.NetworkSegment)
|
||||
query = query.filter(
|
||||
segment_model.NetworkSegment.id == segment_id)
|
||||
segment = query.one()
|
||||
segment = network_obj.NetworkSegment.get_object(context,
|
||||
id=segment_id)
|
||||
if segment.network_id != network_id:
|
||||
raise segment_exc.NetworkIdsDontMatch(
|
||||
subnet_network=network_id,
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron._i18n import _LI
|
||||
from neutron.callbacks import events
|
||||
|
@ -20,6 +19,8 @@ from neutron.callbacks import registry
|
|||
from neutron.callbacks import resources
|
||||
from neutron.db import api as db_api
|
||||
from neutron.db.models import segment as segments_model
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import network as network_obj
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -28,38 +29,35 @@ PHYSICAL_NETWORK = segments_model.NetworkSegment.physical_network.name
|
|||
SEGMENTATION_ID = segments_model.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 _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}
|
||||
|
||||
|
||||
def add_network_segment(context, network_id, segment, segment_index=0,
|
||||
is_dynamic=False):
|
||||
with db_api.context_manager.writer.using(context):
|
||||
record = segments_model.NetworkSegment(
|
||||
id=uuidutils.generate_uuid(),
|
||||
network_id=network_id,
|
||||
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
|
||||
)
|
||||
context.session.add(record)
|
||||
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=record)
|
||||
segment['id'] = record.id
|
||||
segment=netseg_obj)
|
||||
segment['id'] = netseg_obj.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})
|
||||
{'id': netseg_obj.id,
|
||||
'network_type': netseg_obj.network_type,
|
||||
'network_id': netseg_obj.network_id})
|
||||
|
||||
|
||||
def get_network_segments(context, network_id, filter_dynamic=False):
|
||||
|
@ -72,57 +70,54 @@ def get_networks_segments(context, network_ids, filter_dynamic=False):
|
|||
return {}
|
||||
|
||||
with db_api.context_manager.reader.using(context):
|
||||
query = (context.session.query(segments_model.NetworkSegment).
|
||||
filter(segments_model.NetworkSegment.network_id
|
||||
.in_(network_ids)).
|
||||
order_by(segments_model.NetworkSegment.segment_index))
|
||||
filters = {
|
||||
'network_id': network_ids,
|
||||
}
|
||||
if filter_dynamic is not None:
|
||||
query = query.filter_by(is_dynamic=filter_dynamic)
|
||||
records = query.all()
|
||||
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 records:
|
||||
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_manager.reader.using(context):
|
||||
try:
|
||||
record = (context.session.query(segments_model.NetworkSegment).
|
||||
filter_by(id=segment_id).
|
||||
one())
|
||||
return _make_segment_dict(record)
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
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_manager.reader.using(context):
|
||||
query = (context.session.query(segments_model.NetworkSegment).
|
||||
filter_by(network_id=network_id, is_dynamic=True))
|
||||
filters = {
|
||||
'network_id': network_id,
|
||||
'is_dynamic': True,
|
||||
}
|
||||
if physical_network:
|
||||
query = query.filter_by(physical_network=physical_network)
|
||||
filters['physical_network'] = physical_network
|
||||
if segmentation_id:
|
||||
query = query.filter_by(segmentation_id=segmentation_id)
|
||||
record = query.first()
|
||||
filters['segmentation_id'] = segmentation_id
|
||||
pager = base_obj.Pager(limit=1)
|
||||
objs = network_obj.NetworkSegment.get_objects(
|
||||
context, _pager=pager, **filters)
|
||||
|
||||
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
|
||||
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_manager.writer.using(context):
|
||||
(context.session.query(segments_model.NetworkSegment).
|
||||
filter_by(id=segment_id).delete())
|
||||
network_obj.NetworkSegment.delete_objects(context, id=segment_id)
|
||||
|
|
|
@ -41,19 +41,69 @@ class NetworkSegment(base.NeutronDbObject):
|
|||
fields = {
|
||||
'id': common_types.UUIDField(),
|
||||
'network_id': common_types.UUIDField(),
|
||||
'name': obj_fields.StringField(),
|
||||
'name': obj_fields.StringField(nullable=True),
|
||||
'network_type': obj_fields.StringField(),
|
||||
'physical_network': obj_fields.StringField(nullable=True),
|
||||
'segmentation_id': obj_fields.IntegerField(nullable=True),
|
||||
'is_dynamic': obj_fields.BooleanField(default=False),
|
||||
'segment_index': obj_fields.IntegerField(default=0)
|
||||
'segment_index': obj_fields.IntegerField(default=0),
|
||||
'hosts': obj_fields.ListOfStringsField(nullable=True)
|
||||
}
|
||||
|
||||
synthetic_fields = ['hosts']
|
||||
|
||||
foreign_keys = {
|
||||
'Network': {'network_id': 'id'},
|
||||
'PortBindingLevel': {'id': 'segment_id'},
|
||||
}
|
||||
|
||||
def create(self):
|
||||
fields = self.obj_get_changes()
|
||||
with db_api.autonested_transaction(self.obj_context.session):
|
||||
hosts = self.hosts
|
||||
if hosts is None:
|
||||
hosts = []
|
||||
super(NetworkSegment, self).create()
|
||||
if 'hosts' in fields:
|
||||
self._attach_hosts(hosts)
|
||||
|
||||
def update(self):
|
||||
fields = self.obj_get_changes()
|
||||
with db_api.autonested_transaction(self.obj_context.session):
|
||||
super(NetworkSegment, self).update()
|
||||
if 'hosts' in fields:
|
||||
self._attach_hosts(fields['hosts'])
|
||||
|
||||
def _attach_hosts(self, hosts):
|
||||
SegmentHostMapping.delete_objects(
|
||||
self.obj_context, segment_id=self.id,
|
||||
)
|
||||
if hosts:
|
||||
for host in hosts:
|
||||
SegmentHostMapping(
|
||||
self.obj_context, segment_id=self.id, host=host).create()
|
||||
self.hosts = hosts
|
||||
self.obj_reset_changes(['hosts'])
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
if attrname == 'hosts':
|
||||
return self._load_hosts()
|
||||
super(NetworkSegment, self).obj_load_attr(attrname)
|
||||
|
||||
def _load_hosts(self, db_obj=None):
|
||||
if db_obj:
|
||||
hosts = db_obj.get('segment_host_mapping', [])
|
||||
else:
|
||||
hosts = SegmentHostMapping.get_objects(self.obj_context,
|
||||
segment_id=self.id)
|
||||
|
||||
self.hosts = [host['host'] for host in hosts]
|
||||
self.obj_reset_changes(['hosts'])
|
||||
|
||||
def from_db_object(self, db_obj):
|
||||
super(NetworkSegment, self).from_db_object(db_obj)
|
||||
self._load_hosts(db_obj)
|
||||
|
||||
@classmethod
|
||||
def get_objects(cls, context, _pager=None, **kwargs):
|
||||
if not _pager:
|
||||
|
|
|
@ -15,15 +15,12 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
import functools
|
||||
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
|
@ -35,6 +32,7 @@ from neutron.db.models import segment as segment_model
|
|||
from neutron.db import segments_db as db
|
||||
from neutron.extensions import segment as extension
|
||||
from neutron import manager
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import network
|
||||
from neutron.services.segments import exceptions
|
||||
|
||||
|
@ -43,25 +41,23 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
"""Mixin class to add segment."""
|
||||
|
||||
@staticmethod
|
||||
def _make_segment_dict(segment_db, fields=None):
|
||||
res = {'id': segment_db['id'],
|
||||
'network_id': segment_db['network_id'],
|
||||
'name': segment_db['name'],
|
||||
'description': segment_db['description'],
|
||||
db.PHYSICAL_NETWORK: segment_db[db.PHYSICAL_NETWORK],
|
||||
db.NETWORK_TYPE: segment_db[db.NETWORK_TYPE],
|
||||
db.SEGMENTATION_ID: segment_db[db.SEGMENTATION_ID],
|
||||
'hosts': [mapping.host for mapping in
|
||||
segment_db.segment_host_mapping],
|
||||
'segment_index': segment_db['segment_index']}
|
||||
def _make_segment_dict(segment_obj, fields=None):
|
||||
res = {'id': segment_obj['id'],
|
||||
'network_id': segment_obj['network_id'],
|
||||
'name': segment_obj['name'],
|
||||
'description': segment_obj['description'],
|
||||
db.PHYSICAL_NETWORK: segment_obj[db.PHYSICAL_NETWORK],
|
||||
db.NETWORK_TYPE: segment_obj[db.NETWORK_TYPE],
|
||||
db.SEGMENTATION_ID: segment_obj[db.SEGMENTATION_ID],
|
||||
'hosts': segment_obj['hosts'],
|
||||
'segment_index': segment_obj['segment_index']}
|
||||
return db_utils.resource_fields(res, fields)
|
||||
|
||||
def _get_segment(self, context, segment_id):
|
||||
try:
|
||||
return self._get_by_id(
|
||||
context, segment_model.NetworkSegment, segment_id)
|
||||
except exc.NoResultFound:
|
||||
segment = network.NetworkSegment.get_object(context, id=segment_id)
|
||||
if not segment:
|
||||
raise exceptions.SegmentNotFound(segment_id=segment_id)
|
||||
return segment
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create_segment(self, context, segment):
|
||||
|
@ -113,12 +109,13 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
segment_index = (segments[-1].get('segment_index') + 1)
|
||||
args['segment_index'] = segment_index
|
||||
|
||||
new_segment = segment_model.NetworkSegment(**args)
|
||||
context.session.add(new_segment)
|
||||
new_segment = network.NetworkSegment(context, **args)
|
||||
new_segment.create()
|
||||
# Do some preliminary operations before committing the segment to
|
||||
# db
|
||||
registry.notify(resources.SEGMENT, events.PRECOMMIT_CREATE, self,
|
||||
context=context, segment=new_segment)
|
||||
registry.notify(
|
||||
resources.SEGMENT, events.PRECOMMIT_CREATE, self,
|
||||
context=context, segment=new_segment)
|
||||
return new_segment
|
||||
|
||||
@log_helpers.log_method_call
|
||||
|
@ -127,7 +124,8 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
segment = segment['segment']
|
||||
with db_api.context_manager.writer.using(context):
|
||||
curr_segment = self._get_segment(context, uuid)
|
||||
curr_segment.update(segment)
|
||||
curr_segment.update_fields(segment)
|
||||
curr_segment.update()
|
||||
return self._make_segment_dict(curr_segment)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
|
@ -139,23 +137,16 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
def get_segments(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
marker_obj = self._get_marker_obj(context, 'segment', limit, marker)
|
||||
make_segment_dict = functools.partial(self._make_segment_dict)
|
||||
return self._get_collection(context,
|
||||
segment_model.NetworkSegment,
|
||||
make_segment_dict,
|
||||
filters=filters,
|
||||
fields=fields,
|
||||
sorts=sorts,
|
||||
limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
filters = filters or {}
|
||||
pager = base_obj.Pager(sorts, limit, page_reverse, marker)
|
||||
segment_objs = network.NetworkSegment.get_objects(
|
||||
context, _pager=pager, **filters)
|
||||
return [self._make_segment_dict(obj) for obj in segment_objs]
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def get_segments_count(self, context, filters=None):
|
||||
return self._get_collection_count(context,
|
||||
segment_model.NetworkSegment,
|
||||
filters=filters)
|
||||
filters = filters or {}
|
||||
return network.NetworkSegment.count(context, **filters)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def get_segments_by_hosts(self, context, hosts):
|
||||
|
@ -168,11 +159,11 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
@log_helpers.log_method_call
|
||||
def delete_segment(self, context, uuid, for_net_delete=False):
|
||||
"""Delete an existing segment."""
|
||||
segment = self.get_segment(context, uuid)
|
||||
segment_dict = self.get_segment(context, uuid)
|
||||
# Do some preliminary operations before deleting the segment
|
||||
registry.notify(resources.SEGMENT, events.BEFORE_DELETE,
|
||||
self.delete_segment, context=context,
|
||||
segment=segment, for_net_delete=for_net_delete)
|
||||
segment=segment_dict, for_net_delete=for_net_delete)
|
||||
|
||||
# Delete segment in DB
|
||||
with db_api.context_manager.writer.using(context):
|
||||
|
@ -183,11 +174,11 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
|
|||
# Do some preliminary operations before deleting segment in db
|
||||
registry.notify(resources.SEGMENT, events.PRECOMMIT_DELETE,
|
||||
self.delete_segment, context=context,
|
||||
segment=segment)
|
||||
segment=segment_dict)
|
||||
|
||||
registry.notify(resources.SEGMENT, events.AFTER_DELETE,
|
||||
self.delete_segment, context=context,
|
||||
segment=segment)
|
||||
segment=segment_dict)
|
||||
|
||||
|
||||
def update_segment_host_mapping(context, host, current_segment_ids):
|
||||
|
@ -221,7 +212,7 @@ def _get_phys_nets(agent):
|
|||
mappings = configurations_dict.get('bridge_mappings', {})
|
||||
mappings.update(configurations_dict.get('interface_mappings', {}))
|
||||
mappings.update(configurations_dict.get('device_mappings', {}))
|
||||
return mappings.keys()
|
||||
return list(mappings.keys())
|
||||
|
||||
|
||||
reported_hosts = set()
|
||||
|
@ -242,9 +233,8 @@ def get_segments_with_phys_nets(context, phys_nets):
|
|||
return []
|
||||
|
||||
with db_api.context_manager.reader.using(context):
|
||||
segments = context.session.query(segment_model.NetworkSegment).filter(
|
||||
segment_model.NetworkSegment.physical_network.in_(phys_nets))
|
||||
return segments
|
||||
return network.NetworkSegment.get_objects(
|
||||
context, physical_network=phys_nets)
|
||||
|
||||
|
||||
def map_segment_to_hosts(context, segment_id, hosts):
|
||||
|
|
|
@ -1338,9 +1338,9 @@ class BaseDbObjectTestCase(_BaseObjectTestCase,
|
|||
return port
|
||||
|
||||
def _create_test_segment(self, network):
|
||||
self._segment = net_obj.NetworkSegment(self.context,
|
||||
network_id=network['id'],
|
||||
network_type='vxlan')
|
||||
attr = self.get_random_object_fields(net_obj.NetworkSegment)
|
||||
attr['network_id'] = network['id']
|
||||
self._segment = net_obj.NetworkSegment(self.context, **attr)
|
||||
self._segment.create()
|
||||
|
||||
def _create_test_router(self):
|
||||
|
|
|
@ -54,6 +54,27 @@ class NetworkSegmentDbObjTestCase(obj_test_base.BaseDbObjectTestCase,
|
|||
network = self._create_network()
|
||||
self.update_obj_fields({'network_id': network.id})
|
||||
|
||||
def test_hosts(self):
|
||||
hosts = ['host1', 'host2']
|
||||
obj = self._make_object(self.obj_fields[0])
|
||||
obj.hosts = hosts
|
||||
obj.create()
|
||||
|
||||
obj = network.NetworkSegment.get_object(self.context, id=obj.id)
|
||||
self.assertEqual(hosts, obj.hosts)
|
||||
|
||||
obj.hosts = ['host3']
|
||||
obj.update()
|
||||
|
||||
obj = network.NetworkSegment.get_object(self.context, id=obj.id)
|
||||
self.assertEqual(['host3'], obj.hosts)
|
||||
|
||||
obj.hosts = None
|
||||
obj.update()
|
||||
|
||||
obj = network.NetworkSegment.get_object(self.context, id=obj.id)
|
||||
self.assertFalse(obj.hosts)
|
||||
|
||||
|
||||
class NetworkObjectIfaceTestCase(obj_test_base.BaseObjectIfaceTestCase):
|
||||
_test_class = network.Network
|
||||
|
|
|
@ -51,7 +51,7 @@ object_data = {
|
|||
'Network': '1.0-f2f6308f79731a767b92b26b0f4f3849',
|
||||
'NetworkDNSDomain': '1.0-420db7910294608534c1e2e30d6d8319',
|
||||
'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3',
|
||||
'NetworkSegment': '1.0-40707ef6bd9a0bf095038158d995cc7d',
|
||||
'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8',
|
||||
'Port': '1.1-5bf48d12a7bf7f5b7a319e8003b437a5',
|
||||
'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578',
|
||||
'PortBindingLevel': '1.0-de66a4c61a083b8f34319fa9dde5b060',
|
||||
|
|
Loading…
Reference in New Issue