Revert "Integration of (Distributed) Port Binding OVO"
This reverts commit febeaf5d40
.
This patch broke postgres tempest jobs, as well as introduced potential
race conditions in database layer because of mixed usage of old and new
engine facades.
Related-Bug: #1744829
Change-Id: Ic142ae7faf4e5f10cbdf761d7e6f3d442e94a3eb
This commit is contained in:
parent
03b1cca794
commit
906eda44d2
|
@ -27,7 +27,6 @@ from oslo_versionedobjects import base as obj_base
|
||||||
from oslo_versionedobjects import exception as obj_exception
|
from oslo_versionedobjects import exception as obj_exception
|
||||||
from oslo_versionedobjects import fields as obj_fields
|
from oslo_versionedobjects import fields as obj_fields
|
||||||
import six
|
import six
|
||||||
from sqlalchemy import exc as sql_exc
|
|
||||||
|
|
||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
from neutron.db import api as db_api
|
from neutron.db import api as db_api
|
||||||
|
@ -319,11 +318,7 @@ def _detach_db_obj(func):
|
||||||
# TODO(ihrachys) consider refreshing just changed attributes
|
# TODO(ihrachys) consider refreshing just changed attributes
|
||||||
self.obj_context.session.refresh(self.db_obj)
|
self.obj_context.session.refresh(self.db_obj)
|
||||||
# detach the model so that consequent fetches don't reuse it
|
# detach the model so that consequent fetches don't reuse it
|
||||||
try:
|
self.obj_context.session.expunge(self.db_obj)
|
||||||
self.obj_context.session.expunge(self.db_obj)
|
|
||||||
except sql_exc.InvalidRequestError:
|
|
||||||
# already detached
|
|
||||||
pass
|
|
||||||
return res
|
return res
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
@ -350,8 +345,6 @@ class DeclarativeObject(abc.ABCMeta):
|
||||||
if key in cls.fields or key in cls.obj_extra_fields:
|
if key in cls.fields or key in cls.obj_extra_fields:
|
||||||
fields_no_update_set.add(key)
|
fields_no_update_set.add(key)
|
||||||
cls.fields_no_update = list(fields_no_update_set)
|
cls.fields_no_update = list(fields_no_update_set)
|
||||||
if name in ('PortBinding', 'DistributedPortBinding'):
|
|
||||||
cls.fields_no_update.remove('host')
|
|
||||||
|
|
||||||
model = getattr(cls, 'db_model', None)
|
model = getattr(cls, 'db_model', None)
|
||||||
if model:
|
if model:
|
||||||
|
@ -502,12 +495,7 @@ class NeutronDbObject(NeutronObject):
|
||||||
obj = cls(context)
|
obj = cls(context)
|
||||||
obj.from_db_object(db_obj)
|
obj.from_db_object(db_obj)
|
||||||
# detach the model so that consequent fetches don't reuse it
|
# detach the model so that consequent fetches don't reuse it
|
||||||
# TODO(lujinluo): remove the try block when Port OVO is in place.
|
context.session.expunge(obj.db_obj)
|
||||||
try:
|
|
||||||
context.session.expunge(obj.db_obj)
|
|
||||||
except sql_exc.InvalidRequestError:
|
|
||||||
# already detached
|
|
||||||
pass
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def obj_load_attr(self, attrname):
|
def obj_load_attr(self, attrname):
|
||||||
|
|
|
@ -36,22 +36,6 @@ class PortBindingBase(base.NeutronDbObject):
|
||||||
'Port': {'port_id': 'id'},
|
'Port': {'port_id': 'id'},
|
||||||
}
|
}
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Override to handle host update in Port Binding.
|
|
||||||
Delete old Port Binding entry, update the hostname and create new
|
|
||||||
Port Binding with all values saved in DB.
|
|
||||||
This is done due to host being a primary key, and OVO is not able
|
|
||||||
to update primary key fields.
|
|
||||||
"""
|
|
||||||
if self.db_obj and self.host != self.db_obj.host:
|
|
||||||
with self.obj_context.session.begin(subtransactions=True):
|
|
||||||
old_obj = self._load_object(self.obj_context, self.db_obj)
|
|
||||||
old_obj.delete()
|
|
||||||
self._changed_fields = set(self.fields.keys())
|
|
||||||
self.create()
|
|
||||||
else:
|
|
||||||
super(PortBindingBase, self).update()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def modify_fields_to_db(cls, fields):
|
def modify_fields_to_db(cls, fields):
|
||||||
result = super(PortBindingBase, cls).modify_fields_to_db(fields)
|
result = super(PortBindingBase, cls).modify_fields_to_db(fields)
|
||||||
|
@ -85,7 +69,7 @@ class PortBinding(PortBindingBase):
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'port_id': common_types.UUIDField(),
|
'port_id': common_types.UUIDField(),
|
||||||
'host': obj_fields.StringField(default=''),
|
'host': obj_fields.StringField(),
|
||||||
'profile': common_types.DictOfMiscValuesField(),
|
'profile': common_types.DictOfMiscValuesField(),
|
||||||
'vif_type': obj_fields.StringField(),
|
'vif_type': obj_fields.StringField(),
|
||||||
'vif_details': common_types.DictOfMiscValuesField(nullable=True),
|
'vif_details': common_types.DictOfMiscValuesField(nullable=True),
|
||||||
|
|
|
@ -18,8 +18,8 @@ from neutron_lib.callbacks import events
|
||||||
from neutron_lib.callbacks import registry
|
from neutron_lib.callbacks import registry
|
||||||
from neutron_lib.callbacks import resources
|
from neutron_lib.callbacks import resources
|
||||||
from neutron_lib import constants as n_const
|
from neutron_lib import constants as n_const
|
||||||
from neutron_lib.objects import exceptions
|
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
|
from oslo_db import exception as db_exc
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
|
@ -31,7 +31,6 @@ from neutron.db import api as db_api
|
||||||
from neutron.db.models import securitygroup as sg_models
|
from neutron.db.models import securitygroup as sg_models
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.objects import ports as port_obj
|
from neutron.objects import ports as port_obj
|
||||||
from neutron.objects import utils as obj_utils
|
|
||||||
from neutron.plugins.ml2 import models
|
from neutron.plugins.ml2 import models
|
||||||
from neutron.services.segments import exceptions as seg_exc
|
from neutron.services.segments import exceptions as seg_exc
|
||||||
|
|
||||||
|
@ -43,10 +42,11 @@ MAX_PORTS_PER_QUERY = 500
|
||||||
|
|
||||||
@db_api.context_manager.writer
|
@db_api.context_manager.writer
|
||||||
def add_port_binding(context, port_id):
|
def add_port_binding(context, port_id):
|
||||||
binding = port_obj.PortBinding(
|
record = models.PortBinding(
|
||||||
context, port_id=port_id, vif_type=portbindings.VIF_TYPE_UNBOUND)
|
port_id=port_id,
|
||||||
binding.create()
|
vif_type=portbindings.VIF_TYPE_UNBOUND)
|
||||||
return binding
|
context.session.add(record)
|
||||||
|
return record
|
||||||
|
|
||||||
|
|
||||||
@db_api.context_manager.writer
|
@db_api.context_manager.writer
|
||||||
|
@ -91,32 +91,35 @@ def clear_binding_levels(context, port_id, host):
|
||||||
|
|
||||||
|
|
||||||
def ensure_distributed_port_binding(context, port_id, host, router_id=None):
|
def ensure_distributed_port_binding(context, port_id, host, router_id=None):
|
||||||
binding_obj = port_obj.DistributedPortBinding.get_object(
|
with db_api.context_manager.reader.using(context):
|
||||||
context, port_id=port_id, host=host)
|
record = (context.session.query(models.DistributedPortBinding).
|
||||||
if binding_obj:
|
filter_by(port_id=port_id, host=host).first())
|
||||||
return binding_obj
|
if record:
|
||||||
|
return record
|
||||||
|
|
||||||
try:
|
try:
|
||||||
binding_obj = port_obj.DistributedPortBinding(
|
with db_api.context_manager.writer.using(context):
|
||||||
context,
|
record = models.DistributedPortBinding(
|
||||||
port_id=port_id,
|
port_id=port_id,
|
||||||
host=host,
|
host=host,
|
||||||
router_id=router_id,
|
router_id=router_id,
|
||||||
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
status=n_const.PORT_STATUS_DOWN)
|
status=n_const.PORT_STATUS_DOWN)
|
||||||
binding_obj.create()
|
context.session.add(record)
|
||||||
return binding_obj
|
return record
|
||||||
except exceptions.NeutronDbObjectDuplicateEntry:
|
except db_exc.DBDuplicateEntry:
|
||||||
LOG.debug("Distributed Port %s already bound", port_id)
|
LOG.debug("Distributed Port %s already bound", port_id)
|
||||||
return port_obj.DistributedPortBinding.get_object(
|
with db_api.context_manager.reader.using(context):
|
||||||
context, port_id=port_id, host=host)
|
return (context.session.query(models.DistributedPortBinding).
|
||||||
|
filter_by(port_id=port_id, host=host).one())
|
||||||
|
|
||||||
|
|
||||||
def delete_distributed_port_binding_if_stale(context, binding):
|
def delete_distributed_port_binding_if_stale(context, binding):
|
||||||
if not binding.router_id and binding.status == n_const.PORT_STATUS_DOWN:
|
if not binding.router_id and binding.status == n_const.PORT_STATUS_DOWN:
|
||||||
LOG.debug("Distributed port: Deleting binding %s", binding)
|
with db_api.context_manager.writer.using(context):
|
||||||
binding.delete()
|
LOG.debug("Distributed port: Deleting binding %s", binding)
|
||||||
|
context.session.delete(binding)
|
||||||
|
|
||||||
|
|
||||||
def get_port(context, port_id):
|
def get_port(context, port_id):
|
||||||
|
@ -209,27 +212,29 @@ def make_port_dict_with_security_groups(port, sec_groups):
|
||||||
|
|
||||||
|
|
||||||
def get_port_binding_host(context, port_id):
|
def get_port_binding_host(context, port_id):
|
||||||
binding = port_obj.PortBinding.get_objects(
|
try:
|
||||||
context, port_id=obj_utils.StringStarts(port_id))
|
with db_api.context_manager.reader.using(context):
|
||||||
if not binding:
|
query = (context.session.query(models.PortBinding).
|
||||||
|
filter(models.PortBinding.port_id.startswith(port_id)).
|
||||||
|
one())
|
||||||
|
except exc.NoResultFound:
|
||||||
LOG.debug("No binding found for port %(port_id)s",
|
LOG.debug("No binding found for port %(port_id)s",
|
||||||
{'port_id': port_id})
|
{'port_id': port_id})
|
||||||
return
|
return
|
||||||
if len(binding) > 1:
|
except exc.MultipleResultsFound:
|
||||||
LOG.error("Multiple ports have port_id starting with %s",
|
LOG.error("Multiple ports have port_id starting with %s",
|
||||||
port_id)
|
port_id)
|
||||||
return
|
return
|
||||||
return binding[0].host
|
return query.host
|
||||||
|
|
||||||
|
|
||||||
@db_api.context_manager.reader
|
@db_api.context_manager.reader
|
||||||
def generate_distributed_port_status(context, port_id):
|
def generate_distributed_port_status(context, port_id):
|
||||||
# an OR'ed value of status assigned to parent port from the
|
# an OR'ed value of status assigned to parent port from the
|
||||||
# distributedportbinding bucket
|
# distributedportbinding bucket
|
||||||
|
query = context.session.query(models.DistributedPortBinding)
|
||||||
final_status = n_const.PORT_STATUS_BUILD
|
final_status = n_const.PORT_STATUS_BUILD
|
||||||
bindings = port_obj.DistributedPortBinding.get_objects(context,
|
for bind in query.filter(models.DistributedPortBinding.port_id == port_id):
|
||||||
port_id=port_id)
|
|
||||||
for bind in bindings:
|
|
||||||
if bind.status == n_const.PORT_STATUS_ACTIVE:
|
if bind.status == n_const.PORT_STATUS_ACTIVE:
|
||||||
return bind.status
|
return bind.status
|
||||||
elif bind.status == n_const.PORT_STATUS_DOWN:
|
elif bind.status == n_const.PORT_STATUS_DOWN:
|
||||||
|
@ -238,10 +243,10 @@ def generate_distributed_port_status(context, port_id):
|
||||||
|
|
||||||
|
|
||||||
def get_distributed_port_binding_by_host(context, port_id, host):
|
def get_distributed_port_binding_by_host(context, port_id, host):
|
||||||
bindings = port_obj.DistributedPortBinding.get_objects(
|
with db_api.context_manager.reader.using(context):
|
||||||
context, port_id=obj_utils.StringStarts(port_id), host=host)
|
binding = (context.session.query(models.DistributedPortBinding).
|
||||||
binding = bindings.pop() if bindings else None
|
filter(models.DistributedPortBinding.port_id.startswith(port_id),
|
||||||
|
models.DistributedPortBinding.host == host).first())
|
||||||
if not binding:
|
if not binding:
|
||||||
LOG.debug("No binding for distributed port %(port_id)s with host "
|
LOG.debug("No binding for distributed port %(port_id)s with host "
|
||||||
"%(host)s", {'port_id': port_id, 'host': host})
|
"%(host)s", {'port_id': port_id, 'host': host})
|
||||||
|
@ -249,8 +254,10 @@ def get_distributed_port_binding_by_host(context, port_id, host):
|
||||||
|
|
||||||
|
|
||||||
def get_distributed_port_bindings(context, port_id):
|
def get_distributed_port_bindings(context, port_id):
|
||||||
bindings = port_obj.DistributedPortBinding.get_objects(
|
with db_api.context_manager.reader.using(context):
|
||||||
context, port_id=obj_utils.StringStarts(port_id))
|
bindings = (context.session.query(models.DistributedPortBinding).
|
||||||
|
filter(models.DistributedPortBinding.port_id.startswith(
|
||||||
|
port_id)).all())
|
||||||
if not bindings:
|
if not bindings:
|
||||||
LOG.debug("No bindings for distributed port %s", port_id)
|
LOG.debug("No bindings for distributed port %s", port_id)
|
||||||
return bindings
|
return bindings
|
||||||
|
|
|
@ -17,6 +17,7 @@ from neutron_lib.api.definitions import portbindings
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib.plugins.ml2 import api
|
from neutron_lib.plugins.ml2 import api
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from neutron.db import segments_db
|
from neutron.db import segments_db
|
||||||
|
@ -123,7 +124,9 @@ class PortContext(MechanismDriverContext, api.PortContext):
|
||||||
else:
|
else:
|
||||||
self._network_context = NetworkContext(
|
self._network_context = NetworkContext(
|
||||||
plugin, plugin_context, network) if network else None
|
plugin, plugin_context, network) if network else None
|
||||||
self._binding = binding
|
# NOTE(kevinbenton): InstanceSnapshot can go away once we are working
|
||||||
|
# with OVO objects instead of native SQLA objects.
|
||||||
|
self._binding = InstanceSnapshot(binding)
|
||||||
self._binding_levels = [InstanceSnapshot(l)
|
self._binding_levels = [InstanceSnapshot(l)
|
||||||
for l in (binding_levels or [])]
|
for l in (binding_levels or [])]
|
||||||
self._segments_to_bind = None
|
self._segments_to_bind = None
|
||||||
|
@ -292,7 +295,7 @@ class PortContext(MechanismDriverContext, api.PortContext):
|
||||||
# TODO(rkukura) Verify binding allowed, segment in network
|
# TODO(rkukura) Verify binding allowed, segment in network
|
||||||
self._new_bound_segment = segment_id
|
self._new_bound_segment = segment_id
|
||||||
self._binding.vif_type = vif_type
|
self._binding.vif_type = vif_type
|
||||||
self._binding.vif_details = vif_details
|
self._binding.vif_details = jsonutils.dumps(vif_details)
|
||||||
self._new_port_status = status
|
self._new_port_status = status
|
||||||
|
|
||||||
def continue_binding(self, segment_id, next_segments_to_bind):
|
def continue_binding(self, segment_id, next_segments_to_bind):
|
||||||
|
|
|
@ -125,6 +125,6 @@ class DistributedPortBinding(model_base.BASEV2):
|
||||||
models_v2.Port,
|
models_v2.Port,
|
||||||
load_on_pending=True,
|
load_on_pending=True,
|
||||||
backref=orm.backref("distributed_port_binding",
|
backref=orm.backref("distributed_port_binding",
|
||||||
lazy='joined',
|
lazy='subquery',
|
||||||
cascade='delete'))
|
cascade='delete'))
|
||||||
revises_on_change = ('port', )
|
revises_on_change = ('port', )
|
||||||
|
|
|
@ -83,7 +83,6 @@ from neutron.db import subnet_service_type_db_models as service_type_db
|
||||||
from neutron.db import vlantransparent_db
|
from neutron.db import vlantransparent_db
|
||||||
from neutron.extensions import providernet as provider
|
from neutron.extensions import providernet as provider
|
||||||
from neutron.extensions import vlantransparent
|
from neutron.extensions import vlantransparent
|
||||||
from neutron.objects import ports as obj_port
|
|
||||||
from neutron.plugins.common import utils as p_utils
|
from neutron.plugins.common import utils as p_utils
|
||||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||||
from neutron.plugins.ml2 import db
|
from neutron.plugins.ml2 import db
|
||||||
|
@ -317,6 +316,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
port = mech_context.current
|
port = mech_context.current
|
||||||
port_id = port['id']
|
port_id = port['id']
|
||||||
changes = False
|
changes = False
|
||||||
|
|
||||||
host = const.ATTR_NOT_SPECIFIED
|
host = const.ATTR_NOT_SPECIFIED
|
||||||
if attrs and portbindings.HOST_ID in attrs:
|
if attrs and portbindings.HOST_ID in attrs:
|
||||||
host = attrs.get(portbindings.HOST_ID) or ''
|
host = attrs.get(portbindings.HOST_ID) or ''
|
||||||
|
@ -340,9 +340,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
|
||||||
if profile not in (None, const.ATTR_NOT_SPECIFIED,
|
if profile not in (None, const.ATTR_NOT_SPECIFIED,
|
||||||
self._get_profile(binding)):
|
self._get_profile(binding)):
|
||||||
binding.profile = profile
|
binding.profile = jsonutils.dumps(profile)
|
||||||
if (len(jsonutils.dumps(binding.profile)) >
|
if len(binding.profile) > models.BINDING_PROFILE_LEN:
|
||||||
models.BINDING_PROFILE_LEN):
|
|
||||||
msg = _("binding:profile value too large")
|
msg = _("binding:profile value too large")
|
||||||
raise exc.InvalidInput(error_message=msg)
|
raise exc.InvalidInput(error_message=msg)
|
||||||
changes = True
|
changes = True
|
||||||
|
@ -350,8 +349,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
# Unbind the port if needed.
|
# Unbind the port if needed.
|
||||||
if changes:
|
if changes:
|
||||||
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
||||||
binding.vif_details = None
|
binding.vif_details = ''
|
||||||
binding.update()
|
|
||||||
db.clear_binding_levels(plugin_context, port_id, original_host)
|
db.clear_binding_levels(plugin_context, port_id, original_host)
|
||||||
mech_context._clear_binding_levels()
|
mech_context._clear_binding_levels()
|
||||||
port['status'] = const.PORT_STATUS_DOWN
|
port['status'] = const.PORT_STATUS_DOWN
|
||||||
|
@ -361,14 +359,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
|
||||||
if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
|
if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
|
||||||
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
||||||
binding.vif_details = None
|
binding.vif_details = ''
|
||||||
db.clear_binding_levels(plugin_context, port_id, original_host)
|
db.clear_binding_levels(plugin_context, port_id, original_host)
|
||||||
mech_context._clear_binding_levels()
|
mech_context._clear_binding_levels()
|
||||||
binding.host = ''
|
binding.host = ''
|
||||||
binding.update()
|
|
||||||
|
|
||||||
self._update_port_dict_binding(port, binding)
|
self._update_port_dict_binding(port, binding)
|
||||||
binding.update()
|
binding.persist_state_to_session(plugin_context.session)
|
||||||
return changes
|
return changes
|
||||||
|
|
||||||
@db_api.retry_db_errors
|
@db_api.retry_db_errors
|
||||||
|
@ -440,15 +437,12 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
# transaction.
|
# transaction.
|
||||||
port = orig_context.current
|
port = orig_context.current
|
||||||
orig_binding = orig_context._binding
|
orig_binding = orig_context._binding
|
||||||
profile = orig_binding.profile or {}
|
new_binding = models.PortBinding(
|
||||||
new_binding = obj_port.PortBinding(
|
|
||||||
orig_context._plugin_context,
|
|
||||||
port_id=orig_binding.port_id,
|
|
||||||
host=orig_binding.host,
|
host=orig_binding.host,
|
||||||
vnic_type=orig_binding.vnic_type,
|
vnic_type=orig_binding.vnic_type,
|
||||||
profile=profile,
|
profile=orig_binding.profile,
|
||||||
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
||||||
vif_details=None
|
vif_details=''
|
||||||
)
|
)
|
||||||
self._update_port_dict_binding(port, new_binding)
|
self._update_port_dict_binding(port, new_binding)
|
||||||
new_context = driver_context.PortContext(
|
new_context = driver_context.PortContext(
|
||||||
|
@ -485,13 +479,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
# mechanism driver update_port_*commit() calls.
|
# mechanism driver update_port_*commit() calls.
|
||||||
try:
|
try:
|
||||||
port_db = self._get_port(plugin_context, port_id)
|
port_db = self._get_port(plugin_context, port_id)
|
||||||
plugin_context.session.refresh(port_db)
|
cur_binding = port_db.port_binding
|
||||||
# TODO(korzen) replace get_objects with port_obj.binding when
|
|
||||||
# Port OVO is integrated in _get_port
|
|
||||||
bindings = obj_port.PortBinding.get_objects(
|
|
||||||
plugin_context, port_id=port_db.id,
|
|
||||||
status=const.ACTIVE)
|
|
||||||
cur_binding = bindings.pop() if bindings else None
|
|
||||||
except exc.PortNotFound:
|
except exc.PortNotFound:
|
||||||
port_db, cur_binding = None, None
|
port_db, cur_binding = None, None
|
||||||
if not port_db or not cur_binding:
|
if not port_db or not cur_binding:
|
||||||
|
@ -558,10 +546,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
cur_binding.host)
|
cur_binding.host)
|
||||||
db.set_binding_levels(plugin_context,
|
db.set_binding_levels(plugin_context,
|
||||||
bind_context._binding_levels)
|
bind_context._binding_levels)
|
||||||
cur_context._binding = cur_binding
|
# refresh context with a snapshot of updated state
|
||||||
|
cur_context._binding = driver_context.InstanceSnapshot(
|
||||||
|
cur_binding)
|
||||||
cur_context._binding_levels = bind_context._binding_levels
|
cur_context._binding_levels = bind_context._binding_levels
|
||||||
cur_binding.update()
|
|
||||||
plugin_context.session.refresh(port_db)
|
|
||||||
|
|
||||||
# Update PortContext's port dictionary to reflect the
|
# Update PortContext's port dictionary to reflect the
|
||||||
# updated binding state.
|
# updated binding state.
|
||||||
|
@ -612,10 +600,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
def _get_vif_details(self, binding):
|
def _get_vif_details(self, binding):
|
||||||
if binding.vif_details:
|
if binding.vif_details:
|
||||||
try:
|
try:
|
||||||
# TODO(lujinluo): remove isinstance check once we switch to
|
|
||||||
# objects for all operations.
|
|
||||||
if isinstance(binding.vif_details, dict):
|
|
||||||
return binding.vif_details
|
|
||||||
return jsonutils.loads(binding.vif_details)
|
return jsonutils.loads(binding.vif_details)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.error("Serialized vif_details DB value '%(value)s' "
|
LOG.error("Serialized vif_details DB value '%(value)s' "
|
||||||
|
@ -627,10 +611,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
def _get_profile(self, binding):
|
def _get_profile(self, binding):
|
||||||
if binding.profile:
|
if binding.profile:
|
||||||
try:
|
try:
|
||||||
# TODO(lujinluo): remove isinstance check once we switch to
|
|
||||||
# objects for all operations.
|
|
||||||
if isinstance(binding.profile, dict):
|
|
||||||
return binding.profile
|
|
||||||
return jsonutils.loads(binding.profile)
|
return jsonutils.loads(binding.profile)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.error("Serialized profile DB value '%(value)s' for "
|
LOG.error("Serialized profile DB value '%(value)s' for "
|
||||||
|
@ -1314,12 +1294,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
original_port=original_port)
|
original_port=original_port)
|
||||||
with db_api.context_manager.writer.using(context):
|
with db_api.context_manager.writer.using(context):
|
||||||
port_db = self._get_port(context, id)
|
port_db = self._get_port(context, id)
|
||||||
context.session.refresh(port_db)
|
binding = port_db.port_binding
|
||||||
# TODO(korzen) replace _get_objects with port_obj.binding when
|
|
||||||
# Port OVO is integrated in _get_port
|
|
||||||
bindings = obj_port.PortBinding.get_objects(
|
|
||||||
context, port_id=port_db.id)
|
|
||||||
binding = bindings.pop() if bindings else None
|
|
||||||
if not binding:
|
if not binding:
|
||||||
raise exc.PortNotFound(port_id=id)
|
raise exc.PortNotFound(port_id=id)
|
||||||
mac_address_updated = self._check_mac_update_allowed(
|
mac_address_updated = self._check_mac_update_allowed(
|
||||||
|
@ -1458,21 +1433,19 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
binding = mech_context._binding
|
binding = mech_context._binding
|
||||||
port = mech_context.current
|
port = mech_context.current
|
||||||
port_id = port['id']
|
port_id = port['id']
|
||||||
clear_host = None
|
|
||||||
|
|
||||||
if binding.vif_type != portbindings.VIF_TYPE_UNBOUND:
|
if binding.vif_type != portbindings.VIF_TYPE_UNBOUND:
|
||||||
binding.vif_details = None
|
binding.vif_details = ''
|
||||||
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
binding.vif_type = portbindings.VIF_TYPE_UNBOUND
|
||||||
if binding.host:
|
if binding.host:
|
||||||
db.clear_binding_levels(plugin_context, port_id, binding.host)
|
db.clear_binding_levels(plugin_context, port_id, binding.host)
|
||||||
clear_host = ''
|
binding.host = ''
|
||||||
|
|
||||||
self._update_port_dict_binding(port, binding)
|
self._update_port_dict_binding(port, binding)
|
||||||
new_host = attrs and attrs.get(portbindings.HOST_ID) or clear_host
|
binding.host = attrs and attrs.get(portbindings.HOST_ID)
|
||||||
binding.router_id = attrs and attrs.get('device_id')
|
binding.router_id = attrs and attrs.get('device_id')
|
||||||
if new_host:
|
# merge into session to reflect changes
|
||||||
binding.host = new_host
|
binding.persist_state_to_session(plugin_context.session)
|
||||||
binding.update()
|
|
||||||
|
|
||||||
@utils.transaction_guard
|
@utils.transaction_guard
|
||||||
@db_api.retry_if_session_inactive()
|
@db_api.retry_if_session_inactive()
|
||||||
|
@ -1543,11 +1516,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
with db_api.context_manager.writer.using(context):
|
with db_api.context_manager.writer.using(context):
|
||||||
try:
|
try:
|
||||||
port_db = self._get_port(context, id)
|
port_db = self._get_port(context, id)
|
||||||
# TODO(korzen) replace get_objects with port_obj.binding when
|
binding = port_db.port_binding
|
||||||
# Port OVO is integrated in _get_port
|
|
||||||
bindings = obj_port.PortBinding.get_objects(
|
|
||||||
context, port_id=port_db.id)
|
|
||||||
binding = bindings.pop() if bindings else None
|
|
||||||
except exc.PortNotFound:
|
except exc.PortNotFound:
|
||||||
LOG.debug("The port '%s' was deleted", id)
|
LOG.debug("The port '%s' was deleted", id)
|
||||||
return
|
return
|
||||||
|
@ -1791,7 +1760,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
return
|
return
|
||||||
if binding.status != status:
|
if binding.status != status:
|
||||||
binding.status = status
|
binding.status = status
|
||||||
binding.update()
|
|
||||||
updated = True
|
updated = True
|
||||||
|
|
||||||
if (updated and
|
if (updated and
|
||||||
|
|
|
@ -62,7 +62,7 @@ object_data = {
|
||||||
'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3',
|
'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3',
|
||||||
'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8',
|
'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8',
|
||||||
'Port': '1.1-5bf48d12a7bf7f5b7a319e8003b437a5',
|
'Port': '1.1-5bf48d12a7bf7f5b7a319e8003b437a5',
|
||||||
'PortBinding': '1.0-0ad9727c4e72d609d5b4f70bcd3bc727',
|
'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578',
|
||||||
'PortBindingLevel': '1.0-de66a4c61a083b8f34319fa9dde5b060',
|
'PortBindingLevel': '1.0-de66a4c61a083b8f34319fa9dde5b060',
|
||||||
'PortDataPlaneStatus': '1.0-25be74bda46c749653a10357676c0ab2',
|
'PortDataPlaneStatus': '1.0-25be74bda46c749653a10357676c0ab2',
|
||||||
'PortDNS': '1.1-c5ca2dc172bdd5fafee3fc986d1d7023',
|
'PortDNS': '1.1-c5ca2dc172bdd5fafee3fc986d1d7023',
|
||||||
|
|
|
@ -23,6 +23,7 @@ from neutron_lib import context
|
||||||
from neutron_lib.plugins.ml2 import api
|
from neutron_lib.plugins.ml2 import api
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
|
from sqlalchemy.orm import query
|
||||||
|
|
||||||
from neutron.db import api as db_api
|
from neutron.db import api as db_api
|
||||||
from neutron.db import db_base_plugin_v2
|
from neutron.db import db_base_plugin_v2
|
||||||
|
@ -32,6 +33,7 @@ from neutron.db import segments_db
|
||||||
from neutron.objects import network as network_obj
|
from neutron.objects import network as network_obj
|
||||||
from neutron.objects import ports as port_obj
|
from neutron.objects import ports as port_obj
|
||||||
from neutron.plugins.ml2 import db as ml2_db
|
from neutron.plugins.ml2 import db as ml2_db
|
||||||
|
from neutron.plugins.ml2 import models
|
||||||
from neutron.tests.unit import testlib_api
|
from neutron.tests.unit import testlib_api
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,8 +64,10 @@ class Ml2DBTestCase(testlib_api.SqlTestCase):
|
||||||
return port
|
return port
|
||||||
|
|
||||||
def _setup_neutron_portbinding(self, port_id, vif_type, host):
|
def _setup_neutron_portbinding(self, port_id, vif_type, host):
|
||||||
port_obj.PortBinding(
|
with db_api.context_manager.writer.using(self.ctx):
|
||||||
self.ctx, port_id=port_id, vif_type=vif_type, host=host).create()
|
self.ctx.session.add(models.PortBinding(port_id=port_id,
|
||||||
|
vif_type=vif_type,
|
||||||
|
host=host))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sort_segments(segments):
|
def _sort_segments(segments):
|
||||||
|
@ -314,45 +318,44 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
|
||||||
|
|
||||||
def _setup_distributed_binding(self, network_id,
|
def _setup_distributed_binding(self, network_id,
|
||||||
port_id, router_id, host_id):
|
port_id, router_id, host_id):
|
||||||
binding_obj = port_obj.DistributedPortBinding(
|
with db_api.context_manager.writer.using(self.ctx):
|
||||||
self.ctx,
|
record = models.DistributedPortBinding(
|
||||||
port_id=port_id,
|
port_id=port_id,
|
||||||
host=host_id,
|
host=host_id,
|
||||||
router_id=router_id,
|
router_id=router_id,
|
||||||
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
vif_type=portbindings.VIF_TYPE_UNBOUND,
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
status='DOWN')
|
status='DOWN')
|
||||||
binding_obj.create()
|
self.ctx.session.add(record)
|
||||||
return binding_obj
|
return record
|
||||||
|
|
||||||
def test_ensure_distributed_port_binding_deals_with_db_duplicate(self):
|
def test_ensure_distributed_port_binding_deals_with_db_duplicate(self):
|
||||||
network_id = uuidutils.generate_uuid()
|
network_id = uuidutils.generate_uuid()
|
||||||
port_id = uuidutils.generate_uuid()
|
port_id = uuidutils.generate_uuid()
|
||||||
router_id = uuidutils.generate_uuid()
|
router_id = 'foo_router_id'
|
||||||
host_id = uuidutils.generate_uuid()
|
host_id = 'foo_host_id'
|
||||||
self._setup_neutron_network(network_id, [port_id])
|
self._setup_neutron_network(network_id, [port_id])
|
||||||
dpb = self._setup_distributed_binding(network_id, port_id,
|
self._setup_distributed_binding(network_id, port_id,
|
||||||
router_id, host_id)
|
router_id, host_id)
|
||||||
with mock.patch.object(port_obj.DistributedPortBinding,
|
with mock.patch.object(query.Query, 'first') as query_first:
|
||||||
'get_object') as get_object:
|
query_first.return_value = []
|
||||||
get_object.side_effect = [None, dpb]
|
with mock.patch.object(ml2_db.LOG, 'debug') as log_trace:
|
||||||
binding = ml2_db.ensure_distributed_port_binding(
|
binding = ml2_db.ensure_distributed_port_binding(
|
||||||
self.ctx, port_id, host_id, router_id)
|
self.ctx, port_id, host_id, router_id)
|
||||||
self.assertTrue(get_object.called)
|
self.assertTrue(query_first.called)
|
||||||
|
self.assertTrue(log_trace.called)
|
||||||
self.assertEqual(port_id, binding.port_id)
|
self.assertEqual(port_id, binding.port_id)
|
||||||
|
|
||||||
def test_ensure_distributed_port_binding(self):
|
def test_ensure_distributed_port_binding(self):
|
||||||
network_id = uuidutils.generate_uuid()
|
network_id = uuidutils.generate_uuid()
|
||||||
expected_port_id = uuidutils.generate_uuid()
|
port_id = uuidutils.generate_uuid()
|
||||||
self._setup_neutron_network(network_id, [expected_port_id])
|
self._setup_neutron_network(network_id, [port_id])
|
||||||
router = self._setup_neutron_router()
|
router = self._setup_neutron_router()
|
||||||
ml2_db.ensure_distributed_port_binding(
|
ml2_db.ensure_distributed_port_binding(
|
||||||
self.ctx, expected_port_id, 'foo_host', router.id)
|
self.ctx, port_id, 'foo_host', router.id)
|
||||||
actual_objs = port_obj.DistributedPortBinding.get_objects(
|
expected = (self.ctx.session.query(models.DistributedPortBinding).
|
||||||
self.ctx, port_id=expected_port_id)
|
filter_by(port_id=port_id).one())
|
||||||
self.assertEqual(1, len(actual_objs))
|
self.assertEqual(port_id, expected.port_id)
|
||||||
actual_obj = actual_objs.pop()
|
|
||||||
self.assertEqual(expected_port_id, actual_obj.port_id)
|
|
||||||
|
|
||||||
def test_ensure_distributed_port_binding_multiple_bindings(self):
|
def test_ensure_distributed_port_binding_multiple_bindings(self):
|
||||||
network_id = uuidutils.generate_uuid()
|
network_id = uuidutils.generate_uuid()
|
||||||
|
@ -363,9 +366,9 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
|
||||||
self.ctx, port_id, 'foo_host_1', router.id)
|
self.ctx, port_id, 'foo_host_1', router.id)
|
||||||
ml2_db.ensure_distributed_port_binding(
|
ml2_db.ensure_distributed_port_binding(
|
||||||
self.ctx, port_id, 'foo_host_2', router.id)
|
self.ctx, port_id, 'foo_host_2', router.id)
|
||||||
count_objs = port_obj.DistributedPortBinding.count(
|
bindings = (self.ctx.session.query(models.DistributedPortBinding).
|
||||||
self.ctx, port_id=port_id)
|
filter_by(port_id=port_id).all())
|
||||||
self.assertEqual(2, count_objs)
|
self.assertEqual(2, len(bindings))
|
||||||
|
|
||||||
def test_delete_distributed_port_binding_if_stale(self):
|
def test_delete_distributed_port_binding_if_stale(self):
|
||||||
network_id = uuidutils.generate_uuid()
|
network_id = uuidutils.generate_uuid()
|
||||||
|
@ -374,23 +377,21 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
|
||||||
binding = self._setup_distributed_binding(
|
binding = self._setup_distributed_binding(
|
||||||
network_id, port_id, None, 'foo_host_id')
|
network_id, port_id, None, 'foo_host_id')
|
||||||
|
|
||||||
ml2_db.delete_distributed_port_binding_if_stale(self.ctx, binding)
|
ml2_db.delete_distributed_port_binding_if_stale(self.ctx,
|
||||||
|
binding)
|
||||||
obj_exists = port_obj.DistributedPortBinding.objects_exist(
|
count = (self.ctx.session.query(models.DistributedPortBinding).
|
||||||
self.ctx, port_id=binding.port_id)
|
filter_by(port_id=binding.port_id).count())
|
||||||
self.assertFalse(obj_exists)
|
self.assertFalse(count)
|
||||||
|
|
||||||
def test_get_distributed_port_binding_by_host_not_found(self):
|
def test_get_distributed_port_binding_by_host_not_found(self):
|
||||||
port_id = uuidutils.generate_uuid()
|
|
||||||
host_id = uuidutils.generate_uuid()
|
|
||||||
port = ml2_db.get_distributed_port_binding_by_host(
|
port = ml2_db.get_distributed_port_binding_by_host(
|
||||||
self.ctx, port_id, host_id)
|
self.ctx, 'foo_port_id', 'foo_host_id')
|
||||||
self.assertIsNone(port)
|
self.assertIsNone(port)
|
||||||
|
|
||||||
def test_get_distributed_port_bindings_not_found(self):
|
def test_get_distributed_port_bindings_not_found(self):
|
||||||
port = ml2_db.get_distributed_port_bindings(self.ctx,
|
port = ml2_db.get_distributed_port_bindings(self.ctx,
|
||||||
uuidutils.generate_uuid())
|
'foo_port_id')
|
||||||
self.assertEqual(0, len(port))
|
self.assertFalse(len(port))
|
||||||
|
|
||||||
def test_get_distributed_port_bindings(self):
|
def test_get_distributed_port_bindings(self):
|
||||||
network_id = uuidutils.generate_uuid()
|
network_id = uuidutils.generate_uuid()
|
||||||
|
@ -411,9 +412,8 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
|
||||||
network_obj.Network(self.ctx, id=network_id).create()
|
network_obj.Network(self.ctx, id=network_id).create()
|
||||||
with db_api.context_manager.writer.using(self.ctx):
|
with db_api.context_manager.writer.using(self.ctx):
|
||||||
device_owner = constants.DEVICE_OWNER_DVR_INTERFACE
|
device_owner = constants.DEVICE_OWNER_DVR_INTERFACE
|
||||||
port_id = uuidutils.generate_uuid()
|
|
||||||
port = models_v2.Port(
|
port = models_v2.Port(
|
||||||
id=port_id,
|
id='port_id',
|
||||||
network_id=network_id,
|
network_id=network_id,
|
||||||
mac_address='00:11:22:33:44:55',
|
mac_address='00:11:22:33:44:55',
|
||||||
admin_state_up=True,
|
admin_state_up=True,
|
||||||
|
@ -421,22 +421,25 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase):
|
||||||
device_id='device_id',
|
device_id='device_id',
|
||||||
device_owner=device_owner)
|
device_owner=device_owner)
|
||||||
self.ctx.session.add(port)
|
self.ctx.session.add(port)
|
||||||
binding_kwarg = {
|
binding_kwarg = {
|
||||||
'port_id': port_id,
|
'port_id': 'port_id',
|
||||||
'host': 'host',
|
'host': 'host',
|
||||||
'vif_type': portbindings.VIF_TYPE_UNBOUND,
|
'vif_type': portbindings.VIF_TYPE_UNBOUND,
|
||||||
'vnic_type': portbindings.VNIC_NORMAL,
|
'vnic_type': portbindings.VNIC_NORMAL,
|
||||||
'router_id': 'router_id',
|
'router_id': 'router_id',
|
||||||
'status': constants.PORT_STATUS_DOWN
|
'status': constants.PORT_STATUS_DOWN
|
||||||
}
|
}
|
||||||
port_obj.DistributedPortBinding(self.ctx, **binding_kwarg).create()
|
self.ctx.session.add(models.DistributedPortBinding(
|
||||||
binding_kwarg['host'] = 'another-host'
|
**binding_kwarg))
|
||||||
port_obj.DistributedPortBinding(self.ctx, **binding_kwarg).create()
|
binding_kwarg['host'] = 'another-host'
|
||||||
|
self.ctx.session.add(models.DistributedPortBinding(
|
||||||
|
**binding_kwarg))
|
||||||
with warnings.catch_warnings(record=True) as warning_list:
|
with warnings.catch_warnings(record=True) as warning_list:
|
||||||
with db_api.context_manager.writer.using(self.ctx):
|
with db_api.context_manager.writer.using(self.ctx):
|
||||||
self.ctx.session.delete(port)
|
self.ctx.session.delete(port)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[], warning_list,
|
[], warning_list,
|
||||||
'Warnings: %s' % ';'.join([str(w) for w in warning_list]))
|
'Warnings: %s' % ';'.join([str(w) for w in warning_list]))
|
||||||
bindings = ml2_db.get_distributed_port_bindings(self.ctx, port_id)
|
ports = ml2_db.get_distributed_port_bindings(self.ctx,
|
||||||
self.assertEqual(0, len(bindings))
|
'port_id')
|
||||||
|
self.assertEqual(0, len(ports))
|
||||||
|
|
|
@ -47,7 +47,6 @@ from neutron.db import provisioning_blocks
|
||||||
from neutron.db import segments_db
|
from neutron.db import segments_db
|
||||||
from neutron.extensions import multiprovidernet as mpnet
|
from neutron.extensions import multiprovidernet as mpnet
|
||||||
from neutron.objects import base as base_obj
|
from neutron.objects import base as base_obj
|
||||||
from neutron.objects import ports as obj_port
|
|
||||||
from neutron.objects import router as l3_obj
|
from neutron.objects import router as l3_obj
|
||||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||||
from neutron.plugins.ml2 import db as ml2_db
|
from neutron.plugins.ml2 import db as ml2_db
|
||||||
|
@ -1692,10 +1691,9 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
# create a port and delete it so we have an expired mechanism context
|
# create a port and delete it so we have an expired mechanism context
|
||||||
with self.port() as port:
|
with self.port() as port:
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = plugin._get_port(self.context,
|
||||||
self.context, port_id=port['port']['id'], host='')
|
port['port']['id']).port_binding
|
||||||
binding.host = 'test'
|
binding['host'] = 'test'
|
||||||
binding.update()
|
|
||||||
mech_context = driver_context.PortContext(
|
mech_context = driver_context.PortContext(
|
||||||
plugin, self.context, port['port'],
|
plugin, self.context, port['port'],
|
||||||
plugin.get_network(self.context, port['port']['network_id']),
|
plugin.get_network(self.context, port['port']['network_id']),
|
||||||
|
@ -1714,11 +1712,10 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
def _create_port_and_bound_context(self, port_vif_type, bound_vif_type):
|
def _create_port_and_bound_context(self, port_vif_type, bound_vif_type):
|
||||||
with self.port() as port:
|
with self.port() as port:
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = plugin._get_port(
|
||||||
self.context, port_id=port['port']['id'], host='')
|
self.context, port['port']['id']).port_binding
|
||||||
binding.host = 'fake_host'
|
binding['host'] = 'fake_host'
|
||||||
binding['vif_type'] = port_vif_type
|
binding['vif_type'] = port_vif_type
|
||||||
binding.update()
|
|
||||||
# Generates port context to be used before the bind.
|
# Generates port context to be used before the bind.
|
||||||
port_context = driver_context.PortContext(
|
port_context = driver_context.PortContext(
|
||||||
plugin, self.context, port['port'],
|
plugin, self.context, port['port'],
|
||||||
|
@ -1830,10 +1827,10 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
def test_update_port_binding_host_id_none(self):
|
def test_update_port_binding_host_id_none(self):
|
||||||
with self.port() as port:
|
with self.port() as port:
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = plugin._get_port(
|
||||||
self.context, port_id=port['port']['id'], host='')
|
self.context, port['port']['id']).port_binding
|
||||||
binding.host = 'test'
|
with self.context.session.begin(subtransactions=True):
|
||||||
binding.update()
|
binding.host = 'test'
|
||||||
mech_context = driver_context.PortContext(
|
mech_context = driver_context.PortContext(
|
||||||
plugin, self.context, port['port'],
|
plugin, self.context, port['port'],
|
||||||
plugin.get_network(self.context, port['port']['network_id']),
|
plugin.get_network(self.context, port['port']['network_id']),
|
||||||
|
@ -1844,18 +1841,15 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
self.assertEqual('test', binding.host)
|
self.assertEqual('test', binding.host)
|
||||||
with self.context.session.begin(subtransactions=True):
|
with self.context.session.begin(subtransactions=True):
|
||||||
plugin._process_port_binding(mech_context, attrs)
|
plugin._process_port_binding(mech_context, attrs)
|
||||||
updated_binding = obj_port.PortBinding.get_objects(self.context,
|
|
||||||
port_id=port['port']['id']).pop()
|
|
||||||
self.assertTrue(update_mock.mock_calls)
|
self.assertTrue(update_mock.mock_calls)
|
||||||
self.assertEqual('', updated_binding.host)
|
self.assertEqual('', binding.host)
|
||||||
|
|
||||||
def test_update_port_binding_host_id_not_changed(self):
|
def test_update_port_binding_host_id_not_changed(self):
|
||||||
with self.port() as port:
|
with self.port() as port:
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = plugin._get_port(
|
||||||
self.context, port_id=port['port']['id'], host='')
|
self.context, port['port']['id']).port_binding
|
||||||
binding.host = 'test'
|
binding['host'] = 'test'
|
||||||
binding.update()
|
|
||||||
mech_context = driver_context.PortContext(
|
mech_context = driver_context.PortContext(
|
||||||
plugin, self.context, port['port'],
|
plugin, self.context, port['port'],
|
||||||
plugin.get_network(self.context, port['port']['network_id']),
|
plugin.get_network(self.context, port['port']['network_id']),
|
||||||
|
@ -1868,34 +1862,30 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
self.assertEqual('test', binding.host)
|
self.assertEqual('test', binding.host)
|
||||||
|
|
||||||
def test_process_distributed_port_binding_update_router_id(self):
|
def test_process_distributed_port_binding_update_router_id(self):
|
||||||
with self.port() as port:
|
host_id = 'host'
|
||||||
host_id = 'host'
|
binding = models.DistributedPortBinding(
|
||||||
ctxt = context.get_admin_context()
|
port_id='port_id',
|
||||||
binding_obj = obj_port.DistributedPortBinding(
|
host=host_id,
|
||||||
ctxt,
|
router_id='old_router_id',
|
||||||
port_id=port['port']['id'],
|
vif_type=portbindings.VIF_TYPE_OVS,
|
||||||
host=host_id,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
profile={},
|
status=constants.PORT_STATUS_DOWN)
|
||||||
router_id='old_router_id',
|
plugin = directory.get_plugin()
|
||||||
vif_type=portbindings.VIF_TYPE_OVS,
|
mock_network = {'id': 'net_id'}
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
mock_port = {'id': 'port_id'}
|
||||||
status=constants.PORT_STATUS_DOWN)
|
ctxt = context.get_admin_context()
|
||||||
binding_obj.create()
|
new_router_id = 'new_router'
|
||||||
plugin = directory.get_plugin()
|
attrs = {'device_id': new_router_id, portbindings.HOST_ID: host_id}
|
||||||
mock_network = {'id': 'net_id'}
|
with mock.patch.object(plugin, '_update_port_dict_binding'):
|
||||||
mock_port = {'id': 'port_id'}
|
with mock.patch.object(segments_db, 'get_network_segments',
|
||||||
new_router_id = 'new_router'
|
return_value=[]):
|
||||||
attrs = {'device_id': new_router_id, portbindings.HOST_ID: host_id}
|
mech_context = driver_context.PortContext(
|
||||||
with mock.patch.object(plugin, '_update_port_dict_binding'):
|
self, ctxt, mock_port, mock_network, binding, None)
|
||||||
with mock.patch.object(segments_db, 'get_network_segments',
|
plugin._process_distributed_port_binding(mech_context,
|
||||||
return_value=[]):
|
ctxt, attrs)
|
||||||
mech_context = driver_context.PortContext(
|
self.assertEqual(new_router_id,
|
||||||
self, ctxt, mock_port, mock_network, binding_obj, None)
|
mech_context._binding.router_id)
|
||||||
plugin._process_distributed_port_binding(mech_context,
|
self.assertEqual(host_id, mech_context._binding.host)
|
||||||
ctxt, attrs)
|
|
||||||
self.assertEqual(new_router_id,
|
|
||||||
mech_context._binding.router_id)
|
|
||||||
self.assertEqual(host_id, mech_context._binding.host)
|
|
||||||
|
|
||||||
def test_update_distributed_port_binding_on_concurrent_port_delete(self):
|
def test_update_distributed_port_binding_on_concurrent_port_delete(self):
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
|
@ -1926,20 +1916,9 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
def test__bind_port_original_port_set(self):
|
def test__bind_port_original_port_set(self):
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
plugin.mechanism_manager = mock.Mock()
|
plugin.mechanism_manager = mock.Mock()
|
||||||
mock_port = {'id': uuidutils.generate_uuid()}
|
mock_port = {'id': 'port_id'}
|
||||||
context = mock.Mock()
|
context = mock.Mock()
|
||||||
binding_obj = obj_port.DistributedPortBinding(
|
|
||||||
mock.MagicMock(),
|
|
||||||
port_id=mock_port['id'],
|
|
||||||
host='vm_host',
|
|
||||||
profile={},
|
|
||||||
router_id='old_router_id',
|
|
||||||
vif_type='',
|
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
|
||||||
status=constants.PORT_STATUS_DOWN)
|
|
||||||
binding_obj.create()
|
|
||||||
context.network.current = {'id': 'net_id'}
|
context.network.current = {'id': 'net_id'}
|
||||||
context._binding = binding_obj
|
|
||||||
context.original = mock_port
|
context.original = mock_port
|
||||||
with mock.patch.object(plugin, '_update_port_dict_binding'), \
|
with mock.patch.object(plugin, '_update_port_dict_binding'), \
|
||||||
mock.patch.object(segments_db, 'get_network_segments',
|
mock.patch.object(segments_db, 'get_network_segments',
|
||||||
|
@ -2615,15 +2594,13 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase):
|
||||||
def test_update_distributed_router_interface_port(self):
|
def test_update_distributed_router_interface_port(self):
|
||||||
"""Test validate distributed router interface update succeeds."""
|
"""Test validate distributed router interface update succeeds."""
|
||||||
host_id = 'host'
|
host_id = 'host'
|
||||||
binding_obj = obj_port.DistributedPortBinding(
|
binding = models.DistributedPortBinding(
|
||||||
mock.MagicMock(),
|
port_id='port_id',
|
||||||
port_id=uuidutils.generate_uuid(),
|
host=host_id,
|
||||||
host=host_id,
|
router_id='old_router_id',
|
||||||
router_id='old_router_id',
|
vif_type=portbindings.VIF_TYPE_OVS,
|
||||||
vif_type=portbindings.VIF_TYPE_OVS,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
status=constants.PORT_STATUS_DOWN)
|
||||||
status=constants.PORT_STATUS_DOWN)
|
|
||||||
binding_obj.create()
|
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
mech_test.TestMechanismDriver,
|
mech_test.TestMechanismDriver,
|
||||||
'update_port_postcommit',
|
'update_port_postcommit',
|
||||||
|
@ -2633,7 +2610,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase):
|
||||||
'update_port_precommit') as port_pre,\
|
'update_port_precommit') as port_pre,\
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
ml2_db, 'get_distributed_port_bindings') as dist_bindings:
|
ml2_db, 'get_distributed_port_bindings') as dist_bindings:
|
||||||
dist_bindings.return_value = [binding_obj]
|
dist_bindings.return_value = [binding]
|
||||||
port_pre.return_value = True
|
port_pre.return_value = True
|
||||||
with self.network() as network:
|
with self.network() as network:
|
||||||
with self.subnet(network=network) as subnet:
|
with self.subnet(network=network) as subnet:
|
||||||
|
@ -2856,10 +2833,9 @@ class TestML2Segments(Ml2PluginV2TestCase):
|
||||||
# add writer here to make sure that the following operations are
|
# add writer here to make sure that the following operations are
|
||||||
# performed in the same session
|
# performed in the same session
|
||||||
with db_api.context_manager.writer.using(self.context):
|
with db_api.context_manager.writer.using(self.context):
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = plugin._get_port(
|
||||||
self.context, port_id=port['port']['id'], host='')
|
self.context, port['port']['id']).port_binding
|
||||||
binding.host = 'host-ovs-no_filter'
|
binding['host'] = 'host-ovs-no_filter'
|
||||||
binding.update()
|
|
||||||
mech_context = driver_context.PortContext(
|
mech_context = driver_context.PortContext(
|
||||||
plugin, self.context, port['port'],
|
plugin, self.context, port['port'],
|
||||||
plugin.get_network(self.context,
|
plugin.get_network(self.context,
|
||||||
|
|
|
@ -19,10 +19,11 @@ from neutron_lib import constants as const
|
||||||
from neutron_lib import context
|
from neutron_lib import context
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from neutron.conf.plugins.ml2.drivers import driver_type
|
from neutron.conf.plugins.ml2.drivers import driver_type
|
||||||
from neutron.objects import ports as obj_port
|
|
||||||
from neutron.plugins.ml2 import driver_context
|
from neutron.plugins.ml2 import driver_context
|
||||||
|
from neutron.plugins.ml2 import models as ml2_models
|
||||||
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
|
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,8 +111,10 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||||
ctx = context.get_admin_context()
|
ctx = context.get_admin_context()
|
||||||
with self.port(name='name') as port:
|
with self.port(name='name') as port:
|
||||||
# emulating concurrent binding deletion
|
# emulating concurrent binding deletion
|
||||||
obj_port.PortBinding.delete_objects(
|
with ctx.session.begin():
|
||||||
ctx, port_id=port['port']['id'])
|
for item in (ctx.session.query(ml2_models.PortBinding).
|
||||||
|
filter_by(port_id=port['port']['id'])):
|
||||||
|
ctx.session.delete(item)
|
||||||
self.assertIsNone(
|
self.assertIsNone(
|
||||||
self.plugin.get_bound_port_context(ctx, port['port']['id']))
|
self.plugin.get_bound_port_context(ctx, port['port']['id']))
|
||||||
|
|
||||||
|
@ -188,9 +191,13 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||||
attrs['binding:host_id'] = 'host2'
|
attrs['binding:host_id'] = 'host2'
|
||||||
updated_port = attrs.copy()
|
updated_port = attrs.copy()
|
||||||
network = {'id': attrs['network_id']}
|
network = {'id': attrs['network_id']}
|
||||||
binding = obj_port.PortBinding.get_object(
|
binding = ml2_models.PortBinding(
|
||||||
ctx, port_id=original_port['id'],
|
port_id=original_port['id'],
|
||||||
host=original_port['binding:host_id'])
|
host=original_port['binding:host_id'],
|
||||||
|
vnic_type=original_port['binding:vnic_type'],
|
||||||
|
profile=jsonutils.dumps(original_port['binding:profile']),
|
||||||
|
vif_type=original_port['binding:vif_type'],
|
||||||
|
vif_details=original_port['binding:vif_details'])
|
||||||
levels = []
|
levels = []
|
||||||
mech_context = driver_context.PortContext(
|
mech_context = driver_context.PortContext(
|
||||||
plugin, ctx, updated_port, network, binding, levels,
|
plugin, ctx, updated_port, network, binding, levels,
|
||||||
|
|
Loading…
Reference in New Issue