use payloads for PORT AFTER_DELETE events
This patch switches over to callback payloads for PORT AFTER_DELETE events. Some shims were removed. Change-Id: If69e37b84fe1b027777b1d673b3d08a6651a979e
This commit is contained in:
parent
93ff5afdbf
commit
3cae410b30
|
@ -111,22 +111,12 @@ class DhcpAgentNotifyAPI(object):
|
||||||
self.uses_native_notifications[resource] = {'create': False,
|
self.uses_native_notifications[resource] = {'create': False,
|
||||||
'update': False,
|
'update': False,
|
||||||
'delete': False}
|
'delete': False}
|
||||||
callback = self._native_event_send_dhcp_notification
|
registry.subscribe(self._native_event_send_dhcp_notification,
|
||||||
|
|
||||||
# TODO(boden): remove shim below once all events use payloads
|
|
||||||
if resource in [resources.NETWORK, resources.SUBNET]:
|
|
||||||
callback = self._native_event_send_dhcp_notification_payload
|
|
||||||
if resource == resources.PORT:
|
|
||||||
registry.subscribe(
|
|
||||||
self._native_event_send_dhcp_notification_payload,
|
|
||||||
resource, events.AFTER_CREATE)
|
resource, events.AFTER_CREATE)
|
||||||
registry.subscribe(
|
registry.subscribe(self._native_event_send_dhcp_notification,
|
||||||
self._native_event_send_dhcp_notification_payload,
|
|
||||||
resource, events.AFTER_UPDATE)
|
resource, events.AFTER_UPDATE)
|
||||||
else:
|
registry.subscribe(self._native_event_send_dhcp_notification,
|
||||||
registry.subscribe(callback, resource, events.AFTER_CREATE)
|
resource, events.AFTER_DELETE)
|
||||||
registry.subscribe(callback, resource, events.AFTER_UPDATE)
|
|
||||||
registry.subscribe(callback, resource, events.AFTER_DELETE)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def plugin(self):
|
def plugin(self):
|
||||||
|
@ -291,11 +281,8 @@ class DhcpAgentNotifyAPI(object):
|
||||||
{'port_id': port['id']},
|
{'port_id': port['id']},
|
||||||
port['network_id'])
|
port['network_id'])
|
||||||
|
|
||||||
def _native_event_send_dhcp_notification_payload(
|
def _native_event_send_dhcp_notification(self, resource, event, trigger,
|
||||||
self, resource, event, trigger, payload=None):
|
payload):
|
||||||
|
|
||||||
# TODO(boden): collapse the native event methods back into one
|
|
||||||
|
|
||||||
action = event.replace('after_', '')
|
action = event.replace('after_', '')
|
||||||
# we unsubscribe the _send_dhcp_notification method now that we know
|
# we unsubscribe the _send_dhcp_notification method now that we know
|
||||||
# the loaded core plugin emits native resource events
|
# the loaded core plugin emits native resource events
|
||||||
|
@ -309,30 +296,12 @@ class DhcpAgentNotifyAPI(object):
|
||||||
resource)
|
resource)
|
||||||
method_name = '.'.join((resource, action, 'end'))
|
method_name = '.'.join((resource, action, 'end'))
|
||||||
data = {resource: payload.latest_state}
|
data = {resource: payload.latest_state}
|
||||||
self.notify(payload.context, data, method_name)
|
if resource == resources.PORT and event == events.AFTER_UPDATE:
|
||||||
|
if self._only_status_changed(payload.states[0],
|
||||||
def _native_event_send_dhcp_notification(self, resource, event, trigger,
|
payload.latest_state):
|
||||||
context, **kwargs):
|
|
||||||
action = event.replace('after_', '')
|
|
||||||
# we unsubscribe the _send_dhcp_notification method now that we know
|
|
||||||
# the loaded core plugin emits native resource events
|
|
||||||
if resource not in self._unsubscribed_resources:
|
|
||||||
self.uses_native_notifications[resource][action] = True
|
|
||||||
if all(self.uses_native_notifications[resource].values()):
|
|
||||||
# only unsubscribe the API level listener if we are
|
|
||||||
# receiving all event types for this resource
|
|
||||||
self._unsubscribed_resources.append(resource)
|
|
||||||
registry.unsubscribe_by_resource(self._send_dhcp_notification,
|
|
||||||
resource)
|
|
||||||
method_name = '.'.join((resource, action, 'end'))
|
|
||||||
payload = kwargs[resource]
|
|
||||||
data = {resource: payload}
|
|
||||||
if resource == resources.PORT:
|
|
||||||
if self._only_status_changed(kwargs.get('original_port'),
|
|
||||||
kwargs.get('port')):
|
|
||||||
# don't waste time updating the DHCP agent for status updates
|
# don't waste time updating the DHCP agent for status updates
|
||||||
return
|
return
|
||||||
self.notify(context, data, method_name)
|
self.notify(payload.context, data, method_name)
|
||||||
|
|
||||||
def _only_status_changed(self, orig, new):
|
def _only_status_changed(self, orig, new):
|
||||||
# a status change will manifest as a bumped revision number, a new
|
# a status change will manifest as a bumped revision number, a new
|
||||||
|
|
|
@ -1943,9 +1943,9 @@ class L3RpcNotifierMixin(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
||||||
def _notify_routers_callback(resource, event, trigger, **kwargs):
|
def _notify_routers_callback(resource, event, trigger, payload):
|
||||||
context = kwargs['context']
|
context = payload.context
|
||||||
router_ids = kwargs['router_ids']
|
router_ids = payload.metadata['router_ids']
|
||||||
l3plugin = directory.get_plugin(plugin_constants.L3)
|
l3plugin = directory.get_plugin(plugin_constants.L3)
|
||||||
if l3plugin:
|
if l3plugin:
|
||||||
l3plugin.notify_routers_updated(context, router_ids)
|
l3plugin.notify_routers_updated(context, router_ids)
|
||||||
|
|
|
@ -546,10 +546,11 @@ def _notify_l3_agent_new_port(resource, event, trigger, payload=None):
|
||||||
l3plugin.update_arp_entry_for_dvr_service_port(context, port)
|
l3plugin.update_arp_entry_for_dvr_service_port(context, port)
|
||||||
|
|
||||||
|
|
||||||
def _notify_port_delete(event, resource, trigger, **kwargs):
|
def _notify_port_delete(event, resource, trigger, payload):
|
||||||
context = kwargs['context']
|
context = payload.context
|
||||||
port = kwargs['port']
|
port = payload.latest_state
|
||||||
get_related_hosts_info = kwargs.get("get_related_hosts_info", True)
|
get_related_hosts_info = payload.metadata.get(
|
||||||
|
"get_related_hosts_info", True)
|
||||||
l3plugin = directory.get_plugin(plugin_constants.L3)
|
l3plugin = directory.get_plugin(plugin_constants.L3)
|
||||||
if port:
|
if port:
|
||||||
port_host = port.get(portbindings.HOST_ID)
|
port_host = port.get(portbindings.HOST_ID)
|
||||||
|
@ -607,14 +608,13 @@ def _notify_l3_agent_port_update(resource, event, trigger, payload):
|
||||||
original_port,
|
original_port,
|
||||||
get_related_hosts_info=False)
|
get_related_hosts_info=False)
|
||||||
if removed_routers:
|
if removed_routers:
|
||||||
removed_router_args = {
|
|
||||||
'context': context,
|
|
||||||
'port': original_port,
|
|
||||||
'removed_routers': removed_routers,
|
|
||||||
'get_related_hosts_info': False,
|
|
||||||
}
|
|
||||||
_notify_port_delete(
|
_notify_port_delete(
|
||||||
event, resource, trigger, **removed_router_args)
|
event, resource, trigger,
|
||||||
|
payload=events.DBEventPayload(
|
||||||
|
context,
|
||||||
|
metadata={'removed_routers': removed_routers,
|
||||||
|
'get_related_hosts_info': False},
|
||||||
|
states=(original_port,)))
|
||||||
|
|
||||||
def _should_notify_on_fip_update():
|
def _should_notify_on_fip_update():
|
||||||
if not fip_router_id:
|
if not fip_router_id:
|
||||||
|
|
|
@ -42,11 +42,11 @@ class SecurityGroupServerNotifierRpcMixin(sg_db.SecurityGroupDbMixin):
|
||||||
"""Mixin class to add agent-based security group implementation."""
|
"""Mixin class to add agent-based security group implementation."""
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_CREATE,
|
@registry.receives(resources.PORT, [events.AFTER_CREATE,
|
||||||
events.AFTER_UPDATE])
|
events.AFTER_UPDATE,
|
||||||
def _notify_sg_on_port_after_create_and_update(
|
events.AFTER_DELETE])
|
||||||
self, resource, event, trigger, payload):
|
def _notify_sg_on_port_change(self, resource, event, trigger, payload):
|
||||||
# TODO(boden): refact back into single method when all callbacks are
|
"""Trigger notification to other SG members on port changes."""
|
||||||
# moved to payload style events
|
|
||||||
context = payload.context
|
context = payload.context
|
||||||
port = payload.latest_state
|
port = payload.latest_state
|
||||||
if event == events.AFTER_UPDATE:
|
if event == events.AFTER_UPDATE:
|
||||||
|
@ -56,13 +56,6 @@ class SecurityGroupServerNotifierRpcMixin(sg_db.SecurityGroupDbMixin):
|
||||||
else:
|
else:
|
||||||
self.notify_security_groups_member_updated(context, port)
|
self.notify_security_groups_member_updated(context, port)
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
|
||||||
def notify_sg_on_port_change(self, resource, event, trigger, context,
|
|
||||||
port, *args, **kwargs):
|
|
||||||
"""Trigger notification to other SG members on port changes."""
|
|
||||||
|
|
||||||
self.notify_security_groups_member_updated(context, port)
|
|
||||||
|
|
||||||
def create_security_group_rule(self, context, security_group_rule):
|
def create_security_group_rule(self, context, security_group_rule):
|
||||||
rule = super(SecurityGroupServerNotifierRpcMixin,
|
rule = super(SecurityGroupServerNotifierRpcMixin,
|
||||||
self).create_security_group_rule(context,
|
self).create_security_group_rule(context,
|
||||||
|
|
|
@ -123,9 +123,9 @@ class Notifier(object):
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
||||||
def process_port_delete_event(self, resource, event, trigger,
|
def process_port_delete_event(self, resource, event, trigger,
|
||||||
original_port=None, port=None,
|
payload):
|
||||||
**kwargs):
|
|
||||||
# We only want to notify about baremetal ports.
|
# We only want to notify about baremetal ports.
|
||||||
|
port = payload.latest_state
|
||||||
if not (port[portbindings_def.VNIC_TYPE] ==
|
if not (port[portbindings_def.VNIC_TYPE] ==
|
||||||
portbindings_def.VNIC_BAREMETAL):
|
portbindings_def.VNIC_BAREMETAL):
|
||||||
# TODO(TheJulia): Add the smartnic flag at some point...
|
# TODO(TheJulia): Add the smartnic flag at some point...
|
||||||
|
|
|
@ -25,7 +25,6 @@ from neutron_lib import context as n_ctx
|
||||||
from neutron_lib.db import api as db_api
|
from neutron_lib.db import api as db_api
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron._i18n import _
|
|
||||||
from neutron.api.rpc.callbacks import events as rpc_events
|
from neutron.api.rpc.callbacks import events as rpc_events
|
||||||
from neutron.api.rpc.handlers import resources_rpc
|
from neutron.api.rpc.handlers import resources_rpc
|
||||||
from neutron.objects import address_group
|
from neutron.objects import address_group
|
||||||
|
@ -40,11 +39,6 @@ LOG = logging.getLogger(__name__)
|
||||||
class _ObjectChangeHandler(object):
|
class _ObjectChangeHandler(object):
|
||||||
MAX_IDLE_FOR = 1
|
MAX_IDLE_FOR = 1
|
||||||
_TO_CLEAN = weakref.WeakSet()
|
_TO_CLEAN = weakref.WeakSet()
|
||||||
_PAYLOAD_RESOURCES = (resources.NETWORK,
|
|
||||||
resources.ADDRESS_GROUP,
|
|
||||||
resources.SECURITY_GROUP_RULE,
|
|
||||||
resources.SUBNET,
|
|
||||||
resources.SECURITY_GROUP)
|
|
||||||
|
|
||||||
def __init__(self, resource, object_class, resource_push_api):
|
def __init__(self, resource, object_class, resource_push_api):
|
||||||
self._resource = resource
|
self._resource = resource
|
||||||
|
@ -54,15 +48,8 @@ class _ObjectChangeHandler(object):
|
||||||
self._semantic_warned = False
|
self._semantic_warned = False
|
||||||
for event in (events.AFTER_CREATE, events.AFTER_UPDATE,
|
for event in (events.AFTER_CREATE, events.AFTER_UPDATE,
|
||||||
events.AFTER_DELETE):
|
events.AFTER_DELETE):
|
||||||
handler = self.handle_event
|
registry.subscribe(self.handle_event, resource, event)
|
||||||
|
|
||||||
# TODO(boden): remove shim below once all events use payloads
|
|
||||||
if resource in self._PAYLOAD_RESOURCES:
|
|
||||||
handler = self.handle_payload_event
|
|
||||||
if resource == resources.PORT and event in (events.AFTER_CREATE,
|
|
||||||
events.AFTER_UPDATE):
|
|
||||||
handler = self.handle_payload_event
|
|
||||||
registry.subscribe(handler, resource, event)
|
|
||||||
self._stop = threading.Event()
|
self._stop = threading.Event()
|
||||||
self._worker = threading.Thread(
|
self._worker = threading.Thread(
|
||||||
target=self.dispatch_events,
|
target=self.dispatch_events,
|
||||||
|
@ -98,8 +85,12 @@ class _ObjectChangeHandler(object):
|
||||||
self._semantic_warned = True
|
self._semantic_warned = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def handle_payload_event(self, resource, event,
|
def handle_event(self, resource, event, trigger, payload):
|
||||||
trigger, payload=None):
|
"""Callback handler for resource change that pushes change to RPC.
|
||||||
|
|
||||||
|
We always retrieve the latest state and ignore what was in the
|
||||||
|
payload to ensure that we don't get any stale data.
|
||||||
|
"""
|
||||||
if self._is_session_semantic_violated(
|
if self._is_session_semantic_violated(
|
||||||
payload.context, resource, event):
|
payload.context, resource, event):
|
||||||
return
|
return
|
||||||
|
@ -108,20 +99,6 @@ class _ObjectChangeHandler(object):
|
||||||
# to the server-side event that triggered it
|
# to the server-side event that triggered it
|
||||||
self._resources_to_push.put((resource_id, payload.context.to_dict()))
|
self._resources_to_push.put((resource_id, payload.context.to_dict()))
|
||||||
|
|
||||||
def handle_event(self, resource, event, trigger,
|
|
||||||
context, *args, **kwargs):
|
|
||||||
"""Callback handler for resource change that pushes change to RPC.
|
|
||||||
|
|
||||||
We always retrieve the latest state and ignore what was in the
|
|
||||||
payload to ensure that we don't get any stale data.
|
|
||||||
"""
|
|
||||||
if self._is_session_semantic_violated(context, resource, event):
|
|
||||||
return
|
|
||||||
resource_id = self._extract_resource_id(kwargs)
|
|
||||||
# we preserve the context so we can trace a receive on the agent back
|
|
||||||
# to the server-side event that triggered it
|
|
||||||
self._resources_to_push.put((resource_id, context.to_dict()))
|
|
||||||
|
|
||||||
def dispatch_events(self):
|
def dispatch_events(self):
|
||||||
# TODO(kevinbenton): now that we are batching these, convert to a
|
# TODO(kevinbenton): now that we are batching these, convert to a
|
||||||
# single get_objects call for all of them
|
# single get_objects call for all of them
|
||||||
|
@ -157,14 +134,6 @@ class _ObjectChangeHandler(object):
|
||||||
{'name': self._worker.name,
|
{'name': self._worker.name,
|
||||||
'msgs': self._resources_to_push.unfinished_tasks})
|
'msgs': self._resources_to_push.unfinished_tasks})
|
||||||
|
|
||||||
def _extract_resource_id(self, callback_kwargs):
|
|
||||||
id_kwarg = '%s_id' % self._resource
|
|
||||||
if id_kwarg in callback_kwargs:
|
|
||||||
return callback_kwargs[id_kwarg]
|
|
||||||
if self._resource in callback_kwargs:
|
|
||||||
return callback_kwargs[self._resource]['id']
|
|
||||||
raise RuntimeError(_("Couldn't find resource ID in callback event"))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clean_up(cls, *args, **kwargs):
|
def clean_up(cls, *args, **kwargs):
|
||||||
"""Ensure all threads that were created were destroyed cleanly."""
|
"""Ensure all threads that were created were destroyed cleanly."""
|
||||||
|
|
|
@ -1998,12 +1998,12 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
|
||||||
def _post_delete_port(self, context, port, router_ids,
|
def _post_delete_port(self, context, port, router_ids,
|
||||||
bound_mech_contexts):
|
bound_mech_contexts):
|
||||||
kwargs = {
|
registry.publish(resources.PORT, events.AFTER_DELETE, self,
|
||||||
'context': context,
|
payload=events.DBEventPayload(
|
||||||
'port': port,
|
context,
|
||||||
'router_ids': router_ids,
|
metadata={'router_ids': router_ids},
|
||||||
}
|
resource_id=port['id'],
|
||||||
registry.notify(resources.PORT, events.AFTER_DELETE, self, **kwargs)
|
states=(port,)))
|
||||||
try:
|
try:
|
||||||
# Note that DVR Interface ports will have bindings on
|
# Note that DVR Interface ports will have bindings on
|
||||||
# multiple hosts, and so will have multiple mech_contexts,
|
# multiple hosts, and so will have multiple mech_contexts,
|
||||||
|
|
|
@ -420,17 +420,12 @@ class NovaSegmentNotifier(object):
|
||||||
'routed network segment %(segment_id)s',
|
'routed network segment %(segment_id)s',
|
||||||
{'host': event.host, 'segment_id': segment_id})
|
{'host': event.host, 'segment_id': segment_id})
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_CREATE])
|
@registry.receives(resources.PORT, [events.AFTER_CREATE,
|
||||||
def _notify_port_created(self, resource, event, trigger,
|
events.AFTER_DELETE])
|
||||||
payload=None):
|
|
||||||
# TODO(boden): refactor back into 1 method when all code is moved
|
|
||||||
# to event payloads
|
|
||||||
return self._notify_port_created_or_deleted(
|
|
||||||
resource, event, trigger, payload.context, payload.latest_state)
|
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_DELETE])
|
|
||||||
def _notify_port_created_or_deleted(self, resource, event, trigger,
|
def _notify_port_created_or_deleted(self, resource, event, trigger,
|
||||||
context, port, **kwargs):
|
payload):
|
||||||
|
context = payload.context
|
||||||
|
port = payload.latest_state
|
||||||
if not self._does_port_require_nova_inventory_update(port):
|
if not self._does_port_require_nova_inventory_update(port):
|
||||||
return
|
return
|
||||||
ipv4_subnets_number, segment_id = (
|
ipv4_subnets_number, segment_id = (
|
||||||
|
|
|
@ -267,42 +267,7 @@ class TestDhcpAgentNotifyAPI(base.BaseTestCase):
|
||||||
|
|
||||||
def test__native_notification_unsubscribes(self):
|
def test__native_notification_unsubscribes(self):
|
||||||
self.assertFalse(self.notifier._unsubscribed_resources)
|
self.assertFalse(self.notifier._unsubscribed_resources)
|
||||||
for res in (resources.PORT,):
|
for res in (resources.PORT, resources.NETWORK, resources.SUBNET):
|
||||||
self.notifier._unsubscribed_resources = []
|
|
||||||
kwargs = {res: {}}
|
|
||||||
if res == resources.PORT:
|
|
||||||
registry.publish(res, events.AFTER_CREATE, self,
|
|
||||||
payload=events.DBEventPayload(
|
|
||||||
mock.Mock(), states=({res: {}},)))
|
|
||||||
else:
|
|
||||||
registry.notify(res, events.AFTER_CREATE, self,
|
|
||||||
context=mock.Mock(), **kwargs)
|
|
||||||
# don't unsubscribe until all three types are observed
|
|
||||||
self.assertEqual([], self.notifier._unsubscribed_resources)
|
|
||||||
if res == resources.PORT:
|
|
||||||
registry.publish(res, events.AFTER_UPDATE, self,
|
|
||||||
payload=events.DBEventPayload(
|
|
||||||
mock.Mock(), states=({},)))
|
|
||||||
|
|
||||||
else:
|
|
||||||
registry.notify(res, events.AFTER_UPDATE, self,
|
|
||||||
context=mock.Mock(), **kwargs)
|
|
||||||
|
|
||||||
self.assertEqual([], self.notifier._unsubscribed_resources)
|
|
||||||
registry.notify(res, events.AFTER_DELETE, self,
|
|
||||||
context=mock.Mock(), **kwargs)
|
|
||||||
self.assertEqual([res], self.notifier._unsubscribed_resources)
|
|
||||||
# after first time, no further unsubscribing should happen
|
|
||||||
if res == resources.PORT:
|
|
||||||
registry.publish(res, events.AFTER_CREATE, self,
|
|
||||||
payload=events.DBEventPayload(
|
|
||||||
mock.Mock(), states=({res: {}})))
|
|
||||||
else:
|
|
||||||
registry.notify(res, events.AFTER_CREATE, self,
|
|
||||||
context=mock.Mock(), **kwargs)
|
|
||||||
self.assertEqual([res], self.notifier._unsubscribed_resources)
|
|
||||||
|
|
||||||
for res in (resources.NETWORK, resources.SUBNET):
|
|
||||||
self.notifier._unsubscribed_resources = []
|
self.notifier._unsubscribed_resources = []
|
||||||
registry.publish(res, events.AFTER_CREATE, self,
|
registry.publish(res, events.AFTER_CREATE, self,
|
||||||
payload=events.DBEventPayload(mock.Mock()))
|
payload=events.DBEventPayload(mock.Mock()))
|
||||||
|
|
|
@ -133,9 +133,11 @@ class TestIronicNotifier(base.BaseTestCase):
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test_process_port_delete_event(self, mock_queue_event):
|
def test_process_port_delete_event(self, mock_queue_event):
|
||||||
port = get_fake_port()
|
port = get_fake_port()
|
||||||
|
original_port = None
|
||||||
self.ironic_notifier.process_port_delete_event(
|
self.ironic_notifier.process_port_delete_event(
|
||||||
'fake_resource', 'fake_event', 'fake_trigger', original_port=None,
|
'fake_resource', 'fake_event', 'fake_trigger',
|
||||||
port=port, **{})
|
payload=events.DBEventPayload(
|
||||||
|
mock.Mock(), states=(original_port, port)))
|
||||||
mock_queue_event.assert_called_with(
|
mock_queue_event.assert_called_with(
|
||||||
self.ironic_notifier.batch_notifier,
|
self.ironic_notifier.batch_notifier,
|
||||||
{'event': 'network.delete_port',
|
{'event': 'network.delete_port',
|
||||||
|
@ -150,10 +152,12 @@ class TestIronicNotifier(base.BaseTestCase):
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test_process_port_event_empty_uuid_field(self, mock_queue_event):
|
def test_process_port_event_empty_uuid_field(self, mock_queue_event):
|
||||||
port = get_fake_port()
|
port = get_fake_port()
|
||||||
|
original_port = None
|
||||||
port.update({'device_id': ''})
|
port.update({'device_id': ''})
|
||||||
self.ironic_notifier.process_port_delete_event(
|
self.ironic_notifier.process_port_delete_event(
|
||||||
'fake_resource', 'fake_event', 'fake_trigger', original_port=None,
|
'fake_resource', 'fake_event', 'fake_trigger',
|
||||||
port=port, **{})
|
payload=events.DBEventPayload(
|
||||||
|
mock.Mock(), states=(original_port, port)))
|
||||||
mock_queue_event.assert_called_with(
|
mock_queue_event.assert_called_with(
|
||||||
self.ironic_notifier.batch_notifier,
|
self.ironic_notifier.batch_notifier,
|
||||||
{'event': 'network.delete_port',
|
{'event': 'network.delete_port',
|
||||||
|
@ -166,9 +170,11 @@ class TestIronicNotifier(base.BaseTestCase):
|
||||||
@mock.patch.object(eventlet, 'spawn_n', autospec=True)
|
@mock.patch.object(eventlet, 'spawn_n', autospec=True)
|
||||||
def test_queue_events(self, mock_spawn_n):
|
def test_queue_events(self, mock_spawn_n):
|
||||||
port = get_fake_port()
|
port = get_fake_port()
|
||||||
|
original_port = None
|
||||||
self.ironic_notifier.process_port_delete_event(
|
self.ironic_notifier.process_port_delete_event(
|
||||||
'fake_resource', 'fake_event', 'fake_trigger', original_port=None,
|
'fake_resource', 'fake_event', 'fake_trigger',
|
||||||
port=port, **{})
|
payload=events.DBEventPayload(
|
||||||
|
mock.Mock(), states=(original_port, port)))
|
||||||
|
|
||||||
port = get_fake_port()
|
port = get_fake_port()
|
||||||
port.update({'status': n_const.PORT_STATUS_ACTIVE})
|
port.update({'status': n_const.PORT_STATUS_ACTIVE})
|
||||||
|
|
|
@ -1099,8 +1099,9 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
||||||
|
|
||||||
def test_port_after_delete_outside_transaction(self):
|
def test_port_after_delete_outside_transaction(self):
|
||||||
self.tx_open = True
|
self.tx_open = True
|
||||||
receive = lambda *a, **k: setattr(self, 'tx_open',
|
receive = lambda r, e, t, payload: \
|
||||||
k['context'].session.is_active)
|
setattr(self, 'tx_open', payload.context.session.is_active)
|
||||||
|
|
||||||
with self.port() as p:
|
with self.port() as p:
|
||||||
registry.subscribe(receive, resources.PORT, events.AFTER_DELETE)
|
registry.subscribe(receive, resources.PORT, events.AFTER_DELETE)
|
||||||
self._delete('ports', p['port']['id'])
|
self._delete('ports', p['port']['id'])
|
||||||
|
@ -2093,29 +2094,34 @@ class TestMl2DvrPortsV2(TestMl2PortsV2):
|
||||||
return_value=router_ids):
|
return_value=router_ids):
|
||||||
port_id = port['port']['id']
|
port_id = port['port']['id']
|
||||||
self.plugin.delete_port(self.context, port_id)
|
self.plugin.delete_port(self.context, port_id)
|
||||||
self.assertEqual(2, notify.call_count)
|
self.assertEqual(1, notify.call_count)
|
||||||
self.assertEqual(1, publish.call_count)
|
self.assertEqual(2, publish.call_count)
|
||||||
# needed for a full match in the assertion below
|
# needed for a full match in the assertion below
|
||||||
port['port']['extra_dhcp_opts'] = []
|
port['port']['extra_dhcp_opts'] = []
|
||||||
port['port']['standard_attr_id'] = mock.ANY
|
port['port']['standard_attr_id'] = mock.ANY
|
||||||
|
|
||||||
expected = [mock.call(resources.PORT, events.PRECOMMIT_DELETE,
|
expected = [mock.call(resources.PORT, events.PRECOMMIT_DELETE,
|
||||||
mock.ANY, network=mock.ANY, bind=mock.ANY,
|
mock.ANY, network=mock.ANY, bind=mock.ANY,
|
||||||
port=port['port'], port_db=mock.ANY,
|
port=port['port'], port_db=mock.ANY,
|
||||||
context=self.context, levels=mock.ANY,
|
context=self.context, levels=mock.ANY,
|
||||||
id=mock.ANY, bindings=mock.ANY),
|
id=mock.ANY, bindings=mock.ANY)]
|
||||||
mock.call(resources.PORT, events.AFTER_DELETE,
|
|
||||||
mock.ANY, context=self.context,
|
|
||||||
port=port['port'],
|
|
||||||
router_ids=router_ids)]
|
|
||||||
notify.assert_has_calls(expected)
|
notify.assert_has_calls(expected)
|
||||||
|
|
||||||
expected = [mock.call(resources.PORT, events.BEFORE_DELETE,
|
expected = [mock.call(resources.PORT, events.BEFORE_DELETE,
|
||||||
mock.ANY, payload=mock.ANY)]
|
mock.ANY, payload=mock.ANY)]
|
||||||
publish.assert_has_calls(expected)
|
publish.assert_has_calls(expected)
|
||||||
payload = publish.call_args[1]['payload']
|
|
||||||
|
payload = publish.call_args_list[0][1]['payload']
|
||||||
self.assertEqual(port_id, payload.resource_id)
|
self.assertEqual(port_id, payload.resource_id)
|
||||||
self.assertTrue(payload.metadata['port_check'])
|
self.assertTrue(payload.metadata['port_check'])
|
||||||
|
|
||||||
|
expected = [mock.call(resources.PORT, events.AFTER_DELETE,
|
||||||
|
mock.ANY, payload=mock.ANY)]
|
||||||
|
publish.assert_has_calls(expected)
|
||||||
|
|
||||||
|
payload = publish.call_args_list[1][1]['payload']
|
||||||
|
self.assertEqual(port_id, payload.resource_id)
|
||||||
|
|
||||||
def test_delete_port_with_floatingip_notifies_l3_plugin(self):
|
def test_delete_port_with_floatingip_notifies_l3_plugin(self):
|
||||||
self.test_delete_port_notifies_l3_plugin(floating_ip=True)
|
self.test_delete_port_notifies_l3_plugin(floating_ip=True)
|
||||||
|
|
||||||
|
|
|
@ -1250,19 +1250,16 @@ class L3DvrSchedulerTestCase(L3SchedulerBaseMixin,
|
||||||
portbindings.HOST_ID: 'host1',
|
portbindings.HOST_ID: 'host1',
|
||||||
}
|
}
|
||||||
|
|
||||||
kwargs = {
|
|
||||||
'context': self.adminContext,
|
|
||||||
'port': port,
|
|
||||||
'removed_routers': [
|
|
||||||
{'agent_id': 'foo_agent', 'router_id': 'foo_id'},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
removed_routers = [{'agent_id': 'foo_agent',
|
removed_routers = [{'agent_id': 'foo_agent',
|
||||||
'router_id': 'foo_id',
|
'router_id': 'foo_id',
|
||||||
'host': 'foo_host'}]
|
'host': 'foo_host'}]
|
||||||
l3plugin.get_dvr_routers_to_remove.return_value = removed_routers
|
l3plugin.get_dvr_routers_to_remove.return_value = removed_routers
|
||||||
l3_dvrscheduler_db._notify_port_delete(
|
l3_dvrscheduler_db._notify_port_delete(
|
||||||
'port', 'after_delete', plugin, **kwargs)
|
'port', 'after_delete', plugin,
|
||||||
|
payload=events.DBEventPayload(
|
||||||
|
self.adminContext,
|
||||||
|
metadata={'removed_routers': removed_routers},
|
||||||
|
states=(port,)))
|
||||||
l3plugin.delete_arp_entry_for_dvr_service_port.\
|
l3plugin.delete_arp_entry_for_dvr_service_port.\
|
||||||
assert_called_once_with(
|
assert_called_once_with(
|
||||||
self.adminContext, mock.ANY)
|
self.adminContext, mock.ANY)
|
||||||
|
|
Loading…
Reference in New Issue