Server-side push notifications for address groups

Adds server side code to enable the ML2 plugin to push notifications for
address groups. A follow up patch adds the corresponding code for the
OVS agent to process the notifications.

Change-Id: I49fc6e41a69f849a14da2ae67d1e4bff561dd4ec
Related-Bug: #1592028
This commit is contained in:
Miguel Lavalle 2020-10-12 16:39:08 -05:00
parent e279a67d8f
commit 4937928652
4 changed files with 53 additions and 0 deletions

View File

@ -11,6 +11,7 @@
# under the License.
from neutron._i18n import _
from neutron.objects import address_group
from neutron.objects import conntrack_helper
from neutron.objects.logapi import logging_resource as log_object
from neutron.objects import network
@ -34,6 +35,7 @@ SECURITYGROUP = securitygroup.SecurityGroup.obj_name()
SECURITYGROUPRULE = securitygroup.SecurityGroupRule.obj_name()
PORTFORWARDING = port_forwarding.PortForwarding.obj_name()
CONNTRACKHELPER = conntrack_helper.ConntrackHelper.obj_name()
ADDRESSGROUP = address_group.AddressGroup.obj_name()
_VALID_CLS = (
@ -48,6 +50,7 @@ _VALID_CLS = (
log_object.Log,
port_forwarding.PortForwarding,
conntrack_helper.ConntrackHelper,
address_group.AddressGroup,
)
_TYPE_TO_CLS_MAP = {cls.obj_name(): cls for cls in _VALID_CLS}

View File

@ -11,6 +11,8 @@
# under the License.
import netaddr
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib import constants
from neutron_lib.db import resource_extend
from neutron_lib.db import utils as db_utils
@ -22,6 +24,13 @@ from neutron.objects import address_group as ag_obj
from neutron.objects import base as base_obj
# TODO(mlavalle) Following line should be deleted when
# https://review.opendev.org/#/c/756927/ is released. All references in this
# module to ADDRESS_GROUP should point to the definition in
# neutron_lib/callbacks/resources
ADDRESS_GROUP = 'address_group'
@resource_extend.has_resource_extenders
class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
"""Mixin class to add address group to db_base_plugin_v2."""
@ -104,6 +113,12 @@ class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
if fields.get('addresses') is not constants.ATTR_NOT_SPECIFIED:
self.add_addresses(context, ag.id, fields)
ag.update() # reload synthetic fields
# TODO(mlavalle) this notification should be updated to publish when
# the callback handler handle_event, class _ObjectChangeHandler in
# neutron.plugins.ml2.ovo_rpc is updated to receive notifications with
# new style payload objects as argument.
registry.notify(ADDRESS_GROUP, events.AFTER_CREATE, self,
context=context, address_group_id=ag.id)
return self._make_address_group_dict(ag)
def update_address_group(self, context, id, address_group):
@ -111,6 +126,12 @@ class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
ag = self._get_address_group(context, id)
ag.update_fields(fields)
ag.update()
# TODO(mlavalle) this notification should be updated to publish when
# the callback handler handle_event, class _ObjectChangeHandler in
# neutron.plugins.ml2.ovo_rpc is updated to receive notifications with
# new style payload objects as argument.
registry.notify(ADDRESS_GROUP, events.AFTER_UPDATE, self,
context=context, address_group_id=ag.id)
return self._make_address_group_dict(ag)
def get_address_group(self, context, id, fields=None):
@ -131,3 +152,9 @@ class AddressGroupDbMixin(ag_ext.AddressGroupPluginBase):
def delete_address_group(self, context, id):
address_group = self._get_address_group(context, id)
address_group.delete()
# TODO(mlavalle) this notification should be updated to publish when
# the callback handler handle_event, class _ObjectChangeHandler in
# neutron.plugins.ml2.ovo_rpc is updated to receive notifications with
# new style payload objects as argument.
registry.notify(ADDRESS_GROUP, events.AFTER_DELETE, self,
context=context, address_group_id=id)

View File

@ -27,6 +27,7 @@ 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.handlers import resources_rpc
from neutron.objects import address_group
from neutron.objects import network
from neutron.objects import ports
from neutron.objects import securitygroup
@ -147,6 +148,10 @@ class OVOServerRpcInterface(object):
resources.NETWORK: network.Network,
resources.SECURITY_GROUP: securitygroup.SecurityGroup,
resources.SECURITY_GROUP_RULE: securitygroup.SecurityGroupRule,
# TODO(mlavalle) Following line should be replaced by:
# resources.ADDRESS_GROUP: address_group.AddressGroup,
# when https://review.opendev.org/#/c/756927/ is released
'address_group': address_group.AddressGroup,
}
self._resource_handlers = {
res: _ObjectChangeHandler(res, obj_class, self._rpc_pusher)

View File

@ -17,6 +17,7 @@ from neutron_lib import context
from neutron_lib.db import api as db_api
from neutron_lib.plugins import directory
from neutron.objects import address_group
from neutron.objects import network
from neutron.objects import securitygroup
from neutron.objects import subnet
@ -101,3 +102,20 @@ class OVOServerRpcInterfaceTestCase(test_plugin.Ml2PluginV2TestCase):
'description': 'desc',
'name': 'test'}})
self.assertEqual([], self.received)
def test_address_group_lifecycle(self):
ag = self.plugin.create_address_group(self.ctx,
{'address_group': {'project_id': self._tenant_id,
'name': 'an-address-group',
'description': 'An address group',
'addresses': ['10.0.0.1/32',
'2001:db8::/32']}})
self._assert_object_received(
address_group.AddressGroup, ag['id'], 'updated')
self.plugin.update_address_group(self.ctx, ag['id'],
{'address_group': {'name': 'an-address-group-other-name'}})
self._assert_object_received(
address_group.AddressGroup, ag['id'], 'updated')
self.plugin.delete_address_group(self.ctx, ag['id'])
self._assert_object_received(
address_group.AddressGroup, ag['id'], 'deleted')