]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
call security_groups_member_updated in port_update
authorXu Chen <xchenum@gmail.com>
Thu, 19 Jun 2014 19:01:33 +0000 (15:01 -0400)
committerXu Chen <xchenum@gmail.com>
Mon, 21 Jul 2014 18:22:09 +0000 (14:22 -0400)
When a running VM is added to a security group, all existing VMs (ports)
in the security group should be notified/updated - otherwise they would
have incorrect rules, not knowing the new VM/port added.

The current behavior would only update the port of the added VM. This
patch forces an security_groups_member_updated() call for all the
security groups that have ports removed or added.

Change-Id: Ibdcd74f47043762386b62f3ec0fa1723060446ac
Closes-Bug: 1316618

neutron/plugins/openvswitch/ovs_neutron_plugin.py
neutron/tests/unit/openvswitch/test_openvswitch_plugin.py

index 005fb308b7ba2c35222eb50a064d1d75ae749c3a..3b86238c7488640112cea9de2f51c6e18df8501a 100644 (file)
@@ -44,6 +44,7 @@ from neutron.extensions import allowedaddresspairs as addr_pair
 from neutron.extensions import extra_dhcp_opt as edo_ext
 from neutron.extensions import portbindings
 from neutron.extensions import providernet as provider
+from neutron.extensions import securitygroup as ext_sg
 from neutron import manager
 from neutron.openstack.common import importutils
 from neutron.openstack.common import log as logging
@@ -603,8 +604,9 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             need_port_update_notify |= self._update_extra_dhcp_opts_on_port(
                 context, id, port, updated_port)
 
-        need_port_update_notify |= self.is_security_group_member_updated(
+        secgrp_member_updated = self.is_security_group_member_updated(
             context, original_port, updated_port)
+        need_port_update_notify |= secgrp_member_updated
         if original_port['admin_state_up'] != updated_port['admin_state_up']:
             need_port_update_notify = True
 
@@ -615,6 +617,14 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                                       binding.network_type,
                                       binding.segmentation_id,
                                       binding.physical_network)
+
+        if secgrp_member_updated:
+            old_set = set(original_port.get(ext_sg.SECURITYGROUPS))
+            new_set = set(updated_port.get(ext_sg.SECURITYGROUPS))
+            self.notifier.security_groups_member_updated(
+                context,
+                old_set ^ new_set)
+
         return updated_port
 
     def delete_port(self, context, id, l3_port_check=True):
index 234a8feb82ea4a905b31cb496fe4e1e2f97d7777..af1c1d0425f546cfa641b7b81f4cccebc9ac6714 100644 (file)
 
 from oslo.config import cfg
 
+from neutron import context
 from neutron.extensions import portbindings
+from neutron.extensions import securitygroup as ext_sg
+from neutron.plugins.openvswitch import ovs_neutron_plugin
 from neutron.tests.unit import _test_extension_portbindings as test_bindings
 from neutron.tests.unit import test_db_plugin as test_plugin
 from neutron.tests.unit import test_extension_allowedaddresspairs as test_pair
 from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc
 
+import mock
+
 
 class OpenvswitchPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
 
@@ -86,3 +91,69 @@ class TestOpenvswitchPortBindingHost(
 class TestOpenvswitchAllowedAddressPairs(OpenvswitchPluginV2TestCase,
                                          test_pair.TestAllowedAddressPairs):
     pass
+
+
+class TestOpenvswitchUpdatePort(OpenvswitchPluginV2TestCase,
+                                ovs_neutron_plugin.OVSNeutronPluginV2):
+
+    def test_update_port_add_remove_security_group(self):
+        get_port_func = (
+            'neutron.db.db_base_plugin_v2.'
+            'NeutronDbPluginV2.get_port'
+        )
+        with mock.patch(get_port_func) as mock_get_port:
+            mock_get_port.return_value = {
+                ext_sg.SECURITYGROUPS: ["sg1", "sg2"],
+                "admin_state_up": True,
+                "fixed_ips": "fake_ip",
+                "network_id": "fake_id"}
+
+            update_port_func = (
+                'neutron.db.db_base_plugin_v2.'
+                'NeutronDbPluginV2.update_port'
+            )
+            with mock.patch(update_port_func) as mock_update_port:
+                mock_update_port.return_value = {
+                    ext_sg.SECURITYGROUPS: ["sg2", "sg3"],
+                    "admin_state_up": True,
+                    "fixed_ips": "fake_ip",
+                    "network_id": "fake_id"}
+
+                fake_func = (
+                    'neutron.plugins.openvswitch.'
+                    'ovs_db_v2.get_network_binding'
+                )
+                with mock.patch(fake_func) as mock_func:
+                    class MockBinding:
+                        network_type = "fake"
+                        segmentation_id = "fake"
+                        physical_network = "fake"
+
+                    mock_func.return_value = MockBinding()
+
+                    ctx = context.Context('', 'somebody')
+                    self.update_port(ctx, "id", {
+                        "port": {
+                            ext_sg.SECURITYGROUPS: [
+                                "sg2", "sg3"]}})
+
+                    sgmu = self.notifier.security_groups_member_updated
+                    sgmu.assert_called_with(ctx, set(['sg1', 'sg3']))
+
+    def setUp(self):
+        super(TestOpenvswitchUpdatePort, self).setUp()
+        self.update_security_group_on_port = mock.MagicMock(return_value=True)
+        self._process_portbindings_create_and_update = mock.MagicMock(
+            return_value=True)
+        self._update_extra_dhcp_opts_on_port = mock.MagicMock(
+            return_value=True)
+        self.update_address_pairs_on_port = mock.MagicMock(
+            return_value=True)
+
+        class MockNotifier:
+            def __init__(self):
+                self.port_update = mock.MagicMock(return_value=True)
+                self.security_groups_member_updated = mock.MagicMock(
+                    return_value=True)
+
+        self.notifier = MockNotifier()