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:
parent
2a64fabd52
commit
c17c78df7c
@ -18,6 +18,7 @@ NETWORK = 'network'
|
|||||||
NETWORKS = 'networks'
|
NETWORKS = 'networks'
|
||||||
PORT = 'port'
|
PORT = 'port'
|
||||||
PORTS = 'ports'
|
PORTS = 'ports'
|
||||||
|
PORT_DEVICE = 'port_device'
|
||||||
PROCESS = 'process'
|
PROCESS = 'process'
|
||||||
ROUTER = 'router'
|
ROUTER = 'router'
|
||||||
ROUTER_GATEWAY = 'router_gateway'
|
ROUTER_GATEWAY = 'router_gateway'
|
||||||
|
@ -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 rpc as agent_rpc
|
||||||
from neutron.agent import securitygroups_rpc as sg_rpc
|
from neutron.agent import securitygroups_rpc as sg_rpc
|
||||||
from neutron.api.rpc.callbacks import resources
|
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 config as common_config
|
||||||
from neutron.common import constants as n_const
|
from neutron.common import constants as n_const
|
||||||
from neutron.common import topics
|
from neutron.common import topics
|
||||||
@ -303,6 +306,10 @@ class CommonAgentLoop(service.Service):
|
|||||||
device_details['port_id'],
|
device_details['port_id'],
|
||||||
device_details['device'])
|
device_details['device'])
|
||||||
self.ext_manager.handle_port(self.context, device_details)
|
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:
|
else:
|
||||||
LOG.info(_LI("Device %s not defined on plugin"), device)
|
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,
|
self.ext_manager.delete_port(self.context,
|
||||||
{'device': device,
|
{'device': device,
|
||||||
'port_id': port_id})
|
'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:
|
if self.prevent_arp_spoofing:
|
||||||
self.mgr.delete_arp_spoofing_protection(devices)
|
self.mgr.delete_arp_spoofing_protection(devices)
|
||||||
return resync
|
return resync
|
||||||
|
@ -20,6 +20,9 @@ from oslo_config import cfg
|
|||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from neutron.agent.linux import bridge_lib
|
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.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 _agent_manager_base as amb
|
||||||
from neutron.plugins.ml2.drivers.agent import _common_agent as ca
|
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"):
|
with mock.patch.object(self.agent, "daemon_loop"):
|
||||||
self.agent.start()
|
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):
|
def test_treat_devices_removed_with_existed_device(self):
|
||||||
agent = self.agent
|
agent = self.agent
|
||||||
agent.mgr.ensure_port_admin_state = mock.Mock()
|
agent.mgr.ensure_port_admin_state = mock.Mock()
|
||||||
|
Loading…
Reference in New Issue
Block a user