Support for NVP advanced FwaaS service

The patch adds advanced FWaaS service support for NVP with
VCNS:
        * NVP FWaaS is an advanced Service of NVP depending on NVP
          advanced service router
            - Once an advanced router id created, one corresponding
              vshield edge will be deployed, and then we can configure
              FW service on the vshield edge
        * NVP FWaaS service plugin still uses FWaaS DB service logic,
          while finally calling vShield Edge to support FWaaS service
            - When firewall object is created, we will attach the
              object to the advanced router with routedserviceinsertion_db
              service
        * on driver part, the driver will first convert the object
          to VSM known object input, and then send a synchronous JSON
          calling to VSM, and receive the result

Implements: blueprint nvp-fwaas-plugin
Change-Id: Id43af8821f5c553356e3cc870993eef99ef7def3
This commit is contained in:
berlin 2013-08-22 15:58:58 +08:00 committed by Kaiwei Fan
parent 4afee8006c
commit db9c24a519
22 changed files with 2026 additions and 65 deletions

View File

@ -0,0 +1,60 @@
# 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')

View File

@ -65,13 +65,34 @@ class RoutedServiceInsertionDbMixin(object):
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'],
@ -82,6 +103,6 @@ class RoutedServiceInsertionDbMixin(object):
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)

View File

@ -34,6 +34,12 @@ EXTENDED_ATTRIBUTES_2_0 = {
'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},
}
}

View File

@ -1,4 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 VMware, Inc.
# All Rights Reserved
@ -18,13 +18,16 @@
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
@ -38,6 +41,7 @@ from neutron.plugins.nicira.vshield.common.constants import RouterStatus
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__)
@ -66,11 +70,15 @@ ROUTER_STATUS_LEVEL = {
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):
@ -652,7 +660,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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
@ -664,7 +672,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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
@ -675,7 +683,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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)
@ -687,7 +695,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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)
@ -701,7 +709,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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)
@ -717,16 +725,291 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
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
except exceptions.BadRequest as e:
self._firewall_set_status(
context, fw['id'], service_constants.ERROR)
LOG.exception(_("Bad Firewall request Input"))
raise e
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
"""Edge callback implementation Callback functions for
asynchronous tasks.
"""
def __init__(self, plugin):
self.plugin = plugin

View File

@ -62,3 +62,17 @@ class MaintenanceInProgress(NvpPluginException):
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")

View File

@ -15,6 +15,9 @@
# 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
@ -48,3 +51,47 @@ def delete_vcns_router_binding(session, router_id):
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()

View File

@ -36,3 +36,18 @@ class VcnsRouterBinding(model_base.BASEV2, models_v2.HasStatusDescription):
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))

View File

@ -1,7 +1,7 @@
# 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

View File

@ -29,6 +29,14 @@ class VcnsGeneralException(VcnsException):
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.")

View File

@ -0,0 +1,354 @@
# 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)

View File

@ -28,6 +28,10 @@ HTTP_DELETE = "DELETE"
HTTP_PUT = "PUT"
URI_PREFIX = "/api/4.0/edges"
#FwaaS constants
FIREWALL_SERVICE = "firewall/config"
FIREWALL_RULE_RESOURCE = "rules"
class Vcns(object):
@ -106,3 +110,69 @@ 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

View File

@ -20,11 +20,13 @@ from oslo.config import cfg
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__()
@ -40,5 +42,4 @@ class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver):
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)

View File

@ -58,23 +58,25 @@ class FirewallPluginDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase):
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,

View File

@ -22,13 +22,18 @@ from neutron.plugins.nicira import extensions
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__)
@ -38,6 +43,9 @@ SERVICE_PLUGIN_NAME = '%s.%s' % (nvp_service_plugin.__module__,
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):

View File

@ -61,15 +61,17 @@ class ServiceRouterTestExtensionManager(object):
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 = (
@ -93,7 +95,7 @@ class ServiceRouterTestCase(NvpRouterTestCase):
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")
@ -103,8 +105,11 @@ class ServiceRouterTestCase(NvpRouterTestCase):
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)
@ -122,7 +127,7 @@ class ServiceRouterTestCase(NvpRouterTestCase):
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,
@ -145,6 +150,9 @@ class ServiceRouterTestCase(NvpRouterTestCase):
return router_req.get_response(self.ext_api)
class ServiceRouterTestCase(ServiceRouterTest, NvpRouterTestCase):
def test_router_create(self):
name = 'router1'
tenant_id = _uuid()

View File

@ -0,0 +1,564 @@
# 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)

View File

@ -474,13 +474,13 @@ class TestNiciraL3ExtensionManager(object):
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] = (
@ -488,16 +488,18 @@ class TestNiciraL3NatTestCase(test_l3_plugin.L3NatDBIntTestCase,
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'

View File

@ -1,16 +0,0 @@
# 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.

View File

@ -20,10 +20,20 @@ import copy
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
@ -32,6 +42,12 @@ class FakeVcns(object):
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
@ -243,7 +259,123 @@ class FakeVcns(object):
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 = {}

View File

@ -0,0 +1,381 @@
# 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'])

View File

@ -1653,14 +1653,15 @@ class L3AgentDbTestCaseBase(L3NatTestCaseMixin):
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

View File

@ -52,8 +52,8 @@ class RouterServiceInsertionTestPlugin(
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):
@ -104,7 +104,7 @@ class RouterServiceInsertionTestPlugin(
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
@ -116,7 +116,7 @@ class RouterServiceInsertionTestPlugin(
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):