Merge "Notify nova with network-vif-plugged in case of live migration"
This commit is contained in:
commit
3fb38b41f7
|
@ -172,26 +172,31 @@ class Notifier(object):
|
|||
else:
|
||||
return self._get_network_changed_event(port['device_id'])
|
||||
|
||||
def _can_notify(self, port):
|
||||
if not port.id:
|
||||
LOG.warning(_LW("Port ID not set! Nova will not be notified of "
|
||||
"port status change."))
|
||||
return False
|
||||
|
||||
# If there is no device_id set there is nothing we can do here.
|
||||
if not port.device_id:
|
||||
LOG.debug("device_id is not set on port %s yet.", port.id)
|
||||
return False
|
||||
|
||||
# We only want to notify about nova ports.
|
||||
if not self._is_compute_port(port):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def record_port_status_changed(self, port, current_port_status,
|
||||
previous_port_status, initiator):
|
||||
"""Determine if nova needs to be notified due to port status change.
|
||||
"""
|
||||
# clear out previous _notify_event
|
||||
port._notify_event = None
|
||||
# If there is no device_id set there is nothing we can do here.
|
||||
if not port.device_id:
|
||||
LOG.debug("device_id is not set on port yet.")
|
||||
if not self._can_notify(port):
|
||||
return
|
||||
|
||||
if not port.id:
|
||||
LOG.warning(_LW("Port ID not set! Nova will not be notified of "
|
||||
"port status change."))
|
||||
return
|
||||
|
||||
# We only want to notify about nova ports.
|
||||
if not self._is_compute_port(port):
|
||||
return
|
||||
|
||||
# We notify nova when a vif is unplugged which only occurs when
|
||||
# the status goes from ACTIVE to DOWN.
|
||||
if (previous_port_status == constants.PORT_STATUS_ACTIVE and
|
||||
|
@ -228,6 +233,24 @@ class Notifier(object):
|
|||
self.batch_notifier.queue_event(event)
|
||||
port._notify_event = None
|
||||
|
||||
def notify_port_active_direct(self, port):
|
||||
"""Notify nova about active port
|
||||
|
||||
Used when port was wired on the host other than port's current host
|
||||
according to port binding. This happens during live migration.
|
||||
In this case ml2 plugin skips port status update but we still we need
|
||||
to notify nova.
|
||||
"""
|
||||
if not self._can_notify(port):
|
||||
return
|
||||
|
||||
port._notify_event = (
|
||||
{'server_uuid': port.device_id,
|
||||
'name': VIF_PLUGGED,
|
||||
'status': 'completed',
|
||||
'tag': port.id})
|
||||
self.send_port_status(None, None, port)
|
||||
|
||||
def send_events(self, batched_events):
|
||||
LOG.debug("Sending events: %s", batched_events)
|
||||
try:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
from neutron_lib import constants as n_const
|
||||
from neutron_lib import exceptions
|
||||
from oslo_log import log
|
||||
import oslo_messaging
|
||||
from sqlalchemy.orm import exc
|
||||
|
@ -209,6 +210,17 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
|||
LOG.debug("Device %(device)s not bound to the"
|
||||
" agent host %(host)s",
|
||||
{'device': device, 'host': host})
|
||||
# this might mean that a VM is in the process of live migration
|
||||
# and vif was plugged on the destination compute node;
|
||||
# need to notify nova explicitly
|
||||
try:
|
||||
port = plugin._get_port(rpc_context, port_id)
|
||||
except exceptions.PortNotFound:
|
||||
LOG.debug("Port %s not found, will not notify nova.", port_id)
|
||||
else:
|
||||
if port.device_owner.startswith(
|
||||
n_const.DEVICE_OWNER_COMPUTE_PREFIX):
|
||||
plugin.nova_notifier.notify_port_active_direct(port)
|
||||
return
|
||||
if port and port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE:
|
||||
# NOTE(kevinbenton): we have to special case DVR ports because of
|
||||
|
|
|
@ -340,3 +340,19 @@ class TestNovaNotify(base.BaseTestCase):
|
|||
region_name=cfg.CONF.nova.region_name,
|
||||
endpoint_type='internal',
|
||||
extensions=mock.ANY)
|
||||
|
||||
def test_notify_port_active_direct(self):
|
||||
device_id = '32102d7b-1cf4-404d-b50a-97aae1f55f87'
|
||||
port_id = 'bee50827-bcee-4cc8-91c1-a27b0ce54222'
|
||||
port = models_v2.Port(id=port_id, device_id=device_id,
|
||||
device_owner=DEVICE_OWNER_COMPUTE)
|
||||
expected_event = {'server_uuid': device_id,
|
||||
'name': nova.VIF_PLUGGED,
|
||||
'status': 'completed',
|
||||
'tag': port_id}
|
||||
self.nova_notifier.notify_port_active_direct(port)
|
||||
|
||||
self.assertEqual(
|
||||
1, len(self.nova_notifier.batch_notifier.pending_events))
|
||||
self.assertEqual(expected_event,
|
||||
self.nova_notifier.batch_notifier.pending_events[0])
|
||||
|
|
|
@ -222,6 +222,9 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
|||
def test_update_device_up_with_device_not_bound_to_host(self):
|
||||
self.assertIsNone(self._test_update_device_not_bound_to_host(
|
||||
self.callbacks.update_device_up))
|
||||
port = self.plugin._get_port.return_value
|
||||
(self.plugin.nova_notifier.notify_port_active_direct.
|
||||
assert_called_once_with(port))
|
||||
|
||||
def test_update_device_down_with_device_not_bound_to_host(self):
|
||||
self.assertEqual(
|
||||
|
|
Loading…
Reference in New Issue