Delete the PB level registers when deleting the duplicated PB
The ``neutron-remove-duplicated-port-bindings`` script removes the duplicated port binding registers ("ml2_port_bindings" table) that have status=INACTIVE. This patch also removes the corresponding port binding levels ("ml2_port_binding_levels" table) associated to those inactive port bindings. Closes-Bug: #2000078 Change-Id: I12fa0764cd0ff509f1859b61060d64cc5a54a7b9 (cherry picked from commit572185e1fd
) (cherry picked from commit07855a6826
)
This commit is contained in:
parent
fe0ffa1a2e
commit
2fb9ddb01e
|
@ -34,7 +34,7 @@ def setup_conf(conf):
|
|||
|
||||
|
||||
def main():
|
||||
"""Main method for removing the duplicated port binding registers.
|
||||
"""Main method for removing duplicated port binding and pb level registers.
|
||||
|
||||
This script finds all ``PortBinding`` registers with the same ``port_id``.
|
||||
That happens during the live-migration process. Once finished, the inactive
|
||||
|
@ -42,6 +42,10 @@ def main():
|
|||
live-migration, an error occurs and this deletion is not executed. The
|
||||
related port cannot be migrated anymore.
|
||||
|
||||
This script removes the inactive ``PortBinding`` referred to a port ID and
|
||||
the corresponding ``PortBindingLevel`` registers associated to this port
|
||||
ID and ``PortBinding.host``.
|
||||
|
||||
This script should not be executed during a live migration process. It will
|
||||
remove the inactive port binding and will break the migration.
|
||||
"""
|
||||
|
@ -53,12 +57,15 @@ def main():
|
|||
dup_pbindings = ports_obj.PortBinding.get_duplicated_port_bindings(
|
||||
admin_ctx)
|
||||
|
||||
# Clean duplicated port bindings that are INACTIVE (if not in dry-run).
|
||||
# Clean duplicated port bindings that are INACTIVE and the
|
||||
# corresponding port binding level registers (if not in dry-run).
|
||||
if not _dry_run:
|
||||
for pbinding in dup_pbindings:
|
||||
port_id, host = pbinding.port_id, pbinding.host
|
||||
ports_obj.PortBinding.delete_objects(
|
||||
admin_ctx, status=constants.INACTIVE,
|
||||
port_id=pbinding.port_id)
|
||||
admin_ctx, status=constants.INACTIVE, port_id=port_id)
|
||||
ports_obj.PortBindingLevel.delete_objects(
|
||||
admin_ctx, port_id=port_id, host=host)
|
||||
|
||||
if dup_pbindings:
|
||||
port_ids = [pbinding.port_id for pbinding in dup_pbindings]
|
||||
|
|
|
@ -106,9 +106,19 @@ class PortBinding(PortBindingBase):
|
|||
@classmethod
|
||||
@db_api.CONTEXT_READER
|
||||
def get_duplicated_port_bindings(cls, context):
|
||||
return context.session.query(
|
||||
cls.db_model).group_by(
|
||||
cls.db_model.port_id).having(sqlalchemy.func.count() > 1).all()
|
||||
# This query will return the port_id of all "ml2_port_bindings"
|
||||
# registers that appears more than once (duplicated
|
||||
# "ml2_port_bindings" registers).
|
||||
# At the same time, this query returns only the "ml2_port_bindings"
|
||||
# that have status=INACTIVE.
|
||||
select = (
|
||||
sqlalchemy.select(cls.db_model.port_id).
|
||||
select_from(cls.db_model).
|
||||
group_by(cls.db_model.port_id).
|
||||
having(sqlalchemy.func.count(cls.db_model.port_id) > 1))
|
||||
_filter = and_(cls.db_model.port_id.in_(select),
|
||||
cls.db_model.status == constants.INACTIVE)
|
||||
return context.session.query(cls.db_model).filter(_filter).all()
|
||||
|
||||
|
||||
@base.NeutronObjectRegistry.register
|
||||
|
|
|
@ -56,14 +56,20 @@ class PortBindingDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
|
|||
|
||||
def test_get_duplicated_port_bindings(self):
|
||||
port_id = self._create_test_port_id()
|
||||
self.update_obj_fields({'port_id': port_id},
|
||||
objs=[self.objs[0], self.objs[1]])
|
||||
self.update_obj_fields(
|
||||
{'port_id': port_id, 'status': constants.ACTIVE},
|
||||
obj_fields=[self.obj_fields[0]])
|
||||
self.update_obj_fields(
|
||||
{'port_id': port_id, 'status': constants.INACTIVE},
|
||||
obj_fields=[self.obj_fields[1]])
|
||||
for i in range(3):
|
||||
_obj = self._make_object(self.obj_fields[i])
|
||||
_obj.create()
|
||||
dup_pb = ports.PortBinding.get_duplicated_port_bindings(self.context)
|
||||
self.assertEqual(1, len(dup_pb))
|
||||
self.assertEqual(port_id, dup_pb[0].port_id)
|
||||
# The PB register returned is the INACTIVE one.
|
||||
self.assertEqual(self.obj_fields[1]['host'], dup_pb[0].host)
|
||||
|
||||
|
||||
class DistributedPortBindingIfaceObjTestCase(
|
||||
|
|
Loading…
Reference in New Issue