--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 OpenStack Foundation
+#
+# 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.
+#
+
+"""nvp fwaas plugin
+
+Revision ID: 3ed8f075e38a
+Revises: 338d7508968c
+Create Date: 2013-09-13 19:14:25.509033
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3ed8f075e38a'
+down_revision = '338d7508968c'
+
+# Change to ['*'] if this migration applies to all plugins
+
+migration_for_plugins = [
+ 'neutron.plugins.nicira.NeutronServicePlugin.NvpAdvancedPlugin'
+]
+
+from alembic import op
+import sqlalchemy as sa
+
+from neutron.db import migration
+
+
+def upgrade(active_plugins=None, options=None):
+ if not migration.should_run(active_plugins, migration_for_plugins):
+ return
+
+ op.create_table(
+ 'vcns_firewall_rule_bindings',
+ sa.Column('rule_id', sa.String(length=36), nullable=False),
+ sa.Column('edge_id', sa.String(length=36), nullable=False),
+ sa.Column('rule_vseid', sa.String(length=36), nullable=True),
+ sa.ForeignKeyConstraint(['rule_id'], ['firewall_rules.id'], ),
+ sa.PrimaryKeyConstraint('rule_id', 'edge_id')
+ )
+
+
+def downgrade(active_plugins=None, options=None):
+ if not migration.should_run(active_plugins, migration_for_plugins):
+ return
+
+ op.drop_table('vcns_firewall_rule_bindings')
context, resource['resource_id'], model)
resource[rsi.ROUTER_ID] = binding['router_id']
- def _get_resource_router_id_binding(self, context, resource_id, model):
+ def _get_resource_router_id_binding(self, context, model,
+ resource_id=None,
+ router_id=None):
query = self._model_query(context, ServiceRouterBinding)
query = query.filter(
- ServiceRouterBinding.resource_id == resource_id,
ServiceRouterBinding.resource_type == model.__tablename__)
+ if resource_id:
+ query = query.filter(
+ ServiceRouterBinding.resource_id == resource_id)
+ if router_id:
+ query = query.filter(
+ ServiceRouterBinding.router_id == router_id)
return query.first()
+ def _get_resource_router_id_bindings(self, context, model,
+ resource_ids=None,
+ router_ids=None):
+ query = self._model_query(context, ServiceRouterBinding)
+ query = query.filter(
+ ServiceRouterBinding.resource_type == model.__tablename__)
+ if resource_ids:
+ query = query.filter(
+ ServiceRouterBinding.resource_id.in_(resource_ids))
+ if router_ids:
+ query = query.filter(
+ ServiceRouterBinding.router_id.in_(router_ids))
+ return query.all()
+
def _make_resource_router_id_dict(self, resource_router_binding, model,
fields=None):
resource = {'resource_id': resource_router_binding['resource_id'],
def _delete_resource_router_id_binding(self, context, resource_id, model):
with context.session.begin(subtransactions=True):
binding = self._get_resource_router_id_binding(
- context, resource_id, model)
+ context, model, resource_id=resource_id)
if binding:
context.session.delete(binding)
'validate': {'type:uuid_or_none': None},
'default': None, 'is_visible': True},
},
+
+ 'firewalls': {
+ ROUTER_ID: {'allow_post': True, 'allow_put': False,
+ 'validate': {'type:uuid_or_none': None},
+ 'default': None, 'is_visible': True},
+ }
}
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
+ # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 VMware, Inc.
# All Rights Reserved
import netaddr
from oslo.config import cfg
-from sqlalchemy.orm import exc as sa_exc
from neutron.common import exceptions as q_exc
+from neutron.db.firewall import firewall_db
from neutron.db import l3_db
+from neutron.db import routedserviceinsertion_db as rsi_db
+from neutron.extensions import firewall as fw_ext
from neutron.openstack.common import log as logging
from neutron.plugins.common import constants as service_constants
from neutron.plugins.nicira.common import config # noqa
+from neutron.plugins.nicira.common import exceptions as nvp_exc
from neutron.plugins.nicira.dbexts import servicerouter as sr_db
from neutron.plugins.nicira.dbexts import vcns_db
from neutron.plugins.nicira.dbexts import vcns_models
from neutron.plugins.nicira.vshield.common import exceptions
from neutron.plugins.nicira.vshield.tasks.constants import TaskStatus
from neutron.plugins.nicira.vshield import vcns_driver
+from sqlalchemy.orm import exc as sa_exc
LOG = logging.getLogger(__name__)
class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
- NeutronPlugin.NvpPluginV2):
-
+ NeutronPlugin.NvpPluginV2,
+ rsi_db.RoutedServiceInsertionDbMixin,
+ firewall_db.Firewall_db_mixin,
+ ):
supported_extension_aliases = (
NeutronPlugin.NvpPluginV2.supported_extension_aliases + [
- 'service-router'
+ "service-router",
+ "routed-service-insertion",
+ "fwaas"
])
def __init__(self):
router = self._get_router(context, router_id)
if router.enable_snat:
self._update_nat_rules(context, router)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._vcns_update_static_routes(context, router=router)
return info
router = self._get_router(context, router_id)
if router.enable_snat:
self._update_nat_rules(context, router)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._vcns_update_static_routes(context, router=router)
return info
router_id = fip.get('router_id')
if router_id and self._is_advanced_service_router(context, router_id):
router = self._get_router(context, router_id)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._update_interface(context, router)
self._update_nat_rules(context, router)
router_id = fip.get('router_id')
if router_id and self._is_advanced_service_router(context, router_id):
router = self._get_router(context, router_id)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._update_interface(context, router)
self._update_nat_rules(context, router)
super(NvpAdvancedPlugin, self).delete_floatingip(context, id)
if router_id and self._is_advanced_service_router(context, router_id):
router = self._get_router(context, router_id)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._update_interface(context, router)
self._update_nat_rules(context, router)
port_id)
if router_id and self._is_advanced_service_router(context, router_id):
router = self._get_router(context, router_id)
- # TODO(fank): do rollback if error, or have a dedicated thread
+ # TODO(fank): do rollback on error, or have a dedicated thread
# do sync work (rollback, re-configure, or make router down)
self._update_interface(context, router)
self._update_nat_rules(context, router)
+ #
+ # FWaaS plugin implementation
+ #
+ def _firewall_set_status(
+ self, context, firewall_id, status, firewall=None):
+ with context.session.begin(subtransactions=True):
+ fw_db = self._get_firewall(context, firewall_id)
+ if status == service_constants.PENDING_UPDATE and (
+ fw_db.status == service_constants.PENDING_DELETE):
+ raise fw_ext.FirewallInPendingState(
+ firewall_id=firewall_id, pending_state=status)
+ else:
+ fw_db.status = status
+ if firewall:
+ firewall['status'] = status
+
+ def _ensure_firewall_update_allowed(self, context, firewall_id):
+ fwall = self.get_firewall(context, firewall_id)
+ if fwall['status'] in [service_constants.PENDING_CREATE,
+ service_constants.PENDING_UPDATE,
+ service_constants.PENDING_DELETE]:
+ raise fw_ext.FirewallInPendingState(firewall_id=firewall_id,
+ pending_state=fwall['status'])
+
+ def _ensure_firewall_policy_update_allowed(
+ self, context, firewall_policy_id):
+ firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
+ for firewall_id in firewall_policy.get('firewall_list', []):
+ self._ensure_firewall_update_allowed(context, firewall_id)
+
+ def _ensure_update_or_delete_firewall_rule(
+ self, context, firewall_rule_id):
+ fw_rule = self.get_firewall_rule(context, firewall_rule_id)
+ if fw_rule.get('firewall_policy_id'):
+ self._ensure_firewall_policy_update_allowed(
+ context, fw_rule['firewall_policy_id'])
+
+ def _make_firewall_rule_list_by_policy_id(self, context, fw_policy_id):
+ if not fw_policy_id:
+ return None
+ firewall_policy_db = self._get_firewall_policy(context, fw_policy_id)
+ return [
+ self._make_firewall_rule_dict(fw_rule_db)
+ for fw_rule_db in firewall_policy_db['firewall_rules']
+ ]
+
+ def _get_edge_id_by_vcns_edge_binding(self, context,
+ router_id):
+ #Get vcns_router_binding mapping between router and edge
+ router_binding = vcns_db.get_vcns_router_binding(
+ context.session, router_id)
+ return router_binding.edge_id
+
+ def _get_firewall_list_from_firewall_policy(self, context, policy_id):
+ firewall_policy_db = self._get_firewall_policy(context, policy_id)
+ return [
+ self._make_firewall_dict(fw_db)
+ for fw_db in firewall_policy_db['firewalls']
+ ]
+
+ def _get_firewall_list_from_firewall_rule(self, context, rule_id):
+ rule = self._get_firewall_rule(context, rule_id)
+ if not rule.firewall_policy_id:
+ # The firewall rule is not associated with firewall policy yet
+ return None
+
+ return self._get_firewall_list_from_firewall_policy(
+ context, rule.firewall_policy_id)
+
+ def _vcns_update_firewall(self, context, fw, router_id=None, **kwargs):
+ edge_id = kwargs.get('edge_id')
+ if not edge_id:
+ edge_id = self._get_edge_id_by_vcns_edge_binding(
+ context, router_id)
+ firewall_rule_list = kwargs.get('firewall_rule_list')
+ if not firewall_rule_list:
+ firewall_rule_list = self._make_firewall_rule_list_by_policy_id(
+ context, fw['firewall_policy_id'])
+ fw_with_rules = fw
+ fw_with_rules['firewall_rule_list'] = firewall_rule_list
+ try:
+ self.vcns_driver.update_firewall(context, edge_id, fw_with_rules)
+ except exceptions.VcnsApiException as e:
+ self._firewall_set_status(
+ context, fw['id'], service_constants.ERROR)
+ msg = (_("Failed to create firewall on vShield Edge "
+ "bound on router %s") % router_id)
+ LOG.exception(msg)
+ raise e
-class VcnsCallbacks(object):
- """Edge callback implementation
+ except exceptions.BadRequest as e:
+ self._firewall_set_status(
+ context, fw['id'], service_constants.ERROR)
+ LOG.exception(_("Bad Firewall request Input"))
+ raise e
- Callback functions for asynchronous tasks
+ def _vcns_delete_firewall(self, context, router_id=None, **kwargs):
+ edge_id = kwargs.get('edge_id')
+ if not edge_id:
+ edge_id = self._get_edge_id_by_vcns_edge_binding(
+ context, router_id)
+ #TODO(linb):do rollback on error
+ self.vcns_driver.delete_firewall(context, edge_id)
+
+ def create_firewall(self, context, firewall):
+ LOG.debug(_("create_firewall() called"))
+ router_id = firewall['firewall'].get(vcns_const.ROUTER_ID)
+ if not router_id:
+ msg = _("router_id is not provided!")
+ LOG.error(msg)
+ raise q_exc.BadRequest(resource='router', msg=msg)
+ if not self._is_advanced_service_router(context, router_id):
+ msg = _("router_id:%s is not an advanced router!") % router_id
+ LOG.error(msg)
+ raise q_exc.BadRequest(resource='router', msg=msg)
+ if self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, router_id=router_id):
+ msg = _("A firewall is already associated with the router")
+ LOG.error(msg)
+ raise nvp_exc.NvpServiceOverQuota(
+ overs='firewall', err_msg=msg)
+
+ fw = super(NvpAdvancedPlugin, self).create_firewall(context, firewall)
+ #Add router service insertion binding with firewall object
+ res = {
+ 'id': fw['id'],
+ 'router_id': router_id
+ }
+ self._process_create_resource_router_id(
+ context, res, firewall_db.Firewall)
+ #Since there is only one firewall per edge,
+ #here would be bulk configureation operation on firewall
+ self._vcns_update_firewall(context, fw, router_id)
+ self._firewall_set_status(
+ context, fw['id'], service_constants.ACTIVE, fw)
+ return fw
+
+ def update_firewall(self, context, id, firewall):
+ LOG.debug(_("update_firewall() called"))
+ self._ensure_firewall_update_allowed(context, id)
+ rule_list_pre = self._make_firewall_rule_list_by_policy_id(
+ context,
+ self.get_firewall(context, id)['firewall_policy_id'])
+ firewall['firewall']['status'] = service_constants.PENDING_UPDATE
+ fw = super(NvpAdvancedPlugin, self).update_firewall(
+ context, id, firewall)
+ rule_list_new = self._make_firewall_rule_list_by_policy_id(
+ context, fw['firewall_policy_id'])
+ if rule_list_pre == rule_list_new:
+ self._firewall_set_status(
+ context, fw['id'], service_constants.ACTIVE, fw)
+ return fw
+ else:
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=id)
+ self._vcns_update_firewall(
+ context, fw, service_router_binding.router_id)
+ self._firewall_set_status(
+ context, fw['id'], service_constants.ACTIVE, fw)
+ return fw
+
+ def delete_firewall(self, context, id):
+ LOG.debug(_("delete_firewall() called"))
+ self._firewall_set_status(
+ context, id, service_constants.PENDING_DELETE)
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=id)
+ self._vcns_delete_firewall(context, service_router_binding.router_id)
+ super(NvpAdvancedPlugin, self).delete_firewall(context, id)
+ self._delete_resource_router_id_binding(
+ context, id, firewall_db.Firewall)
+
+ def update_firewall_rule(self, context, id, firewall_rule):
+ LOG.debug(_("update_firewall_rule() called"))
+ self._ensure_update_or_delete_firewall_rule(context, id)
+ fwr_pre = self.get_firewall_rule(context, id)
+ fwr = super(NvpAdvancedPlugin, self).update_firewall_rule(
+ context, id, firewall_rule)
+ if fwr_pre == fwr:
+ return fwr
+
+ # check if this rule is associated with firewall
+ fw_list = self._get_firewall_list_from_firewall_rule(context, id)
+ if not fw_list:
+ return fwr
+
+ for fw in fw_list:
+ # get router service insertion binding with firewall id
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=fw['id'])
+ edge_id = self._get_edge_id_by_vcns_edge_binding(
+ context, service_router_binding.router_id)
+
+ #TODO(linb): do rollback on error
+ self.vcns_driver.update_firewall_rule(context, id, edge_id, fwr)
+
+ return fwr
+
+ def update_firewall_policy(self, context, id, firewall_policy):
+ LOG.debug(_("update_firewall_policy() called"))
+ self._ensure_firewall_policy_update_allowed(context, id)
+ firewall_rules_pre = self._make_firewall_rule_list_by_policy_id(
+ context, id)
+ fwp = super(NvpAdvancedPlugin, self).update_firewall_policy(
+ context, id, firewall_policy)
+ firewall_rules = self._make_firewall_rule_list_by_policy_id(
+ context, id)
+ if firewall_rules_pre == firewall_rules:
+ return fwp
+
+ # check if this policy is associated with firewall
+ fw_list = self._get_firewall_list_from_firewall_policy(context, id)
+ if not fw_list:
+ return fwp
+
+ for fw in fw_list:
+ # Get the router_service insertion binding with firewall id
+ # TODO(fank): optimized by using _get_resource_router_id_bindings
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=fw['id'])
+ self._vcns_update_firewall(
+ context, fw, service_router_binding.router_id)
+ return fwp
+
+ def insert_rule(self, context, id, rule_info):
+ LOG.debug(_("insert_rule() called"))
+ self._ensure_firewall_policy_update_allowed(context, id)
+ fwp = super(NvpAdvancedPlugin, self).insert_rule(
+ context, id, rule_info)
+ fwr = super(NvpAdvancedPlugin, self).get_firewall_rule(
+ context, rule_info['firewall_rule_id'])
+
+ # check if this policy is associated with firewall
+ fw_list = self._get_firewall_list_from_firewall_policy(context, id)
+ if not fw_list:
+ return fwp
+ for fw in fw_list:
+ # TODO(fank): optimized by using _get_resource_router_id_bindings
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=fw['id'])
+ edge_id = self._get_edge_id_by_vcns_edge_binding(
+ context, service_router_binding.router_id)
+
+ if rule_info.get('insert_before') or rule_info.get('insert_after'):
+ #if insert_before or insert_after is set, we would call
+ #VCNS insert_rule API
+ #TODO(linb): do rollback on error
+ self.vcns_driver.insert_rule(context, rule_info, edge_id, fwr)
+ else:
+ #Else we would call bulk configuration on the firewall
+ self._vcns_update_firewall(context, fw, edge_id=edge_id)
+ return fwp
+
+ def remove_rule(self, context, id, rule_info):
+ LOG.debug(_("remove_rule() called"))
+ self._ensure_firewall_policy_update_allowed(context, id)
+ fwp = super(NvpAdvancedPlugin, self).remove_rule(
+ context, id, rule_info)
+ fwr = super(NvpAdvancedPlugin, self).get_firewall_rule(
+ context, rule_info['firewall_rule_id'])
+
+ # check if this policy is associated with firewall
+ fw_list = self._get_firewall_list_from_firewall_policy(context, id)
+ if not fw_list:
+ return fwp
+ for fw in fw_list:
+ # TODO(fank): optimized by using _get_resource_router_id_bindings
+ service_router_binding = self._get_resource_router_id_binding(
+ context, firewall_db.Firewall, resource_id=fw['id'])
+ edge_id = self._get_edge_id_by_vcns_edge_binding(
+ context, service_router_binding.router_id)
+ #TODO(linb): do rollback on error
+ self.vcns_driver.delete_firewall_rule(
+ context, fwr['id'], edge_id)
+ return fwp
+
+
+class VcnsCallbacks(object):
+ """Edge callback implementation Callback functions for
+ asynchronous tasks.
"""
def __init__(self, plugin):
self.plugin = plugin
message = _("The networking backend is currently in maintenance mode and "
"therefore unable to accept requests which modify its state. "
"Please try later.")
+
+
+class NvpServicePluginException(q_exc.NeutronException):
+ """NVP Service Plugin exceptions."""
+ message = _("An unexpected error happened "
+ "in the NVP Service Plugin:%(err_msg)s")
+
+
+class NvpServiceOverQuota(q_exc.Conflict):
+ message = _("Quota exceeded for Vcns resource: %(overs)s: %(err_msg)s")
+
+
+class NvpVcnsDriverException(NvpServicePluginException):
+ message = _("Error happened in NVP VCNS Driver: %(err_msg)s")
# License for the specific language governing permissions and limitations
# under the License.
+from sqlalchemy.orm import exc
+
+from neutron.plugins.nicira.common import exceptions as nvp_exc
from neutron.plugins.nicira.dbexts import vcns_models
binding = (session.query(vcns_models.VcnsRouterBinding).
filter_by(router_id=router_id).one())
session.delete(binding)
+
+
+#
+# Edge Firewall binding methods
+def add_vcns_edge_firewallrule_binding(session, map_info):
+ with session.begin(subtransactions=True):
+ binding = vcns_models.VcnsEdgeFirewallRuleBinding(
+ rule_id=map_info['rule_id'],
+ rule_vseid=map_info['rule_vseid'],
+ edge_id=map_info['edge_id'])
+ session.add(binding)
+ return binding
+
+
+def delete_vcns_edge_firewallrule_binding(session, id):
+ with session.begin(subtransactions=True):
+ if not (session.query(vcns_models.VcnsEdgeFirewallRuleBinding).
+ filter_by(rule_id=id).delete()):
+ msg = _("Rule Resource binding with id:%s not found!") % id
+ raise nvp_exc.NvpServicePluginException(err_msg=msg)
+
+
+def get_vcns_edge_firewallrule_binding(session, id, edge_id):
+ with session.begin(subtransactions=True):
+ return (session.query(vcns_models.VcnsEdgeFirewallRuleBinding).
+ filter_by(rule_id=id, edge_id=edge_id).first())
+
+
+def get_vcns_edge_firewallrule_binding_by_vseid(
+ session, edge_id, rule_vseid):
+ with session.begin(subtransactions=True):
+ try:
+ return (session.query(vcns_models.VcnsEdgeFirewallRuleBinding).
+ filter_by(edge_id=edge_id, rule_vseid=rule_vseid).one())
+ except exc.NoResultFound:
+ msg = _("Rule Resource binding not found!")
+ raise nvp_exc.NvpServicePluginException(err_msg=msg)
+
+
+def cleanup_vcns_edge_firewallrule_binding(session, edge_id):
+ with session.begin(subtransactions=True):
+ session.query(
+ vcns_models.VcnsEdgeFirewallRuleBinding).filter_by(
+ edge_id=edge_id).delete()
nullable=True)
lswitch_id = sa.Column(sa.String(36),
nullable=False)
+
+
+#
+# VCNS Edge FW mapping tables
+#
+class VcnsEdgeFirewallRuleBinding(model_base.BASEV2):
+ """1:1 mapping between firewall rule and edge firewall rule_id."""
+
+ __tablename__ = 'vcns_firewall_rule_bindings'
+
+ rule_id = sa.Column(sa.String(36),
+ sa.ForeignKey("firewall_rules.id"),
+ primary_key=True)
+ edge_id = sa.Column(sa.String(36), primary_key=True)
+ rule_vseid = sa.Column(sa.String(36))
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2013 VMware, Inc.
-# All Rights Reserved
+# Copyright 2013 VMware, 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
super(VcnsGeneralException, self).__init__()
+class VcnsBadRequest(exceptions.BadRequest):
+ pass
+
+
+class VcnsNotFound(exceptions.NotFound):
+ message = _('%(resource)s not found: %(msg)s')
+
+
class VcnsApiException(VcnsException):
message = _("An unknown exception %(status)s occurred: %(response)s.")
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 VMware, Inc
+#
+# 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.
+#
+# @author: Leon Cui, VMware
+
+from neutron.db import db_base_plugin_v2
+from neutron.openstack.common import excutils
+from neutron.openstack.common import log as logging
+from neutron.plugins.common import constants
+from neutron.plugins.nicira.dbexts import vcns_db
+from neutron.plugins.nicira.vshield.common import (
+ exceptions as vcns_exc)
+
+LOG = logging.getLogger(__name__)
+
+VSE_FWAAS_ALLOW = "accept"
+VSE_FWAAS_DENY = "deny"
+
+
+class EdgeFirewallDriver(db_base_plugin_v2.NeutronDbPluginV2):
+ """Implementation of driver APIs for
+ Edge Firewall feature configuration
+ """
+ def _convert_firewall_action(self, action):
+ if action == constants.FWAAS_ALLOW:
+ return VSE_FWAAS_ALLOW
+ elif action == constants.FWAAS_DENY:
+ return VSE_FWAAS_DENY
+ else:
+ msg = _("Invalid action value %s in a firewall rule") % action
+ raise vcns_exc.BadRequest(resource='firewall_rule', msg=msg)
+
+ def _restore_firewall_action(self, action):
+ if action == VSE_FWAAS_ALLOW:
+ return constants.FWAAS_ALLOW
+ elif action == VSE_FWAAS_DENY:
+ return constants.FWAAS_DENY
+ else:
+ msg = (_("Invalid action value %s in "
+ "a vshield firewall rule") % action)
+ raise vcns_exc.BadRequest(resource='firewall_rule', msg=msg)
+
+ def _get_port_range_from_min_max_ports(self, min_port, max_port):
+ if not min_port:
+ return None
+ if min_port == max_port:
+ return str(min_port)
+ else:
+ return '%d:%d' % (min_port, max_port)
+
+ def _get_min_max_ports_from_range(self, port_range):
+ if not port_range:
+ return [None, None]
+ min_port, sep, max_port = port_range.partition(":")
+ if not max_port:
+ max_port = min_port
+ return [int(min_port), int(max_port)]
+
+ def _convert_firewall_rule(self, context, rule, index=None):
+ vcns_rule = {
+ "name": rule['name'],
+ "description": rule['description'],
+ "action": self._convert_firewall_action(rule['action']),
+ "enabled": rule['enabled']}
+ if rule.get('source_ip_address'):
+ vcns_rule['source'] = {
+ "ipAddress": [rule['source_ip_address']]
+ }
+ if rule.get('destination_ip_address'):
+ vcns_rule['destination'] = {
+ "ipAddress": [rule['destination_ip_address']]
+ }
+ service = {}
+ if rule.get('source_port'):
+ min_port, max_port = self._get_min_max_ports_from_range(
+ rule['source_port'])
+ service['sourcePort'] = [i for i in range(min_port, max_port + 1)]
+ if rule.get('destination_port'):
+ min_port, max_port = self._get_min_max_ports_from_range(
+ rule['destination_port'])
+ service['port'] = [i for i in range(min_port, max_port + 1)]
+ if rule.get('protocol'):
+ service['protocol'] = rule['protocol']
+ if service:
+ vcns_rule['application'] = {
+ 'service': [service]
+ }
+ if index:
+ vcns_rule['ruleTag'] = index
+ return vcns_rule
+
+ def _restore_firewall_rule(self, context, edge_id, response):
+ rule = response
+ rule_binding = vcns_db.get_vcns_edge_firewallrule_binding_by_vseid(
+ context.session, edge_id, rule['ruleId'])
+ service = rule['application']['service'][0]
+ src_port_range = self._get_port_range_from_min_max_ports(
+ service['sourcePort'][0], service['sourcePort'][-1])
+ dst_port_range = self._get_port_range_from_min_max_ports(
+ service['port'][0], service['port'][-1])
+ return {
+ 'firewall_rule': {
+ 'name': rule['name'],
+ 'id': rule_binding['rule_id'],
+ 'description': rule['description'],
+ 'source_ip_address': rule['source']['ipAddress'][0],
+ 'destination_ip_address': rule['destination']['ipAddress'][0],
+ 'protocol': service['protocol'],
+ 'destination_port': dst_port_range,
+ 'source_port': src_port_range,
+ 'action': self._restore_firewall_action(rule['action']),
+ 'enabled': rule['enabled']}}
+
+ def _convert_firewall(self, context, firewall):
+ #bulk configuration on firewall and rescheduling the rule binding
+ ruleTag = 1
+ vcns_rules = []
+ for rule in firewall['firewall_rule_list']:
+ vcns_rule = self._convert_firewall_rule(context, rule, ruleTag)
+ vcns_rules.append(vcns_rule)
+ ruleTag += 1
+ return {
+ 'featureType': "firewall_4.0",
+ 'firewallRules': {
+ 'firewallRules': vcns_rules}}
+
+ def _restore_firewall(self, context, edge_id, response):
+ res = {}
+ res['firewall_rule_list'] = []
+ for rule in response['firewallRules']['firewallRules']:
+ rule_binding = (
+ vcns_db.get_vcns_edge_firewallrule_binding_by_vseid(
+ context.session, edge_id, rule['ruleId']))
+ if rule_binding is None:
+ continue
+ service = rule['application']['service'][0]
+ src_port_range = self._get_port_range_from_min_max_ports(
+ service['sourcePort'][0], service['sourcePort'][-1])
+ dst_port_range = self._get_port_range_from_min_max_ports(
+ service['port'][0], service['port'][-1])
+ item = {
+ 'firewall_rule': {
+ 'name': rule['name'],
+ 'id': rule_binding['rule_id'],
+ 'description': rule['description'],
+ 'source_ip_address': rule['source']['ipAddress'][0],
+ 'destination_ip_address': rule[
+ 'destination']['ipAddress'][0],
+ 'protocol': service['protocol'],
+ 'destination_port': dst_port_range,
+ 'source_port': src_port_range,
+ 'action': self._restore_firewall_action(rule['action']),
+ 'enabled': rule['enabled']}}
+ res['firewall_rule_list'].append(item)
+ return res
+
+ def _create_rule_id_mapping(
+ self, context, edge_id, firewall, vcns_fw):
+ for rule in vcns_fw['firewallRules']['firewallRules']:
+ index = rule['ruleTag'] - 1
+ #TODO(linb):a simple filter of the retrived rules which may be
+ #created by other operations unintentionally
+ if index < len(firewall['firewall_rule_list']):
+ rule_vseid = rule['ruleId']
+ rule_id = firewall['firewall_rule_list'][index]['id']
+ map_info = {
+ 'rule_id': rule_id,
+ 'rule_vseid': rule_vseid,
+ 'edge_id': edge_id
+ }
+ vcns_db.add_vcns_edge_firewallrule_binding(
+ context.session, map_info)
+
+ def _get_firewall(self, context, edge_id):
+ try:
+ return self.vcns.get_firewall(edge_id)[1]
+ except vcns_exc.VcnsApiException as e:
+ LOG.exception(_("Failed to get firewall with edge "
+ "id: %s"), edge_id)
+ raise e
+
+ def _get_firewall_rule_next(self, context, edge_id, rule_vseid):
+ # Return the firewall rule below 'rule_vseid'
+ fw_cfg = self._get_firewall(context, edge_id)
+ for i in range(len(fw_cfg['firewallRules']['firewallRules'])):
+ rule_cur = fw_cfg['firewallRules']['firewallRules'][i]
+ if str(rule_cur['ruleId']) == rule_vseid:
+ if (i + 1) == len(fw_cfg['firewallRules']['firewallRules']):
+ return None
+ else:
+ return fw_cfg['firewallRules']['firewallRules'][i + 1]
+
+ def get_firewall_rule(self, context, id, edge_id):
+ rule_map = vcns_db.get_vcns_edge_firewallrule_binding(
+ context.session, id, edge_id)
+ if rule_map is None:
+ msg = _("No rule id:%s found in the edge_firewall_binding") % id
+ LOG.error(msg)
+ raise vcns_exc.VcnsNotFound(
+ resource='vcns_firewall_rule_bindings', msg=msg)
+ vcns_rule_id = rule_map.rule_vseid
+ try:
+ response = self.vcns.get_firewall_rule(
+ edge_id, vcns_rule_id)[1]
+ except vcns_exc.VcnsApiException as e:
+ LOG.exception(_("Failed to get firewall rule: %(rule_id)s "
+ "with edge_id: %(edge_id)s"), {
+ 'rule_id': id,
+ 'edge_id': edge_id})
+ raise e
+ return self._restore_firewall_rule(context, edge_id, response)
+
+ def get_firewall(self, context, edge_id):
+ response = self._get_firewall(context, edge_id)
+ return self._restore_firewall(context, edge_id, response)
+
+ def update_firewall(self, context, edge_id, firewall):
+ fw_req = self._convert_firewall(context, firewall)
+ try:
+ self.vcns.update_firewall(edge_id, fw_req)
+ except vcns_exc.VcnsApiException as e:
+ LOG.exception(_("Failed to update firewall "
+ "with edge_id: %s"), edge_id)
+ raise e
+ fw_res = self._get_firewall(context, edge_id)
+ vcns_db.cleanup_vcns_edge_firewallrule_binding(
+ context.session, edge_id)
+ self._create_rule_id_mapping(context, edge_id, firewall, fw_res)
+
+ def delete_firewall(self, context, edge_id):
+ try:
+ self.vcns.delete_firewall(edge_id)
+ except vcns_exc.VcnsApiException as e:
+ LOG.exception(_("Failed to delete firewall "
+ "with edge_id:%s"), edge_id)
+ raise e
+ vcns_db.cleanup_vcns_edge_firewallrule_binding(
+ context.session, edge_id)
+
+ def update_firewall_rule(self, context, id, edge_id, firewall_rule):
+ rule_map = vcns_db.get_vcns_edge_firewallrule_binding(
+ context.session, id, edge_id)
+ vcns_rule_id = rule_map.rule_vseid
+ fwr_req = self._convert_firewall_rule(context, firewall_rule)
+ try:
+ self.vcns.update_firewall_rule(edge_id, vcns_rule_id, fwr_req)
+ except vcns_exc.VcnsApiException:
+ with excutils.save_and_reraise_exception():
+ LOG.exception(_("Failed to update firewall rule: %(rule_id)s "
+ "with edge_id: %(edge_id)s"),
+ {'rule_id': id,
+ 'edge_id': edge_id})
+
+ def delete_firewall_rule(self, context, id, edge_id):
+ rule_map = vcns_db.get_vcns_edge_firewallrule_binding(
+ context.session, id, edge_id)
+ vcns_rule_id = rule_map.rule_vseid
+ try:
+ self.vcns.delete_firewall_rule(edge_id, vcns_rule_id)
+ except vcns_exc.VcnsApiException:
+ with excutils.save_and_reraise_exception():
+ LOG.exception(_("Failed to delete firewall rule: %(rule_id)s "
+ "with edge_id: %(edge_id)s"),
+ {'rule_id': id,
+ 'edge_id': edge_id})
+ vcns_db.delete_vcns_edge_firewallrule_binding(
+ context.session, id)
+
+ def _add_rule_above(self, context, ref_rule_id, edge_id, firewall_rule):
+ rule_map = vcns_db.get_vcns_edge_firewallrule_binding(
+ context.session, ref_rule_id, edge_id)
+ ref_vcns_rule_id = rule_map.rule_vseid
+ fwr_req = self._convert_firewall_rule(context, firewall_rule)
+ try:
+ header = self.vcns.add_firewall_rule_above(
+ edge_id, ref_vcns_rule_id, fwr_req)[0]
+ except vcns_exc.VcnsApiException:
+ with excutils.save_and_reraise_exception():
+ LOG.exception(_("Failed to add firewall rule above: "
+ "%(rule_id)s with edge_id: %(edge_id)s"),
+ {'rule_id': ref_vcns_rule_id,
+ 'edge_id': edge_id})
+
+ objuri = header['location']
+ fwr_vseid = objuri[objuri.rfind("/") + 1:]
+ map_info = {
+ 'rule_id': firewall_rule['id'],
+ 'rule_vseid': fwr_vseid,
+ 'edge_id': edge_id}
+ vcns_db.add_vcns_edge_firewallrule_binding(
+ context.session, map_info)
+
+ def _add_rule_below(self, context, ref_rule_id, edge_id, firewall_rule):
+ rule_map = vcns_db.get_vcns_edge_firewallrule_binding(
+ context.session, ref_rule_id, edge_id)
+ ref_vcns_rule_id = rule_map.rule_vseid
+ fwr_vse_next = self._get_firewall_rule_next(
+ context, edge_id, ref_vcns_rule_id)
+ fwr_req = self._convert_firewall_rule(context, firewall_rule)
+ if fwr_vse_next:
+ ref_vcns_rule_id = fwr_vse_next['ruleId']
+ try:
+ header = self.vcns.add_firewall_rule_above(
+ edge_id, int(ref_vcns_rule_id), fwr_req)[0]
+ except vcns_exc.VcnsApiException:
+ with excutils.save_and_reraise_exception():
+ LOG.exception(_("Failed to add firewall rule above: "
+ "%(rule_id)s with edge_id: %(edge_id)s"),
+ {'rule_id': ref_vcns_rule_id,
+ 'edge_id': edge_id})
+ else:
+ # append the rule at the bottom
+ try:
+ header = self.vcns.add_firewall_rule(
+ edge_id, fwr_req)[0]
+ except vcns_exc.VcnsApiException:
+ with excutils.save_and_reraise_exception():
+ LOG.exception(_("Failed to append a firewall rule"
+ "with edge_id: %s"), edge_id)
+
+ objuri = header['location']
+ fwr_vseid = objuri[objuri.rfind("/") + 1:]
+ map_info = {
+ 'rule_id': firewall_rule['id'],
+ 'rule_vseid': fwr_vseid,
+ 'edge_id': edge_id
+ }
+ vcns_db.add_vcns_edge_firewallrule_binding(
+ context.session, map_info)
+
+ def insert_rule(self, context, rule_info, edge_id, fwr):
+ if rule_info.get('insert_before'):
+ self._add_rule_above(
+ context, rule_info['insert_before'], edge_id, fwr)
+ elif rule_info.get('insert_after'):
+ self._add_rule_below(
+ context, rule_info['insert_after'], edge_id, fwr)
+ else:
+ msg = _("Can't execute insert rule operation "
+ "without reference rule_id")
+ raise vcns_exc.BadRequest(resource='firewall_rule', msg=msg)
HTTP_PUT = "PUT"
URI_PREFIX = "/api/4.0/edges"
+#FwaaS constants
+FIREWALL_SERVICE = "firewall/config"
+FIREWALL_RULE_RESOURCE = "rules"
+
class Vcns(object):
def delete_lswitch(self, lswitch_id):
uri = "/api/ws.v1/lswitch/%s" % lswitch_id
return self.do_request(HTTP_DELETE, uri)
+
+ def update_firewall(self, edge_id, fw_req):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE)
+ return self.do_request(HTTP_PUT, uri, fw_req)
+
+ def delete_firewall(self, edge_id):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE, None)
+ return self.do_request(HTTP_DELETE, uri)
+
+ def update_firewall_rule(self, edge_id, vcns_rule_id, fwr_req):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE,
+ FIREWALL_RULE_RESOURCE,
+ vcns_rule_id)
+ return self.do_request(HTTP_PUT, uri, fwr_req)
+
+ def delete_firewall_rule(self, edge_id, vcns_rule_id):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE,
+ FIREWALL_RULE_RESOURCE,
+ vcns_rule_id)
+ return self.do_request(HTTP_DELETE, uri)
+
+ def add_firewall_rule_above(self, edge_id, ref_vcns_rule_id, fwr_req):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE,
+ FIREWALL_RULE_RESOURCE)
+ uri += "?aboveRuleId=" + ref_vcns_rule_id
+ return self.do_request(HTTP_POST, uri, fwr_req)
+
+ def add_firewall_rule(self, edge_id, fwr_req):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE,
+ FIREWALL_RULE_RESOURCE)
+ return self.do_request(HTTP_POST, uri, fwr_req)
+
+ def get_firewall(self, edge_id):
+ uri = self._build_uri_path(edge_id, FIREWALL_SERVICE)
+ return self.do_request(HTTP_GET, uri, decode=True)
+
+ def get_firewall_rule(self, edge_id, vcns_rule_id):
+ uri = self._build_uri_path(
+ edge_id, FIREWALL_SERVICE,
+ FIREWALL_RULE_RESOURCE,
+ vcns_rule_id)
+ return self.do_request(HTTP_GET, uri, decode=True)
+
+ def _build_uri_path(self, edge_id,
+ service,
+ resource=None,
+ resource_id=None,
+ parent_resource_id=None,
+ fields=None,
+ relations=None,
+ filters=None,
+ types=None,
+ is_attachment=False):
+ uri_prefix = "%s/%s/%s" % (URI_PREFIX, edge_id, service)
+ if resource:
+ res_path = resource + (resource_id and "/%s" % resource_id or '')
+ uri_path = "%s/%s" % (uri_prefix, res_path)
+ else:
+ uri_path = uri_prefix
+ return uri_path
from neutron.plugins.nicira.common import config # noqa
from neutron.plugins.nicira.vshield import edge_appliance_driver
+from neutron.plugins.nicira.vshield import edge_firewall_driver
from neutron.plugins.nicira.vshield.tasks import tasks
from neutron.plugins.nicira.vshield import vcns
-class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver):
+class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver,
+ edge_firewall_driver.EdgeFirewallDriver):
def __init__(self, callbacks):
super(VcnsDriver, self).__init__()
interval = cfg.CONF.vcns.task_status_check_interval
self.task_manager = tasks.TaskManager(interval)
self.task_manager.start()
-
self.vcns = vcns.Vcns(self.vcns_uri, self.vcns_user, self.vcns_passwd)
for k in firewall.RESOURCE_ATTRIBUTE_MAP.keys()
)
- def setUp(self, core_plugin=None, fw_plugin=None):
+ def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
if not fw_plugin:
fw_plugin = DB_FW_PLUGIN_KLASS
service_plugins = {'fw_plugin_name': fw_plugin}
fdb.Firewall_db_mixin.supported_extension_aliases = ["fwaas"]
super(FirewallPluginDbTestCase, self).setUp(
+ ext_mgr=ext_mgr,
service_plugins=service_plugins
)
- self.plugin = importutils.import_object(fw_plugin)
- ext_mgr = api_ext.PluginAwareExtensionManager(
- extensions_path,
- {constants.FIREWALL: self.plugin}
- )
- app = config.load_paste_app('extensions_test_app')
- self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
+ if not ext_mgr:
+ self.plugin = importutils.import_object(fw_plugin)
+ ext_mgr = api_ext.PluginAwareExtensionManager(
+ extensions_path,
+ {constants.FIREWALL: self.plugin}
+ )
+ app = config.load_paste_app('extensions_test_app')
+ self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
def _test_list_resources(self, resource, items,
neutron_context=None,
import neutron.plugins.nicira.NeutronPlugin as plugin
import neutron.plugins.nicira.NeutronServicePlugin as service_plugin
import neutron.plugins.nicira.NvpApiClient as nvpapi
+from neutron.plugins.nicira.vshield.common import (
+ VcnsApiClient as vcnsapi)
from neutron.plugins.nicira.vshield import vcns
+import neutron.plugins.nicira.vshield.vcns_driver as vcnsdriver
nvp_plugin = plugin.NvpPluginV2
nvp_service_plugin = service_plugin.NvpAdvancedPlugin
api_helper = nvpapi.NVPApiHelper
nvp_client = client.NvpApiClientEventlet
vcns_class = vcns.Vcns
+vcns_driver = vcnsdriver.VcnsDriver
+vcns_api_helper = vcnsapi.VcnsApiHelper
STUBS_PATH = os.path.join(os.path.dirname(__file__), 'etc')
NVPEXT_PATH = os.path.dirname(extensions.__file__)
nvp_service_plugin.__name__)
CLIENT_NAME = '%s.%s' % (nvp_client.__module__, nvp_client.__name__)
VCNS_NAME = '%s.%s' % (vcns_class.__module__, vcns_class.__name__)
+VCNS_DRIVER_NAME = '%s.%s' % (vcns_driver.__module__, vcns_driver.__name__)
+VCNSAPI_NAME = '%s.%s' % (vcns_api_helper.__module__,
+ vcns_api_helper.__name__)
def get_fake_conf(filename):
class NvpRouterTestCase(test_nicira_plugin.TestNiciraL3NatTestCase):
- def setUp(self, plugin=None, ext_mgr=None):
+ def setUp(self, plugin=None, ext_mgr=None, service_plugins=None):
plugin = plugin or SERVICE_PLUGIN_NAME
- super(NvpRouterTestCase, self).setUp(plugin=plugin, ext_mgr=ext_mgr)
+ super(NvpRouterTestCase, self).setUp(plugin=plugin, ext_mgr=ext_mgr,
+ service_plugins=service_plugins)
-class ServiceRouterTestCase(NvpRouterTestCase):
+class ServiceRouterTest(test_nicira_plugin.NiciraL3NatTest):
def vcns_patch(self):
instance = self.mock_vcns.start()
+ self.vcns_instance = instance
instance.return_value.deploy_edge.side_effect = self.fc2.deploy_edge
instance.return_value.get_edge_id.side_effect = self.fc2.get_edge_id
instance.return_value.get_edge_deploy_status.side_effect = (
instance.return_value.delete_lswitch.side_effect = (
self.fc2.delete_lswitch)
- def setUp(self):
+ def setUp(self, ext_mgr=None, service_plugins=None):
cfg.CONF.set_override('api_extensions_path', NVPEXT_PATH)
cfg.CONF.set_override('task_status_check_interval', 100, group="vcns")
self.mock_vcns = mock.patch(VCNS_NAME, autospec=True)
self.vcns_patch()
- super(ServiceRouterTestCase, self).setUp(
- ext_mgr=ServiceRouterTestExtensionManager())
+ ext_mgr = ext_mgr or ServiceRouterTestExtensionManager()
+ super(ServiceRouterTest, self).setUp(
+ plugin=SERVICE_PLUGIN_NAME,
+ service_plugins=service_plugins,
+ ext_mgr=ext_mgr)
self.fc2.set_fake_nvpapi(self.fc)
self.addCleanup(self.fc2.reset_all)
raise Exception(_("Tasks not completed"))
manager.stop()
- super(ServiceRouterTestCase, self).tearDown()
+ super(ServiceRouterTest, self).tearDown()
def _create_router(self, fmt, tenant_id, name=None,
admin_state_up=None, set_context=False,
return router_req.get_response(self.ext_api)
+
+class ServiceRouterTestCase(ServiceRouterTest, NvpRouterTestCase):
+
def test_router_create(self):
name = 'router1'
tenant_id = _uuid()
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 VMware, 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.
+#
+
+import contextlib
+import copy
+import webob.exc
+
+from neutron.api.v2 import attributes
+from neutron import context
+from neutron.extensions import firewall
+from neutron import manager
+from neutron.openstack.common import uuidutils
+from neutron.plugins.common import constants as const
+from neutron.tests.unit.db.firewall import test_db_firewall
+from neutron.tests.unit.nicira import test_edge_router
+
+_uuid = uuidutils.generate_uuid
+
+FW_PLUGIN_CLASS = (
+ "neutron.plugins.nicira.NeutronServicePlugin.NvpAdvancedPlugin"
+)
+
+
+class FirewallTestExtensionManager(
+ test_edge_router.ServiceRouterTestExtensionManager):
+
+ def get_resources(self):
+ # If l3 resources have been loaded and updated by main API
+ # router, update the map in the l3 extension so it will load
+ # the same attributes as the API router
+ resources = super(FirewallTestExtensionManager, self).get_resources()
+ firewall_attr_map = copy.deepcopy(firewall.RESOURCE_ATTRIBUTE_MAP)
+ for res in firewall.RESOURCE_ATTRIBUTE_MAP.keys():
+ attr_info = attributes.RESOURCE_ATTRIBUTE_MAP.get(res)
+ if attr_info:
+ firewall.RESOURCE_ATTRIBUTE_MAP[res] = attr_info
+ fw_resources = firewall.Firewall.get_resources()
+ # restore the original resources once the controllers are created
+ firewall.RESOURCE_ATTRIBUTE_MAP = firewall_attr_map
+
+ resources.extend(fw_resources)
+
+ return resources
+
+ def get_actions(self):
+ return []
+
+ def get_request_extensions(self):
+ return []
+
+
+class FirewallPluginTestCase(test_db_firewall.FirewallPluginDbTestCase,
+ test_edge_router.ServiceRouterTest):
+
+ def vcns_firewall_patch(self):
+ self.vcns_instance.return_value.update_firewall.side_effect = (
+ self.fc2.update_firewall)
+ self.vcns_instance.return_value.delete_firewall.side_effect = (
+ self.fc2.delete_firewall)
+ self.vcns_instance.return_value.update_firewall_rule.side_effect = (
+ self.fc2.update_firewall_rule)
+ self.vcns_instance.return_value.delete_firewall_rule.side_effect = (
+ self.fc2.delete_firewall_rule)
+ self.vcns_instance.return_value.add_firewall_rule_above.side_effect = (
+ self.fc2.add_firewall_rule_above)
+ self.vcns_instance.return_value.add_firewall_rule.side_effect = (
+ self.fc2.add_firewall_rule)
+ self.vcns_instance.return_value.get_firewall.side_effect = (
+ self.fc2.get_firewall)
+ self.vcns_instance.return_value.get_firewall_rule.side_effect = (
+ self.fc2.get_firewall_rule)
+
+ def setUp(self):
+ # Save the global RESOURCE_ATTRIBUTE_MAP
+ self.saved_attr_map = {}
+ for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems():
+ self.saved_attr_map[resource] = attrs.copy()
+
+ super(FirewallPluginTestCase, self).setUp(
+ ext_mgr=FirewallTestExtensionManager(),
+ fw_plugin=FW_PLUGIN_CLASS)
+ self.vcns_firewall_patch()
+ self.plugin = manager.NeutronManager.get_plugin()
+ self.router_id = None
+
+ def tearDown(self):
+ super(FirewallPluginTestCase, self).tearDown()
+ # Restore the global RESOURCE_ATTRIBUTE_MAP
+ attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
+ self.ext_api = None
+ self.plugin = None
+
+ def _fake_router_edge_mapping(self):
+ req = self._create_router(self.fmt, self._tenant_id)
+ res = self.deserialize(self.fmt, req)
+ self.router_id = res['router']['id']
+
+ def _create_firewall(self, fmt, name, description, firewall_policy_id,
+ admin_state_up=True, expected_res_status=None,
+ **kwargs):
+ data = {'firewall': {'name': name,
+ 'description': description,
+ 'firewall_policy_id': firewall_policy_id,
+ 'router_id': self.router_id,
+ 'admin_state_up': admin_state_up,
+ 'tenant_id': self._tenant_id}}
+
+ firewall_req = self.new_create_request('firewalls', data, fmt)
+ firewall_res = firewall_req.get_response(self.ext_api)
+ if expected_res_status:
+ self.assertEqual(firewall_res.status_int, expected_res_status)
+
+ return firewall_res
+
+ def test_create_firewall(self):
+ self._fake_router_edge_mapping()
+
+ name = "new_fw"
+ attrs = self._get_test_firewall_attrs(name)
+
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['firewall_policy_id'] = fwp_id
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id,
+ router_id=self.router_id,
+ admin_state_up=
+ test_db_firewall.ADMIN_STATE_UP,
+ expected_res_status=201) as fw:
+ attrs = self._replace_firewall_status(
+ attrs, const.PENDING_CREATE, const.ACTIVE)
+ for k, v in attrs.iteritems():
+ self.assertEqual(fw['firewall'][k], v)
+
+ def test_update_firewall(self):
+ self._fake_router_edge_mapping()
+
+ name = "new_fw"
+ attrs = self._get_test_firewall_attrs(name)
+
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['firewall_policy_id'] = fwp_id
+ with self.firewall(
+ firewall_policy_id=fwp_id, router_id=self.router_id,
+ admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw:
+ fw_id = fw['firewall']['id']
+ new_data = {'firewall': {'name': name}}
+ req = self.new_update_request('firewalls', new_data, fw_id)
+ res = req.get_response(self.ext_api)
+ self.assertEqual(res.status_int, 200)
+ res_json = self.deserialize(
+ self.fmt, res)
+ attrs = self._replace_firewall_status(
+ attrs, const.PENDING_CREATE, const.ACTIVE)
+ for k, v in attrs.iteritems():
+ self.assertEqual(res_json['firewall'][k], v)
+
+ def test_delete_firewall(self):
+ ctx = context.get_admin_context()
+ self._fake_router_edge_mapping()
+
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(
+ firewall_policy_id=fwp_id,
+ router_id=self.router_id,
+ admin_state_up=test_db_firewall.ADMIN_STATE_UP,
+ no_delete=True) as fw:
+ fw_id = fw['firewall']['id']
+ with ctx.session.begin(subtransactions=True):
+ req = self.new_delete_request('firewalls', fw_id)
+ res = req.get_response(self.ext_api)
+ self.assertEqual(res.status_int, 204)
+ self.assertRaises(
+ firewall.FirewallNotFound,
+ self.plugin.get_firewall, ctx, fw_id)
+
+ def test_create_firewall_with_rules(self):
+ ctx = context.get_admin_context()
+ self._fake_router_edge_mapping()
+
+ with contextlib.nested(self.firewall_rule(name='fwr1'),
+ self.firewall_rule(name='fwr2'),
+ self.firewall_rule(name='fwr3')) as fr:
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ data = {'firewall_policy':
+ {'firewall_rules': fw_rule_ids}}
+ req = self.new_update_request(
+ 'firewall_policies', data, fwp_id)
+ req.get_response(self.ext_api)
+ attrs = self._get_test_firewall_attrs()
+ attrs['firewall_policy_id'] = fwp_id
+ with self.firewall(
+ firewall_policy_id=fwp_id, router_id=self.router_id,
+ admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw:
+ rule_list = (
+ self.plugin._make_firewall_rule_list_by_policy_id(
+ ctx, fw['firewall']['firewall_policy_id']))
+ self._compare_firewall_rule_lists(
+ fwp_id, fr, rule_list)
+
+ def test_update_firewall_policy_with_no_firewall(self):
+ name = "new_firewall_policy1"
+ attrs = self._get_test_firewall_policy_attrs(name)
+
+ with self.firewall_policy(shared=test_db_firewall.SHARED,
+ firewall_rules=None,
+ audited=test_db_firewall.AUDITED) as fwp:
+ data = {'firewall_policy': {'name': name}}
+ req = self.new_update_request('firewall_policies', data,
+ fwp['firewall_policy']['id'])
+ res = self.deserialize(self.fmt, req.get_response(self.ext_api))
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_policy'][k], v)
+
+ def test_update_firewall_policy_with_firewall(self):
+ self._fake_router_edge_mapping()
+
+ name = "new_firewall_policy1"
+ attrs = self._get_test_firewall_policy_attrs(name)
+
+ with self.firewall_policy(shared=test_db_firewall.SHARED,
+ firewall_rules=None,
+ audited=test_db_firewall.AUDITED) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(firewall_policy_id=fwp_id,
+ router_id=self.router_id,
+ admin_state_up=
+ test_db_firewall.ADMIN_STATE_UP):
+ data = {'firewall_policy': {'name': name}}
+ req = self.new_update_request(
+ 'firewall_policies', data, fwp['firewall_policy']['id'])
+ res = self.deserialize(
+ self.fmt, req.get_response(self.ext_api))
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_policy'][k], v)
+
+ def test_update_firewall_rule_with_no_firewall(self):
+ name = "new_firewall_rule1"
+ attrs = self._get_test_firewall_rule_attrs(name)
+
+ attrs['source_port'] = '10:20'
+ attrs['destination_port'] = '30:40'
+ with self.firewall_rule() as fwr:
+ data = {'firewall_rule': {'name': name,
+ 'source_port': '10:20',
+ 'destination_port': '30:40'}}
+ req = self.new_update_request(
+ 'firewall_rules', data, fwr['firewall_rule']['id'])
+ res = self.deserialize(
+ self.fmt, req.get_response(self.ext_api))
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_rule'][k], v)
+
+ attrs['source_port'] = '10000'
+ attrs['destination_port'] = '80'
+ with self.firewall_rule() as fwr:
+ data = {'firewall_rule': {'name': name,
+ 'source_port': 10000,
+ 'destination_port': 80}}
+ req = self.new_update_request('firewall_rules', data,
+ fwr['firewall_rule']['id'])
+ res = self.deserialize(self.fmt, req.get_response(self.ext_api))
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_rule'][k], v)
+
+ attrs['source_port'] = None
+ attrs['destination_port'] = None
+ with self.firewall_rule() as fwr:
+ data = {'firewall_rule': {'name': name,
+ 'source_port': None,
+ 'destination_port': None}}
+ req = self.new_update_request(
+ 'firewall_rules', data, fwr['firewall_rule']['id'])
+ res = self.deserialize(
+ self.fmt, req.get_response(self.ext_api))
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_rule'][k], v)
+
+ def test_update_firewall_rule_with_firewall(self):
+ self._fake_router_edge_mapping()
+
+ name = "new_firewall_rule1"
+ attrs = self._get_test_firewall_rule_attrs(name)
+ with self.firewall_rule() as fwr:
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['firewall_policy_id'] = fwp_id
+ with self.firewall(firewall_policy_id=fwp_id,
+ router_id=self.router_id,
+ admin_state_up=
+ test_db_firewall.ADMIN_STATE_UP):
+ fwr_id = fwr['firewall_rule']['id']
+ data = {'firewall_policy': {'firewall_rules': [fwr_id]}}
+ req = self.new_update_request(
+ 'firewall_policies', data,
+ fwp['firewall_policy']['id'])
+ req.get_response(self.ext_api)
+ data = {'firewall_rule': {'name': name}}
+ req = self.new_update_request(
+ 'firewall_rules', data,
+ fwr['firewall_rule']['id'])
+ res = self.deserialize(
+ self.fmt, req.get_response(self.ext_api))
+ attrs['firewall_policy_id'] = fwp_id
+ for k, v in attrs.iteritems():
+ self.assertEqual(res['firewall_rule'][k], v)
+
+ def test_insert_rule_with_no_firewall(self):
+ attrs = self._get_test_firewall_policy_attrs()
+ attrs['audited'] = False
+ attrs['firewall_list'] = []
+ with contextlib.nested(self.firewall_rule(name='fwr0'),
+ self.firewall_rule(name='fwr1'),
+ self.firewall_rule(name='fwr2'),
+ self.firewall_rule(name='fwr3'),
+ self.firewall_rule(name='fwr4'),
+ self.firewall_rule(name='fwr5'),
+ self.firewall_rule(name='fwr6')) as fwr:
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['id'] = fwp_id
+ # test insert when rule list is empty
+ fwr0_id = fwr[0]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr0_id)
+ self._rule_action('insert', fwp_id, fwr0_id,
+ insert_before=None,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert at top of rule list, insert_before and
+ # insert_after not provided
+ fwr1_id = fwr[1]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr1_id)
+ insert_data = {'firewall_rule_id': fwr1_id}
+ self._rule_action('insert', fwp_id, fwr0_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs, body_data=insert_data)
+ # test insert at top of list above existing rule
+ fwr2_id = fwr[2]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr2_id)
+ self._rule_action('insert', fwp_id, fwr2_id,
+ insert_before=fwr1_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert at bottom of list
+ fwr3_id = fwr[3]['firewall_rule']['id']
+ attrs['firewall_rules'].append(fwr3_id)
+ self._rule_action('insert', fwp_id, fwr3_id,
+ insert_before=None,
+ insert_after=fwr0_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert in the middle of the list using
+ # insert_before
+ fwr4_id = fwr[4]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr4_id)
+ self._rule_action('insert', fwp_id, fwr4_id,
+ insert_before=fwr1_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert in the middle of the list using
+ # insert_after
+ fwr5_id = fwr[5]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr5_id)
+ self._rule_action('insert', fwp_id, fwr5_id,
+ insert_before=None,
+ insert_after=fwr2_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert when both insert_before and
+ # insert_after are set
+ fwr6_id = fwr[6]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr6_id)
+ self._rule_action('insert', fwp_id, fwr6_id,
+ insert_before=fwr5_id,
+ insert_after=fwr5_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+
+ def test_insert_rule_with_firewall(self):
+ self._fake_router_edge_mapping()
+
+ attrs = self._get_test_firewall_policy_attrs()
+ attrs['audited'] = False
+ attrs['firewall_list'] = []
+ with contextlib.nested(self.firewall_rule(name='fwr0'),
+ self.firewall_rule(name='fwr1'),
+ self.firewall_rule(name='fwr2'),
+ self.firewall_rule(name='fwr3'),
+ self.firewall_rule(name='fwr4'),
+ self.firewall_rule(name='fwr5'),
+ self.firewall_rule(name='fwr6')) as fwr:
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['id'] = fwp_id
+ with self.firewall(router_id=self.router_id,
+ firewall_policy_id=fwp_id) as fw:
+ # test insert when rule list is empty
+ fwr0_id = fwr[0]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr0_id)
+ attrs['firewall_list'].insert(0, fw['firewall']['id'])
+ self._rule_action('insert', fwp_id, fwr0_id,
+ insert_before=None,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert at top of rule list, insert_before and
+ # insert_after not provided
+ fwr1_id = fwr[1]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr1_id)
+ insert_data = {'firewall_rule_id': fwr1_id}
+ self._rule_action(
+ 'insert', fwp_id, fwr0_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs, body_data=insert_data)
+ # test insert at top of list above existing rule
+ fwr2_id = fwr[2]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(0, fwr2_id)
+ self._rule_action('insert', fwp_id, fwr2_id,
+ insert_before=fwr1_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert at bottom of list
+ fwr3_id = fwr[3]['firewall_rule']['id']
+ attrs['firewall_rules'].append(fwr3_id)
+ self._rule_action('insert', fwp_id, fwr3_id,
+ insert_before=None,
+ insert_after=fwr0_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert in the middle of the list using
+ # insert_before
+ fwr4_id = fwr[4]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr4_id)
+ self._rule_action('insert', fwp_id, fwr4_id,
+ insert_before=fwr1_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert in the middle of the list using
+ # insert_after
+ fwr5_id = fwr[5]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr5_id)
+ self._rule_action('insert', fwp_id, fwr5_id,
+ insert_before=None,
+ insert_after=fwr2_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+ # test insert when both insert_before and
+ # insert_after are set
+ fwr6_id = fwr[6]['firewall_rule']['id']
+ attrs['firewall_rules'].insert(1, fwr6_id)
+ self._rule_action('insert', fwp_id, fwr6_id,
+ insert_before=fwr5_id,
+ insert_after=fwr5_id,
+ expected_code=webob.exc.HTTPOk.code,
+ expected_body=attrs)
+
+ def test_remove_rule_with_no_firewall(self):
+ attrs = self._get_test_firewall_policy_attrs()
+ attrs['audited'] = False
+ attrs['firewall_list'] = []
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['id'] = fwp_id
+ with contextlib.nested(self.firewall_rule(name='fwr1'),
+ self.firewall_rule(name='fwr2'),
+ self.firewall_rule(name='fwr3')) as fr1:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr1]
+ attrs['firewall_rules'] = fw_rule_ids[:]
+ data = {'firewall_policy':
+ {'firewall_rules': fw_rule_ids}}
+ req = self.new_update_request('firewall_policies', data,
+ fwp_id)
+ req.get_response(self.ext_api)
+ # test removing a rule from a policy that does not exist
+ self._rule_action('remove', '123', fw_rule_ids[1],
+ expected_code=webob.exc.HTTPNotFound.code,
+ expected_body=None)
+ # test removing a rule in the middle of the list
+ attrs['firewall_rules'].remove(fw_rule_ids[1])
+ self._rule_action('remove', fwp_id, fw_rule_ids[1],
+ expected_body=attrs)
+ # test removing a rule at the top of the list
+ attrs['firewall_rules'].remove(fw_rule_ids[0])
+ self._rule_action('remove', fwp_id, fw_rule_ids[0],
+ expected_body=attrs)
+ # test removing remaining rule in the list
+ attrs['firewall_rules'].remove(fw_rule_ids[2])
+ self._rule_action('remove', fwp_id, fw_rule_ids[2],
+ expected_body=attrs)
+ # test removing rule that is not associated with the policy
+ self._rule_action('remove', fwp_id, fw_rule_ids[2],
+ expected_code=webob.exc.HTTPBadRequest.code,
+ expected_body=None)
+
+ def test_remove_rule_with_firewall(self):
+ self._fake_router_edge_mapping()
+
+ attrs = self._get_test_firewall_policy_attrs()
+ attrs['audited'] = False
+ attrs['firewall_list'] = []
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ attrs['id'] = fwp_id
+ with self.firewall(router_id=self.router_id,
+ firewall_policy_id=fwp_id) as fw:
+ attrs['firewall_list'].insert(0, fw['firewall']['id'])
+ with contextlib.nested(self.firewall_rule(name='fwr1'),
+ self.firewall_rule(name='fwr2'),
+ self.firewall_rule(name='fwr3')) as fr1:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr1]
+ attrs['firewall_rules'] = fw_rule_ids[:]
+ data = {'firewall_policy':
+ {'firewall_rules': fw_rule_ids}}
+ req = self.new_update_request(
+ 'firewall_policies', data, fwp_id)
+ req.get_response(self.ext_api)
+ # test removing a rule from a policy that does not exist
+ self._rule_action(
+ 'remove', '123',
+ fw_rule_ids[1],
+ expected_code=webob.exc.HTTPNotFound.code,
+ expected_body=None)
+ # test removing a rule in the middle of the list
+ attrs['firewall_rules'].remove(fw_rule_ids[1])
+ self._rule_action('remove', fwp_id, fw_rule_ids[1],
+ expected_body=attrs)
+ # test removing a rule at the top of the list
+ attrs['firewall_rules'].remove(fw_rule_ids[0])
+ self._rule_action('remove', fwp_id, fw_rule_ids[0],
+ expected_body=attrs)
+ # test removing remaining rule in the list
+ attrs['firewall_rules'].remove(fw_rule_ids[2])
+ self._rule_action('remove', fwp_id, fw_rule_ids[2],
+ expected_body=attrs)
+ # test removing rule that is not
+ #associated with the policy
+ self._rule_action(
+ 'remove', fwp_id, fw_rule_ids[2],
+ expected_code=webob.exc.HTTPBadRequest.code,
+ expected_body=None)
return []
-class TestNiciraL3NatTestCase(test_l3_plugin.L3NatDBIntTestCase,
- NiciraPluginV2TestCase):
+class NiciraL3NatTest(test_l3_plugin.L3BaseForIntTests,
+ NiciraPluginV2TestCase):
def _restore_l3_attribute_map(self):
l3.RESOURCE_ATTRIBUTE_MAP = self._l3_attribute_map_bk
- def setUp(self, plugin=None, ext_mgr=None):
+ def setUp(self, plugin=None, ext_mgr=None, service_plugins=None):
self._l3_attribute_map_bk = {}
for item in l3.RESOURCE_ATTRIBUTE_MAP:
self._l3_attribute_map_bk[item] = (
cfg.CONF.set_override('api_extensions_path', NVPEXT_PATH)
self.addCleanup(self._restore_l3_attribute_map)
ext_mgr = ext_mgr or TestNiciraL3ExtensionManager()
- super(TestNiciraL3NatTestCase, self).setUp(
- plugin=plugin, ext_mgr=ext_mgr)
+ super(NiciraL3NatTest, self).setUp(
+ plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
plugin_instance = NeutronManager.get_plugin()
self._plugin_name = "%s.%s" % (
plugin_instance.__module__,
plugin_instance.__class__.__name__)
self._plugin_class = plugin_instance.__class__
- def tearDown(self):
- super(TestNiciraL3NatTestCase, self).tearDown()
+
+class TestNiciraL3NatTestCase(NiciraL3NatTest,
+ test_l3_plugin.L3NatDBIntTestCase,
+ NiciraPluginV2TestCase):
def _create_l3_ext_network(self, vlan_id=None):
name = 'l3_ext_net'
+++ /dev/null
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2013 OpenStack Foundation.
-# 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.
import json
from neutron.openstack.common import uuidutils
+from neutron.plugins.nicira.vshield.common import exceptions
class FakeVcns(object):
+ errors = {
+ 303: exceptions.ResourceRedirect,
+ 400: exceptions.RequestBad,
+ 403: exceptions.Forbidden,
+ 404: exceptions.ResourceNotFound,
+ 415: exceptions.MediaTypeUnsupport,
+ 503: exceptions.ServiceUnavailable
+ }
+
def __init__(self, unique_router_name=True):
self._jobs = {}
self._job_idx = 0
self._lswitches = {}
self._unique_router_name = unique_router_name
self._fake_nvpapi = None
+ self.fake_firewall_dict = {}
+ self.temp_firewall = {
+ "firewallRules": {
+ "firewallRules": []
+ }
+ }
def set_fake_nvpapi(self, fake_nvpapi):
self._fake_nvpapi = fake_nvpapi
response = ''
return (header, response)
+ def update_firewall(self, edge_id, fw_req):
+ self.fake_firewall_dict[edge_id] = fw_req
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ index = 10
+ for rule in rules:
+ rule['ruleId'] = index
+ index += 10
+ header = {'status': 204}
+ response = ""
+ return self.return_helper(header, response)
+
+ def delete_firewall(self, edge_id):
+ header = {'status': 404}
+ if edge_id in self.fake_firewall_dict:
+ header = {'status': 204}
+ del self.fake_firewall_dict[edge_id]
+ response = ""
+ return self.return_helper(header, response)
+
+ def update_firewall_rule(self, edge_id, vcns_rule_id, fwr_req):
+ if edge_id not in self.fake_firewall_dict:
+ raise Exception(_("Edge %s does not exist") % edge_id)
+ header = {'status': 404}
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ for rule in rules:
+ if rule['ruleId'] == int(vcns_rule_id):
+ header['status'] = 204
+ rule.update(fwr_req)
+ break
+ response = ""
+ return self.return_helper(header, response)
+
+ def delete_firewall_rule(self, edge_id, vcns_rule_id):
+ if edge_id not in self.fake_firewall_dict:
+ raise Exception(_("Edge %s does not exist") % edge_id)
+ header = {'status': 404}
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ for index in range(len(rules)):
+ if rules[index]['ruleId'] == int(vcns_rule_id):
+ header['status'] = 204
+ del rules[index]
+ break
+ response = ""
+ return self.return_helper(header, response)
+
+ def add_firewall_rule_above(self, edge_id, ref_vcns_rule_id, fwr_req):
+ if edge_id not in self.fake_firewall_dict:
+ raise Exception(_("Edge %s does not exist") % edge_id)
+ header = {'status': 404}
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ pre = 0
+ for index in range(len(rules)):
+ if rules[index]['ruleId'] == int(ref_vcns_rule_id):
+ rules.insert(index, fwr_req)
+ rules[index]['ruleId'] = (int(ref_vcns_rule_id) + pre) / 2
+ header = {
+ 'status': 204,
+ 'location': "https://host/api/4.0/edges/edge_id/firewall"
+ "/config/rules/%s" % rules[index]['ruleId']}
+ break
+ pre = int(rules[index]['ruleId'])
+ response = ""
+ return self.return_helper(header, response)
+
+ def add_firewall_rule(self, edge_id, fwr_req):
+ if edge_id not in self.fake_firewall_dict:
+ self.fake_firewall_dict[edge_id] = self.temp_firewall
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ rules.append(fwr_req)
+ index = len(rules)
+ rules[index - 1]['ruleId'] = index * 10
+ header = {
+ 'status': 204,
+ 'location': "https://host/api/4.0/edges/edge_id/firewall"
+ "/config/rules/%s" % rules[index - 1]['ruleId']}
+ response = ""
+ return self.return_helper(header, response)
+
+ def get_firewall(self, edge_id):
+ if edge_id not in self.fake_firewall_dict:
+ self.fake_firewall_dict[edge_id] = self.temp_firewall
+ header = {'status': 204}
+ response = self.fake_firewall_dict[edge_id]
+ return self.return_helper(header, response)
+
+ def get_firewall_rule(self, edge_id, vcns_rule_id):
+ if edge_id not in self.fake_firewall_dict:
+ raise Exception(_("Edge %s does not exist") % edge_id)
+ header = {'status': 404}
+ response = ""
+ rules = self.fake_firewall_dict[edge_id][
+ 'firewallRules']['firewallRules']
+ for rule in rules:
+ if rule['ruleId'] == int(vcns_rule_id):
+ header['status'] = 204
+ response = rule
+ break
+ return self.return_helper(header, response)
+
+ def return_helper(self, header, response):
+ status = int(header['status'])
+ if 200 <= status <= 300:
+ return (header, response)
+ if status in self.errors:
+ cls = self.errors[status]
+ else:
+ cls = exceptions.VcnsApiException
+ raise cls(
+ status=status, header=header, uri='fake_url', response=response)
+
def reset_all(self):
self._jobs.clear()
self._edges.clear()
self._lswitches.clear()
+ self.fake_firewall_dict = {}
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 VMware, Inc
+#
+# 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.
+#
+# @author: linb, VMware
+
+import contextlib
+import mock
+import webob.exc
+
+from neutron.common import config as n_config
+from neutron import context
+from neutron.db.firewall import firewall_db
+from neutron.openstack.common import uuidutils
+from neutron.plugins.nicira.vshield.common import exceptions as vcns_exc
+from neutron.plugins.nicira.vshield import vcns_driver
+from neutron.tests.unit.db.firewall import test_db_firewall
+from neutron.tests.unit.nicira import get_fake_conf
+from neutron.tests.unit.nicira import VCNS_NAME
+from neutron.tests.unit.nicira.vshield import fake_vcns
+
+
+_uuid = uuidutils.generate_uuid
+
+VSE_ID = 'edge-1'
+ROUTER_ID = '42f95450-5cc9-44e4-a744-1320e592a9d5'
+
+VCNS_CONFIG_FILE = get_fake_conf("vcns.ini.test")
+
+
+class VcnsDriverTestCase(test_db_firewall.FirewallPluginDbTestCase,
+ firewall_db.Firewall_db_mixin):
+
+ def vcns_firewall_patch(self):
+ instance = self.mock_vcns.start()
+ instance.return_value.update_firewall.side_effect = (
+ self.fc2.update_firewall)
+ instance.return_value.delete_firewall.side_effect = (
+ self.fc2.delete_firewall)
+ instance.return_value.update_firewall_rule.side_effect = (
+ self.fc2.update_firewall_rule)
+ instance.return_value.delete_firewall_rule.side_effect = (
+ self.fc2.delete_firewall_rule)
+ instance.return_value.add_firewall_rule_above.side_effect = (
+ self.fc2.add_firewall_rule_above)
+ instance.return_value.add_firewall_rule.side_effect = (
+ self.fc2.add_firewall_rule)
+ instance.return_value.get_firewall.side_effect = (
+ self.fc2.get_firewall)
+ instance.return_value.get_firewall_rule.side_effect = (
+ self.fc2.get_firewall_rule)
+
+ def setUp(self):
+
+ n_config.parse(['--config-file', VCNS_CONFIG_FILE])
+ # mock vcns
+ self.fc2 = fake_vcns.FakeVcns(unique_router_name=False)
+ self.mock_vcns = mock.patch(VCNS_NAME, autospec=True)
+ self.vcns_firewall_patch()
+
+ self.nvp_service_plugin_callback = mock.Mock()
+ self.driver = vcns_driver.VcnsDriver(self.nvp_service_plugin_callback)
+
+ super(VcnsDriverTestCase, self).setUp()
+ self.addCleanup(self.fc2.reset_all)
+ self.addCleanup(self.mock_vcns.stop)
+
+ self.tenant_id = _uuid()
+ self.subnet_id = _uuid()
+
+
+class TestEdgeFwDriver(VcnsDriverTestCase):
+
+ def _make_firewall_dict_with_rules(self, context, firewall_id):
+ fw = self.get_firewall(context, firewall_id)
+ fw_policy_id = fw['firewall_policy_id']
+ if fw_policy_id:
+ firewall_policy_db = self._get_firewall_policy(
+ context, fw_policy_id)
+ fw['firewall_rule_list'] = [
+ self._make_firewall_rule_dict(fw_rule_db)
+ for fw_rule_db in firewall_policy_db['firewall_rules']
+ ]
+
+ return fw
+
+ def _compare_firewall_rule_lists(self, firewall_policy_id,
+ list1, list2):
+ for r1, r2 in zip(list1, list2):
+ rule = r1['firewall_rule']
+ rule['firewall_policy_id'] = firewall_policy_id
+ for k in rule:
+ self.assertEqual(rule[k], r2[k])
+
+ def test_create_and_get_firewall(self):
+ ctx = context.get_admin_context()
+ name = 'firewall'
+ with contextlib.nested(self.firewall_rule(name='fwr1',
+ no_delete=True),
+ self.firewall_rule(name='fwr2',
+ no_delete=True),
+ self.firewall_rule(name='fwr3',
+ no_delete=True)) as fr:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ with self.firewall_policy(firewall_rules=fw_rule_ids,
+ no_delete=True) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_expect)
+ fw_get = self.driver.get_firewall(ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+
+ def test_update_firewall_with_rules(self):
+ ctx = context.get_admin_context()
+ name = 'new_firewall'
+ with contextlib.nested(self.firewall_rule(name='fwr1',
+ no_delete=True),
+ self.firewall_rule(name='fwr2',
+ no_delete=True),
+ self.firewall_rule(name='fwr3',
+ no_delete=True)) as fr:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ with self.firewall_policy(firewall_rules=fw_rule_ids,
+ no_delete=True) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_create = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_create)
+
+ data = {'firewall_rule': {'name': name,
+ 'source_port': '10:20',
+ 'destination_port': '30:40'}}
+ self.new_update_request('firewall_rules', data,
+ fr[0]['firewall_rule']['id'])
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_expect)
+
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+
+ def test_delete_firewall(self):
+ ctx = context.get_admin_context()
+ name = 'firewall'
+ with contextlib.nested(self.firewall_rule(name='fwr1',
+ no_delete=True),
+ self.firewall_rule(name='fwr2',
+ no_delete=True),
+ self.firewall_rule(name='fwr3',
+ no_delete=True)) as fr:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ with self.firewall_policy(firewall_rules=fw_rule_ids,
+ no_delete=True) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_expect)
+ self.driver.delete_firewall(ctx, VSE_ID)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self.assertFalse(fw_get['firewall_rule_list'])
+
+ def test_update_firewall_rule(self):
+ ctx = context.get_admin_context()
+ name = 'new_firewall'
+ with contextlib.nested(self.firewall_rule(name='fwr1',
+ no_delete=True)) as fr:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ with self.firewall_policy(firewall_rules=fw_rule_ids,
+ no_delete=True) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_create = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_create)
+
+ data = {'firewall_rule': {'name': name,
+ 'source_port': '10:20',
+ 'destination_port': '30:40'}}
+ req = self.new_update_request(
+ 'firewall_rules', data,
+ fr[0]['firewall_rule']['id'])
+ res = self.deserialize(self.fmt,
+ req.get_response(self.ext_api))
+ rule_expect = res['firewall_rule']
+ rule_expect['edge_id'] = VSE_ID
+ self.driver.update_firewall_rule(
+ ctx, rule_expect['id'], VSE_ID, rule_expect)
+ rule_get = self.driver.get_firewall_rule(
+ ctx, rule_expect['id'], VSE_ID)
+ for k, v in rule_get['firewall_rule'].items():
+ self.assertEqual(rule_expect[k], v)
+
+ def test_delete_firewall_rule(self):
+ ctx = context.get_admin_context()
+ name = 'new_firewall'
+ with contextlib.nested(self.firewall_rule(name='fwr1',
+ no_delete=True),
+ self.firewall_rule(name='fwr2',
+ no_delete=True)) as fr:
+ fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
+ with self.firewall_policy(firewall_rules=fw_rule_ids,
+ no_delete=True) as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(name=name,
+ firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_create = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_create)
+
+ fr[0]['firewall_rule']['edge_id'] = VSE_ID
+ self.driver.delete_firewall_rule(
+ ctx, fr[0]['firewall_rule']['id'],
+ VSE_ID)
+ self.assertRaises(vcns_exc.VcnsNotFound,
+ self.driver.get_firewall_rule,
+ ctx, fr[0]['firewall_rule']['id'],
+ VSE_ID)
+
+ def test_insert_rule(self):
+ ctx = context.get_admin_context()
+ with self.firewall_policy() as fwp:
+ fwp_id = fwp['firewall_policy']['id']
+ with self.firewall(firewall_policy_id=fwp_id) as firewall:
+ fw_create = firewall['firewall']
+ fw_create = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_create)
+ with contextlib.nested(self.firewall_rule(name='fwr0',
+ no_delete=True),
+ self.firewall_rule(name='fwr1',
+ no_delete=True),
+ self.firewall_rule(name='fwr2',
+ no_delete=True),
+ self.firewall_rule(name='fwr3',
+ no_delete=True),
+ self.firewall_rule(name='fwr4',
+ no_delete=True),
+ self.firewall_rule(name='fwr5',
+ no_delete=True),
+ self.firewall_rule(
+ name='fwr6',
+ no_delete=True)) as fwr:
+ # test insert when rule list is empty
+ fwr0_id = fwr[0]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr0_id,
+ insert_before=None,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code)
+ fw_update = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+ self.driver.update_firewall(ctx, VSE_ID, fw_update)
+ # test insert at top of list above existing rule
+ fwr1_id = fwr[1]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr1_id,
+ insert_before=fwr0_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code)
+
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+
+ rule_info = {'firewall_rule_id': fwr1_id,
+ 'insert_before': fwr0_id,
+ 'insert_after': None}
+ rule = fwr[1]['firewall_rule']
+ self.driver.insert_rule(ctx, rule_info, VSE_ID, rule)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+ # test insert at bottom of list
+ fwr2_id = fwr[2]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr2_id,
+ insert_before=None,
+ insert_after=fwr0_id,
+ expected_code=webob.exc.HTTPOk.code)
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+
+ rule_info = {'firewall_rule_id': fwr2_id,
+ 'insert_before': None,
+ 'insert_after': fwr0_id}
+ rule = fwr[2]['firewall_rule']
+ self.driver.insert_rule(ctx, rule_info, VSE_ID, rule)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+ # test insert in the middle of the list using
+ # insert_before
+ fwr3_id = fwr[3]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr3_id,
+ insert_before=fwr2_id,
+ insert_after=None,
+ expected_code=webob.exc.HTTPOk.code)
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+
+ rule_info = {'firewall_rule_id': fwr3_id,
+ 'insert_before': fwr2_id,
+ 'insert_after': None}
+ rule = fwr[3]['firewall_rule']
+ self.driver.insert_rule(ctx, rule_info, VSE_ID, rule)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+ # test insert in the middle of the list using
+ # insert_after
+ fwr4_id = fwr[4]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr4_id,
+ insert_before=None,
+ insert_after=fwr3_id,
+ expected_code=webob.exc.HTTPOk.code)
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+
+ rule_info = {'firewall_rule_id': fwr4_id,
+ 'insert_before': None,
+ 'insert_after': fwr3_id}
+ rule = fwr[4]['firewall_rule']
+ self.driver.insert_rule(ctx, rule_info, VSE_ID, rule)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
+ # test insert when both insert_before and
+ # insert_after are set
+ fwr5_id = fwr[5]['firewall_rule']['id']
+ self._rule_action('insert', fwp_id, fwr5_id,
+ insert_before=fwr4_id,
+ insert_after=fwr4_id,
+ expected_code=webob.exc.HTTPOk.code)
+ fw_expect = self._make_firewall_dict_with_rules(
+ ctx, fw_create['id'])
+
+ rule_info = {'firewall_rule_id': fwr5_id,
+ 'insert_before': fwr4_id,
+ 'insert_after': fwr4_id}
+ rule = fwr[5]['firewall_rule']
+ self.driver.insert_rule(ctx, rule_info, VSE_ID, rule)
+ fw_get = self.driver.get_firewall(
+ ctx, VSE_ID)
+ self._compare_firewall_rule_lists(
+ fwp_id, fw_get['firewall_rule_list'],
+ fw_expect['firewall_rule_list'])
class L3BaseForIntTests(test_db_plugin.NeutronDbPluginV2TestCase):
- def setUp(self, plugin=None, ext_mgr=None):
+ def setUp(self, plugin=None, ext_mgr=None, service_plugins=None):
test_config['plugin_name_v2'] = (
'neutron.tests.unit.test_l3_plugin.TestL3NatIntPlugin')
# for these tests we need to enable overlapping ips
cfg.CONF.set_default('allow_overlapping_ips', True)
ext_mgr = ext_mgr or L3TestExtensionManager()
test_config['extension_manager'] = ext_mgr
- super(L3BaseForIntTests, self).setUp(plugin=plugin, ext_mgr=ext_mgr)
+ super(L3BaseForIntTests, self).setUp(plugin=plugin, ext_mgr=ext_mgr,
+ service_plugins=service_plugins)
# Set to None to reload the drivers
notifier_api._drivers = None
db_base_plugin_v2.NeutronDbPluginV2):
supported_extension_aliases = [
- "router", "router-service-type",
- "routed-service-insertion", "service-type", "lbaas"
+ "router", "router-service-type", "routed-service-insertion",
+ "service-type", "lbaas"
]
def create_router(self, context, router):
o = method(context, id, fields)
if fields is None or rsi.ROUTER_ID in fields:
rsbind = self._get_resource_router_id_binding(
- context, id, model)
+ context, model, id)
if rsbind:
o[rsi.ROUTER_ID] = rsbind['router_id']
return o
method_name)
method(context, id)
self._delete_resource_router_id_binding(context, id, model)
- if self._get_resource_router_id_binding(context, id, model):
+ if self._get_resource_router_id_binding(context, model, id):
raise Exception("{0}-router binding is not deleted".format(res))
def create_pool(self, context, pool):