[OVN][Trunk] Set the subports correct host during live migration
During the trunk migration, the parent port multiple port binding
will contain the destination host. Because this update is done
before the migration is done (in other words, the parent port
still has two port binding registers), the method setting the
binding profile of the subport will use the destination host
in advance. At the end of the live migration, the subports
host will point to the correct hostname.
Related-Bug: #2027605
Change-Id: I2370ea2f96e2e31dbd43bf232a63394388e6945f
(cherry picked from commit 7ed79c1f78
)
This commit is contained in:
parent
f2a74b8c4c
commit
6d3c29723e
@ -14,6 +14,7 @@ from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib.callbacks import events
|
||||
from neutron_lib.callbacks import registry
|
||||
from neutron_lib.callbacks import resources
|
||||
from neutron_lib import constants as n_const
|
||||
from neutron_lib import context as n_context
|
||||
from neutron_lib.db import api as db_api
|
||||
from neutron_lib import exceptions as n_exc
|
||||
@ -51,7 +52,11 @@ class OVNTrunkHandler(object):
|
||||
context = n_context.get_admin_context()
|
||||
db_parent_port = port_obj.Port.get_object(context, id=parent_port)
|
||||
parent_port_status = db_parent_port.status
|
||||
parent_port_bindings = db_parent_port.bindings[0]
|
||||
try:
|
||||
parent_port_bindings = [pb for pb in db_parent_port.bindings
|
||||
if pb.status == n_const.ACTIVE][-1]
|
||||
except IndexError:
|
||||
parent_port_bindings = None
|
||||
for subport in subports:
|
||||
with db_api.CONTEXT_WRITER.using(context), (
|
||||
txn(check_error=True)) as ovn_txn:
|
||||
@ -85,8 +90,10 @@ class OVNTrunkHandler(object):
|
||||
db_port.id, db_port, ovn_const.TYPE_PORTS)
|
||||
ovn_txn.add(check_rev_cmd)
|
||||
parent_binding_host = ''
|
||||
if parent_port_bindings.host:
|
||||
parent_binding_host = parent_port_bindings.host
|
||||
if parent_port_bindings and parent_port_bindings.host:
|
||||
migrating_to = parent_port_bindings.profile.get(
|
||||
ovn_const.MIGRATING_ATTR)
|
||||
parent_binding_host = migrating_to or parent_port_bindings.host
|
||||
try:
|
||||
# NOTE(flaviof): We expect binding's host to be set. Otherwise,
|
||||
# sub-port will not transition from DOWN to ACTIVE.
|
||||
|
@ -97,13 +97,23 @@ class TestOVNTrunkDriver(base.TestOVNFunctionalBase):
|
||||
if trunk.get('status'):
|
||||
self.assertEqual(trunk_consts.TRUNK_ACTIVE_STATUS, trunk['status'])
|
||||
|
||||
def _bind_port(self, port_id, host):
|
||||
def _bind_port(self, port_id, host_source, host_dest=None):
|
||||
with db_api.CONTEXT_WRITER.using(self.context):
|
||||
pb = port_obj.PortBinding.get_object(self.context,
|
||||
port_id=port_id, host='')
|
||||
pb.delete()
|
||||
port_obj.PortBinding(self.context, port_id=port_id, host=host,
|
||||
vif_type=portbindings.VIF_TYPE_OVS).create()
|
||||
for pb in port_obj.PortBinding.get_objects(self.context,
|
||||
port_id=port_id):
|
||||
pb.delete()
|
||||
profile = {}
|
||||
if host_dest:
|
||||
# When "host_dest" there are 2 port bindings, as in a live
|
||||
# migration; the second one (destination host) is inactive.
|
||||
profile[ovn_const.MIGRATING_ATTR] = host_dest
|
||||
port_obj.PortBinding(
|
||||
self.context, port_id=port_id, host=host_dest,
|
||||
vif_type=portbindings.VIF_TYPE_OVS,
|
||||
status=n_consts.INACTIVE).create()
|
||||
port_obj.PortBinding(
|
||||
self.context, port_id=port_id, host=host_source,
|
||||
profile=profile, vif_type=portbindings.VIF_TYPE_OVS).create()
|
||||
|
||||
def test_trunk_create(self):
|
||||
with self.trunk() as trunk:
|
||||
@ -148,6 +158,21 @@ class TestOVNTrunkDriver(base.TestOVNFunctionalBase):
|
||||
self._verify_trunk_info(new_trunk, has_items=True,
|
||||
host='host1')
|
||||
|
||||
def test_subport_add_live_migration_multiple_port_binding(self):
|
||||
with self.subport() as subport:
|
||||
with self.trunk() as trunk:
|
||||
self.trunk_plugin.add_subports(self.context, trunk['id'],
|
||||
{'sub_ports': [subport]})
|
||||
new_trunk = self.trunk_plugin.get_trunk(self.context,
|
||||
trunk['id'])
|
||||
self._verify_trunk_info(new_trunk, has_items=True)
|
||||
# Bind parent port. That will trigger the binding of the
|
||||
# trunk subports too, using the same host ID.
|
||||
self._bind_port(trunk['port_id'], 'host1', host_dest='host2')
|
||||
self.mech_driver.set_port_status_up(trunk['port_id'])
|
||||
self._verify_trunk_info(new_trunk, has_items=True,
|
||||
host='host2')
|
||||
|
||||
def test_subport_delete(self):
|
||||
with self.subport() as subport:
|
||||
with self.trunk([subport]) as trunk:
|
||||
|
Loading…
Reference in New Issue
Block a user