]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Security groups extension for PLUMgrid plugin
authorFawad Khaliq <fawad@plumgrid.com>
Tue, 8 Jul 2014 18:10:12 +0000 (11:10 -0700)
committerFawad Khaliq <fawad@plumgrid.com>
Mon, 14 Jul 2014 06:48:27 +0000 (23:48 -0700)
This patch includes immplementation of security groups
extension in PLUMgrid plugin.

APIs include CRUD operations for security groups
and security group rules.

Added unit tests.

Implements: blueprint plumgrid-plugin-security-groups
Change-Id: I23fea3fe6c3abbe310e883e00706b93863db3bfb

neutron/plugins/plumgrid/drivers/fake_plumlib.py
neutron/plugins/plumgrid/drivers/plumlib.py
neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py
neutron/tests/unit/plumgrid/extensions/__init__.py [new file with mode: 0644]
neutron/tests/unit/plumgrid/extensions/test_securitygroups.py [new file with mode: 0644]
neutron/tests/unit/plumgrid/test_plumgrid_plugin.py

index 16ce799fcf654f20b135bad5720c07e4f860494b..dab2a99a06cb4432f79c15488133c2f1d4828c81 100644 (file)
@@ -96,3 +96,21 @@ class Plumlib():
     def disassociate_floatingips(self, fip, port_id):
         return dict((key, fip[key]) for key in ("id", "floating_network_id",
                                                 "floating_ip_address"))
+
+    def create_security_group(self, sg_db):
+        pass
+
+    def update_security_group(self, sg_db):
+        pass
+
+    def delete_security_group(self, sg_db):
+        pass
+
+    def create_security_group_rule(self, sg_rule_db):
+        pass
+
+    def create_security_group_rule_bulk(self, sg_rule_db):
+        pass
+
+    def delete_security_group_rule(self, sg_rule_db):
+        pass
index e0c59dd56671caec434e96c8eb0827365e27a026..ba241f4b360c3df1fe793173ece4127c8dd72ecb 100644 (file)
@@ -97,3 +97,21 @@ class Plumlib(object):
 
     def disassociate_floatingips(self, floating_ip, port_id):
         self.plumlib.disassociate_floatingips(floating_ip, port_id)
+
+    def create_security_group(self, sg_db):
+        self.plumlib.create_security_group(sg_db)
+
+    def update_security_group(self, sg_db):
+        self.plumlib.update_security_group(sg_db)
+
+    def delete_security_group(self, sg_db):
+        self.plumlib.delete_security_group(sg_db)
+
+    def create_security_group_rule(self, sg_rule_db):
+        self.plumlib.create_security_group_rule(sg_rule_db)
+
+    def create_security_group_rule_bulk(self, sg_rule_db):
+        self.plumlib.create_security_group_rule_bulk(sg_rule_db)
+
+    def delete_security_group_rule(self, sg_rule_db):
+        self.plumlib.delete_security_group_rule(sg_rule_db)
index 32177fdfc0f5bb4bfd22a2e6ed7feb8d74b37294..5e1aed5552eb38f1f6804af153ac0269fe6f93dc 100644 (file)
@@ -31,7 +31,9 @@ from neutron.db import external_net_db
 from neutron.db import l3_db
 from neutron.db import portbindings_db
 from neutron.db import quota_db  # noqa
+from neutron.db import securitygroups_db
 from neutron.extensions import portbindings
+from neutron.extensions import securitygroup as sec_grp
 from neutron.openstack.common import importutils
 from neutron.openstack.common import log as logging
 from neutron.plugins.plumgrid.common import exceptions as plum_excep
@@ -58,12 +60,13 @@ cfg.CONF.register_opts(director_server_opts, "plumgriddirector")
 
 
 class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
-                              portbindings_db.PortBindingMixin,
                               external_net_db.External_net_db_mixin,
-                              l3_db.L3_NAT_db_mixin):
+                              l3_db.L3_NAT_db_mixin,
+                              portbindings_db.PortBindingMixin,
+                              securitygroups_db.SecurityGroupDbMixin):
 
-    supported_extension_aliases = ["external-net", "router", "binding",
-                                   "quotas", "provider"]
+    supported_extension_aliases = ["binding", "external-net", "provider",
+                                   "quotas", "router", "security-group"]
 
     binding_view = "extension:port_binding:view"
     binding_set = "extension:port_binding:set"
@@ -74,8 +77,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         super(NeutronPluginPLUMgridV2, self).__init__()
         self.plumgrid_init()
 
-        LOG.debug(_('Neutron PLUMgrid Director: Neutron server with '
-                    'PLUMgrid Plugin has started'))
+        LOG.debug('Neutron PLUMgrid Director: Neutron server with '
+                  'PLUMgrid Plugin has started')
 
     def plumgrid_init(self):
         """PLUMgrid initialization."""
@@ -98,7 +101,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Creates a PLUMgrid-based bridge.
         """
 
-        LOG.debug(_('Neutron PLUMgrid Director: create_network() called'))
+        LOG.debug('Neutron PLUMgrid Director: create_network() called')
 
         # Plugin DB - Network Create and validation
         tenant_id = self._get_tenant_id_for_create(context,
@@ -110,9 +113,10 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                            self).create_network(context, network)
             # Propagate all L3 data into DB
             self._process_l3_create(context, net_db, network['network'])
+            self._ensure_default_security_group(context, tenant_id)
 
             try:
-                LOG.debug(_('PLUMgrid Library: create_network() called'))
+                LOG.debug('PLUMgrid Library: create_network() called')
                 self._plumlib.create_network(tenant_id, net_db, network)
 
             except Exception as err_message:
@@ -127,7 +131,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Updates a PLUMgrid-based bridge.
         """
 
-        LOG.debug(_("Neutron PLUMgrid Director: update_network() called"))
+        LOG.debug("Neutron PLUMgrid Director: update_network() called")
         self._network_admin_state(network)
         tenant_id = self._get_tenant_id_for_create(context, network["network"])
 
@@ -139,7 +143,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
             self._process_l3_update(context, net_db, network['network'])
 
             try:
-                LOG.debug(_("PLUMgrid Library: update_network() called"))
+                LOG.debug("PLUMgrid Library: update_network() called")
                 self._plumlib.update_network(tenant_id, net_id)
 
             except Exception as err_message:
@@ -154,7 +158,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Deletes a PLUMgrid-based bridge.
         """
 
-        LOG.debug(_("Neutron PLUMgrid Director: delete_network() called"))
+        LOG.debug("Neutron PLUMgrid Director: delete_network() called")
         net_db = super(NeutronPluginPLUMgridV2,
                        self).get_network(context, net_id)
 
@@ -165,7 +169,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                                                                 net_id)
 
             try:
-                LOG.debug(_("PLUMgrid Library: update_network() called"))
+                LOG.debug("PLUMgrid Library: update_network() called")
                 self._plumlib.delete_network(net_db, net_id)
 
             except Exception as err_message:
@@ -177,18 +181,33 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Creates a PLUMgrid-based port on the specific Virtual Network
         Function (VNF).
         """
-        LOG.debug(_("Neutron PLUMgrid Director: create_port() called"))
+        LOG.debug("Neutron PLUMgrid Director: create_port() called")
 
         # Port operations on PLUMgrid Director is an automatic operation
         # from the VIF driver operations in Nova.
         # It requires admin_state_up to be True
 
         port["port"]["admin_state_up"] = True
+        port_data = port["port"]
 
         with context.session.begin(subtransactions=True):
             # Plugin DB - Port Create and Return port
             port_db = super(NeutronPluginPLUMgridV2, self).create_port(context,
                                                                        port)
+            # Update port security
+            port_data.update(port_db)
+
+            self._ensure_default_security_group_on_port(context, port)
+
+            port_data[sec_grp.SECURITYGROUPS] = (
+                self._get_security_groups_on_port(context, port))
+
+            self._process_port_create_security_group(
+                context, port_db, port_data[sec_grp.SECURITYGROUPS])
+
+            self._process_portbindings_create_and_update(context,
+                                                         port_data, port_db)
+
             device_id = port_db["device_id"]
             if port_db["device_owner"] == constants.DEVICE_OWNER_ROUTER_GW:
                 router_db = self._get_router(context, device_id)
@@ -196,7 +215,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                 router_db = None
 
             try:
-                LOG.debug(_("PLUMgrid Library: create_port() called"))
+                LOG.debug("PLUMgrid Library: create_port() called")
                 self._plumlib.create_port(port_db, router_db)
 
             except Exception as err_message:
@@ -211,7 +230,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Updates a PLUMgrid-based port on the specific Virtual Network
         Function (VNF).
         """
-        LOG.debug(_("Neutron PLUMgrid Director: update_port() called"))
+        LOG.debug("Neutron PLUMgrid Director: update_port() called")
 
         with context.session.begin(subtransactions=True):
             # Plugin DB - Port Create and Return port
@@ -222,8 +241,22 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                 router_db = self._get_router(context, device_id)
             else:
                 router_db = None
+
+            if (self._check_update_deletes_security_groups(port) or
+                    self._check_update_has_security_groups(port)):
+                self._delete_port_security_group_bindings(context,
+                                                          port_db["id"])
+                sg_ids = self._get_security_groups_on_port(context, port)
+                self._process_port_create_security_group(context,
+                                                         port_db,
+                                                         sg_ids)
+
+            self._process_portbindings_create_and_update(context,
+                                                         port['port'],
+                                                         port_db)
+
             try:
-                LOG.debug(_("PLUMgrid Library: create_port() called"))
+                LOG.debug("PLUMgrid Library: create_port() called")
                 self._plumlib.update_port(port_db, router_db)
 
             except Exception as err_message:
@@ -239,7 +272,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Function (VNF).
         """
 
-        LOG.debug(_("Neutron PLUMgrid Director: delete_port() called"))
+        LOG.debug("Neutron PLUMgrid Director: delete_port() called")
 
         with context.session.begin(subtransactions=True):
             # Plugin DB - Port Create and Return port
@@ -255,7 +288,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
             else:
                 router_db = None
             try:
-                LOG.debug(_("PLUMgrid Library: delete_port() called"))
+                LOG.debug("PLUMgrid Library: delete_port() called")
                 self._plumlib.delete_port(port_db, router_db)
 
             except Exception as err_message:
@@ -287,7 +320,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         Functions (VNFs).
         """
 
-        LOG.debug(_("Neutron PLUMgrid Director: create_subnet() called"))
+        LOG.debug("Neutron PLUMgrid Director: create_subnet() called")
 
         with context.session.begin(subtransactions=True):
             # Plugin DB - Subnet Create
@@ -311,7 +344,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                 context, subnet)
 
             try:
-                LOG.debug(_("PLUMgrid Library: create_subnet() called"))
+                LOG.debug("PLUMgrid Library: create_subnet() called")
                 self._plumlib.create_subnet(sub_db, net_db, ipnet)
             except Exception as err_message:
                 raise plum_excep.PLUMgridException(err_msg=err_message)
@@ -321,7 +354,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
     def delete_subnet(self, context, subnet_id):
         """Delete subnet core Neutron API."""
 
-        LOG.debug(_("Neutron PLUMgrid Director: delete_subnet() called"))
+        LOG.debug("Neutron PLUMgrid Director: delete_subnet() called")
         # Collecting subnet info
         sub_db = self._get_subnet(context, subnet_id)
         tenant_id = self._get_tenant_id_for_create(context, subnet_id)
@@ -333,7 +366,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
             super(NeutronPluginPLUMgridV2, self).delete_subnet(
                 context, subnet_id)
             try:
-                LOG.debug(_("PLUMgrid Library: delete_subnet() called"))
+                LOG.debug("PLUMgrid Library: delete_subnet() called")
                 self._plumlib.delete_subnet(tenant_id, net_db, net_id)
             except Exception as err_message:
                 raise plum_excep.PLUMgridException(err_msg=err_message)
@@ -341,7 +374,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
     def update_subnet(self, context, subnet_id, subnet):
         """Update subnet core Neutron API."""
 
-        LOG.debug(_("update_subnet() called"))
+        LOG.debug("update_subnet() called")
         # Collecting subnet info
         orig_sub_db = self._get_subnet(context, subnet_id)
 
@@ -353,7 +386,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
 
             try:
                 # PLUMgrid Server does not support updating resources yet
-                LOG.debug(_("PLUMgrid Library: update_network() called"))
+                LOG.debug("PLUMgrid Library: update_network() called")
                 self._plumlib.update_subnet(orig_sub_db, new_sub_db, ipnet)
 
             except Exception as err_message:
@@ -365,7 +398,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         """
         Create router extension Neutron API
         """
-        LOG.debug(_("Neutron PLUMgrid Director: create_router() called"))
+        LOG.debug("Neutron PLUMgrid Director: create_router() called")
 
         tenant_id = self._get_tenant_id_for_create(context, router["router"])
 
@@ -377,7 +410,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
             # Create router on the network controller
             try:
                 # Add Router to VND
-                LOG.debug(_("PLUMgrid Library: create_router() called"))
+                LOG.debug("PLUMgrid Library: create_router() called")
                 self._plumlib.create_router(tenant_id, router_db)
             except Exception as err_message:
                 raise plum_excep.PLUMgridException(err_msg=err_message)
@@ -387,13 +420,13 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
 
     def update_router(self, context, router_id, router):
 
-        LOG.debug(_("Neutron PLUMgrid Director: update_router() called"))
+        LOG.debug("Neutron PLUMgrid Director: update_router() called")
 
         with context.session.begin(subtransactions=True):
             router_db = super(NeutronPluginPLUMgridV2,
                               self).update_router(context, router_id, router)
             try:
-                LOG.debug(_("PLUMgrid Library: update_router() called"))
+                LOG.debug("PLUMgrid Library: update_router() called")
                 self._plumlib.update_router(router_db, router_id)
             except Exception as err_message:
                 raise plum_excep.PLUMgridException(err_msg=err_message)
@@ -402,7 +435,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         return router_db
 
     def delete_router(self, context, router_id):
-        LOG.debug(_("Neutron PLUMgrid Director: delete_router() called"))
+        LOG.debug("Neutron PLUMgrid Director: delete_router() called")
 
         with context.session.begin(subtransactions=True):
             orig_router = self._get_router(context, router_id)
@@ -412,7 +445,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                                                                router_id)
 
             try:
-                LOG.debug(_("PLUMgrid Library: delete_router() called"))
+                LOG.debug("PLUMgrid Library: delete_router() called")
                 self._plumlib.delete_router(tenant_id, router_id)
 
             except Exception as err_message:
@@ -420,8 +453,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
 
     def add_router_interface(self, context, router_id, interface_info):
 
-        LOG.debug(_("Neutron PLUMgrid Director: "
-                    "add_router_interface() called"))
+        LOG.debug("Neutron PLUMgrid Director: "
+                  "add_router_interface() called")
         with context.session.begin(subtransactions=True):
             # Validate args
             router_db = self._get_router(context, router_id)
@@ -440,7 +473,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
 
             # Create interface on the network controller
             try:
-                LOG.debug(_("PLUMgrid Library: add_router_interface() called"))
+                LOG.debug("PLUMgrid Library: add_router_interface() called")
                 self._plumlib.add_router_interface(tenant_id, router_id,
                                                    port_db, ipnet)
 
@@ -451,8 +484,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
 
     def remove_router_interface(self, context, router_id, int_info):
 
-        LOG.debug(_("Neutron PLUMgrid Director: "
-                    "remove_router_interface() called"))
+        LOG.debug("Neutron PLUMgrid Director: remove_router_interface()"
+                  " called")
         with context.session.begin(subtransactions=True):
             # Validate args
             router_db = self._get_router(context, router_id)
@@ -473,8 +506,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                                                                  int_info)
 
             try:
-                LOG.debug(_("PLUMgrid Library: "
-                            "remove_router_interface() called"))
+                LOG.debug("PLUMgrid Library: "
+                          "remove_router_interface() called")
                 self._plumlib.remove_router_interface(tenant_id,
                                                       net_id, router_id)
 
@@ -484,14 +517,14 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         return del_int_router
 
     def create_floatingip(self, context, floatingip):
-        LOG.debug(_("Neutron PLUMgrid Director: create_floatingip() called"))
+        LOG.debug("Neutron PLUMgrid Director: create_floatingip() called")
 
         with context.session.begin(subtransactions=True):
 
             floating_ip = super(NeutronPluginPLUMgridV2,
                                 self).create_floatingip(context, floatingip)
             try:
-                LOG.debug(_("PLUMgrid Library: create_floatingip() called"))
+                LOG.debug("PLUMgrid Library: create_floatingip() called")
                 self._plumlib.create_floatingip(floating_ip)
 
             except Exception as err_message:
@@ -500,7 +533,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         return floating_ip
 
     def update_floatingip(self, context, id, floatingip):
-        LOG.debug(_("Neutron PLUMgrid Director: update_floatingip() called"))
+        LOG.debug("Neutron PLUMgrid Director: update_floatingip() called")
 
         with context.session.begin(subtransactions=True):
             floating_ip_orig = super(NeutronPluginPLUMgridV2,
@@ -509,7 +542,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                                 self).update_floatingip(context, id,
                                                         floatingip)
             try:
-                LOG.debug(_("PLUMgrid Library: update_floatingip() called"))
+                LOG.debug("PLUMgrid Library: update_floatingip() called")
                 self._plumlib.update_floatingip(floating_ip_orig, floating_ip,
                                                 id)
 
@@ -519,7 +552,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
         return floating_ip
 
     def delete_floatingip(self, context, id):
-        LOG.debug(_("Neutron PLUMgrid Director: delete_floatingip() called"))
+        LOG.debug("Neutron PLUMgrid Director: delete_floatingip() called")
 
         with context.session.begin(subtransactions=True):
 
@@ -529,22 +562,22 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
             super(NeutronPluginPLUMgridV2, self).delete_floatingip(context, id)
 
             try:
-                LOG.debug(_("PLUMgrid Library: delete_floatingip() called"))
+                LOG.debug("PLUMgrid Library: delete_floatingip() called")
                 self._plumlib.delete_floatingip(floating_ip_orig, id)
 
             except Exception as err_message:
                 raise plum_excep.PLUMgridException(err_msg=err_message)
 
     def disassociate_floatingips(self, context, port_id, do_notify=True):
-        LOG.debug(_("Neutron PLUMgrid Director: disassociate_floatingips() "
-                    "called"))
+        LOG.debug("Neutron PLUMgrid Director: disassociate_floatingips() "
+                  "called")
 
         try:
             fip_qry = context.session.query(l3_db.FloatingIP)
             floating_ip = fip_qry.filter_by(fixed_port_id=port_id).one()
 
-            LOG.debug(_("PLUMgrid Library: disassociate_floatingips()"
-                        " called"))
+            LOG.debug("PLUMgrid Library: disassociate_floatingips()"
+                      " called")
             self._plumlib.disassociate_floatingips(floating_ip, port_id)
 
         except sa_exc.NoResultFound:
@@ -557,6 +590,166 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                      self).disassociate_floatingips(
                              context, port_id, do_notify=do_notify)
 
+    def create_security_group(self, context, security_group, default_sg=False):
+        """Create a security group
+
+        Create a new security group, including the default security group
+        """
+        LOG.debug("Neutron PLUMgrid Director: create_security_group()"
+                  " called")
+
+        with context.session.begin(subtransactions=True):
+
+            sg = security_group.get('security_group')
+
+            tenant_id = self._get_tenant_id_for_create(context, sg)
+            if not default_sg:
+                self._ensure_default_security_group(context, tenant_id)
+
+            sg_db = super(NeutronPluginPLUMgridV2,
+                          self).create_security_group(context, security_group,
+                                                      default_sg)
+            try:
+                LOG.debug("PLUMgrid Library: create_security_group()"
+                          " called")
+                self._plumlib.create_security_group(sg_db)
+
+            except Exception as err_message:
+                raise plum_excep.PLUMgridException(err_msg=err_message)
+
+        return sg_db
+
+    def update_security_group(self, context, sg_id, security_group):
+        """Update a security group
+
+        Update security group name/description in Neutron and PLUMgrid
+        platform
+        """
+        with context.session.begin(subtransactions=True):
+            sg_db = (super(NeutronPluginPLUMgridV2,
+                           self).update_security_group(context,
+                                                       sg_id,
+                                                       security_group))
+            if ('name' in security_group['security_group'] and
+                sg_db['name'] != 'default'):
+                try:
+                    LOG.debug("PLUMgrid Library: update_security_group()"
+                              " called")
+                    self._plumlib.update_security_group(sg_db)
+
+                except Exception as err_message:
+                    raise plum_excep.PLUMgridException(err_msg=err_message)
+            return sg_db
+
+    def delete_security_group(self, context, sg_id):
+        """Delete a security group
+
+        Delete security group from Neutron and PLUMgrid Platform
+
+        :param sg_id: security group ID of the rule to be removed
+        """
+        with context.session.begin(subtransactions=True):
+
+            sg = super(NeutronPluginPLUMgridV2, self).get_security_group(
+                context, sg_id)
+            if not sg:
+                raise sec_grp.SecurityGroupNotFound(id=sg_id)
+
+            if sg['name'] == 'default' and not context.is_admin:
+                raise sec_grp.SecurityGroupCannotRemoveDefault()
+
+            sec_grp_ip = sg['id']
+            filters = {'security_group_id': [sec_grp_ip]}
+            if super(NeutronPluginPLUMgridV2,
+                     self)._get_port_security_group_bindings(context,
+                                                             filters):
+                raise sec_grp.SecurityGroupInUse(id=sec_grp_ip)
+
+            sec_db = super(NeutronPluginPLUMgridV2,
+                           self).delete_security_group(context, sg_id)
+            try:
+                LOG.debug("PLUMgrid Library: delete_security_group()"
+                          " called")
+                self._plumlib.delete_security_group(sg)
+
+            except Exception as err_message:
+                raise plum_excep.PLUMgridException(err_msg=err_message)
+
+            return sec_db
+
+    def create_security_group_rule(self, context, security_group_rule):
+        """Create a security group rule
+
+        Create a security group rule in Neutron and PLUMgrid Platform
+        """
+        LOG.debug("Neutron PLUMgrid Director: create_security_group_rule()"
+                  " called")
+        bulk_rule = {'security_group_rules': [security_group_rule]}
+        return self.create_security_group_rule_bulk(context, bulk_rule)[0]
+
+    def create_security_group_rule_bulk(self, context, security_group_rule):
+        """Create security group rules
+
+        Create security group rules in Neutron and PLUMgrid Platform
+
+        :param security_group_rule: list of rules to create
+        """
+        sg_rules = security_group_rule.get('security_group_rules')
+
+        with context.session.begin(subtransactions=True):
+            sg_id = super(NeutronPluginPLUMgridV2,
+                          self)._validate_security_group_rules(
+                          context, security_group_rule)
+
+            # Check to make sure security group exists
+            security_group = super(NeutronPluginPLUMgridV2,
+                                   self).get_security_group(context,
+                                                            sg_id)
+
+            if not security_group:
+                raise sec_grp.SecurityGroupNotFound(id=sg_id)
+
+            # Check for duplicate rules
+            self._check_for_duplicate_rules(context, sg_rules)
+
+            sec_db = (super(NeutronPluginPLUMgridV2,
+                            self).create_security_group_rule_bulk_native(
+                            context, security_group_rule))
+            try:
+                LOG.debug("PLUMgrid Library: create_security_"
+                          "group_rule_bulk() called")
+                self._plumlib.create_security_group_rule_bulk(sec_db)
+
+            except Exception as err_message:
+                raise plum_excep.PLUMgridException(err_msg=err_message)
+
+            return sec_db
+
+    def delete_security_group_rule(self, context, sgr_id):
+        """Delete a security group rule
+
+        Delete a security group rule in Neutron and PLUMgrid Platform
+        """
+
+        LOG.debug("Neutron PLUMgrid Director: delete_security_group_rule()"
+                  " called")
+
+        sgr = (super(NeutronPluginPLUMgridV2,
+                     self).get_security_group_rule(context, sgr_id))
+
+        if not sgr:
+            raise sec_grp.SecurityGroupRuleNotFound(id=sgr_id)
+
+        super(NeutronPluginPLUMgridV2,
+              self).delete_security_group_rule(context, sgr_id)
+        try:
+            LOG.debug("PLUMgrid Library: delete_security_"
+                      "group_rule() called")
+            self._plumlib.delete_security_group_rule(sgr)
+
+        except Exception as err_message:
+            raise plum_excep.PLUMgridException(err_msg=err_message)
+
     """
     Internal PLUMgrid Fuctions
     """
diff --git a/neutron/tests/unit/plumgrid/extensions/__init__.py b/neutron/tests/unit/plumgrid/extensions/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/neutron/tests/unit/plumgrid/extensions/test_securitygroups.py b/neutron/tests/unit/plumgrid/extensions/test_securitygroups.py
new file mode 100644 (file)
index 0000000..702549d
--- /dev/null
@@ -0,0 +1,67 @@
+# Copyright 2014 PLUMgrid, Inc. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+"""
+PLUMgrid plugin security group extension unit tests
+"""
+
+import mock
+
+from neutron.openstack.common import importutils
+from neutron.plugins.plumgrid.plumgrid_plugin import plumgrid_plugin
+from neutron.tests.unit import test_extension_security_group as ext_sg
+
+
+PLUM_DRIVER = ('neutron.plugins.plumgrid.drivers.fake_plumlib.Plumlib')
+FAKE_DIRECTOR = '1.1.1.1'
+FAKE_PORT = '1234'
+FAKE_USERNAME = 'fake_admin'
+FAKE_PASSWORD = 'fake_password'
+FAKE_TIMEOUT = '0'
+
+
+class SecurityGroupsTestCase(ext_sg.SecurityGroupDBTestCase):
+    _plugin_name = ('neutron.plugins.plumgrid.plumgrid_plugin.'
+                    'plumgrid_plugin.NeutronPluginPLUMgridV2')
+
+    def setUp(self):
+        def mocked_plumlib_init(self):
+            director_plumgrid = FAKE_DIRECTOR
+            director_port = FAKE_PORT
+            director_username = FAKE_USERNAME
+            director_password = FAKE_PASSWORD
+            timeout = FAKE_TIMEOUT
+            self._plumlib = importutils.import_object(PLUM_DRIVER)
+            self._plumlib.director_conn(director_plumgrid,
+                                        director_port, timeout,
+                                        director_username,
+                                        director_password)
+
+        with mock.patch.object(plumgrid_plugin.NeutronPluginPLUMgridV2,
+                               'plumgrid_init', new=mocked_plumlib_init):
+            super(SecurityGroupsTestCase, self).setUp(self._plugin_name)
+
+    def tearDown(self):
+        super(SecurityGroupsTestCase, self).tearDown()
+
+
+class TestSecurityGroups(ext_sg.TestSecurityGroups, SecurityGroupsTestCase):
+
+    pass
+
+
+class TestSecurityGroupsXML(TestSecurityGroups):
+
+    fmt = 'xml'
index 83daf2d809079ce4d20850a244ced5e8a2d39d92..7a1a6a7a00e3bfb342a4795048f081625429bce0 100644 (file)
@@ -96,6 +96,7 @@ class TestPlumgridPluginSubnetsV2(test_plugin.TestSubnetsV2,
 class TestPlumgridPluginPortBinding(PLUMgridPluginV2TestCase,
                                     test_bindings.PortBindingsTestCase):
     VIF_TYPE = portbindings.VIF_TYPE_IOVISOR
+    HAS_PORT_FILTER = True
 
     def setUp(self):
         super(TestPlumgridPluginPortBinding, self).setUp()