Clear DVR MAC on last agent deletion from host
Once all agents are deleted from a host, the DVR MAC generated for that host should be deleted as well to prevent a buildup of pointless flows generated in the OVS agent for hosts that don't exist. Closes-Bug: #1568206 Change-Id: I51e736aa0431980a595ecf810f148ca62d990d20
This commit is contained in:
parent
3e26a7851e
commit
92527c2de2
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
# String literals representing core resources.
|
||||
AGENT = 'agent'
|
||||
EXTERNAL_NETWORK = 'external_network'
|
||||
FLOATING_IP = 'floating_ip'
|
||||
PORT = 'port'
|
||||
|
@ -31,6 +31,9 @@ from sqlalchemy import sql
|
||||
from neutron._i18n import _, _LE, _LI, _LW
|
||||
from neutron.api.rpc.callbacks import version_manager
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants
|
||||
from neutron import context
|
||||
from neutron.db import api as db_api
|
||||
@ -251,8 +254,10 @@ class AgentDbMixin(ext_agent.AgentPluginBase, AgentAvailabilityZoneMixin):
|
||||
return self._fields(res, fields)
|
||||
|
||||
def delete_agent(self, context, id):
|
||||
agent = self._get_agent(context, id)
|
||||
registry.notify(resources.AGENT, events.BEFORE_DELETE, self,
|
||||
context=context, agent=agent)
|
||||
with context.session.begin(subtransactions=True):
|
||||
agent = self._get_agent(context, id)
|
||||
context.session.delete(agent)
|
||||
|
||||
def update_agent(self, context, id, agent):
|
||||
|
@ -22,6 +22,9 @@ from sqlalchemy import or_
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron._i18n import _, _LE
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.common import utils
|
||||
@ -60,9 +63,36 @@ class DistributedVirtualRouterMacAddress(model_base.BASEV2):
|
||||
mac_address = sa.Column(sa.String(32), nullable=False, unique=True)
|
||||
|
||||
|
||||
def _delete_mac_associated_with_agent(resource, event, trigger, context, agent,
|
||||
**kwargs):
|
||||
host = agent['host']
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
if [a for a in plugin.get_agents(context, filters={'host': [host]})
|
||||
if a['id'] != agent['id']]:
|
||||
# there are still agents on this host, don't mess with the mac entry
|
||||
# until they are all deleted.
|
||||
return
|
||||
try:
|
||||
with context.session.begin(subtransactions=True):
|
||||
entry = (context.session.query(DistributedVirtualRouterMacAddress).
|
||||
filter(DistributedVirtualRouterMacAddress.host == host).
|
||||
one())
|
||||
context.session.delete(entry)
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
# notify remaining agents so they cleanup flows
|
||||
dvr_macs = plugin.get_dvr_mac_address_list(context)
|
||||
plugin.notifier.dvr_mac_address_update(context, dvr_macs)
|
||||
|
||||
|
||||
class DVRDbMixin(ext_dvr.DVRMacAddressPluginBase):
|
||||
"""Mixin class to add dvr mac address to db_plugin_base_v2."""
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
registry.subscribe(_delete_mac_associated_with_agent,
|
||||
resources.AGENT, events.BEFORE_DELETE)
|
||||
return super(DVRDbMixin, cls).__new__(cls)
|
||||
|
||||
@property
|
||||
def plugin(self):
|
||||
try:
|
||||
|
@ -16,11 +16,15 @@
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants
|
||||
from neutron import context
|
||||
from neutron.db import dvr_mac_db
|
||||
from neutron.extensions import dvr
|
||||
from neutron.extensions import portbindings
|
||||
from neutron import manager
|
||||
from neutron.tests.unit.plugins.ml2 import test_plugin
|
||||
|
||||
|
||||
@ -75,6 +79,34 @@ class DvrDbMixinTestCase(test_plugin.Ml2PluginV2TestCase):
|
||||
self.ctx, "foo_host_2")
|
||||
self.assertEqual(new_retries, f.call_count)
|
||||
|
||||
def test_mac_not_cleared_on_agent_delete_event_with_remaining_agents(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
self._create_dvr_mac_entry('host_1', 'mac_1')
|
||||
self._create_dvr_mac_entry('host_2', 'mac_2')
|
||||
agent1 = {'host': 'host_1', 'id': 'a1'}
|
||||
agent2 = {'host': 'host_1', 'id': 'a2'}
|
||||
with mock.patch.object(plugin, 'get_agents', return_value=[agent2]):
|
||||
with mock.patch.object(plugin, 'notifier') as notifier:
|
||||
registry.notify(resources.AGENT, events.BEFORE_DELETE, self,
|
||||
context=self.ctx, agent=agent1)
|
||||
mac_list = self.mixin.get_dvr_mac_address_list(self.ctx)
|
||||
self.assertEqual(2, len(mac_list))
|
||||
self.assertFalse(notifier.dvr_mac_address_update.called)
|
||||
|
||||
def test_mac_cleared_on_agent_delete_event(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
self._create_dvr_mac_entry('host_1', 'mac_1')
|
||||
self._create_dvr_mac_entry('host_2', 'mac_2')
|
||||
agent = {'host': 'host_1', 'id': 'a1'}
|
||||
with mock.patch.object(plugin, 'notifier') as notifier:
|
||||
registry.notify(resources.AGENT, events.BEFORE_DELETE, self,
|
||||
context=self.ctx, agent=agent)
|
||||
mac_list = self.mixin.get_dvr_mac_address_list(self.ctx)
|
||||
self.assertEqual(1, len(mac_list))
|
||||
self.assertEqual('host_2', mac_list[0]['host'])
|
||||
notifier.dvr_mac_address_update.assert_called_once_with(
|
||||
self.ctx, mac_list)
|
||||
|
||||
def test_get_dvr_mac_address_list(self):
|
||||
self._create_dvr_mac_entry('host_1', 'mac_1')
|
||||
self._create_dvr_mac_entry('host_2', 'mac_2')
|
||||
|
Loading…
Reference in New Issue
Block a user