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:
parent
4afee8006c
commit
db9c24a519
@ -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')
|
@ -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)
|
||||
|
@ -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},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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.")
|
||||
|
||||
|
354
neutron/plugins/nicira/vshield/edge_firewall_driver.py
Normal file
354
neutron/plugins/nicira/vshield/edge_firewall_driver.py
Normal 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)
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
564
neutron/tests/unit/nicira/test_fwaas_plugin.py
Normal file
564
neutron/tests/unit/nicira/test_fwaas_plugin.py
Normal 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)
|
@ -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'
|
||||
|
@ -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.
|
@ -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 = {}
|
||||
|
381
neutron/tests/unit/nicira/vshield/test_firewall_driver.py
Normal file
381
neutron/tests/unit/nicira/vshield/test_firewall_driver.py
Normal 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'])
|
@ -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
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user