Port device events for common agent

Some of the agent code may want to receive events whenever
a device is added/updated/deleted. Currently the only way
to do that is to modify the loop directly or create an
extension. Neither of these options are good if it's code
we don't want users to disable (the extensions) and it's
specific to one agent (so we don't want to modify the loop).

Partially-Implements: blueprint vlan-aware-vms
Change-Id: I3468c7f46cc1b4000cdd537e8f216d207a14727a
This commit is contained in:
Kevin Benton 2016-07-31 03:10:35 -07:00
parent 2a64fabd52
commit c17c78df7c
3 changed files with 44 additions and 0 deletions

View File

@ -18,6 +18,7 @@ NETWORK = 'network'
NETWORKS = 'networks'
PORT = 'port'
PORTS = 'ports'
PORT_DEVICE = 'port_device'
PROCESS = 'process'
ROUTER = 'router'
ROUTER_GATEWAY = 'router_gateway'

View File

@ -32,6 +32,9 @@ from neutron.agent.l2 import l2_agent_extensions_manager as ext_manager
from neutron.agent import rpc as agent_rpc
from neutron.agent import securitygroups_rpc as sg_rpc
from neutron.api.rpc.callbacks import resources
from neutron.callbacks import events
from neutron.callbacks import registry
from neutron.callbacks import resources as local_resources
from neutron.common import config as common_config
from neutron.common import constants as n_const
from neutron.common import topics
@ -303,6 +306,10 @@ class CommonAgentLoop(service.Service):
device_details['port_id'],
device_details['device'])
self.ext_manager.handle_port(self.context, device_details)
registry.notify(local_resources.PORT_DEVICE,
events.AFTER_UPDATE, self,
context=self.context,
device_details=device_details)
else:
LOG.info(_LI("Device %s not defined on plugin"), device)
@ -339,6 +346,9 @@ class CommonAgentLoop(service.Service):
self.ext_manager.delete_port(self.context,
{'device': device,
'port_id': port_id})
registry.notify(local_resources.PORT_DEVICE, events.AFTER_DELETE,
self, context=self.context, device=device,
port_id=port_id)
if self.prevent_arp_spoofing:
self.mgr.delete_arp_spoofing_protection(devices)
return resync

View File

@ -20,6 +20,9 @@ from oslo_config import cfg
import testtools
from neutron.agent.linux import bridge_lib
from neutron.callbacks import events
from neutron.callbacks import registry
from neutron.callbacks import resources
from neutron.common import constants as n_const
from neutron.plugins.ml2.drivers.agent import _agent_manager_base as amb
from neutron.plugins.ml2.drivers.agent import _common_agent as ca
@ -68,6 +71,36 @@ class TestCommonAgentLoop(base.BaseTestCase):
with mock.patch.object(self.agent, "daemon_loop"):
self.agent.start()
def test_treat_devices_removed_notify(self):
handler = mock.Mock()
registry.subscribe(handler, resources.PORT_DEVICE, events.AFTER_DELETE)
devices = [DEVICE_1]
self.agent.treat_devices_removed(devices)
handler.assert_called_once_with(mock.ANY, mock.ANY, self.agent,
context=mock.ANY, device=DEVICE_1,
port_id=mock.ANY)
def test_treat_devices_added_updated_notify(self):
handler = mock.Mock()
registry.subscribe(handler, resources.PORT_DEVICE, events.AFTER_UPDATE)
agent = self.agent
mock_details = {'device': 'dev123',
'port_id': 'port123',
'network_id': 'net123',
'admin_state_up': True,
'network_type': 'vlan',
'segmentation_id': 100,
'physical_network': 'physnet1',
'device_owner': 'horse'}
agent.plugin_rpc = mock.Mock()
agent.plugin_rpc.get_devices_details_list.return_value = [mock_details]
agent.mgr = mock.Mock()
agent.mgr.plug_interface.return_value = True
agent.treat_devices_added_updated(set(['dev123']))
handler.assert_called_once_with(mock.ANY, mock.ANY, self.agent,
context=mock.ANY,
device_details=mock_details)
def test_treat_devices_removed_with_existed_device(self):
agent = self.agent
agent.mgr.ensure_port_admin_state = mock.Mock()