diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 158720083..000000000 --- a/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = neutron_fwaas -omit = neutron_fwaas/tests/* - -[report] -ignore_errors = True diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15da71cf2..000000000 --- a/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -AUTHORS -build/* -build-stamp -ChangeLog -cover/ -covhtml/ -dist/ -doc/build -doc/source/_static/config_samples/*.sample -doc/source/_static/*.policy.yaml.sample -doc/source/contributor/api/ -etc/*.sample -*.DS_Store -*.pyc -neutron.egg-info/ -neutron_fwaas.egg-info/ -neutron/vcsversion.py -neutron/versioninfo -pbr*.egg/ -run_tests.err.log -run_tests.log -setuptools*.egg/ -subunit.log -*.mo -*.sw? -*~ -/.* -!/.coveragerc -!/.gitignore -!/.gitreview -!/.mailmap -!/.pylintrc -!/.zuul.yaml -!/.stestr.conf - -# Files created by releasenotes build -releasenotes/build diff --git a/.mailmap b/.mailmap deleted file mode 100644 index f3e7e5e1a..000000000 --- a/.mailmap +++ /dev/null @@ -1,11 +0,0 @@ -# Format is: -# -# -lawrancejing -Jiajun Liu -Zhongyue Luo -Kun Huang -Zhenguo Niu -Isaku Yamahata -Isaku Yamahata -Morgan Fainberg diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 0aa449044..000000000 --- a/.pylintrc +++ /dev/null @@ -1,130 +0,0 @@ -# The format of this file isn't really documented; just use --generate-rcfile -[MASTER] -# Add to the black list. It should be a base name, not a -# path. You may set this option multiple times. -# -ignore=.git,tests - -[MESSAGES CONTROL] -# NOTE(gus): This is a long list. A number of these are important and -# should be re-enabled once the offending code is fixed (or marked -# with a local disable) -disable= -# "F" Fatal errors that prevent further processing - import-error, -# "I" Informational noise - locally-disabled, -# "E" Error for important programming issues (likely bugs) - access-member-before-definition, - bad-super-call, - maybe-no-member, - no-member, - no-method-argument, - no-self-argument, - not-callable, - no-value-for-parameter, - super-on-old-class, - too-few-format-args, -# "W" Warnings for stylistic problems or minor programming issues - abstract-method, - anomalous-backslash-in-string, - anomalous-unicode-escape-in-string, - arguments-differ, - attribute-defined-outside-init, - bad-builtin, - bad-indentation, - broad-except, - dangerous-default-value, - deprecated-lambda, - duplicate-key, - expression-not-assigned, - fixme, - global-statement, - global-variable-not-assigned, - logging-not-lazy, - no-init, - non-parent-init-called, - pointless-string-statement, - protected-access, - redefined-builtin, - redefined-outer-name, - redefine-in-handler, - signature-differs, - star-args, - super-init-not-called, - unnecessary-lambda, - unnecessary-pass, - unpacking-non-sequence, - unreachable, - unused-argument, - unused-import, - unused-variable, -# TODO(dougwig) - disable nonstandard-exception while we have neutron_lib shims - nonstandard-exception, -# "C" Coding convention violations - bad-continuation, - invalid-name, - missing-docstring, - old-style-class, - superfluous-parens, -# "R" Refactor recommendations - abstract-class-little-used, - abstract-class-not-used, - duplicate-code, - interface-not-implemented, - no-self-use, - too-few-public-methods, - too-many-ancestors, - too-many-arguments, - too-many-branches, - too-many-instance-attributes, - too-many-lines, - too-many-locals, - too-many-public-methods, - too-many-return-statements, - too-many-statements - -[BASIC] -# Variable names can be 1 to 31 characters long, with lowercase and underscores -variable-rgx=[a-z_][a-z0-9_]{0,30}$ - -# Argument names can be 2 to 31 characters long, with lowercase and underscores -argument-rgx=[a-z_][a-z0-9_]{1,30}$ - -# Method names should be at least 3 characters long -# and be lowercased with underscores -method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$ - -# Module names matching neutron-* are ok (files in bin/) -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$ - -# Don't require docstrings on tests. -no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ - -[FORMAT] -# Maximum number of characters on a single line. -max-line-length=79 - -[VARIABLES] -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -# _ is used by our localization -additional-builtins=_ - -[CLASSES] -# List of interface methods to ignore, separated by a comma. -ignore-iface-methods= - -[IMPORTS] -# Deprecated modules which should not be used, separated by a comma -deprecated-modules= -# should use oslo_serialization.jsonutils - json - -[TYPECHECK] -# List of module names for which member attributes should not be checked -ignored-modules=six.moves,_MovedItems - -[REPORTS] -# Tells whether to display a full report or only the messages -reports=no diff --git a/.stestr.conf b/.stestr.conf deleted file mode 100644 index bd1baede4..000000000 --- a/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=${OS_TEST_PATH:-./neutron_fwaas/tests/unit} -top_dir=./ diff --git a/.zuul.yaml b/.zuul.yaml deleted file mode 100644 index e0ec897bf..000000000 --- a/.zuul.yaml +++ /dev/null @@ -1,72 +0,0 @@ -- project: - templates: - - check-requirements - - openstack-cover-jobs-neutron - - openstack-lower-constraints-jobs-neutron - - openstack-python3-ussuri-jobs-neutron - - periodic-stable-jobs-neutron - - publish-openstack-docs-pti - - release-notes-jobs-python3 - check: - jobs: - - neutron-fwaas-functional - - neutron-tempest-plugin-fwaas - - neutron-fwaas-v2-dsvm-tempest-multinode: - voting: false - gate: - jobs: - - neutron-fwaas-functional - - neutron-tempest-plugin-fwaas - experimental: - jobs: - - neutron-fwaas-fullstack - -- job: - name: neutron-fwaas-functional - parent: neutron-functional - vars: - project_name: neutron-fwaas - -- job: - name: neutron-fwaas-fullstack - parent: neutron-fullstack - vars: - project_name: neutron-fwaas - -- job: - name: neutron-fwaas-v2-dsvm-tempest-multinode - parent: tempest-multinode-full-py3 - roles: - - zuul: openstack/devstack - required-projects: - - openstack/devstack-gate - - openstack/neutron - - openstack/neutron-fwaas - - openstack/neutron-tempest-plugin - - openstack/tempest - vars: - tox_envlist: all-plugin - tempest_test_regex: ^neutron_tempest_plugin\.fwaas - devstack_plugins: - neutron: https://opendev.org/openstack/neutron.git - neutron-fwaas: https://opendev.org/openstack/neutron-fwaas.git - neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git - devstack_services: - q-fwaas-v2: true - devstack_localrc: - NETWORK_API_EXTENSIONS: "agent,binding,dhcp_agent_scheduler,external-net,ext-gw-mode,extra_dhcp_opts,quotas,router,security-group,subnet_allocation,network-ip-availability,auto-allocated-topology,timestamp_core,tag,service-type,rbac-policies,standard-attr-description,pagination,sorting,project-id,fwaas_v2" - group-vars: - subnode: - devstack_services: - q-agt: true - devstack_localrc: - USE_PYTHON3: true - devstack_local_conf: - post-config: - # NOTE(slaweq): We can get rid of this hardcoded absolute path when - # devstack-tempest job will be switched to use lib/neutron instead of - # lib/neutron-legacy - "/$NEUTRON_CORE_PLUGIN_CONF": - ovs: - tunnel_bridge: br-tun - bridge_mappings: public:br-ex diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 7d446b44a..000000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,4 +0,0 @@ -Please see the Neutron CONTRIBUTING.rst file for how to contribute to -neutron-fwaas: - -`Neutron CONTRIBUTING.rst `_ diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 6ad86a5ca..000000000 --- a/HACKING.rst +++ /dev/null @@ -1,7 +0,0 @@ -Neutron FWaaS Style Commandments -================================ - -Please see the Neutron HACKING.rst file for style commandments for -neutron-fwaas: - -`Neutron HACKING.rst `_ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 68c771a09..000000000 --- a/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/README.rst b/README.rst index b3a7ea108..86e34d67c 100644 --- a/README.rst +++ b/README.rst @@ -1,38 +1,10 @@ -======================== -Team and repository tags -======================== +This project is no longer maintained. -.. image:: https://governance.openstack.org/tc/badges/neutron-fwaas.svg - :target: https://governance.openstack.org/tc/reference/tags/index.html +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". -.. Change things from this point on - -.. warning:: - Due to lack of maintainers this project is now deprecated in the Neutron - stadium and will be removed from stadium in ``W`` cycle. - If You want to step in and be maintainer of this project to keep it in the - Neutron stadium, please contact the ``neutron team`` via - openstack-discuss@lists.openstack.org or IRC channel #openstack-neutron - @freenode. - -Welcome! -======== - -This package contains the code for the Neutron Firewall as a Service -(FWaaS) service. This package requires Neutron to run. - -External Resources: -=================== - -The homepage for Neutron is: https://launchpad.net/neutron. Use this -site for asking for help, and filing bugs. We use a single Launchpad -page for all Neutron projects. - -Code is available on git.openstack.org at: -. - -Please refer to Neutron documentation for more information: -`Neutron README.rst `_ - -Get release notes: -`Neutron FWaaS Release Notes `_ +For any further questions, please email +openstack-discuss@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/TESTING.rst b/TESTING.rst deleted file mode 100644 index 9a9fc2f33..000000000 --- a/TESTING.rst +++ /dev/null @@ -1,12 +0,0 @@ -Testing Neutron FWaaS -===================== - -Please see the TESTING.rst file for the Neutron project itself. This will have -the latest up to date instructions for how to test Neutron, and will -be applicable to neutron-fwaas as well: - -`Neutron TESTING.rst `_ - -For instructions on how to use FWaaS with devstack, look at: - -`Neutron-FWaaS DevStack `_ diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb76..000000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/bindep.txt b/bindep.txt deleted file mode 100644 index 86fab166e..000000000 --- a/bindep.txt +++ /dev/null @@ -1,10 +0,0 @@ -# This file contains runtime (non-python) dependencies -# More info at: http://docs.openstack.org/infra/bindep/readme.html - -# MySQL and PostgreSQL databases since some jobs are set up in -# OpenStack infra that need these like -libpq-dev [test] - -# Packages required e.g. in functional tests -libnetfilter-log1 [platform:dpkg platform:suse] -libnetfilter-log [platform:rpm !platform:suse] diff --git a/devstack/README.rst b/devstack/README.rst deleted file mode 100644 index 3d76f196b..000000000 --- a/devstack/README.rst +++ /dev/null @@ -1,30 +0,0 @@ -========================= -neutron-fwaas in DevStack -========================= - -This is setup as a DevStack plugin. For more information on DevStack plugins, -see the `DevStack Plugins documentation -`_. - -Please note that the old 'q-fwaas' keyword still exists, You can specify -enable_service q-fwaas or enable_service q-fwaas-v2 in local.conf - -How to run FWaaS V2 in DevStack -=============================== - -Add the following to the localrc section of your local.conf to configure -FWaaS v2. - -.. code-block:: ini - - [[local|localrc]] - enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas - -To check a specific patchset that is currently under development, use a form -like the below example, which is checking out change 214350 patch set 14 for -testing. - -.. code-block:: ini - - [[local|localrc]] - enable_plugin neutron-fwaas https://review.openstack.org/p/openstack/neutron-fwaas refs/changes/50/214350/14 diff --git a/devstack/lib/l2_agent b/devstack/lib/l2_agent deleted file mode 100644 index 1f1ca9d02..000000000 --- a/devstack/lib/l2_agent +++ /dev/null @@ -1,16 +0,0 @@ -# This file was shamelessly stolen from the neutron repository here: -# https://opendev.org/openstack/neutron/src/branch/master/devstack/lib/l2_agent - -function plugin_agent_add_l2_agent_extension { - local l2_agent_extension=$1 - if [[ -z "$L2_AGENT_EXTENSIONS" ]]; then - L2_AGENT_EXTENSIONS=$l2_agent_extension - elif [[ ! ,${L2_AGENT_EXTENSIONS}, =~ ,${l2_agent_extension}, ]]; then - L2_AGENT_EXTENSIONS+=",$l2_agent_extension" - fi -} - - -function configure_l2_agent { - iniset /$Q_PLUGIN_CONF_FILE agent extensions "$L2_AGENT_EXTENSIONS" -} diff --git a/devstack/lib/l3_agent b/devstack/lib/l3_agent deleted file mode 100644 index d3541d315..000000000 --- a/devstack/lib/l3_agent +++ /dev/null @@ -1,16 +0,0 @@ -# This file is completely based on one in the neutron repository here: -# https://opendev.org/openstack/neutron/src/branch/master/devstack/lib/l2_agent - -function plugin_agent_add_l3_agent_extension { - local l3_agent_extension=$1 - if [[ -z "$L3_AGENT_EXTENSIONS" ]]; then - L3_AGENT_EXTENSIONS=$l3_agent_extension - elif [[ ! ,${L3_AGENT_EXTENSIONS}, =~ ,${l3_agent_extension}, ]]; then - L3_AGENT_EXTENSIONS+=",$l3_agent_extension" - fi -} - - -function configure_l3_agent { - iniset $Q_L3_CONF_FILE agent extensions "$L3_AGENT_EXTENSIONS" -} diff --git a/devstack/plugin.sh b/devstack/plugin.sh deleted file mode 100755 index 138659d85..000000000 --- a/devstack/plugin.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -# 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. - -# Dependencies: -# -# ``functions`` file -# ``DEST`` must be defined - -# Save trace setting -XTRACE=$(set +o | grep xtrace) -set +o xtrace - -# Source in L2 and L3 agent extension management -LIBDIR=$DEST/neutron-fwaas/devstack/lib -source $LIBDIR/l2_agent -source $LIBDIR/l3_agent - -function install_fwaas() { - # Install the service. - : - setup_develop $DEST/neutron-fwaas - if is_ubuntu; then - install_package libnetfilter-log1 - else - # EPEL - install_package libnetfilter_log - fi -} - -function configure_fwaas_v2() { - # Add conf file - cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf.sample $NEUTRON_FWAAS_CONF - neutron_server_config_add $NEUTRON_FWAAS_CONF - inicomment $NEUTRON_FWAAS_CONF service_providers service_provider - iniadd $NEUTRON_FWAAS_CONF service_providers service_provider $NEUTRON_FWAAS_SERVICE_PROVIDERV2 - - neutron_fwaas_configure_driver fwaas_v2 - if is_service_enabled q-l3; then - iniset_multiline $Q_L3_CONF_FILE fwaas agent_version v2 - iniset_multiline $Q_L3_CONF_FILE fwaas driver $FWAAS_DRIVER_V2 - fi - if is_service_enabled q-agt; then - # TODO(hoangcx) we can remove the slashes below once neutron-legacy has gone - iniset /$NEUTRON_CORE_PLUGIN_CONF fwaas firewall_l2_driver $FW_L2_DRIVER - iniset /$NEUTRON_CORE_PLUGIN_CONF agent extensions fwaas_v2 - fi -} - -function configure_l3_log_fwaas_v2(){ - if is_service_enabled q-l3; then - iniadd $Q_L3_CONF_FILE agent extensions fwaas_v2_log - fi -} - -function neutron_fwaas_generate_config_files { - (cd $NEUTRON_FWAAS_DIR && exec ./tools/generate_config_file_samples.sh) -} - -function init_fwaas() { - # Initialize and start the service. - : - # Using sudo to gain the root privilege to be able to copy file to rootwrap.d - sudo cp $DEST/neutron-fwaas/etc/neutron/rootwrap.d/fwaas-privsep.filters /etc/neutron/rootwrap.d/fwaas-privsep.filters -} - -function shutdown_fwaas() { - # Shut the service down. - : -} - -function cleanup_fwaas() { - # Cleanup the service. - : - if is_ubuntu; then - uninstall_package libnetfilter-log1 - else - # EPEL - uninstall_package libnetfilter_log - fi -} - -function neutron_fwaas_configure_common { - neutron_service_plugin_class_add $FWAAS_PLUGIN_V2 -} - -function neutron_fwaas_configure_driver { - if is_service_enabled q-l3; then - plugin_agent_add_l3_agent_extension $1 - configure_l3_agent - iniset_multiline $Q_L3_CONF_FILE fwaas enabled True - fi -} - -# check for service enabled -if is_service_enabled q-svc neutron-api && is_service_enabled q-fwaas q-fwaas-v2 neutron-fwaas-v2; then - - if [[ "$1" == "stack" && "$2" == "install" ]]; then - # Perform installation of service source - echo_summary "Installing neutron-fwaas" - install_fwaas - - elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then - # Configure after the other layer 1 and 2 services have been configured - neutron_fwaas_configure_common - neutron_fwaas_generate_config_files - echo_summary "Configuring neutron-fwaas for FWaaS v2" - configure_fwaas_v2 - if is_service_enabled q-log neutron-log; then - echo_summary "Configuring FwaaS V2 packet log for l3 extension" - configure_l3_log_fwaas_v2 - fi - - elif [[ "$1" == "stack" && "$2" == "extra" ]]; then - # Initialize and start the neutron-fwaas service - echo_summary "Initializing neutron-fwaas" - init_fwaas - fi - - if [[ "$1" == "unstack" ]]; then - # Shut down neutron-fwaas services - # no-op - shutdown_fwaas - fi - - if [[ "$1" == "clean" ]]; then - # Remove state and transient data - # Remember clean.sh first calls unstack.sh - # no-op - cleanup_fwaas - fi -fi - -# Restore xtrace -$XTRACE diff --git a/devstack/settings b/devstack/settings deleted file mode 100644 index e3b3b58fa..000000000 --- a/devstack/settings +++ /dev/null @@ -1,12 +0,0 @@ -FWAAS_DRIVER_V2=${FWAAS_DRIVER_V2:-iptables_v2} -FW_L2_DRIVER=${FW_L2_DRIVER:-noop} -FWAAS_PLUGIN_V2=${FWAAS_PLUGIN:-firewall_v2} - -NEUTRON_FWAAS_DIR=$DEST/neutron-fwaas -NEUTRON_FWAAS_CONF_FILE=neutron_fwaas.conf - -NEUTRON_FWAAS_CONF=$NEUTRON_CONF_DIR/$NEUTRON_FWAAS_CONF_FILE - -NEUTRON_FWAAS_SERVICE_PROVIDERV2=${NEUTRON_FWAAS_SERVICE_PROVIDERV2:-FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default} - -enable_service q-fwaas-v2 diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index b75bacac1..000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD -sphinxcontrib-apidoc>=0.2.0 # BSD -sphinxmark>=0.1.14 # Apache-2.0 -openstackdocstheme>=1.18.1 # Apache-2.0 -reno>=2.5.0 # Apache-2.0 diff --git a/doc/source/_static/.placeholder b/doc/source/_static/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index 2f8d1f6ff..000000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,311 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2010 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. - -# -# Keystone documentation build configuration file, created by -# sphinx-quickstart on Tue May 18 13:50:15 2010. -# -# This file is execfile()'d with the current directory set to it's containing -# dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -ROOT_DIR = os.path.abspath(os.path.join(BASE_DIR, "..", "..")) -sys.path.insert(0, ROOT_DIR) - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinxcontrib.apidoc', - 'sphinx.ext.coverage', - 'sphinx.ext.ifconfig', - 'sphinx.ext.graphviz', - 'sphinx.ext.todo', - 'oslo_config.sphinxext', - 'oslo_config.sphinxconfiggen', - 'oslo_policy.sphinxext', - 'oslo_policy.sphinxpolicygen', - 'openstackdocstheme',] - -try: - import openstackdocstheme - extensions.append('openstackdocstheme') -except ImportError: - openstackdocstheme = None - -todo_include_todos = True - -# sphinxcontrib.apidoc options -apidoc_module_dir = '../../neutron_fwaas' -apidoc_output_dir = 'contributor/api' -# TODO(hoangcx): remove 'services/logapi/*' and -# 'services/firewall/fwaas_plugin_v2.py' after the next neutron release -# (current release is Rocky-3) - -# NOTE(longkb): Due to libnetfilter_log library is not installed in sphinx-docs -# gate, so we would like to ignore 'privileged/netfilter_log/*'. - -apidoc_excluded_paths = [ - 'db/migration/alembic_migrations/*', - 'privileged/netfilter_log/*', - 'services/firewall/fwaas_plugin_v2.py', - 'services/logapi/*', - 'setup.py', - 'tests/*', - 'tests'] -apidoc_separate_modules = True - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Neutron FWaaS' -copyright = u'2011-present, OpenStack Foundation.' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# Version info -from neutron_fwaas.version import version_info as neutron_fwaas_version -release = neutron_fwaas_version.release_string() -# The short X.Y version. -version = neutron_fwaas_version.version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -# unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['neutron_fwaas.'] - -# -- Options for man page output -------------------------------------------- - -# Grouping the document tree for man pages. -# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' - -#man_pages = [ -# ('man/neutron-server', 'neutron-server', u'Neutron Server', -# [u'OpenStack'], 1) -#] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -if openstackdocstheme is not None: - html_theme = 'openstackdocs' -else: - html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = ['_theme'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -#htmlhelp_basename = 'neutrondoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, -# documentclass [howto/manual]). -latex_documents = [ - ('index', 'doc-neutron-fwaas.tex', - u'Neutron Firewall-as-s-Service Documentation', - u'Neutron development team', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 -latex_use_xindy = False - -latex_domain_indices = False - -latex_elements = { - 'makeindex': '', - 'printindex': '', - 'preamble': r'\setcounter{tocdepth}{3}', -} - -# -- Options for openstackdocstheme ------------------------------------------- -repository_name = 'openstack/neutron-fwaas' -bug_project = 'neutron' -bug_tag = 'doc' - -# -- Options for oslo_config.sphinxconfiggen --------------------------------- - -_config_generator_config_files = [ - 'fwaas_driver.ini', - 'neutron_fwaas.conf', -] - - -def _get_config_generator_config_definition(conf): - config_file_path = '../../etc/oslo-config-generator/%s' % conf - # oslo_config.sphinxconfiggen appends '.conf.sample' to the filename, - # strip file extentension (.conf or .ini). - output_file_path = '_static/config_samples/%s' % conf.rsplit('.', 1)[0] - return (config_file_path, output_file_path) - - -config_generator_config_file = [ - _get_config_generator_config_definition(conf) - for conf in _config_generator_config_files -] - -# -- Options for oslo_policy.sphinxpolicygen --------------------------------- - -policy_generator_config_file = '../../etc/oslo-policy-generator/policy.conf' -sample_policy_basename = '_static/neutron-fwaas' diff --git a/doc/source/configuration/fwaas_driver.rst b/doc/source/configuration/fwaas_driver.rst deleted file mode 100644 index 015740d3f..000000000 --- a/doc/source/configuration/fwaas_driver.rst +++ /dev/null @@ -1,6 +0,0 @@ -================ -fwaas_driver.ini -================ - -.. show-options:: - :config-file: etc/oslo-config-generator/fwaas_driver.ini diff --git a/doc/source/configuration/index.rst b/doc/source/configuration/index.rst deleted file mode 100644 index 988ea7e7d..000000000 --- a/doc/source/configuration/index.rst +++ /dev/null @@ -1,41 +0,0 @@ -.. _configuring: - -================================= -Neutron FWaaS Configuration Guide -================================= - -This section provides a list of all possible options for each -configuration file. - -Configuration -------------- - -Neutron FWaaS uses the following configuration files for its various services. - -.. toctree:: - :maxdepth: 1 - - neutron_fwaas - fwaas_driver - -The following are sample configuration files for Neutron FWaaS and utilities. -These are generated from code and reflect the current state of code -in the neutron-fwaas repository. - -.. toctree:: - :glob: - :maxdepth: 1 - - samples/* - -Policy ------- - -Neutron FWaaS, like most OpenStack projects, uses a policy language to restrict -permissions on REST API actions. - -.. toctree:: - :maxdepth: 1 - - Policy Reference - Sample Policy File diff --git a/doc/source/configuration/neutron_fwaas.rst b/doc/source/configuration/neutron_fwaas.rst deleted file mode 100644 index e390f0f1b..000000000 --- a/doc/source/configuration/neutron_fwaas.rst +++ /dev/null @@ -1,6 +0,0 @@ -================== -neutron_fwaas.conf -================== - -.. show-options:: - :config-file: etc/oslo-config-generator/neutron_fwaas.conf diff --git a/doc/source/configuration/policy-sample.rst b/doc/source/configuration/policy-sample.rst deleted file mode 100644 index d5c9cd537..000000000 --- a/doc/source/configuration/policy-sample.rst +++ /dev/null @@ -1,16 +0,0 @@ -================================ -Sample Neutron FWaaS Policy File -================================ - -The following is a sample neutron-fwaas policy file for adaptation and use. - -The sample policy can also be viewed in :download:`file form -`. - -.. important:: - - The sample policy file is auto-generated from neutron-fwaas when this - documentation is built. You must ensure your version of neutron-fwaas - matches the version of this documentation. - -.. literalinclude:: /_static/neutron-fwaas.policy.yaml.sample diff --git a/doc/source/configuration/policy.rst b/doc/source/configuration/policy.rst deleted file mode 100644 index 697aa96d7..000000000 --- a/doc/source/configuration/policy.rst +++ /dev/null @@ -1,9 +0,0 @@ -====================== -neutron-fwaas policies -====================== - -The following is an overview of all available policies in neutron-fwaas. -For a sample configuration file, refer to :doc:`/configuration/policy-sample`. - -.. show-policy:: - :config-file: etc/oslo-policy-generator/policy.conf diff --git a/doc/source/configuration/samples/fwaas_driver.rst b/doc/source/configuration/samples/fwaas_driver.rst deleted file mode 100644 index 2314f4ce4..000000000 --- a/doc/source/configuration/samples/fwaas_driver.rst +++ /dev/null @@ -1,8 +0,0 @@ -======================= -Sample fwaas_driver.ini -======================= - -This sample configuration can also be viewed in `the raw format -<../../_static/config_samples/fwaas_driver.conf.sample>`_. - -.. literalinclude:: ../../_static/config_samples/fwaas_driver.conf.sample diff --git a/doc/source/configuration/samples/neutron_fwaas.rst b/doc/source/configuration/samples/neutron_fwaas.rst deleted file mode 100644 index 1e1fd0ced..000000000 --- a/doc/source/configuration/samples/neutron_fwaas.rst +++ /dev/null @@ -1,8 +0,0 @@ -========================= -Sample neutron_fwaas.conf -========================= - -This sample configuration can also be viewed in `the raw format -<../../_static/config_samples/neutron_fwaas.conf.sample>`_. - -.. literalinclude:: ../../_static/config_samples/neutron_fwaas.conf.sample diff --git a/doc/source/contributor/contributing.rst b/doc/source/contributor/contributing.rst deleted file mode 100644 index a163a5e62..000000000 --- a/doc/source/contributor/contributing.rst +++ /dev/null @@ -1,28 +0,0 @@ -============================= -Contributing to neutron-fwaas -============================= - -If you would like to contribute to the development of OpenStack, you must -follow the steps documented at: -https://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack should be submitted -for review via the Gerrit tool, following the workflow documented at: -https://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad in the 'neutron' project: -https://bugs.launchpad.net/neutron - -To get in touch with the neutron-fwaas community, -look at the following resources: - -- Join the #openstack-fwaas IRC channel on Freenode. This is where the - FireWall-as-a-Service team is available for discussion. -- Join the `FireWall-as-a-Service weekly IRC meeting - `_ - where the status of new initiatives and bugs is discussed. - -These are a great places to get recommendations on where to start contributing -to neutron-fwaas. diff --git a/doc/source/contributor/devstack.rst b/doc/source/contributor/devstack.rst deleted file mode 100644 index da85f63d0..000000000 --- a/doc/source/contributor/devstack.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../devstack/README.rst diff --git a/doc/source/contributor/fwaas_v2.rst b/doc/source/contributor/fwaas_v2.rst deleted file mode 100644 index 8ee0662fc..000000000 --- a/doc/source/contributor/fwaas_v2.rst +++ /dev/null @@ -1,7 +0,0 @@ -FireWall as a Service V2 -======================== - -The `FireWall as a Service API V2 -`_ -specification lists the changes that together compose FWaaS V2. These changes -are not fully implemented. diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst deleted file mode 100644 index ca3f7d137..000000000 --- a/doc/source/contributor/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -================= -Contributor Guide -================= - -.. toctree:: - :maxdepth: 2 - - contributing - fwaas_v2 - devstack - -.. API reference contains a lot of sections, toctree with maxdepth 1 is used. -.. toctree:: - :glob: - :maxdepth: 1 - - modules diff --git a/doc/source/contributor/modules.rst b/doc/source/contributor/modules.rst deleted file mode 100644 index b1a5cbe52..000000000 --- a/doc/source/contributor/modules.rst +++ /dev/null @@ -1,19 +0,0 @@ -================ -Module Reference -================ - -.. The module reference is rendered in HTML version much much better. - PDF version is not good for reading due to page width, lack of TOC - in subsections and so on, so we skip the module reference in PDF version. - -.. only:: html - - .. toctree:: - :maxdepth: 1 - :glob: - - api/* - -.. only:: latex - - See the online version of this document for the module reference. diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 55cc5a123..000000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -=========================== -neutron-fwaas documentation -=========================== - -.. warning:: - Due to lack of maintainers this project is now deprecated in the Neutron - stadium and will be removed from stadium in ``W`` cycle. - If You want to step in and be maintainer of this project to keep it in the - Neutron stadium, please contact the ``neutron team`` via - openstack-discuss@lists.openstack.org or IRC channel #openstack-neutron - @freenode. - -.. toctree:: - :glob: - :maxdepth: 2 - - install/index - configuration/index - contributor/index - -.. only:: html - - .. rubric:: Indices and tables - - * :ref:`genindex` - * :ref:`modindex` - * :ref:`search` diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst deleted file mode 100644 index 69044d889..000000000 --- a/doc/source/install/index.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. - 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. - - - Convention for heading levels in Neutron devref: - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - (Avoid deeper levels because they do not render well.) - - -============ -Installation -============ - -At the command line:: - - $ pip install neutron-fwaas - -Or, if you have virtualenvwrapper installed:: - - $ mkvirtualenv neutron-fwaas - $ pip install neutron-fwaas - -For information on what to do with FWaaS once it is installed, please check the -Networking Guide `Firewall-as-a-Service (FWaaS) v2 scenario `_ or -the `Firewall-as-a-Service (FWaaS) v1 scenario `_. diff --git a/etc/README.txt b/etc/README.txt deleted file mode 100644 index 074e68141..000000000 --- a/etc/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -To generate the sample neutron-fwaas configuration files, run the following -command from the top level of the neutron-fwaas directory: - -tox -e genconfig - -If a 'tox' environment is unavailable, then you can run the following script -instead to generate the configuration files: - -./tools/generate_config_file_samples.sh diff --git a/etc/neutron/rootwrap.d/fwaas-privsep.filters b/etc/neutron/rootwrap.d/fwaas-privsep.filters deleted file mode 100644 index 6b631417d..000000000 --- a/etc/neutron/rootwrap.d/fwaas-privsep.filters +++ /dev/null @@ -1,7 +0,0 @@ -# neutron-fwaas privsep filters - -# This file should be owned by (and only-writeable by) the root user - -[Filters] - -privsep-rootwrap: PathFilter, privsep-helper, root, privsep-helper, --config-file, /etc/(?!\.\.).*, --privsep_context, neutron_fwaas.privileged.default diff --git a/etc/oslo-config-generator/fwaas_driver.ini b/etc/oslo-config-generator/fwaas_driver.ini deleted file mode 100644 index aa5205db7..000000000 --- a/etc/oslo-config-generator/fwaas_driver.ini +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -output_file = etc/fwaas_driver.ini.sample -wrap_width = 79 - -namespace = firewall.agent diff --git a/etc/oslo-config-generator/neutron_fwaas.conf b/etc/oslo-config-generator/neutron_fwaas.conf deleted file mode 100644 index ba145acdd..000000000 --- a/etc/oslo-config-generator/neutron_fwaas.conf +++ /dev/null @@ -1,6 +0,0 @@ -[DEFAULT] -output_file = etc/neutron_fwaas.conf.sample -wrap_width = 79 - -namespace = neutron.fwaas - diff --git a/etc/oslo-policy-generator/policy.conf b/etc/oslo-policy-generator/policy.conf deleted file mode 100644 index 8e4aef649..000000000 --- a/etc/oslo-policy-generator/policy.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -output_file = etc/policy.yaml.sample -namespace = neutron-fwaas diff --git a/lower-constraints.txt b/lower-constraints.txt deleted file mode 100644 index 80cedb19a..000000000 --- a/lower-constraints.txt +++ /dev/null @@ -1,147 +0,0 @@ -alabaster==0.7.10 -alembic==0.8.10 -amqp==2.1.1 -appdirs==1.4.3 -Babel==2.3.4 -beautifulsoup4==4.6.0 -cachetools==2.0.0 -cffi==1.7.0 -chardet==3.0.4 -cliff==2.8.0 -cmd2==0.8.0 -contextlib2==0.4.0 -coverage==4.0 -debtcollector==1.2.0 -decorator==3.4.0 -deprecation==1.0 -doc8==0.6.0 -docutils==0.11 -dogpile.cache==0.6.2 -dulwich==0.15.0 -eventlet==0.18.2 -extras==1.0.0 -fasteners==0.7.0 -fixtures==3.0.0 -flake8-import-order==0.12 -flake8==2.6.2 -future==0.16.0 -futurist==1.2.0 -greenlet==0.4.10 -hacking==1.1.0 -httplib2==0.9.1 -imagesize==0.7.1 -iso8601==0.1.11 -Jinja2==2.10 -jmespath==0.9.0 -jsonpatch==1.16 -jsonpointer==1.13 -jsonschema==2.6.0 -keystoneauth1==3.4.0 -keystonemiddleware==4.17.0 -kombu==4.0.0 -linecache2==1.0.0 -logutils==0.3.5 -Mako==0.4.0 -MarkupSafe==1.0 -mccabe==0.2.1 -mock==2.0.0 -monotonic==0.6 -mox3==0.20.0 -msgpack-python==0.4.0 -munch==2.1.0 -netaddr==0.7.18 -netifaces==0.10.4 -neutron-lib==1.26.0 -neutron==14.0.0.0b3 -openstackdocstheme==1.18.1 -openstacksdk==0.11.2 -os-client-config==1.28.0 -os-ken==0.3.0 -os-service-types==1.2.0 -os-xenapi==0.3.1 -osc-lib==1.8.0 -oslo.cache==1.26.0 -oslo.concurrency==3.26.0 -oslo.config==5.2.0 -oslo.context==2.19.2 -oslo.db==4.37.0 -oslo.i18n==3.15.3 -oslo.log==3.36.0 -oslo.messaging==5.29.0 -oslo.middleware==3.31.0 -oslo.policy==1.30.0 -oslo.privsep==1.32.0 -oslo.reports==1.18.0 -oslo.rootwrap==5.8.0 -oslo.serialization==2.18.0 -oslo.service==1.24.0 -oslo.utils==3.33.0 -oslo.versionedobjects==1.31.2 -oslotest==3.2.0 -osprofiler==1.4.0 -ovs==2.8.0 -ovsdbapp==0.9.1 -Paste==2.0.2 -PasteDeploy==1.5.0 -pbr==4.0.0 -pecan==1.3.2 -pep8==1.5.7 -pika-pool==0.1.3 -pika==0.10.0 -positional==1.2.1 -prettytable==0.7.2 -psutil==3.2.2 -psycopg2==2.7.3 -pycadf==1.1.0 -pycodestyle==2.4.0 -pycparser==2.18 -pyflakes==0.8.1 -Pygments==2.2.0 -pyinotify==0.9.6 -PyMySQL==0.7.6 -pyparsing==2.1.0 -pyperclip==1.5.27 -pyroute2==0.5.3 -python-dateutil==2.5.3 -python-designateclient==2.7.0 -python-editor==1.0.3 -python-keystoneclient==3.8.0 -python-mimeparse==1.6.0 -python-neutronclient==6.7.0 -python-novaclient==9.1.0 -python-subunit==1.0.0 -pytz==2013.6 -PyYAML==3.12 -pyzmq==14.3.1 -reno==2.5.0 -repoze.lru==0.7 -requests-mock==1.2.0 -requests==2.14.2 -requestsexceptions==1.2.0 -restructuredtext-lint==1.1.1 -rfc3986==0.3.1 -Routes==2.3.1 -simplejson==3.5.1 -six==1.10.0 -snowballstemmer==1.2.1 -sphinx==1.6.5 -sqlalchemy-migrate==0.11.0 -SQLAlchemy==1.2.0 -sqlparse==0.2.2 -statsd==3.2.1 -stestr==1.0.0 -stevedore==1.20.0 -Tempita==0.5.2 -tenacity==3.2.1 -testrepository==0.0.18 -testresources==2.0.0 -testscenarios==0.4 -testtools==2.2.0 -tinyrpc==0.6 -traceback2==1.4.0 -unittest2==1.1.0 -vine==1.1.4 -waitress==1.1.0 -WebOb==1.8.2 -WebTest==2.0.27 -wrapt==1.7.0 diff --git a/neutron_fwaas/__init__.py b/neutron_fwaas/__init__.py deleted file mode 100644 index 208ffbf15..000000000 --- a/neutron_fwaas/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import gettext - -import six - - -if six.PY2: - gettext.install('neutron', unicode=1) -else: - gettext.install('neutron') diff --git a/neutron_fwaas/_i18n.py b/neutron_fwaas/_i18n.py deleted file mode 100644 index e28f57522..000000000 --- a/neutron_fwaas/_i18n.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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 oslo_i18n - -DOMAIN = "neutron_fwaas" - -_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN) - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# The contextual translation function using the name "_C" -_C = _translators.contextual_form - -# The plural translation function using the name "_P" -_P = _translators.plural_form - - -def get_available_languages(): - return oslo_i18n.get_available_languages(DOMAIN) diff --git a/neutron_fwaas/cmd/__init__.py b/neutron_fwaas/cmd/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/cmd/upgrade_checks/__init__.py b/neutron_fwaas/cmd/upgrade_checks/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/cmd/upgrade_checks/checks.py b/neutron_fwaas/cmd/upgrade_checks/checks.py deleted file mode 100644 index 610b6968e..000000000 --- a/neutron_fwaas/cmd/upgrade_checks/checks.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2019 Red Hat 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. - -from neutron_lib.utils import upgrade_checks as base_checks -from oslo_config import cfg -from oslo_upgradecheck import upgradecheck - -from neutron_fwaas._i18n import _ - - -class Checks(base_checks.BaseChecks): - - def get_checks(self): - return [ - (_("Check FWaaS v1"), self.fwaas_v1_check) - ] - - @staticmethod - def fwaas_v1_check(checker): - fwaas_v1_names = [ - 'firewall', - 'neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin'] - for name in fwaas_v1_names: - if name in cfg.CONF.service_plugins: - return upgradecheck.Result( - upgradecheck.Code.FAILURE, - _("FWaaS v1 is removed. " - "FWaaS v2 should be used instead.")) - return upgradecheck.Result(upgradecheck.Code.SUCCESS) diff --git a/neutron_fwaas/cmd/v1_to_v2_db_migration.py b/neutron_fwaas/cmd/v1_to_v2_db_migration.py deleted file mode 100644 index fa681e637..000000000 --- a/neutron_fwaas/cmd/v1_to_v2_db_migration.py +++ /dev/null @@ -1,136 +0,0 @@ -# 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. - -from neutron.common import config -from neutron.db import models_v2 -from oslo_config import cfg -from oslo_db.sqlalchemy import enginefacade -from oslo_log import log as logging - -from neutron_fwaas.db.firewall import firewall_db as firewall_db_v1 -from neutron_fwaas.db.firewall.v2 import firewall_db_v2 - -LOG = logging.getLogger(__name__) - - -def setup_conf(): - cli_opts = [ - cfg.StrOpt('neutron-db-connection', - required=True, - help=_('neutron database connection string')), - ] - conf = cfg.CONF - conf.register_cli_opts(cli_opts) - conf() - - -def migrate_fwaas_v1_to_v2(db_session): - # the entire migration process will be done under the same transaction to - # allow full rollback in case of error - with db_session.begin(subtransactions=True): - # Read all V1 policies - v1_policies = db_session.query(firewall_db_v1.FirewallPolicy) - - for v1_pol in v1_policies: - LOG.info("Migrating FWaaS V1 policy %s", v1_pol.id) - # read the rules of this policy - v1_rules = db_session.query(firewall_db_v1.FirewallRule).filter_by( - firewall_policy_id=v1_pol.id).all() - # Create the V2 policy - v2_pol = firewall_db_v2.FirewallPolicy( - id=v1_pol.id, - tenant_id=v1_pol.tenant_id, - name=v1_pol.name, - description=v1_pol.description, - shared=v1_pol.shared, - audited=v1_pol.audited, - rule_count=len(v1_rules)) - db_session.add(v2_pol) - - # Add the rules and associate them with the policy - for v1_rule in v1_rules: - LOG.info("Migrating FWaaS V1 rule %s", v1_rule.id) - v2_rule = firewall_db_v2.FirewallRuleV2( - id=v1_rule.id, - name=v1_rule.name, - description=v1_rule.description, - tenant_id=v1_rule.tenant_id, - shared=v1_rule.shared, - protocol=v1_rule.protocol, - ip_version=v1_rule.ip_version, - source_ip_address=v1_rule.source_ip_address, - destination_ip_address=v1_rule.destination_ip_address, - source_port_range_min=v1_rule.source_port_range_min, - source_port_range_max=v1_rule.source_port_range_max, - destination_port_range_min=( - v1_rule.destination_port_range_min), - destination_port_range_max=( - v1_rule.destination_port_range_max), - action=v1_rule.action, - enabled=v1_rule.enabled) - db_session.add(v2_rule) - v2_link = firewall_db_v2.FirewallPolicyRuleAssociation( - firewall_policy_id=v1_pol.id, - firewall_rule_id=v1_rule.id, - position=v1_rule.position) - db_session.add(v2_link) - - # Read all V1 firewalls - v1_fws = db_session.query(firewall_db_v1.Firewall) - for v1_fw in v1_fws: - LOG.info("Migrating FWaaS V1 firewall %s", v1_fw.id) - # create the V2 firewall group - v2_fw_group = firewall_db_v2.FirewallGroup( - id=v1_fw.id, - name=v1_fw.name, - description=v1_fw.description, - tenant_id=v1_fw.tenant_id, - shared=v1_fw.shared, - admin_state_up=v1_fw.admin_state_up, - status=v1_fw.status, - ingress_firewall_policy_id=v1_fw.firewall_policy_id, - egress_firewall_policy_id=v1_fw.firewall_policy_id) - db_session.add(v2_fw_group) - - # for every router in the V1 Firewall router association, add all - # its interface ports to the V2 FirewallGroupPortAssociation - v1_routers = db_session.query( - firewall_db_v1.FirewallRouterAssociation).filter_by( - fw_id=v1_fw.id) - for v1_router in v1_routers: - rtr_id = v1_router.router_id - LOG.info("Migrating FWaaS V1 %s router %s", v1_fw.id, rtr_id) - if_ports = db_session.query(models_v2.Port).filter_by( - device_id=rtr_id, - device_owner="network:router_interface") - for port in if_ports: - fw_port = firewall_db_v2.FirewallGroupPortAssociation( - firewall_group_id=v2_fw_group.id, - port_id=port.id) - db_session.add(fw_port) - - -def main(): - # Initialize the cli options - setup_conf() - config.setup_logging() - - # Get the neutron DB session - neutron_context_manager = enginefacade.transaction_context() - neutron_context_manager.configure( - connection=cfg.CONF.neutron_db_connection) - n_session_maker = neutron_context_manager.writer.get_sessionmaker() - n_session = n_session_maker(autocommit=True) - - # Run DB migration - migrate_fwaas_v1_to_v2(n_session) - LOG.info("DB migration done.") diff --git a/neutron_fwaas/common/__init__.py b/neutron_fwaas/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/common/exceptions.py b/neutron_fwaas/common/exceptions.py deleted file mode 100644 index 261a9d476..000000000 --- a/neutron_fwaas/common/exceptions.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2018 Fujitsu Limited. -# 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. - -from neutron_lib import exceptions as n_exc - -from neutron_fwaas._i18n import _ - - -# TODO(annp): migrate to neutron-lib after Queen release -class FirewallGroupPortNotSupported(n_exc.Conflict): - message = _("Port %(port_id)s is not supported by firewall driver " - "'%(driver_name)s'.") diff --git a/neutron_fwaas/common/fwaas_constants.py b/neutron_fwaas/common/fwaas_constants.py deleted file mode 100644 index c21006975..000000000 --- a/neutron_fwaas/common/fwaas_constants.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2015 Cisco Systems, 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. - -FIREWALL = 'FIREWALL' -FIREWALL_V2 = 'FIREWALL_V2' - -# Constants for "topics" -FIREWALL_PLUGIN = 'q-firewall-plugin' -FW_AGENT = 'firewall_agent' -FIREWALL_RULE_LIST = 'firewall_rule_list' - -# V2 Constants -DEFAULT_FWG = 'default' -DEFAULT_FWP_INGRESS = 'default ingress' -DEFAULT_FWP_EGRESS = 'default egress' - -# Firewall group events for agent-side -DELETE_FWG = 'delete_firewall_group' -UPDATE_FWG = 'update_firewall_group' -CREATE_FWG = 'create_firewall_group' - -# Port events for L2 agent extension -HANDLE_PORT = 'handle_port' -DELETE_PORT = 'delete_port' - -# Resource name - -FIREWALL_GROUP = 'firewall_group' -FIREWALL_RULE = 'firewall_rule' -FIREWALL_POLICY = 'firewall_policy' diff --git a/neutron_fwaas/common/resources.py b/neutron_fwaas/common/resources.py deleted file mode 100644 index 7f6fee431..000000000 --- a/neutron_fwaas/common/resources.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -from neutron_fwaas.db.firewall.v2 import firewall_db_v2 - -FIREWALL_GROUP = firewall_db_v2.FirewallGroup -FIREWALL_POLICY = firewall_db_v2.FirewallPolicy -FIREWALL_RULE = firewall_db_v2.FirewallRuleV2 diff --git a/neutron_fwaas/db/__init__.py b/neutron_fwaas/db/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/firewall/__init__.py b/neutron_fwaas/db/firewall/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/firewall/firewall_db.py b/neutron_fwaas/db/firewall/firewall_db.py deleted file mode 100644 index f3d2018a5..000000000 --- a/neutron_fwaas/db/firewall/firewall_db.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2013 Big Switch Networks, 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. - -from neutron_lib.db import model_base -import sqlalchemy as sa -from sqlalchemy.ext.orderinglist import ordering_list -from sqlalchemy import orm - - -# Note(annp): Keep firewall db v1 structure for migration -class FirewallRule(model_base.BASEV2, model_base.HasId, model_base.HasProject): - """Represents a Firewall rule.""" - __tablename__ = 'firewall_rules' - __table_args__ = ({'mysql_collate': 'utf8_bin'}) - name = sa.Column(sa.String(255)) - description = sa.Column(sa.String(1024)) - firewall_policy_id = sa.Column(sa.String(36), - sa.ForeignKey('firewall_policies.id'), - nullable=True) - shared = sa.Column(sa.Boolean) - protocol = sa.Column(sa.String(40)) - ip_version = sa.Column(sa.Integer, nullable=False) - source_ip_address = sa.Column(sa.String(46)) - destination_ip_address = sa.Column(sa.String(46)) - source_port_range_min = sa.Column(sa.Integer) - source_port_range_max = sa.Column(sa.Integer) - destination_port_range_min = sa.Column(sa.Integer) - destination_port_range_max = sa.Column(sa.Integer) - action = sa.Column(sa.Enum('allow', 'deny', 'reject', - name='firewallrules_action')) - enabled = sa.Column(sa.Boolean) - position = sa.Column(sa.Integer) - - -class Firewall(model_base.BASEV2, model_base.HasId, model_base.HasProject): - """Represents a Firewall resource.""" - __tablename__ = 'firewalls' - __table_args__ = ({'mysql_collate': 'utf8_bin'}) - name = sa.Column(sa.String(255)) - description = sa.Column(sa.String(1024)) - shared = sa.Column(sa.Boolean) - admin_state_up = sa.Column(sa.Boolean) - status = sa.Column(sa.String(16)) - firewall_policy_id = sa.Column(sa.String(36), - sa.ForeignKey('firewall_policies.id'), - nullable=True) - - -class FirewallPolicy(model_base.BASEV2, model_base.HasId, - model_base.HasProject): - """Represents a Firewall Policy resource.""" - __tablename__ = 'firewall_policies' - __table_args__ = ({'mysql_collate': 'utf8_bin'}) - name = sa.Column(sa.String(255)) - description = sa.Column(sa.String(1024)) - shared = sa.Column(sa.Boolean) - firewall_rules = orm.relationship( - FirewallRule, - backref=orm.backref('firewall_policies', cascade='all, delete'), - order_by='FirewallRule.position', - collection_class=ordering_list('position', count_from=1)) - audited = sa.Column(sa.Boolean) - firewalls = orm.relationship(Firewall, backref='firewall_policies') - - -class FirewallRouterAssociation(model_base.BASEV2): - - """Tracks FW Router Association""" - - __tablename__ = 'firewall_router_associations' - - fw_id = sa.Column(sa.String(36), - sa.ForeignKey('firewalls.id', ondelete="CASCADE"), - primary_key=True) - router_id = sa.Column(sa.String(36), - sa.ForeignKey('routers.id', ondelete="CASCADE"), - primary_key=True) diff --git a/neutron_fwaas/db/firewall/v2/__init__.py b/neutron_fwaas/db/firewall/v2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/firewall/v2/firewall_db_v2.py b/neutron_fwaas/db/firewall/v2/firewall_db_v2.py deleted file mode 100644 index 20977f499..000000000 --- a/neutron_fwaas/db/firewall/v2/firewall_db_v2.py +++ /dev/null @@ -1,1101 +0,0 @@ -# Copyright (c) 2016 -# 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 copy - -import netaddr - -from neutron_lib import constants as nl_constants -from neutron_lib.db import api as db_api -from neutron_lib.db import constants as db_constants -from neutron_lib.db import model_base -from neutron_lib.db import model_query -from neutron_lib.db import utils as db_utils -from neutron_lib import exceptions -from neutron_lib.exceptions import firewall_v2 as f_exc -from oslo_config import cfg -from oslo_db import exception as db_exc -from oslo_log import log as logging -from oslo_utils import uuidutils -import sqlalchemy as sa -from sqlalchemy.ext.orderinglist import ordering_list -from sqlalchemy import or_ -from sqlalchemy import orm -from sqlalchemy.orm import exc - -from neutron_fwaas.common import fwaas_constants as const - - -LOG = logging.getLogger(__name__) - - -class FirewallDefaultParameterExists(exceptions.InUse): - """Default Firewall Parameter conflict exception - - Occurs when user creates/updates any existing firewall resource with - reserved parameter names. - """ - message = ("Operation cannot be performed since '%(name)s' " - "is a reserved name for %(resource_type)s.") - - -class FirewallDefaultObjectUpdateRestricted(FirewallDefaultParameterExists): - message = ("Operation cannot be performed on default object " - "'%(resource_id)s' of type %(resource_type)s.") - - -class HasName(object): - name = sa.Column(sa.String(db_constants.NAME_FIELD_SIZE)) - - -class HasDescription(object): - description = sa.Column( - sa.String(db_constants.LONG_DESCRIPTION_FIELD_SIZE)) - - -class FirewallRuleV2(model_base.BASEV2, model_base.HasId, HasName, - HasDescription, model_base.HasProject): - __tablename__ = "firewall_rules_v2" - shared = sa.Column(sa.Boolean) - protocol = sa.Column(sa.String(40)) - ip_version = sa.Column(sa.Integer) - source_ip_address = sa.Column(sa.String(46)) - destination_ip_address = sa.Column(sa.String(46)) - source_port_range_min = sa.Column(sa.Integer) - source_port_range_max = sa.Column(sa.Integer) - destination_port_range_min = sa.Column(sa.Integer) - destination_port_range_max = sa.Column(sa.Integer) - action = sa.Column(sa.Enum('allow', 'deny', 'reject', - name='firewallrules_action')) - enabled = sa.Column(sa.Boolean) - - -class FirewallGroup(model_base.BASEV2, model_base.HasId, HasName, - HasDescription, model_base.HasProject): - __tablename__ = 'firewall_groups_v2' - port_associations = orm.relationship( - 'FirewallGroupPortAssociation', - backref=orm.backref('firewall_group_port_associations_v2', - cascade='all, delete')) - name = sa.Column(sa.String(db_constants.NAME_FIELD_SIZE)) - description = sa.Column( - sa.String(db_constants.LONG_DESCRIPTION_FIELD_SIZE)) - ingress_firewall_policy_id = sa.Column( - sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_policies_v2.id')) - egress_firewall_policy_id = sa.Column( - sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_policies_v2.id')) - admin_state_up = sa.Column(sa.Boolean) - status = sa.Column(sa.String(db_constants.STATUS_FIELD_SIZE)) - shared = sa.Column(sa.Boolean) - - -class DefaultFirewallGroup(model_base.BASEV2, model_base.HasProjectPrimaryKey): - __tablename__ = "default_firewall_groups" - firewall_group_id = sa.Column(sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_groups_v2.id', - ondelete="CASCADE"), - nullable=False) - firewall_group = orm.relationship( - FirewallGroup, lazy='joined', - backref=orm.backref('default_firewall_group', cascade='all,delete'), - primaryjoin="FirewallGroup.id==DefaultFirewallGroup.firewall_group_id", - ) - - -class FirewallGroupPortAssociation(model_base.BASEV2): - __tablename__ = 'firewall_group_port_associations_v2' - firewall_group_id = sa.Column(sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_groups_v2.id', - ondelete="CASCADE"), - primary_key=True) - port_id = sa.Column(sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('ports.id', ondelete="CASCADE"), - unique=True, - primary_key=True) - - -class FirewallPolicyRuleAssociation(model_base.BASEV2): - - """Tracks FW Policy and Rule(s) Association""" - - __tablename__ = 'firewall_policy_rule_associations_v2' - - firewall_policy_id = sa.Column(sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_policies_v2.id', - ondelete="CASCADE"), - primary_key=True) - firewall_rule_id = sa.Column(sa.String(db_constants.UUID_FIELD_SIZE), - sa.ForeignKey('firewall_rules_v2.id', - ondelete="CASCADE"), - primary_key=True) - position = sa.Column(sa.Integer) - - -class FirewallPolicy(model_base.BASEV2, model_base.HasId, HasName, - HasDescription, model_base.HasProject): - __tablename__ = 'firewall_policies_v2' - name = sa.Column(sa.String(db_constants.NAME_FIELD_SIZE)) - description = sa.Column( - sa.String(db_constants.LONG_DESCRIPTION_FIELD_SIZE)) - rule_count = sa.Column(sa.Integer) - audited = sa.Column(sa.Boolean) - rule_associations = orm.relationship( - FirewallPolicyRuleAssociation, - backref=orm.backref('firewall_policies_v2', cascade='all, delete'), - order_by='FirewallPolicyRuleAssociation.position', - collection_class=ordering_list('position', count_from=1)) - shared = sa.Column(sa.Boolean) - - -def _list_firewall_groups_result_filter_hook(query, filters): - values = filters and filters.get('ports', []) - if values: - query = query.join(FirewallGroupPortAssociation) - query = query.filter(FirewallGroupPortAssociation.port_id.in_(values)) - - return query - - -def _list_firewall_policies_result_filter_hook(query, filters): - values = filters and filters.get('firewall_rules', []) - if values: - query = query.join(FirewallPolicyRuleAssociation) - query = query.filter( - FirewallPolicyRuleAssociation.firewall_rule_id.in_(values)) - - return query - - -class FirewallPluginDb(object): - - def __new__(cls, *args, **kwargs): - model_query.register_hook( - FirewallGroup, - "firewall_group_v2_filter_by_port_association", - query_hook=None, - filter_hook=None, - result_filters=_list_firewall_groups_result_filter_hook) - - model_query.register_hook( - FirewallPolicy, - "firewall_policy_v2_filter_by_firewall_rule_association", - query_hook=None, - filter_hook=None, - result_filters=_list_firewall_policies_result_filter_hook) - return super(FirewallPluginDb, cls).__new__(cls, *args, **kwargs) - - def _get_firewall_group(self, context, id): - try: - return model_query.get_by_id(context, FirewallGroup, id) - except exc.NoResultFound: - raise f_exc.FirewallGroupNotFound(firewall_id=id) - - def _get_firewall_policy(self, context, id): - try: - return model_query.get_by_id(context, FirewallPolicy, id) - except exc.NoResultFound: - raise f_exc.FirewallPolicyNotFound(firewall_policy_id=id) - - def _get_firewall_rule(self, context, id): - try: - return model_query.get_by_id(context, FirewallRuleV2, id) - except exc.NoResultFound: - raise f_exc.FirewallRuleNotFound(firewall_rule_id=id) - - def _validate_fwr_protocol_parameters(self, fwr): - protocol = fwr['protocol'] - source_port = fwr['source_port'] - dest_port = fwr['destination_port'] - - if protocol and protocol not in (nl_constants.PROTO_NAME_TCP, - nl_constants.PROTO_NAME_UDP): - if source_port or dest_port: - raise f_exc.FirewallRuleInvalidICMPParameter( - param="Source, destination port") - - if not protocol and (source_port or dest_port): - raise f_exc.FirewallRuleWithPortWithoutProtocolInvalid() - - def _validate_fwr_src_dst_ip_version(self, fwr, fwr_db=None): - src_version = dst_version = None - if fwr.get('source_ip_address', None): - src_version = netaddr.IPNetwork(fwr['source_ip_address']).version - if fwr.get('destination_ip_address', None): - dst_version = netaddr.IPNetwork( - fwr['destination_ip_address']).version - rule_ip_version = fwr.get('ip_version', None) - if not rule_ip_version and fwr_db: - rule_ip_version = fwr_db.ip_version - if ((src_version and src_version != rule_ip_version) or - (dst_version and dst_version != rule_ip_version)): - raise f_exc.FirewallIpAddressConflict() - - def _validate_fwr_port_range(self, min_port, max_port): - if int(min_port) > int(max_port): - port_range = '%s:%s' % (min_port, max_port) - raise f_exc.FirewallRuleInvalidPortValue(port=port_range) - - 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 - self._validate_fwr_port_range(min_port, max_port) - return [int(min_port), int(max_port)] - - 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) - self._validate_fwr_port_range(min_port, max_port) - return '%s:%s' % (min_port, max_port) - - def _make_firewall_rule_dict(self, firewall_rule, fields=None, - policies=None): - src_port_range = self._get_port_range_from_min_max_ports( - firewall_rule['source_port_range_min'], - firewall_rule['source_port_range_max']) - dst_port_range = self._get_port_range_from_min_max_ports( - firewall_rule['destination_port_range_min'], - firewall_rule['destination_port_range_max']) - res = {'id': firewall_rule['id'], - 'tenant_id': firewall_rule['tenant_id'], - 'name': firewall_rule['name'], - 'description': firewall_rule['description'], - 'protocol': firewall_rule['protocol'], - 'firewall_policy_id': policies, - 'ip_version': firewall_rule['ip_version'], - 'source_ip_address': firewall_rule['source_ip_address'], - 'destination_ip_address': - firewall_rule['destination_ip_address'], - 'source_port': src_port_range, - 'destination_port': dst_port_range, - 'action': firewall_rule['action'], - 'enabled': firewall_rule['enabled'], - 'shared': firewall_rule['shared']} - return db_utils.resource_fields(res, fields) - - def _make_firewall_policy_dict(self, firewall_policy, fields=None): - fw_rules = [ - rule_association.firewall_rule_id - for rule_association in firewall_policy['rule_associations']] - res = {'id': firewall_policy['id'], - 'tenant_id': firewall_policy['tenant_id'], - 'name': firewall_policy['name'], - 'description': firewall_policy['description'], - 'audited': firewall_policy['audited'], - 'firewall_rules': fw_rules, - 'shared': firewall_policy['shared']} - return db_utils.resource_fields(res, fields) - - def _make_firewall_group_dict(self, firewall_group_db, fields=None): - fwg_ports = [port_assoc.port_id for port_assoc in - firewall_group_db.port_associations] - res = {'id': firewall_group_db['id'], - 'tenant_id': firewall_group_db['tenant_id'], - 'name': firewall_group_db['name'], - 'description': firewall_group_db['description'], - 'ingress_firewall_policy_id': - firewall_group_db['ingress_firewall_policy_id'], - 'egress_firewall_policy_id': - firewall_group_db['egress_firewall_policy_id'], - 'admin_state_up': firewall_group_db['admin_state_up'], - 'ports': fwg_ports, - 'status': firewall_group_db['status'], - 'shared': firewall_group_db['shared']} - return db_utils.resource_fields(res, fields) - - def _get_policy_ordered_rules(self, context, policy_id): - query = (context.session.query(FirewallRuleV2) - .join(FirewallPolicyRuleAssociation) - .filter_by(firewall_policy_id=policy_id) - .order_by(FirewallPolicyRuleAssociation.position)) - return [self._make_firewall_rule_dict(rule) for rule in query] - - def make_firewall_group_dict_with_rules(self, context, firewall_group_id): - firewall_group = self.get_firewall_group(context, firewall_group_id) - ingress_policy_id = firewall_group['ingress_firewall_policy_id'] - if ingress_policy_id: - firewall_group['ingress_rule_list'] = ( - self._get_policy_ordered_rules(context, ingress_policy_id)) - else: - firewall_group['ingress_rule_list'] = [] - - egress_policy_id = firewall_group['egress_firewall_policy_id'] - if egress_policy_id: - firewall_group['egress_rule_list'] = ( - self._get_policy_ordered_rules(context, egress_policy_id)) - else: - firewall_group['egress_rule_list'] = [] - return firewall_group - - def _check_firewall_rule_conflict(self, fwr_db, fwp_db): - if not fwr_db['shared']: - if fwr_db['tenant_id'] != fwp_db['tenant_id']: - raise f_exc.FirewallRuleConflict( - firewall_rule_id=fwr_db['id'], - project_id=fwr_db['tenant_id']) - - def _process_rule_for_policy(self, context, firewall_policy_id, - firewall_rule_id, position, association_db): - with context.session.begin(subtransactions=True): - fwp_query = context.session.query( - FirewallPolicy).with_lockmode('update') - fwp_db = fwp_query.filter_by(id=firewall_policy_id).one() - if position: - # Note that although position numbering starts at 1, - # internal ordering of the list starts at 0, so we compensate. - fwp_db.rule_associations.insert( - position - 1, - FirewallPolicyRuleAssociation( - firewall_rule_id=firewall_rule_id)) - else: - fwp_db.rule_associations.remove(association_db) - context.session.delete(association_db) - fwp_db.rule_associations.reorder() - fwp_db.audited = False - return self._make_firewall_policy_dict(fwp_db) - - def _get_policy_rule_association_query(self, context, firewall_policy_id, - firewall_rule_id): - fwpra_query = context.session.query(FirewallPolicyRuleAssociation) - return fwpra_query.filter_by(firewall_policy_id=firewall_policy_id, - firewall_rule_id=firewall_rule_id) - - def _ensure_rule_not_already_associated(self, context, firewall_policy_id, - firewall_rule_id): - """Checks that a rule is not already associated with a particular - policy. If it is the function will throw an exception. - """ - try: - self._get_policy_rule_association_query( - context, firewall_policy_id, firewall_rule_id).one() - raise f_exc.FirewallRuleAlreadyAssociated( - firewall_rule_id=firewall_rule_id, - firewall_policy_id=firewall_policy_id) - except exc.NoResultFound: - return - - def _get_policy_rule_association(self, context, firewall_policy_id, - firewall_rule_id): - """Returns the association between a firewall rule and a firewall - policy. Throws an exception if the assocition does not exist. - """ - try: - return self._get_policy_rule_association_query( - context, firewall_policy_id, firewall_rule_id).one() - except exc.NoResultFound: - raise f_exc.FirewallRuleNotAssociatedWithPolicy( - firewall_rule_id=firewall_rule_id, - firewall_policy_id=firewall_policy_id) - - def _create_default_firewall_rules(self, context, tenant_id): - # NOTE(xgerman) Maybe generating the final set of rules from a - # configuration file makes sense. Can be done some time later - - # 1. Firewall rule for ingress IPv4 packets (DROP by default) - in_fwr_v4 = { - 'description': 'default ingress rule for IPv4', - 'name': 'default ingress ipv4', - 'shared': cfg.CONF.default_fwg_rules.shared, - 'protocol': cfg.CONF.default_fwg_rules.protocol, - 'tenant_id': tenant_id, - 'ip_version': nl_constants.IP_VERSION_4, - 'action': cfg.CONF.default_fwg_rules.ingress_action, - 'enabled': cfg.CONF.default_fwg_rules.enabled, - 'source_port': cfg.CONF.default_fwg_rules.ingress_source_port, - 'source_ip_address': - cfg.CONF.default_fwg_rules.ingress_source_ipv4_address, - 'destination_port': - cfg.CONF.default_fwg_rules.ingress_destination_port, - 'destination_ip_address': - cfg.CONF.default_fwg_rules. - ingress_destination_ipv4_address, - } - - # 2. Firewall rule for ingress IPv6 packets (DROP by default) - in_fwr_v6 = copy.deepcopy(in_fwr_v4) - in_fwr_v6['description'] = 'default ingress rule for IPv6' - in_fwr_v6['name'] = 'default ingress ipv6' - in_fwr_v6['ip_version'] = nl_constants.IP_VERSION_6 - in_fwr_v6['source_ip_address'] = \ - cfg.CONF.default_fwg_rules.ingress_source_ipv6_address - in_fwr_v6['destination_ip_address'] = \ - cfg.CONF.default_fwg_rules.ingress_destination_ipv6_address - - # 3. Firewall rule for egress IPv4 packets (ALLOW by default) - eg_fwr_v4 = copy.deepcopy(in_fwr_v4) - eg_fwr_v4['description'] = 'default egress rule for IPv4' - eg_fwr_v4['name'] = 'default egress ipv4' - eg_fwr_v4['action'] = cfg.CONF.default_fwg_rules.egress_action - eg_fwr_v4['source_port'] = \ - cfg.CONF.default_fwg_rules.egress_source_port - eg_fwr_v4['source_ip_address'] = \ - cfg.CONF.default_fwg_rules.egress_source_ipv4_address - eg_fwr_v4['destination_port'] = \ - cfg.CONF.default_fwg_rules.egress_destination_port - eg_fwr_v4['destination_ip_address'] = \ - cfg.CONF.default_fwg_rules.egress_destination_ipv4_address - - # 4. Firewall rule for egress IPv6 packets (ALLOW by default) - eg_fwr_v6 = copy.deepcopy(in_fwr_v6) - eg_fwr_v6['description'] = 'default egress rule for IPv6' - eg_fwr_v6['name'] = 'default egress ipv6' - eg_fwr_v6['action'] = cfg.CONF.default_fwg_rules.egress_action - eg_fwr_v6['source_port'] = \ - cfg.CONF.default_fwg_rules.egress_source_port - eg_fwr_v6['source_ip_address'] = \ - cfg.CONF.default_fwg_rules.egress_source_ipv6_address - eg_fwr_v6['destination_port'] = \ - cfg.CONF.default_fwg_rules.egress_destination_port - eg_fwr_v6['destination_ip_address'] = \ - cfg.CONF.default_fwg_rules.egress_destination_ipv6_address - - return { - 'in_ipv4': self.create_firewall_rule(context, in_fwr_v4)['id'], - 'in_ipv6': self.create_firewall_rule(context, in_fwr_v6)['id'], - 'eg_ipv4': self.create_firewall_rule(context, eg_fwr_v4)['id'], - 'eg_ipv6': self.create_firewall_rule(context, eg_fwr_v6)['id'], - } - - def create_firewall_rule(self, context, firewall_rule): - fwr = firewall_rule - self._validate_fwr_protocol_parameters(fwr) - self._validate_fwr_src_dst_ip_version(fwr) - - src_port_min, src_port_max = self._get_min_max_ports_from_range( - fwr['source_port']) - dst_port_min, dst_port_max = self._get_min_max_ports_from_range( - fwr['destination_port']) - with context.session.begin(subtransactions=True): - fwr_db = FirewallRuleV2( - id=uuidutils.generate_uuid(), - tenant_id=fwr['tenant_id'], - name=fwr['name'], - description=fwr['description'], - protocol=fwr['protocol'], - ip_version=fwr['ip_version'], - source_ip_address=fwr['source_ip_address'], - destination_ip_address=fwr['destination_ip_address'], - source_port_range_min=src_port_min, - source_port_range_max=src_port_max, - destination_port_range_min=dst_port_min, - destination_port_range_max=dst_port_max, - action=fwr['action'], - enabled=fwr['enabled'], - shared=fwr['shared']) - context.session.add(fwr_db) - return self._make_firewall_rule_dict(fwr_db) - - def update_firewall_rule(self, context, id, firewall_rule): - fwr = firewall_rule - fwr_db = self._get_firewall_rule(context, id) - fwr_db_updated = self._make_firewall_rule_dict(fwr_db) - fwr_db_updated.update(fwr) - - self._validate_fwr_protocol_parameters(fwr_db_updated) - self._validate_fwr_src_dst_ip_version(fwr_db_updated) - if 'source_port' in fwr: - src_port_min, src_port_max = self._get_min_max_ports_from_range( - fwr['source_port']) - fwr['source_port_range_min'] = src_port_min - fwr['source_port_range_max'] = src_port_max - del fwr['source_port'] - if 'destination_port' in fwr: - dst_port_min, dst_port_max = self._get_min_max_ports_from_range( - fwr['destination_port']) - fwr['destination_port_range_min'] = dst_port_min - fwr['destination_port_range_max'] = dst_port_max - del fwr['destination_port'] - with context.session.begin(subtransactions=True): - fwr_db.update(fwr) - # if the rule on a policy, fix audited flag - fwp_ids = self.get_policies_with_rule(context, id) - for fwp_id in fwp_ids: - fwp_db = self._get_firewall_policy(context, fwp_id) - fwp_db['audited'] = False - return self._make_firewall_rule_dict(fwr_db) - - def delete_firewall_rule(self, context, id): - with context.session.begin(subtransactions=True): - fwr = self._get_firewall_rule(context, id) - # make sure rule is not associated with any policy - if self.get_policies_with_rule(context, id): - raise f_exc.FirewallRuleInUse(firewall_rule_id=id) - context.session.delete(fwr) - - def insert_rule(self, context, id, rule_info): - firewall_rule_id = rule_info['firewall_rule_id'] - # ensure rule is not already assigned to the policy - self._ensure_rule_not_already_associated(context, id, firewall_rule_id) - insert_before = True - ref_firewall_rule_id = None - if 'insert_before' in rule_info: - ref_firewall_rule_id = rule_info['insert_before'] - if not ref_firewall_rule_id and 'insert_after' in rule_info: - # If insert_before is set, we will ignore insert_after. - ref_firewall_rule_id = rule_info['insert_after'] - insert_before = False - with context.session.begin(subtransactions=True): - fwr_db = self._get_firewall_rule(context, firewall_rule_id) - fwp_db = self._get_firewall_policy(context, id) - self._check_firewall_rule_conflict(fwr_db, fwp_db) - if ref_firewall_rule_id: - # If reference_firewall_rule_id is set, the new rule - # is inserted depending on the value of insert_before. - # If insert_before is set, the new rule is inserted before - # reference_firewall_rule_id, and if it is not set the new - # rule is inserted after reference_firewall_rule_id. - fwpra_db = self._get_policy_rule_association( - context, id, ref_firewall_rule_id) - if insert_before: - position = fwpra_db.position - else: - position = fwpra_db.position + 1 - else: - # If reference_firewall_rule_id is not set, it is assumed - # that the new rule needs to be inserted at the top. - # insert_before field is ignored. - # So default insertion is always at the top. - # Also note that position numbering starts at 1. - position = 1 - return self._process_rule_for_policy(context, id, firewall_rule_id, - position, None) - - def remove_rule(self, context, id, rule_info): - firewall_rule_id = rule_info['firewall_rule_id'] - with context.session.begin(subtransactions=True): - self._get_firewall_rule(context, firewall_rule_id) - fwpra_db = self._get_policy_rule_association(context, id, - firewall_rule_id) - return self._process_rule_for_policy(context, id, firewall_rule_id, - None, fwpra_db) - - def get_firewall_rule(self, context, id, fields=None): - fwr = self._get_firewall_rule(context, id) - policies = self.get_policies_with_rule(context, id) or None - return self._make_firewall_rule_dict(fwr, fields, policies=policies) - - def get_firewall_rules(self, context, filters=None, fields=None): - return model_query.get_collection( - context, FirewallRuleV2, self._make_firewall_rule_dict, - filters=filters, fields=fields) - - def _get_rules_in_policy(self, context, fwpid): - """Gets rules in a firewall policy""" - with context.session.begin(subtransactions=True): - fw_pol_rule_qry = context.session.query( - FirewallPolicyRuleAssociation).filter_by( - firewall_policy_id=fwpid) - fwp_rules = [entry.firewall_rule_id for entry in fw_pol_rule_qry] - return fwp_rules - - def get_policies_with_rule(self, context, fwrid): - """Gets rules in a firewall policy""" - with context.session.begin(subtransactions=True): - fw_pol_rule_qry = context.session.query( - FirewallPolicyRuleAssociation).filter_by( - firewall_rule_id=fwrid) - fwps = [entry.firewall_policy_id for entry in fw_pol_rule_qry] - return fwps - - def _set_rules_in_policy_rule_assoc(self, context, fwp_db, fwp): - # Pull the rules and add it to policy - rule association table - # Set the position (this can be used in the making the dict) - # might be good to track the last position - rule_id_list = fwp['firewall_rules'] - if not rule_id_list: - return - position = 0 - with context.session.begin(subtransactions=True): - for rule_id in rule_id_list: - fw_pol_rul_db = FirewallPolicyRuleAssociation( - firewall_policy_id=fwp_db['id'], - firewall_rule_id=rule_id, - position=position) - context.session.add(fw_pol_rul_db) - position += 1 - - def _check_rules_for_policy_is_valid(self, context, fwp, fwp_db, - rule_id_list, filters): - rules_in_fwr_db = model_query.get_collection_query( - context, FirewallRuleV2, filters=filters) - rules_dict = dict((fwr_db['id'], fwr_db) for fwr_db in rules_in_fwr_db) - for fwrule_id in rule_id_list: - if fwrule_id not in rules_dict: - # Bail as soon as we find an invalid rule. - raise f_exc.FirewallRuleNotFound( - firewall_rule_id=fwrule_id) - if 'shared' in fwp: - if fwp['shared'] and not rules_dict[fwrule_id]['shared']: - raise f_exc.FirewallRuleSharingConflict( - firewall_rule_id=fwrule_id, - firewall_policy_id=fwp_db['id']) - elif fwp_db['shared'] and not rules_dict[fwrule_id]['shared']: - raise f_exc.FirewallRuleSharingConflict( - firewall_rule_id=fwrule_id, - firewall_policy_id=fwp_db['id']) - else: - # the policy is not shared, the rule and policy should be in - # the same project if the rule is not shared. - if not rules_dict[fwrule_id]['shared']: - if (rules_dict[fwrule_id]['tenant_id'] != fwp_db[ - 'tenant_id']): - raise f_exc.FirewallRuleConflict( - firewall_rule_id=fwrule_id, - project_id=rules_dict[fwrule_id]['tenant_id']) - - def _check_if_rules_shared_for_policy_shared(self, context, fwp_db, fwp): - if fwp['shared']: - rules_in_db = fwp_db.rule_associations - for entry in rules_in_db: - fwr_db = self._get_firewall_rule(context, - entry.firewall_rule_id) - if not fwr_db['shared']: - raise f_exc.FirewallPolicySharingConflict( - firewall_rule_id=fwr_db['id'], - firewall_policy_id=fwp_db['id']) - - def get_fwgs_with_policy(self, context, fwp_id): - with context.session.begin(subtransactions=True): - fwg_ing_pol_qry = context.session.query( - FirewallGroup).filter_by( - ingress_firewall_policy_id=fwp_id) - ing_fwg_ids = [entry.id for entry in fwg_ing_pol_qry] - fwg_eg_pol_qry = context.session.query( - FirewallGroup).filter_by( - egress_firewall_policy_id=fwp_id) - eg_fwg_ids = [entry.id for entry in fwg_eg_pol_qry] - return ing_fwg_ids, eg_fwg_ids - - def _check_fwgs_associated_with_policy_in_same_project(self, context, - fwp_id, - fwp_tenant_id): - with context.session.begin(subtransactions=True): - fwg_with_fwp_id_db = context.session.query(FirewallGroup).filter( - or_(FirewallGroup.ingress_firewall_policy_id == fwp_id, - FirewallGroup.egress_firewall_policy_id == fwp_id)) - for entry in fwg_with_fwp_id_db: - if entry.tenant_id != fwp_tenant_id: - raise f_exc.FirewallPolicyInUse( - firewall_policy_id=fwp_id) - - def _delete_all_rules_from_policy(self, context, fwp_db): - """Deletes all FirewallPolicyRuleAssociation objects - - fwp_db is an DB dict representing firewall policy. - Returns a dictionary with updated rule_associations. - """ - for rule_id in [rule_assoc.firewall_rule_id - for rule_assoc in fwp_db['rule_associations']]: - fwpra_db = self._get_policy_rule_association( - context, fwp_db['id'], rule_id) - fwp_db.rule_associations.remove(fwpra_db) - context.session.delete(fwpra_db) - fwp_db.rule_associations = [] - return fwp_db - - def _set_rules_for_policy(self, context, firewall_policy_db, fwp): - rule_id_list = fwp['firewall_rules'] - fwp_db = firewall_policy_db - with context.session.begin(subtransactions=True): - if not rule_id_list: - self._delete_all_rules_from_policy(context, fwp_db) - return - # We will first check if the new list of rules is valid - filters = {'firewall_rule_id': [r_id for r_id in rule_id_list]} - # Run a validation on the Firewall Rules table - self._check_rules_for_policy_is_valid(context, fwp, fwp_db, - rule_id_list, filters) - # new rules are valid, lets delete the old association - self._delete_all_rules_from_policy(context, fwp_db) - # and add in the new association - self._set_rules_in_policy_rule_assoc(context, fwp_db, fwp) - # we need care about the associations related with this policy - # and its rules only. - filters['firewall_policy_id'] = [fwp_db['id']] - rules_in_fpol_rul_db = model_query.get_collection_query( - context, - FirewallPolicyRuleAssociation, - filters=filters) - rules_dict = dict((fpol_rul_db['firewall_rule_id'], fpol_rul_db) - for fpol_rul_db in rules_in_fpol_rul_db) - fwp_db.rule_associations = [] - for fwrule_id in rule_id_list: - fwp_db.rule_associations.append(rules_dict[fwrule_id]) - fwp_db.rule_associations.reorder() - - def _create_default_firewall_policy(self, context, tenant_id, policy_type, - **kwargs): - fwrs = kwargs.get('firewall_rules', []) - description = kwargs.get('description', '') - name = (const.DEFAULT_FWP_INGRESS - if policy_type == 'ingress' else const.DEFAULT_FWP_EGRESS) - firewall_policy = { - 'name': name, - 'description': description, - 'audited': False, - 'shared': False, - 'firewall_rules': fwrs, - 'tenant_id': tenant_id, - } - return self._do_create_firewall_policy(context, firewall_policy) - - def _do_create_firewall_policy(self, context, firewall_policy): - fwp = firewall_policy - with context.session.begin(subtransactions=True): - fwp_db = FirewallPolicy( - id=uuidutils.generate_uuid(), - tenant_id=fwp['tenant_id'], - name=fwp['name'], - description=fwp['description'], - audited=fwp['audited'], - shared=fwp['shared']) - context.session.add(fwp_db) - self._set_rules_for_policy(context, fwp_db, fwp) - return self._make_firewall_policy_dict(fwp_db) - - def create_firewall_policy(self, context, firewall_policy): - self._ensure_not_default_resource(firewall_policy, 'firewall_policy') - return self._do_create_firewall_policy(context, firewall_policy) - - def update_firewall_policy(self, context, id, firewall_policy): - fwp = firewall_policy - with context.session.begin(subtransactions=True): - fwp_db = self._get_firewall_policy(context, id) - self._ensure_not_default_resource(fwp_db, 'firewall_policy', - action="update") - if not fwp.get('shared', True): - # an update is setting shared to False, make sure associated - # firewall groups are in the same project. - self._check_fwgs_associated_with_policy_in_same_project( - context, id, fwp_db['tenant_id']) - if 'shared' in fwp and 'firewall_rules' not in fwp: - self._check_if_rules_shared_for_policy_shared( - context, fwp_db, fwp) - if 'firewall_rules' in fwp: - self._set_rules_for_policy(context, fwp_db, fwp) - del fwp['firewall_rules'] - if 'audited' not in fwp: - fwp['audited'] = False - fwp_db.update(fwp) - return self._make_firewall_policy_dict(fwp_db) - - def delete_firewall_policy(self, context, id): - with context.session.begin(subtransactions=True): - fwp_db = self._get_firewall_policy(context, id) - # check if policy in use - qry = context.session.query(FirewallGroup) - if qry.filter_by(ingress_firewall_policy_id=id).first(): - raise f_exc.FirewallPolicyInUse(firewall_policy_id=id) - elif qry.filter_by(egress_firewall_policy_id=id).first(): - raise f_exc.FirewallPolicyInUse(firewall_policy_id=id) - else: - fwp_db = self._delete_all_rules_from_policy(context, fwp_db) - context.session.delete(fwp_db) - - def get_firewall_policy(self, context, id, fields=None): - fwp = self._get_firewall_policy(context, id) - return self._make_firewall_policy_dict(fwp, fields) - - def get_firewall_policies(self, context, filters=None, fields=None): - return model_query.get_collection( - context, FirewallPolicy, self._make_firewall_policy_dict, - filters=filters, fields=fields) - - def _set_ports_for_firewall_group(self, context, fwg_db, fwg): - port_id_list = fwg['ports'] - if not port_id_list: - return - - exc_ports = [] - for port_id in port_id_list: - try: - with context.session.begin(subtransactions=True): - fwg_port_db = FirewallGroupPortAssociation( - firewall_group_id=fwg_db['id'], - port_id=port_id) - context.session.add(fwg_port_db) - except db_exc.DBDuplicateEntry: - exc_ports.append(port_id) - if exc_ports: - raise f_exc.FirewallGroupPortInUse(port_ids=exc_ports) - - def get_ports_in_firewall_group(self, context, firewall_group_id): - """Get the Ports associated with the firewall group.""" - with context.session.begin(subtransactions=True): - fw_group_port_qry = context.session.query( - FirewallGroupPortAssociation) - fw_group_port_rows = fw_group_port_qry.filter_by( - firewall_group_id=firewall_group_id) - fw_ports = [entry.port_id for entry in fw_group_port_rows] - return fw_ports - - def _delete_ports_in_firewall_group(self, context, firewall_group_id): - """Delete the Ports associated with the firewall group.""" - with context.session.begin(subtransactions=True): - fw_group_port_qry = context.session.query( - FirewallGroupPortAssociation) - fw_group_port_qry.filter_by( - firewall_group_id=firewall_group_id).delete() - return - - def _get_default_fwg_id(self, context, tenant_id): - """Returns an id of default firewall group for given tenant or None""" - default_fwg = model_query.query_with_hooks( - context, FirewallGroup).filter_by( - project_id=tenant_id, name=const.DEFAULT_FWG).first() - if default_fwg: - return default_fwg.id - return None - - def get_fwg_attached_to_port(self, context, port_id): - """Return a firewall group ID that is attached to a given port""" - fwg_port = model_query.query_with_hooks( - context, FirewallGroupPortAssociation).\ - filter_by(port_id=port_id).first() - if fwg_port: - return fwg_port.firewall_group_id - return None - - def get_fwg_ports_in_tenant(self, context, tenant_id): - """Return a list of ports under a given tenant""" - try: - fwg_id = FirewallGroupPortAssociation.firewall_group_id - with context.session.begin(subtransactions=True): - port_qry = context.session.query( - FirewallGroupPortAssociation.port_id).join( - FirewallGroup, FirewallGroup.id == fwg_id).filter( - FirewallGroup.tenant_id == tenant_id).all() - return list({port for (port,) in port_qry}) - except exc.NoResultFound: - return [] - - def _ensure_default_firewall_group(self, context, tenant_id): - """Create a default firewall group if one doesn't exist for a tenant - - Returns the default firewall group id for a given tenant. - """ - exists = self._get_default_fwg_id(context, tenant_id) - if exists: - return exists - - try: - # NOTE(cby): default fwg not created => we try to create it! - with db_api.autonested_transaction(context.session): - - fwr_ids = self._create_default_firewall_rules( - context, tenant_id) - ingress_fwp = { - 'description': 'Ingress firewall policy', - 'firewall_rules': [fwr_ids['in_ipv4'], - fwr_ids['in_ipv6']], - } - egress_fwp = { - 'description': 'Egress firewall policy', - 'firewall_rules': [fwr_ids['eg_ipv4'], - fwr_ids['eg_ipv6']], - } - ingress_fwp_db = self._create_default_firewall_policy( - context, tenant_id, 'ingress', **ingress_fwp) - egress_fwp_db = self._create_default_firewall_policy( - context, tenant_id, 'egress', **egress_fwp) - - fwg = { - 'name': const.DEFAULT_FWG, - 'tenant_id': tenant_id, - 'ingress_firewall_policy_id': ingress_fwp_db['id'], - 'egress_firewall_policy_id': egress_fwp_db['id'], - 'ports': [], - 'shared': False, - 'status': nl_constants.INACTIVE, - 'admin_state_up': True, - 'description': 'Default firewall group', - } - fwg_db = self._create_firewall_group( - context, fwg, default_fwg=True) - context.session.add(DefaultFirewallGroup( - firewall_group_id=fwg_db['id'], - project_id=tenant_id)) - return fwg_db['id'] - - except db_exc.DBDuplicateEntry: - # NOTE(cby): default fwg created concurrently - LOG.debug("Default FWG was concurrently created") - return self._get_default_fwg_id(context, tenant_id) - - def _create_firewall_group(self, context, firewall_group, - default_fwg=False): - """Create a firewall group - - If default_fwg is True then a default firewall group is being created - for a given tenant. - """ - fwg = firewall_group - tenant_id = fwg['tenant_id'] - if firewall_group.get('status') is None: - fwg['status'] = nl_constants.CREATED - - if default_fwg: - # A default firewall group is being created. - default_fwg_id = self._get_default_fwg_id(context, tenant_id) - if default_fwg_id is not None: - # Default fwg for a given tenant exists, fetch it and return - return self.get_firewall_group(context, default_fwg_id) - else: - # An ordinary firewall group is being created BUT let's make sure - # that a default firewall group for given tenant exists - self._ensure_default_firewall_group(context, tenant_id) - - with context.session.begin(subtransactions=True): - fwg_db = FirewallGroup( - id=uuidutils.generate_uuid(), - tenant_id=tenant_id, - name=fwg['name'], - description=fwg['description'], - status=fwg['status'], - ingress_firewall_policy_id=fwg['ingress_firewall_policy_id'], - egress_firewall_policy_id=fwg['egress_firewall_policy_id'], - admin_state_up=fwg['admin_state_up'], - shared=fwg['shared']) - context.session.add(fwg_db) - self._set_ports_for_firewall_group(context, fwg_db, fwg) - return self._make_firewall_group_dict(fwg_db) - - def create_firewall_group(self, context, firewall_group): - self._ensure_not_default_resource(firewall_group, 'firewall_group') - return self._create_firewall_group(context, firewall_group) - - def update_firewall_group(self, context, id, firewall_group): - fwg = firewall_group - # make sure that no group can be updated to have name=default - self._ensure_not_default_resource(fwg, 'firewall_group') - with context.session.begin(subtransactions=True): - fwg_db = self.get_firewall_group(context, id) - if _is_default(fwg_db): - attrs = [ - 'name', 'description', 'admin_state_up', - 'ingress_firewall_policy_id', 'egress_firewall_policy_id' - ] - if context.is_admin: - attrs = ['name'] - for attr in attrs: - if attr in fwg: - raise FirewallDefaultObjectUpdateRestricted( - resource_type='Firewall Group', - resource_id=fwg_db['id']) - if 'ports' in fwg: - LOG.debug("Ports are updated in Firewall Group") - self._delete_ports_in_firewall_group(context, id) - self._set_ports_for_firewall_group(context, fwg_db, fwg) - del fwg['ports'] - # If fwg is empty, skip updating - if fwg: - count = context.session.query( - FirewallGroup).filter_by(id=id).update(fwg) - if not count: - raise f_exc.FirewallGroupNotFound(firewall_id=id) - return self.get_firewall_group(context, id) - - def update_firewall_group_status(self, context, id, status, not_in=None): - """Conditionally update firewall_group status. - Status transition is performed only if firewall is not in the specified - states as defined by 'not_in' list. - """ - # filter in_ wants iterable objects, None isn't. - not_in = not_in or [] - with context.session.begin(subtransactions=True): - return (context.session.query(FirewallGroup). - filter(FirewallGroup.id == id). - filter(~FirewallGroup.status.in_(not_in)). - update({'status': status}, synchronize_session=False)) - - def delete_firewall_group(self, context, id): - # Note: Plugin should ensure that it's okay to delete if the - # firewall is active - - with context.session.begin(subtransactions=True): - # if no such group exists -> don't raise an exception according to - # 80fe2ba1, return None - try: - fwg_db = self._get_firewall_group(context, id) - except f_exc.FirewallGroupNotFound: - return - - if _is_default(fwg_db): - if context.is_admin: - # Like Rules in Default SG, when the Default FWG is deleted - # its associated Rules and policies would also be deleted. - # Delete fwg first and then associated policies - context.session.query( - FirewallGroup).filter_by(id=id).delete() - fwp = [fwg_db['ingress_firewall_policy_id'], - fwg_db['egress_firewall_policy_id']] - for fwp_id in fwp: - self.delete_firewall_policy(context, fwp_id) - else: - # only admin can delete default fwg - raise f_exc.FirewallGroupCannotRemoveDefault() - else: - context.session.query( - FirewallGroup).filter_by(id=id).delete() - - def _ensure_not_default_resource(self, resource_dict, r_type, action=None): - """Checks that a resource is not default by checking its name - - A resource_dict can be either a dictionary in form {r_type : {}} or a - serialized object from db. - - Action is used to determine type of exception to be raised. - """ - resource = resource_dict.get(r_type) or resource_dict - if r_type == 'firewall_group': - if resource.get('name', '') == const.DEFAULT_FWG: - if action == "update": - raise FirewallDefaultObjectUpdateRestricted( - resource_type='Firewall Group', - resource_id=resource['id']) - raise FirewallDefaultParameterExists( - resource_type='Firewall Group', name=resource['name']) - elif r_type == 'firewall_policy': - if resource.get('name', '') in [const.DEFAULT_FWP_INGRESS, - const.DEFAULT_FWP_EGRESS]: - if action == "update": - raise FirewallDefaultObjectUpdateRestricted( - resource_type='Firewall Group', - resource_id=resource['id']) - raise FirewallDefaultParameterExists( - resource_type='Firewall Policy', name=resource['name']) - - def get_firewall_group(self, context, id, fields=None): - fw = self._get_firewall_group(context, id) - return self._make_firewall_group_dict(fw, fields) - - def get_firewall_groups(self, context, filters=None, fields=None): - if context.tenant_id: - tenant_id = filters.get('tenant_id') if filters else None - tenant_id = tenant_id[0] if tenant_id else context.tenant_id - self._ensure_default_firewall_group(context, tenant_id) - return model_query.get_collection( - context, FirewallGroup, self._make_firewall_group_dict, - filters=filters, fields=fields) - - -def _is_default(fwg_db): - return fwg_db['name'] == const.DEFAULT_FWG diff --git a/neutron_fwaas/db/migration/__init__.py b/neutron_fwaas/db/migration/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/migration/alembic_migrations/README b/neutron_fwaas/db/migration/alembic_migrations/README deleted file mode 100644 index 98e4f9c44..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/README +++ /dev/null @@ -1 +0,0 @@ -Generic single-database configuration. \ No newline at end of file diff --git a/neutron_fwaas/db/migration/alembic_migrations/__init__.py b/neutron_fwaas/db/migration/alembic_migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/migration/alembic_migrations/env.py b/neutron_fwaas/db/migration/alembic_migrations/env.py deleted file mode 100644 index 1ee1f6812..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/env.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2014 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. - -from logging import config as logging_config - -from alembic import context -from neutron_lib.db import model_base -from oslo_config import cfg -from oslo_db.sqlalchemy import session -import sqlalchemy as sa -from sqlalchemy import event - - -MYSQL_ENGINE = None -FWAAS_VERSION_TABLE = 'alembic_version_fwaas' -config = context.config -neutron_config = config.neutron_config -logging_config.fileConfig(config.config_file_name) -target_metadata = model_base.BASEV2.metadata - - -def set_mysql_engine(): - try: - mysql_engine = neutron_config.command.mysql_engine - except cfg.NoSuchOptError: - mysql_engine = None - - global MYSQL_ENGINE - MYSQL_ENGINE = (mysql_engine or - model_base.BASEV2.__table_args__['mysql_engine']) - - -def run_migrations_offline(): - set_mysql_engine() - - kwargs = dict() - if neutron_config.database.connection: - kwargs['url'] = neutron_config.database.connection - else: - kwargs['dialect_name'] = neutron_config.database.engine - kwargs['version_table'] = FWAAS_VERSION_TABLE - context.configure(**kwargs) - - with context.begin_transaction(): - context.run_migrations() - - -@event.listens_for(sa.Table, 'after_parent_attach') -def set_storage_engine(target, parent): - if MYSQL_ENGINE: - target.kwargs['mysql_engine'] = MYSQL_ENGINE - - -def run_migrations_online(): - set_mysql_engine() - engine = session.create_engine(neutron_config.database.connection) - - connection = engine.connect() - context.configure( - connection=connection, - target_metadata=target_metadata, - version_table=FWAAS_VERSION_TABLE - ) - try: - with context.begin_transaction(): - context.run_migrations() - finally: - connection.close() - engine.dispose() - - -if context.is_offline_mode(): - run_migrations_offline() -else: - run_migrations_online() diff --git a/neutron_fwaas/db/migration/alembic_migrations/script.py.mako b/neutron_fwaas/db/migration/alembic_migrations/script.py.mako deleted file mode 100644 index 9e0b2ce21..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/script.py.mako +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright ${create_date.year} -# -# 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. -# - -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision} -Create Date: ${create_date} - -""" - -# revision identifiers, used by Alembic. -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -% if branch_labels: -branch_labels = ${repr(branch_labels)} -%endif - -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -def upgrade(): - ${upgrades if upgrades else "pass"} diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_tenant_id.py b/neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_tenant_id.py deleted file mode 100644 index 67213a665..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_tenant_id.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2015 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. -# - -"""add_index_tenant_id - -Revision ID: 4202e3047e47 -Revises: start_neutron_fwaas -Create Date: 2015-02-10 17:17:47.846764 - -""" -from alembic import op - -# revision identifiers, used by Alembic. -revision = '4202e3047e47' -down_revision = 'start_neutron_fwaas' - -TABLES = ['firewall_rules', 'firewalls', 'firewall_policies'] - - -def upgrade(): - for table in TABLES: - op.create_index(op.f('ix_%s_tenant_id' % table), - table, ['tenant_id'], unique=False) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router_insertion.py b/neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router_insertion.py deleted file mode 100644 index 32e7d9ec2..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router_insertion.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2014 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. -# - -"""FWaaS router insertion - -Revision ID: 540142f314f4 -Revises: 4202e3047e47 -Create Date: 2015-02-06 17:02:24.279337 - -""" - -from alembic import op -import sqlalchemy as sa -from sqlalchemy.engine import reflection - -# revision identifiers, used by Alembic. -revision = '540142f314f4' -down_revision = '4202e3047e47' - -SQL_STATEMENT = ( - "insert into firewall_router_associations " - "select " - "f.id as fw_id, r.id as router_id " - "from firewalls f, routers r " - "where " - "f.tenant_id=r.%s" -) - - -def upgrade(): - op.create_table('firewall_router_associations', - sa.Column('fw_id', sa.String(length=36), nullable=False), - sa.Column('router_id', sa.String(length=36), nullable=False), - sa.ForeignKeyConstraint(['fw_id'], ['firewalls.id'], - ondelete='CASCADE'), - sa.ForeignKeyConstraint(['router_id'], ['routers.id'], - ondelete='CASCADE'), - sa.PrimaryKeyConstraint('fw_id', 'router_id'), - ) - - # Depending on when neutron-fwaas is installed with neutron, this script - # may be run before or after the neutron core tables have had their - # tenant_id columns renamed to project_id. Account for both scenarios. - bind = op.get_bind() - insp = reflection.Inspector.from_engine(bind) - columns = insp.get_columns('routers') - if 'tenant_id' in [c['name'] for c in columns]: - op.execute(SQL_STATEMENT % 'tenant_id') - else: - op.execute(SQL_STATEMENT % 'project_id') diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwaas.py b/neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwaas.py deleted file mode 100644 index b9f8f9703..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwaas.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2015 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. -# - -"""cisco_csr_fwaas - -Revision ID: 796c68dffbb -Revises: 540142f314f4 -Create Date: 2015-02-02 13:11:55.184112 - -""" - -from alembic import op -import sqlalchemy as sa - -# revision identifiers, used by Alembic. -revision = '796c68dffbb' -down_revision = '540142f314f4' - - -def upgrade(active_plugins=None, options=None): - - op.create_table('cisco_firewall_associations', - sa.Column('fw_id', sa.String(length=36), nullable=False), - sa.Column('port_id', sa.String(length=36), nullable=True), - sa.Column('direction', sa.String(length=16), nullable=True), - sa.Column('acl_id', sa.String(length=36), nullable=True), - sa.Column('router_id', sa.String(length=36), nullable=True), - sa.ForeignKeyConstraint(['fw_id'], ['firewalls.id'], - ondelete='CASCADE'), - sa.ForeignKeyConstraint(['port_id'], ['ports.id'], - ondelete='CASCADE'), - sa.PrimaryKeyConstraint('fw_id') - ) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/CONTRACT_HEAD b/neutron_fwaas/db/migration/alembic_migrations/versions/CONTRACT_HEAD deleted file mode 100644 index 937996f64..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/CONTRACT_HEAD +++ /dev/null @@ -1 +0,0 @@ -fd38cd995cc0 diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron_fwaas/db/migration/alembic_migrations/versions/EXPAND_HEAD deleted file mode 100644 index f323d45cd..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ /dev/null @@ -1 +0,0 @@ -f24e0d5e5bff diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/kilo_release.py b/neutron_fwaas/db/migration/alembic_migrations/versions/kilo_release.py deleted file mode 100644 index 06ec04387..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/kilo_release.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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. -# - -"""kilo - -Revision ID: kilo -Revises: 796c68dffbb -Create Date: 2015-04-16 00:00:00.000000 - -""" - -# revision identifiers, used by Alembic. -revision = 'kilo' -down_revision = '796c68dffbb' - - -def upgrade(): - """A no-op migration for marking the Kilo release.""" - pass diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d61d5_initial.py b/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d61d5_initial.py deleted file mode 100644 index 1ea901f4c..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d61d5_initial.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2015 Red Hat 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. -# - -"""Initial Liberty no-op script. - -Revision ID: 67c8e8d61d5 -Revises: kilo -Create Date: 2015-07-28 22:18:13.330846 - -""" - -from neutron.db import migration -from neutron_lib.db import constants - - -# revision identifiers, used by Alembic. -revision = '67c8e8d61d5' -down_revision = 'kilo' -branch_labels = (constants.CONTRACT_BRANCH,) - -# milestone identifier, used by neutron-db-manage -neutron_milestone = [migration.LIBERTY] - - -def upgrade(): - pass diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea298795_add_reject_rule.py b/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea298795_add_reject_rule.py deleted file mode 100644 index 8681d18ca..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea298795_add_reject_rule.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2015 NEC Corporation. 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. - -"""add reject rule - -Revision ID: 4b47ea298795 -Revises: c40fbb377ad -Create Date: 2015-04-15 04:19:57.324584 - -""" - -import sqlalchemy as sa - -from neutron.db import migration - - -# revision identifiers, used by Alembic. -revision = '4b47ea298795' -down_revision = 'c40fbb377ad' - -# milestone identifier, used by neutron-db-manage -neutron_milestone = [migration.LIBERTY, migration.MITAKA] - - -new_action = sa.Enum('allow', 'deny', 'reject', name='firewallrules_action') - - -def upgrade(): - # NOTE: postgresql have a builtin ENUM type, so just altering the - # column won't works - # https://bitbucket.org/zzzeek/alembic/issues/270/altering-enum-type - # alter_enum that was already invented for such case in neutron - # https://github.com/openstack/neutron/blob/master/neutron/db/migration/__init__.py - - migration.alter_enum( - 'firewall_rules', 'action', enum_type=new_action, nullable=True) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377ad_initial.py b/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377ad_initial.py deleted file mode 100644 index e0149a78f..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377ad_initial.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2015 Red Hat 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. -# - -"""Initial Liberty no-op script. - -Revision ID: c40fbb377ad -Revises: kilo -Create Date: 2015-07-28 22:18:13.321233 - -""" - -from neutron_lib.db import constants - - -# revision identifiers, used by Alembic. -revision = 'c40fbb377ad' -down_revision = 'kilo' -branch_labels = (constants.EXPAND_BRANCH,) - - -def upgrade(): - pass diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b14b_fw_table_alter.py b/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b14b_fw_table_alter.py deleted file mode 100644 index 1f645e5b9..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b14b_fw_table_alter.py +++ /dev/null @@ -1,49 +0,0 @@ -#Copyright 2015 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. -# - -"""fw_table_alter script to make column case sensitive - -Revision ID: 458aa42b14b -Revises: 67c8e8d61d5 -Create Date: 2015-09-16 11:47:43.061649 - -""" - -from alembic import op - -from neutron.db import migration - - -# revision identifiers, used by Alembic. -revision = '458aa42b14b' -down_revision = '67c8e8d61d5' - -# milestone identifier, used by neutron-db-manage -neutron_milestone = [migration.MITAKA] - - -FW_TAB_NAME = ['firewall_rules', 'firewall_policies', 'firewalls'] -SQL_STATEMENT_UPDATE_CMD = ( - "alter table %s " - "modify name varchar(255) " - "CHARACTER SET utf8 COLLATE utf8_bin" -) - - -def upgrade(): - context = op.get_context() - if context.bind.dialect.name == 'mysql': - for table in FW_TAB_NAME: - op.execute(SQL_STATEMENT_UPDATE_CMD % table) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/newton/contract/f83a0b2964d0_rename_tenant_to_project.py b/neutron_fwaas/db/migration/alembic_migrations/versions/newton/contract/f83a0b2964d0_rename_tenant_to_project.py deleted file mode 100644 index d3a00104e..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/newton/contract/f83a0b2964d0_rename_tenant_to_project.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2016 -# -# 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. -# - -"""rename tenant to project - -Revision ID: f83a0b2964d0 -Revises: 458aa42b14b -Create Date: 2016-07-14 13:11:53.112622 - -""" - -from alembic import op -import sqlalchemy as sa -from sqlalchemy.engine import reflection - -from neutron.db import migration - - -# revision identifiers, used by Alembic. -revision = 'f83a0b2964d0' -down_revision = '458aa42b14b' - -# milestone identifier, used by neutron-db-manage -neutron_milestone = [migration.NEWTON] - -_INSPECTOR = None - - -def get_inspector(): - """Reuse inspector""" - - global _INSPECTOR - - if _INSPECTOR: - return _INSPECTOR - - else: - bind = op.get_bind() - _INSPECTOR = reflection.Inspector.from_engine(bind) - - return _INSPECTOR - - -def get_tables(): - """ - Returns hardcoded list of tables which have ``tenant_id`` column. - - The list is hardcoded to match the state of the schema when this - upgrade script is run. - """ - - tables = [ - 'firewalls', - 'firewall_policies', - 'firewall_rules', - ] - - return tables - - -def get_columns(table): - """Returns list of columns for given table.""" - inspector = get_inspector() - return inspector.get_columns(table) - - -def get_data(): - """Returns combined list of tuples: [(table, column)]. - - The list is built from tables with a tenant_id column. - """ - - output = [] - tables = get_tables() - for table in tables: - columns = get_columns(table) - - for column in columns: - if column['name'] == 'tenant_id': - output.append((table, column)) - - return output - - -def alter_column(table, column): - old_name = 'tenant_id' - new_name = 'project_id' - - op.alter_column( - table_name=table, - column_name=old_name, - new_column_name=new_name, - existing_type=column['type'], - existing_nullable=column['nullable'] - ) - - -def recreate_index(index, table_name): - old_name = index['name'] - new_name = old_name.replace('tenant', 'project') - - op.drop_index(op.f(old_name), table_name) - op.create_index(new_name, table_name, ['project_id']) - - -def upgrade(): - """Code reused from - - Change-Id: I87a8ef342ccea004731ba0192b23a8e79bc382dc - """ - - inspector = get_inspector() - - data = get_data() - for table, column in data: - alter_column(table, column) - - indexes = inspector.get_indexes(table) - for index in indexes: - if 'tenant_id' in index['name']: - recreate_index(index, table) - - -def contract_creation_exceptions(): - """Special migration for the blueprint to support Keystone V3. - We drop all tenant_id columns and create project_id columns instead. - """ - return { - sa.Column: ['.'.join([table, 'project_id']) for table in get_tables()], - sa.Index: get_tables() - } diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/newton/expand/d6a12e637e28_neutron_fwaas_v2_0.py b/neutron_fwaas/db/migration/alembic_migrations/versions/newton/expand/d6a12e637e28_neutron_fwaas_v2_0.py deleted file mode 100644 index 2648867a4..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/newton/expand/d6a12e637e28_neutron_fwaas_v2_0.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2016 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. -# - -"""neutron-fwaas v2.0 - -Revision ID: d6a12e637e28 -Revises: 4b47ea298795 -Create Date: 2016-06-08 19:57:13.848855 - -""" - -from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql - -from neutron.db import migration - - -# revision identifiers, used by Alembic. -revision = 'd6a12e637e28' -down_revision = '4b47ea298795' - -# milestone identifier, used by neutron-db-manage -neutron_milestone = [migration.NEWTON] - - -def get_enum(): - engine = op.get_bind().engine - # In PostgreSQL types created separately, so if type was already created in - # 4b47ea298795_add_reject_rule it should be created one time. - # Use parameter create_type=False for that. - if engine.name == 'postgresql': - return postgresql.ENUM('allow', 'deny', 'reject', - name='firewallrules_action', - create_type=False) - else: - return sa.Enum('allow', 'deny', 'reject', - name='firewallrules_action') - - -def upgrade(): - - op.create_table( - 'firewall_policies_v2', - sa.Column('id', sa.String(length=36), primary_key=True), - sa.Column('name', sa.String(length=255)), - sa.Column('description', sa.String(length=1024)), - sa.Column('project_id', sa.String(length=255), index=True), - sa.Column('audited', sa.Boolean), - sa.Column('public', sa.Boolean), - sa.Column('rule_count', sa.Integer)) - - op.create_table( - 'firewall_rules_v2', - sa.Column('id', sa.String(length=36), primary_key=True), - sa.Column('name', sa.String(length=255)), - sa.Column('description', sa.String(length=1024)), - sa.Column('project_id', sa.String(length=255), index=True), - sa.Column('protocol', sa.String(length=40)), - sa.Column('ip_version', sa.Integer), - sa.Column('source_ip_address', sa.String(length=46)), - sa.Column('destination_ip_address', sa.String(length=46)), - sa.Column('source_port_range_min', sa.Integer), - sa.Column('source_port_range_max', sa.Integer), - sa.Column('destination_port_range_min', sa.Integer), - sa.Column('destination_port_range_max', sa.Integer), - sa.Column('action', get_enum()), - sa.Column('public', sa.Boolean), - sa.Column('enabled', sa.Boolean)) - - op.create_table( - 'firewall_groups_v2', - sa.Column('id', sa.String(length=36), primary_key=True), - sa.Column('name', sa.String(length=255)), - sa.Column('description', sa.String(length=1024)), - sa.Column('project_id', sa.String(length=255), index=True), - sa.Column('status', sa.String(length=16)), - sa.Column('admin_state_up', sa.Boolean), - sa.Column('public', sa.Boolean), - sa.Column('egress_firewall_policy_id', sa.String(length=36), - sa.ForeignKey('firewall_policies_v2.id')), - sa.Column('ingress_firewall_policy_id', sa.String(length=36), - sa.ForeignKey('firewall_policies_v2.id'))) - - op.create_table( - 'firewall_group_port_associations_v2', - sa.Column('firewall_group_id', sa.String(length=36), - sa.ForeignKey('firewall_groups_v2.id', ondelete='CASCADE')), - sa.Column('port_id', sa.String(length=36), - sa.ForeignKey('ports.id', ondelete='CASCADE')) - ) - - op.create_table( - 'firewall_policy_rule_associations_v2', - sa.Column('firewall_policy_id', sa.String(length=36), - sa.ForeignKey('firewall_policies_v2.id', ondelete='CASCADE'), - nullable=False, primary_key=True), - sa.Column('firewall_rule_id', sa.String(length=36), - sa.ForeignKey('firewall_rules_v2.id', ondelete='CASCADE'), - nullable=False, primary_key=True), - sa.Column('position', sa.Integer)) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/pike/contract/fd38cd995cc0_shared_attribute_for_firewall_resources.py b/neutron_fwaas/db/migration/alembic_migrations/versions/pike/contract/fd38cd995cc0_shared_attribute_for_firewall_resources.py deleted file mode 100644 index 4077ced0b..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/pike/contract/fd38cd995cc0_shared_attribute_for_firewall_resources.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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. -# - -"""change shared attribute for firewall resource - -Revision ID: fd38cd995cc0 -Revises: f83a0b2964d0 -Create Date: 2017-03-31 14:22:21.063392 - -""" - -from alembic import op -import sqlalchemy as sa - -# revision identifiers, used by Alembic. -revision = 'fd38cd995cc0' -down_revision = 'f83a0b2964d0' -depends_on = ('d6a12e637e28',) - - -def upgrade(): - op.alter_column('firewall_rules_v2', 'public', new_column_name='shared', - existing_type=sa.Boolean) - op.alter_column('firewall_groups_v2', 'public', new_column_name='shared', - existing_type=sa.Boolean) - op.alter_column('firewall_policies_v2', 'public', new_column_name='shared', - existing_type=sa.Boolean) diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/876782258a43_create_default_firewall_groups_table.py b/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/876782258a43_create_default_firewall_groups_table.py deleted file mode 100644 index e8f4f7786..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/876782258a43_create_default_firewall_groups_table.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2017 FUJITSU LIMITED -# -# 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. -# - -"""create_default_firewall_groups_table - -Revision ID: 876782258a43 -Revises: d6a12e637e28 -Create Date: 2017-01-26 23:47:42.795504 - -""" - -from alembic import op -from neutron_lib.db import constants as db_constants -from neutron_lib import exceptions -import sqlalchemy as sa - -from neutron_fwaas._i18n import _ -from neutron_fwaas.common import fwaas_constants as const -from neutron_fwaas.common import resources - -# revision identifiers, used by Alembic. -revision = '876782258a43' -down_revision = 'd6a12e637e28' - - -class DuplicateDefaultFirewallGroup(exceptions.Conflict): - message = _("Duplicate Firewall group found named '%s'. " - "Database cannot be upgraded. Please, remove all duplicates " - "before upgrading the database.") % const.DEFAULT_FWG - - -def upgrade(): - op.create_table( - 'default_firewall_groups', - sa.Column('project_id', - sa.String(length=db_constants.PROJECT_ID_FIELD_SIZE), - nullable=False), - sa.Column('firewall_group_id', - sa.String(length=db_constants.UUID_FIELD_SIZE), - nullable=False), - sa.PrimaryKeyConstraint('project_id'), - sa.ForeignKeyConstraint(['firewall_group_id'], - ['firewall_groups_v2.id'], ondelete="CASCADE")) - - -def check_sanity(connection): - # check for already existing firewall groups with name == DEFAULT_FWG - insp = sa.engine.reflection.Inspector.from_engine(connection) - if 'firewall_groups_v2' not in insp.get_table_names(): - return [] - session = sa.orm.Session(bind=connection.connect()) - default_fwg = session.query(resources.FIREWALL_GROUP.name).filter( - resources.FIREWALL_GROUP.name == const.DEFAULT_FWG).first() - if default_fwg: - raise DuplicateDefaultFirewallGroup() diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/f24e0d5e5bff_uniq_firewallgroupportassociation0port.py b/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/f24e0d5e5bff_uniq_firewallgroupportassociation0port.py deleted file mode 100644 index e4f084445..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/queens/expand/f24e0d5e5bff_uniq_firewallgroupportassociation0port.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2017 Fujitsu Limited -# -# 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. -# - -"""uniq_firewallgroupportassociation0port - -Revision ID: f24e0d5e5bff -Revises: 876782258a43 -Create Date: 2017-11-08 15:55:40.990272 - -""" - -from alembic import op -from neutron_lib import exceptions -import sqlalchemy as sa - -from neutron._i18n import _ - -# revision identifiers, used by Alembic. -revision = 'f24e0d5e5bff' -down_revision = '876782258a43' - - -fwg_port_association = sa.Table( - 'firewall_group_port_associations_v2', sa.MetaData(), - sa.Column('firewall_group_id', sa.String(36)), - sa.Column('port_id', sa.String(36))) - - -class DuplicatePortRecordinFirewallGroupPortAssociation(exceptions.Conflict): - message = _("Duplicate port(s) %(port_id)s records exist in" - "firewall_group_port_associations_v2 table. Database cannot" - "be upgraded. Please remove all duplicated records before" - "upgrading the database.") - - -def upgrade(): - op.create_unique_constraint( - 'uniq_firewallgroupportassociation0port_id', - 'firewall_group_port_associations_v2', - ['port_id']) - - -def check_sanity(connection): - duplicated_port_ids = ( - get_duplicate_port_records_in_fwg_port_association(connection)) - if duplicated_port_ids: - raise DuplicatePortRecordinFirewallGroupPortAssociation( - port_id=",".join(duplicated_port_ids)) - - -def get_duplicate_port_records_in_fwg_port_association(connection): - insp = sa.engine.reflection.Inspector.from_engine(connection) - if 'firewall_group_port_associations_v2' not in insp.get_table_names(): - return [] - session = sa.orm.Session(bind=connection.connect()) - query = (session.query(fwg_port_association.c.port_id) - .group_by(fwg_port_association.c.port_id) - .having(sa.func.count() > 1)).all() - return [q[0] for q in query] diff --git a/neutron_fwaas/db/migration/alembic_migrations/versions/start_neutron_fwaas.py b/neutron_fwaas/db/migration/alembic_migrations/versions/start_neutron_fwaas.py deleted file mode 100644 index 81f49b8dd..000000000 --- a/neutron_fwaas/db/migration/alembic_migrations/versions/start_neutron_fwaas.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2014 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. -# - -"""start neutron-fwaas chain - -Revision ID: start_neutron_fwaas -Revises: None -Create Date: 2014-12-09 18:42:08.262632 - -""" - -# revision identifiers, used by Alembic. -revision = 'start_neutron_fwaas' -down_revision = None - - -def upgrade(): - pass diff --git a/neutron_fwaas/db/models/__init__.py b/neutron_fwaas/db/models/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/db/models/head.py b/neutron_fwaas/db/models/head.py deleted file mode 100644 index a6251ab21..000000000 --- a/neutron_fwaas/db/models/head.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -from neutron_lib.db import model_base - - -def get_metadata(): - return model_base.BASEV2.metadata diff --git a/neutron_fwaas/extensions/__init__.py b/neutron_fwaas/extensions/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/extensions/firewall_v2.py b/neutron_fwaas/extensions/firewall_v2.py deleted file mode 100644 index 401fd2803..000000000 --- a/neutron_fwaas/extensions/firewall_v2.py +++ /dev/null @@ -1,302 +0,0 @@ -# Copyright (c) 2016 Mirantis, 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. - -import abc - -from debtcollector import moves -from neutron.api.v2 import resource_helper -from neutron_lib.api.definitions import constants as api_const -from neutron_lib.api.definitions import firewall_v2 -from neutron_lib.api import extensions -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib.services import base as service_base -from oslo_config import cfg -import six - -from neutron_fwaas._i18n import _ -from neutron_fwaas.common import fwaas_constants - - -FirewallGroupNotFound = moves.moved_class( - f_exc.FirewallGroupNotFound, 'FirewallGroupNotFound', __name__) -FirewallGroupInUse = moves.moved_class( - f_exc.FirewallGroupInUse, 'FirewallGroupInUse', __name__) -FirewallGroupInPendingState = moves.moved_class( - f_exc.FirewallGroupInPendingState, 'FirewallGroupInPendingState', __name__) -FirewallGroupPortInvalid = moves.moved_class( - f_exc.FirewallGroupPortInvalid, 'FirewallGroupPortInvalid', __name__) -FirewallGroupPortInvalidProject = moves.moved_class( - f_exc.FirewallGroupPortInvalidProject, 'FirewallGroupPortInvalidProject', - __name__) -FirewallGroupPortInUse = moves.moved_class( - f_exc.FirewallGroupPortInUse, 'FirewallGroupPortInUse', __name__) -FirewallPolicyNotFound = moves.moved_class( - f_exc.FirewallPolicyNotFound, 'FirewallPolicyNotFound', __name__) -FirewallPolicyInUse = moves.moved_class( - f_exc.FirewallPolicyInUse, 'FirewallPolicyInUse', __name__) -FirewallPolicyConflict = moves.moved_class( - f_exc.FirewallPolicyConflict, 'FirewallPolicyConflict', __name__) -FirewallRuleSharingConflict = moves.moved_class( - f_exc.FirewallRuleSharingConflict, 'FirewallRuleSharingConflict', - __name__) -FirewallPolicySharingConflict = moves.moved_class( - f_exc.FirewallPolicySharingConflict, 'FirewallPolicySharingConflict', - __name__) -FirewallRuleNotFound = moves.moved_class( - f_exc.FirewallRuleNotFound, 'FirewallRuleNotFound', __name__) -FirewallRuleInUse = moves.moved_class( - f_exc.FirewallRuleInUse, 'FirewallRuleInUse', __name__) -FirewallRuleNotAssociatedWithPolicy = moves.moved_class( - f_exc.FirewallRuleNotAssociatedWithPolicy, - 'FirewallRuleNotAssociatedWithPolicy', - __name__) -FirewallRuleInvalidProtocol = moves.moved_class( - f_exc.FirewallRuleInvalidProtocol, 'FirewallRuleInvalidProtocol', - __name__) -FirewallRuleInvalidAction = moves.moved_class( - f_exc.FirewallRuleInvalidAction, 'FirewallRuleInvalidAction', - __name__) -FirewallRuleInvalidICMPParameter = moves.moved_class( - f_exc.FirewallRuleInvalidICMPParameter, - 'FirewallRuleInvalidICMPParameter', __name__) -FirewallRuleWithPortWithoutProtocolInvalid = moves.moved_class( - f_exc.FirewallRuleWithPortWithoutProtocolInvalid, - 'FirewallRuleWithPortWithoutProtocolInvalid', __name__) -FirewallRuleInvalidPortValue = moves.moved_class( - f_exc.FirewallRuleInvalidPortValue, 'FirewallRuleInvalidPortValue', - __name__) -FirewallRuleInfoMissing = moves.moved_class( - f_exc.FirewallRuleInfoMissing, 'FirewallRuleInfoMissing', __name__) -FirewallIpAddressConflict = moves.moved_class( - f_exc.FirewallIpAddressConflict, 'FirewallIpAddressConflict', __name__) -FirewallInternalDriverError = moves.moved_class( - f_exc.FirewallInternalDriverError, 'FirewallInternalDriverError', __name__) -FirewallRuleConflict = moves.moved_class( - f_exc.FirewallRuleConflict, 'FirewallRuleConflict', __name__) -FirewallRuleAlreadyAssociated = moves.moved_class( - f_exc.FirewallRuleAlreadyAssociated, 'FirewallRuleAlreadyAssociated', - __name__) - -default_fwg_rules_opts = [ - cfg.StrOpt('ingress_action', - default=api_const.FWAAS_DENY, - help=_('Firewall group rule action allow or ' - 'deny or reject for ingress. ' - 'Default is deny.')), - cfg.StrOpt('ingress_source_ipv4_address', - default=None, - help=_('IPv4 source address for ingress ' - '(address or address/netmask). ' - 'Default is None.')), - cfg.StrOpt('ingress_source_ipv6_address', - default=None, - help=_('IPv6 source address for ingress ' - '(address or address/netmask). ' - 'Default is None.')), - cfg.StrOpt('ingress_source_port', - default=None, - help=_('Source port number or range ' - '(min:max) for ingress. ' - 'Default is None.')), - cfg.StrOpt('ingress_destination_ipv4_address', - default=None, - help=_('IPv4 destination address for ingress ' - '(address or address/netmask). ' - 'Default is None.')), - cfg.StrOpt('ingress_destination_ipv6_address', - default=None, - help=_('IPv6 destination address for ingress ' - '(address or address/netmask). ' - 'Default is deny.')), - cfg.StrOpt('ingress_destination_port', - default=None, - help=_('Destination port number or range ' - '(min:max) for ingress. ' - 'Default is None.')), - cfg.StrOpt('egress_action', - default=api_const.FWAAS_ALLOW, - help=_('Firewall group rule action allow or ' - 'deny or reject for egress. ' - 'Default is allow.')), - cfg.StrOpt('egress_source_ipv4_address', - default=None, - help=_('IPv4 source address for egress ' - '(address or address/netmask). ' - 'Default is None.')), - cfg.StrOpt('egress_source_ipv6_address', - default=None, - help=_('IPv6 source address for egress ' - '(address or address/netmask). ' - 'Default is deny.')), - cfg.StrOpt('egress_source_port', - default=None, - help=_('Source port number or range ' - '(min:max) for egress. ' - 'Default is None.')), - cfg.StrOpt('egress_destination_ipv4_address', - default=None, - help=_('IPv4 destination address for egress ' - '(address or address/netmask). ' - 'Default is deny.')), - cfg.StrOpt('egress_destination_ipv6_address', - default=None, - help=_('IPv6 destination address for egress ' - '(address or address/netmask). ' - 'Default is deny.')), - cfg.StrOpt('egress_destination_port', - default=None, - help=_('Destination port number or range ' - '(min:max) for egress. ' - 'Default is None.')), - cfg.BoolOpt('shared', - default=False, - help=_('Firewall group rule shared. ' - 'Default is False.')), - cfg.StrOpt('protocol', - default=None, - help=_('Network protocols (tcp, udp, ...). ' - 'Default is None.')), - cfg.BoolOpt('enabled', - default=True, - help=_('Firewall group rule enabled. ' - 'Default is True.')), -] -firewall_quota_opts = [ - cfg.IntOpt('quota_firewall_group', - default=10, - help=_('Number of firewall groups allowed per tenant. ' - 'A negative value means unlimited.')), - cfg.IntOpt('quota_firewall_policy', - default=10, - help=_('Number of firewall policies allowed per tenant. ' - 'A negative value means unlimited.')), - cfg.IntOpt('quota_firewall_rule', - default=100, - help=_('Number of firewall rules allowed per tenant. ' - 'A negative value means unlimited.')), -] -cfg.CONF.register_opts(default_fwg_rules_opts, 'default_fwg_rules') -cfg.CONF.register_opts(firewall_quota_opts, 'QUOTAS') - - -# TODO(Reedip): Remove the convert_to functionality after bug1706061 is fixed. -def convert_to_string(value): - if value is not None: - return str(value) - return None - - -firewall_v2.RESOURCE_ATTRIBUTE_MAP[api_const.FIREWALL_RULES][ - 'source_port']['convert_to'] = convert_to_string -firewall_v2.RESOURCE_ATTRIBUTE_MAP[api_const.FIREWALL_RULES][ - 'destination_port']['convert_to'] = convert_to_string - - -class Firewall_v2(extensions.APIExtensionDescriptor): - api_definition = firewall_v2 - - @classmethod - def get_resources(cls): - special_mappings = {'firewall_policies': 'firewall_policy'} - plural_mappings = resource_helper.build_plural_mappings( - special_mappings, firewall_v2.RESOURCE_ATTRIBUTE_MAP) - return resource_helper.build_resource_info( - plural_mappings, firewall_v2.RESOURCE_ATTRIBUTE_MAP, - fwaas_constants.FIREWALL_V2, action_map=firewall_v2.ACTION_MAP, - register_quota=True) - - @classmethod - def get_plugin_interface(cls): - return Firewallv2PluginBase - - -@six.add_metaclass(abc.ABCMeta) -class Firewallv2PluginBase(service_base.ServicePluginBase): - - def get_plugin_type(self): - return fwaas_constants.FIREWALL_V2 - - def get_plugin_description(self): - return 'Firewall Service v2 Plugin' - - # Firewall Group - @abc.abstractmethod - def create_firewall_group(self, context, firewall_group): - pass - - @abc.abstractmethod - def delete_firewall_group(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_group(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_groups(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_group(self, context, id, firewall_group): - pass - - # Firewall Policy - @abc.abstractmethod - def create_firewall_policy(self, context, firewall_policy): - pass - - @abc.abstractmethod - def delete_firewall_policy(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_policy(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_policies(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_policy(self, context, id, firewall_policy): - pass - - # Firewall Rule - @abc.abstractmethod - def create_firewall_rule(self, context, firewall_rule): - pass - - @abc.abstractmethod - def delete_firewall_rule(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_rule(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_rules(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_rule(self, context, id, firewall_rule): - pass - - @abc.abstractmethod - def insert_rule(self, context, id, rule_info): - pass - - @abc.abstractmethod - def remove_rule(self, context, id, rule_info): - pass diff --git a/neutron_fwaas/opts.py b/neutron_fwaas/opts.py deleted file mode 100644 index 4a375498a..000000000 --- a/neutron_fwaas/opts.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 neutron.conf.services.provider_configuration - -import neutron_fwaas.services.firewall.service_drivers.agents.\ - firewall_agent_api -import neutron_fwaas.extensions.firewall_v2 - - -def list_agent_opts(): - return [ - ('fwaas', - neutron_fwaas.services.firewall.service_drivers.agents. - firewall_agent_api.FWaaSOpts), - ] - - -def list_opts(): - return [ - ('quotas', - neutron_fwaas.extensions.firewall_v2.firewall_quota_opts), - ('service_providers', - neutron.conf.services.provider_configuration.serviceprovider_opts), - ('default_fwg_rules', - neutron_fwaas.extensions.firewall_v2.default_fwg_rules_opts), - ] diff --git a/neutron_fwaas/policies/__init__.py b/neutron_fwaas/policies/__init__.py deleted file mode 100644 index 0f156640e..000000000 --- a/neutron_fwaas/policies/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# 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 itertools - -from neutron_fwaas.policies import firewall_group -from neutron_fwaas.policies import firewall_policy -from neutron_fwaas.policies import firewall_rule - - -def list_rules(): - return itertools.chain( - firewall_group.list_rules(), - firewall_policy.list_rules(), - firewall_rule.list_rules(), - ) diff --git a/neutron_fwaas/policies/base.py b/neutron_fwaas/policies/base.py deleted file mode 100644 index 463ec829b..000000000 --- a/neutron_fwaas/policies/base.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - - -# TODO(amotoki): Define these in neutron or neutron-lib -RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner' -RULE_ADMIN_ONLY = 'rule:admin_only' -RULE_ANY = 'rule:regular_user' diff --git a/neutron_fwaas/policies/firewall_group.py b/neutron_fwaas/policies/firewall_group.py deleted file mode 100644 index 6e3a42b9a..000000000 --- a/neutron_fwaas/policies/firewall_group.py +++ /dev/null @@ -1,113 +0,0 @@ -# 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. - -from oslo_policy import policy - -from neutron_fwaas.policies import base - - -rules = [ - policy.RuleDefault( - 'shared_firewall_groups', - 'field:firewall_groups:shared=True', - 'Definition of shared firewall groups' - ), - - policy.DocumentedRuleDefault( - 'create_firewall_group', - base.RULE_ANY, - 'Create a firewall group', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_groups', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_group', - base.RULE_ADMIN_OR_OWNER, - 'Update a firewall group', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_groups/{id}', - }, - ] - ), - policy.DocumentedRuleDefault( - 'delete_firewall_group', - base.RULE_ADMIN_OR_OWNER, - 'Delete a firewall group', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_groups/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'create_firewall_group:shared', - base.RULE_ADMIN_ONLY, - 'Create a shared firewall group', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_groups', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_group:shared', - base.RULE_ADMIN_ONLY, - 'Update ``shared`` attribute of a firewall group', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_groups/{id}', - }, - ] - ), - # TODO(amotoki): Drop this rule as it has no effect. - policy.DocumentedRuleDefault( - 'delete_firewall_group:shared', - base.RULE_ADMIN_ONLY, - 'Delete a shared firewall group', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_groups/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'get_firewall_group', - 'rule:admin_or_owner or rule:shared_firewall_groups', - 'Get firewall groups', - [ - { - 'method': 'GET', - 'path': '/fwaas/firewall_groups', - }, - { - 'method': 'GET', - 'path': '/fwaas/firewall_groups/{id}', - }, - ] - ), -] - - -def list_rules(): - return rules diff --git a/neutron_fwaas/policies/firewall_policy.py b/neutron_fwaas/policies/firewall_policy.py deleted file mode 100644 index 03e37952d..000000000 --- a/neutron_fwaas/policies/firewall_policy.py +++ /dev/null @@ -1,113 +0,0 @@ -# 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. - -from oslo_policy import policy - -from neutron_fwaas.policies import base - - -rules = [ - policy.RuleDefault( - 'shared_firewall_policies', - 'field:firewall_policies:shared=True', - 'Definition of shared firewall policies' - ), - - policy.DocumentedRuleDefault( - 'create_firewall_policy', - base.RULE_ANY, - 'Create a firewall policy', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_policies', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_policy', - base.RULE_ADMIN_OR_OWNER, - 'Update a firewall policy', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_policies/{id}', - }, - ] - ), - policy.DocumentedRuleDefault( - 'delete_firewall_policy', - base.RULE_ADMIN_OR_OWNER, - 'Delete a firewall policy', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_policies/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'create_firewall_policy:shared', - base.RULE_ADMIN_ONLY, - 'Create a shared firewall policy', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_policies', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_policy:shared', - base.RULE_ADMIN_ONLY, - 'Update ``shared`` attribute of a firewall policy', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_policies/{id}', - }, - ] - ), - # TODO(amotoki): Drop this rule as it has no effect. - policy.DocumentedRuleDefault( - 'delete_firewall_policy:shared', - base.RULE_ADMIN_ONLY, - 'Delete a shread firewall policy', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_policies/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'get_firewall_policy', - 'rule:admin_or_owner or rule:shared_firewall_policies', - 'Get firewall policies', - [ - { - 'method': 'GET', - 'path': '/fwaas/firewall_policies', - }, - { - 'method': 'GET', - 'path': '/fwaas/firewall_policies/{id}', - }, - ] - ), -] - - -def list_rules(): - return rules diff --git a/neutron_fwaas/policies/firewall_rule.py b/neutron_fwaas/policies/firewall_rule.py deleted file mode 100644 index eb0ce950e..000000000 --- a/neutron_fwaas/policies/firewall_rule.py +++ /dev/null @@ -1,136 +0,0 @@ -# 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. - -from oslo_policy import policy - -from neutron_fwaas.policies import base - - -rules = [ - policy.RuleDefault( - 'shared_firewall_rules', - 'field:firewall_rules:shared=True', - 'Definition of shared firewall rules' - ), - - policy.DocumentedRuleDefault( - 'create_firewall_rule', - base.RULE_ANY, - 'Create a firewall rule', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_rules', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_rule', - base.RULE_ADMIN_OR_OWNER, - 'Update a firewall rule', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_rules/{id}', - }, - ] - ), - policy.DocumentedRuleDefault( - 'delete_firewall_rule', - base.RULE_ADMIN_OR_OWNER, - 'Delete a firewall rule', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_rules/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'create_firewall_rule:shared', - base.RULE_ADMIN_ONLY, - 'Create a shared firewall rule', - [ - { - 'method': 'POST', - 'path': '/fwaas/firewall_rules', - }, - ] - ), - policy.DocumentedRuleDefault( - 'update_firewall_rule:shared', - base.RULE_ADMIN_ONLY, - 'Update ``shared`` attribute of a firewall rule', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_rules/{id}', - }, - ] - ), - # TODO(amotoki): Drop this rule as it has no effect. - policy.DocumentedRuleDefault( - 'delete_firewall_rule:shared', - base.RULE_ADMIN_ONLY, - 'Delete a shread firewall rule', - [ - { - 'method': 'DELETE', - 'path': '/fwaas/firewall_rules/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'get_firewall_rule', - 'rule:admin_or_owner or rule:shared_firewall_rules', - 'Get firewall rules', - [ - { - 'method': 'GET', - 'path': '/fwaas/firewall_rules', - }, - { - 'method': 'GET', - 'path': '/fwaas/firewall_rules/{id}', - }, - ] - ), - - policy.DocumentedRuleDefault( - 'insert_rule', - base.RULE_ADMIN_OR_OWNER, - 'Insert rule into a firewall policy', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_policies/{id}/insert_rule', - }, - ] - ), - policy.DocumentedRuleDefault( - 'remove_rule', - base.RULE_ADMIN_OR_OWNER, - 'Remove rule from a firewall policy', - [ - { - 'method': 'PUT', - 'path': '/fwaas/firewall_policies/{id}/remove_rule', - }, - ] - ), -] - - -def list_rules(): - return rules diff --git a/neutron_fwaas/privileged/__init__.py b/neutron_fwaas/privileged/__init__.py deleted file mode 100644 index 17831c1cc..000000000 --- a/neutron_fwaas/privileged/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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. - -from oslo_privsep import capabilities as c -from oslo_privsep import priv_context - -# It is expected that most (if not all) neutron-fwaas operations can be -# executed with these privileges. -default = priv_context.PrivContext( - __name__, - cfg_section='privsep', - pypath=__name__ + '.default', - # TODO(gus): CAP_SYS_ADMIN is required (only?) for manipulating - # network namespaces. SYS_ADMIN is a lot of scary powers, so - # consider breaking this out into a separate minimal context. - capabilities=[c.CAP_SYS_ADMIN, c.CAP_NET_ADMIN], -) diff --git a/neutron_fwaas/privileged/netfilter_log/__init__.py b/neutron_fwaas/privileged/netfilter_log/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/privileged/netfilter_log/libnetfilter_log.py b/neutron_fwaas/privileged/netfilter_log/libnetfilter_log.py deleted file mode 100644 index fdd389e31..000000000 --- a/neutron_fwaas/privileged/netfilter_log/libnetfilter_log.py +++ /dev/null @@ -1,331 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 multiprocessing -import socket -import struct -import time - -import cffi -import eventlet -from eventlet.green import zmq -from neutron_lib.utils import runtime -from os_ken.lib import addrconv -from os_ken.lib.packet import arp -from os_ken.lib.packet import ether_types -from os_ken.lib.packet import ethernet -from os_ken.lib.packet import ipv4 -from os_ken.lib.packet import ipv6 -from oslo_log import log as logging -from oslo_serialization import jsonutils -from oslo_utils import encodeutils -from oslo_utils import excutils - -from neutron_fwaas._i18n import _ -from neutron_fwaas import privileged -from neutron_fwaas.privileged import utils as fwaas_utils - -LOG = logging.getLogger(__name__) - -# TODO(annp): consider to make a pub-sub pattern which allows other logging -# driver like snat log can consume libnetfilter_log - -NETFILTER_LOG = 'netfilter_log' -ADDR_IPC = "ipc:///var/run/nflog" -CDEF = ''' -typedef unsigned char u_int8_t; -typedef unsigned short int u_int16_t; -typedef unsigned int u_int32_t; - -struct nfulnl_msg_packet_hdr { - u_int16_t hw_protocol; // hw protocol (network order) - u_int8_t hook; // netfilter hook - u_int8_t _pad; -}; - -int nflog_fd(struct nflog_handle *h); -ssize_t recv(int sockfd, void *buf, size_t len, int flags); - -struct nflog_handle *nflog_open(void); -int nflog_close(struct nflog_handle *h); -int nflog_bind_pf(struct nflog_handle *h, u_int16_t pf); -int nflog_unbind_pf(struct nflog_handle *h, u_int16_t pf); -struct nflog_g_handle *nflog_bind_group(struct nflog_handle *h, u_int16_t num); -int nflog_unbind_group(struct nflog_g_handle *gh); - -static const u_int8_t NFULNL_COPY_PACKET; - -int nflog_set_mode(struct nflog_g_handle *gh, u_int8_t mode, unsigned int len); -int nflog_set_timeout(struct nflog_g_handle *gh, u_int32_t timeout); -int nflog_set_flags(struct nflog_g_handle *gh, u_int16_t flags); -int nflog_set_qthresh(struct nflog_g_handle *gh, u_int32_t qthresh); -int nflog_set_nlbufsiz(struct nflog_g_handle *gh, u_int32_t nlbufsiz); - -typedef int nflog_callback(struct nflog_g_handle *gh, -struct nfgenmsg *nfmsg, struct nflog_data *nfd, void *data); -int nflog_callback_register( -struct nflog_g_handle *gh, nflog_callback *cb, void *data); -int nflog_handle_packet(struct nflog_handle *h, char *buf, int len); - -struct nfulnl_msg_packet_hdr *nflog_get_msg_packet_hdr( -struct nflog_data *nfad); - -u_int16_t nflog_get_hwtype(struct nflog_data *nfad); -u_int16_t nflog_get_msg_packet_hwhdrlen(struct nflog_data *nfad); -char *nflog_get_msg_packet_hwhdr(struct nflog_data *nfad); -u_int32_t nflog_get_nfmark(struct nflog_data *nfad); -int nflog_get_timestamp(struct nflog_data *nfad, struct timeval *tv); -u_int32_t nflog_get_indev(struct nflog_data *nfad); -u_int32_t nflog_get_physindev(struct nflog_data *nfad); -u_int32_t nflog_get_outdev(struct nflog_data *nfad); -u_int32_t nflog_get_physoutdev(struct nflog_data *nfad); -struct nfulnl_msg_packet_hw *nflog_get_packet_hw(struct nflog_data *nfad); - -int nflog_get_payload(struct nflog_data *nfad, char **data); - -char *nflog_get_prefix(struct nflog_data *nfad); -''' - -ffi = None -libnflog = None - - -def init_library(): - """Load libnetfilter_log library""" - - global ffi - global libnflog - if not ffi: - ffi = cffi.FFI() - ffi.cdef(CDEF) - if not libnflog: - try: - libnflog = ffi.dlopen(NETFILTER_LOG) - except OSError: - msg = "Could not found libnetfilter-log" - raise Exception(msg) - - return ffi, libnflog - - -ffi, libnflog = init_library() - - -def _payload(nfa): - buf = ffi.new('char **') - pkt_len = libnflog.nflog_get_payload(nfa, buf) - if pkt_len <= 0: - return None - return ffi.buffer(buf[0], pkt_len)[:] - - -def decode(nfa): - """This function analyses nflog packet by using os-ken packet library.""" - - prefix = ffi.string(libnflog.nflog_get_prefix(nfa)) - packet_hdr = libnflog.nflog_get_msg_packet_hdr(nfa) - hw_proto = socket.ntohs(packet_hdr.hw_protocol) - - msg = '' - msg_packet_hwhdr = libnflog.nflog_get_msg_packet_hwhdr(nfa) - if msg_packet_hwhdr != ffi.NULL: - packet_hwhdr = ffi.string(msg_packet_hwhdr) - if len(packet_hwhdr) >= 12: - dst, src = struct.unpack_from('!6s6s', packet_hwhdr) - # Dump ethernet packet to get mac addresses - eth = ethernet.ethernet(addrconv.mac.bin_to_text(dst), - addrconv.mac.bin_to_text(src), - ethertype=hw_proto) - msg = str(eth) - - # Dump IP packet - pkt = _payload(nfa) - if hw_proto == ether_types.ETH_TYPE_IP: - ip_pkt, proto, data = ipv4.ipv4().parser(pkt) - msg += str(ip_pkt) - proto_pkt, a, b = proto.parser(data) - msg += str(proto_pkt) - elif hw_proto == ether_types.ETH_TYPE_IPV6: - ip_pkt, proto, data = ipv6.ipv6().parser(pkt) - proto_pkt, a, b = proto.parser(data) - msg += str(proto_pkt) - elif hw_proto == ether_types.ETH_TYPE_ARP: - ip_pkt, proto, data = arp.arp().parser(pkt) - msg += str(ip_pkt) - else: - msg += "Does not support hw_proto: " + str(hw_proto) - - return {'prefix': encodeutils.safe_decode(prefix), - 'msg': encodeutils.safe_decode(msg)} - - -class NFLogWrapper(object): - """A wrapper for libnetfilter_log api""" - - _instance = None - - def __init__(self): - self.nflog_g_hanldes = {} - - @classmethod - @runtime.synchronized("nflog-wrapper") - def _create_instance(cls): - if not cls.has_instance(): - cls._instance = cls() - - @classmethod - def has_instance(cls): - return cls._instance is not None - - @classmethod - def clear_instance(cls): - cls._instance = None - - @classmethod - def get_instance(cls): - # double checked locking - if not cls.has_instance(): - cls._create_instance() - return cls._instance - - def open(self): - self.nflog_handle = libnflog.nflog_open() - if not self.nflog_handle: - msg = _("Could not open nflog handle") - raise Exception(msg) - self._bind_pf() - - def close(self): - if self.nflog_handle: - libnflog.nflog_close(self.nflog_handle) - - def bind_group(self, group): - g_handle = libnflog.nflog_bind_group(self.nflog_handle, group) - if g_handle: - self.nflog_g_hanldes[group] = g_handle - self._set_mode(g_handle, 0x2, 0xffff) - self._set_callback(g_handle, self.cb) - - def _bind_pf(self): - for pf in (socket.AF_INET, socket.AF_INET6): - libnflog.nflog_unbind_pf(self.nflog_handle, pf) - libnflog.nflog_bind_pf(self.nflog_handle, pf) - - def unbind_group(self, group): - try: - g_handle = self.nflog_g_hanldes[group] - if g_handle: - libnflog.nflog_unbind_group(g_handle) - except Exception: - pass - - def _set_mode(self, g_handle, mode, len): - ret = libnflog.nflog_set_mode(g_handle, mode, len) - if ret != 0: - msg = _("Could not set mode for nflog") - raise Exception(msg) - - @ffi.callback("nflog_callback") - def cb(gh, nfmsg, nfa, data): - ev = decode(nfa) - msg = jsonutils.dumps(ev) + '\n' - ctx = zmq.Context(1) - pub = ctx.socket(zmq.XREQ) - pub.bind(ADDR_IPC) - pub.send(msg.encode('utf-8')) - pub.close() - return 0 - - def _set_callback(self, g_handle, cb): - - ret = libnflog.nflog_callback_register(g_handle, cb, ffi.NULL) - if ret != 0: - msg = _("Could not set callback for nflog") - raise Exception(msg) - - def run_loop(self): - fd = libnflog.nflog_fd(self.nflog_handle) - buff = ffi.new('char[]', 4096) - while True: - try: - pkt_len = libnflog.recv(fd, buff, 4096, 0) - except OSError as err: - # No buffer space available - if err.errno == 11: - continue - msg = _("Unknown exception") - raise Exception(msg) - if pkt_len > 0: - libnflog.nflog_handle_packet(self.nflog_handle, buff, pkt_len) - time.sleep(1.0) - - def start(self): - nflog_process = multiprocessing.Process(target=self.run_loop) - nflog_process.daemon = True - nflog_process.start() - return nflog_process.pid - - -@privileged.default.entrypoint -def run_nflog(namespace=None, group=0): - """Run a nflog process under a namespace - - This process will listen nflog packets, which are sent from kernel to - userspace. Then it decode these packets and send it to IPC address for log - application. - """ - - with fwaas_utils.in_namespace(namespace): - try: - handle = NFLogWrapper.get_instance() - handle.open() - handle.bind_group(group) - pid = handle.start() - except Exception: - with excutils.save_and_reraise_exception(): - LOG.exception("NFLOG thread died of an exception") - try: - handle.unbind_group(group) - handle.close() - except Exception: - pass - return pid - - -class NFLogApp(object): - """Log application for handling nflog packets""" - - callback = None - - def register_packet_handler(self, caller): - self.callback = caller - - def unregister_packet_handler(self): - self.callback = None - - def start(self): - def loop(): - while True: - if self.callback: - ctx = zmq.Context(1) - sub = ctx.socket(zmq.XREQ) - sub.connect(ADDR_IPC) - msg = sub.recv() - if len(msg): - self.callback(jsonutils.loads(msg)) - sub.close() - time.sleep(1.0) - # Spawn loop - eventlet.spawn_n(loop) diff --git a/neutron_fwaas/privileged/netlink_constants.py b/neutron_fwaas/privileged/netlink_constants.py deleted file mode 100644 index 376150fdc..000000000 --- a/neutron_fwaas/privileged/netlink_constants.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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. -# -# Some parts are based on python-conntrack: -# Copyright (c) 2009-2011,2015 Andrew Grigorev -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -import socket - - -CONNTRACK = 0 - -NFCT_O_PLAIN = 0 - -NFCT_OF_TIME_BIT = 1 -NFCT_OF_TIME = 1 << NFCT_OF_TIME_BIT - -NFCT_Q_DESTROY = 2 -NFCT_Q_FLUSH = 4 -NFCT_Q_DUMP = 5 -NFCT_T_DESTROY_BIT = 2 -NFCT_T_DESTROY = 1 << NFCT_T_DESTROY_BIT - -ATTR_IPV4_SRC = 0 -ATTR_IPV4_DST = 1 -ATTR_IPV6_SRC = 4 -ATTR_IPV6_DST = 5 -ATTR_PORT_SRC = 8 -ATTR_PORT_DST = 9 -ATTR_ICMP_TYPE = 12 -ATTR_ICMP_CODE = 13 -ATTR_ICMP_ID = 14 -ATTR_L3PROTO = 15 -ATTR_L4PROTO = 17 - -NFCT_T_NEW_BIT = 0 -NFCT_T_NEW = 1 << NFCT_T_NEW_BIT -NFCT_T_UPDATE_BIT = 1 -NFCT_T_UPDATE = 1 << NFCT_T_UPDATE_BIT -NFCT_T_DESTROY_BIT = 2 -NFCT_T_DESTROY = 1 << NFCT_T_DESTROY_BIT - -NFCT_T_ALL = NFCT_T_NEW | NFCT_T_UPDATE | NFCT_T_DESTROY - -NFCT_CB_CONTINUE = 1 -NFCT_CB_FAILURE = -1 - -NFNL_SUBSYS_CTNETLINK = 0 - -BUFFER = 1024 -# IPv6 address memory buffer -ADDR_BUFFER_6 = 16 -ADDR_BUFFER_4 = 4 - -IPVERSION_SOCKET = {4: socket.AF_INET, 6: socket.AF_INET6} -IPVERSION_BUFFER = {4: ADDR_BUFFER_4, 6: ADDR_BUFFER_6} diff --git a/neutron_fwaas/privileged/netlink_lib.py b/neutron_fwaas/privileged/netlink_lib.py deleted file mode 100644 index 7fac6d250..000000000 --- a/neutron_fwaas/privileged/netlink_lib.py +++ /dev/null @@ -1,314 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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. -# -# Some parts are based on python-conntrack: -# Copyright (c) 2009-2011,2015 Andrew Grigorev -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -import ctypes -from ctypes import util - -from oslo_log import log as logging - -from neutron_lib import constants - -from neutron_fwaas import privileged -from neutron_fwaas.privileged import netlink_constants as nl_constants -from neutron_fwaas.privileged import utils as fwaas_utils - -LOG = logging.getLogger(__name__) - -nfct_lib = util.find_library('netfilter_conntrack') -nfct = ctypes.CDLL(nfct_lib) -libc = ctypes.CDLL(util.find_library('libc.so.6')) - -# In unit tests the actual nfct library may not be installed, and since we -# don't make actual calls to it we don't want to add a hard dependency. -if nfct_lib: - # It's important that the types be defined properly on all of the functions - # we call from nfct, otherwise pointers can be truncated and cause - # segfaults. - nfct.nfct_set_attr.argtypes = [ctypes.c_void_p, - ctypes.c_int, - ctypes.c_void_p] - nfct.nfct_set_attr_u8.argtypes = [ctypes.c_void_p, - ctypes.c_int, - ctypes.c_uint8] - nfct.nfct_set_attr_u16.argtypes = [ctypes.c_void_p, - ctypes.c_int, - ctypes.c_uint16] - nfct.nfct_snprintf.argtypes = [ctypes.c_char_p, - ctypes.c_uint, - ctypes.c_void_p, - ctypes.c_uint, - ctypes.c_uint, - ctypes.c_uint] - nfct.nfct_new.restype = ctypes.c_void_p - nfct.nfct_destroy.argtypes = [ctypes.c_void_p] - nfct.nfct_query.argtypes = [ctypes.c_void_p, - ctypes.c_int, - ctypes.c_void_p] - nfct.nfct_callback_register.argtypes = [ctypes.c_void_p, - ctypes.c_int, - ctypes.c_void_p, - ctypes.c_void_p] - nfct.nfct_open.restype = ctypes.c_void_p - nfct.nfct_close.argtypes = [ctypes.c_void_p] - - -IP_VERSIONS = [constants.IP_VERSION_4, constants.IP_VERSION_6] -DATA_CALLBACK = None - -ATTR_POSITIONS = { - 'icmp': [('type', 6), ('code', 7), ('src', 4), ('dst', 5), ('id', 8)], - 'icmpv6': [('type', 6), ('code', 7), ('src', 4), ('dst', 5), ('id', 8)], - 'tcp': [('sport', 7), ('dport', 8), ('src', 5), ('dst', 6)], - 'udp': [('sport', 6), ('dport', 7), ('src', 4), ('dst', 5)] -} - -TARGET = {'src': {4: nl_constants.ATTR_IPV4_SRC, - 6: nl_constants.ATTR_IPV6_SRC}, - 'dst': {4: nl_constants.ATTR_IPV4_DST, - 6: nl_constants.ATTR_IPV6_DST}, - 'ipversion': {4: nl_constants.ATTR_L3PROTO, - 6: nl_constants.ATTR_L3PROTO}, - 'protocol': {4: nl_constants.ATTR_L4PROTO, - 6: nl_constants.ATTR_L4PROTO}, - 'code': {4: nl_constants.ATTR_ICMP_CODE, - 6: nl_constants.ATTR_ICMP_CODE}, - 'type': {4: nl_constants.ATTR_ICMP_TYPE, - 6: nl_constants.ATTR_ICMP_TYPE}, - 'id': {4: nl_constants.ATTR_ICMP_ID, - 6: nl_constants.ATTR_ICMP_ID}, - 'sport': {4: nl_constants.ATTR_PORT_SRC, - 6: nl_constants.ATTR_PORT_SRC}, - 'dport': {4: nl_constants.ATTR_PORT_DST, - 6: nl_constants.ATTR_PORT_DST}} - -NFCT_CALLBACK = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, - ctypes.c_void_p, ctypes.c_void_p) - - -class ConntrackOpenFailedExit(SystemExit): - """Raised if we fail to open a new conntrack or conntrack handler""" - - -class ConntrackManager(object): - def __init__(self, family_socket=None): - self.family_socket = family_socket - self.set_functions = { - 'src': {4: nfct.nfct_set_attr, - 6: nfct.nfct_set_attr}, - 'dst': {4: nfct.nfct_set_attr, - 6: nfct.nfct_set_attr}, - 'ipversion': {4: nfct.nfct_set_attr_u8, - 6: nfct.nfct_set_attr_u8}, - 'protocol': {4: nfct.nfct_set_attr_u8, - 6: nfct.nfct_set_attr_u8}, - 'type': {4: nfct.nfct_set_attr_u8, - 6: nfct.nfct_set_attr_u8}, - 'code': {4: nfct.nfct_set_attr_u8, - 6: nfct.nfct_set_attr_u8}, - 'id': {4: nfct.nfct_set_attr_u16, - 6: nfct.nfct_set_attr_u16}, - 'sport': {4: nfct.nfct_set_attr_u16, - 6: nfct.nfct_set_attr_u16}, - 'dport': {4: nfct.nfct_set_attr_u16, - 6: nfct.nfct_set_attr_u16}, } - - self.converters = {'src': bytes, - 'dst': bytes, - 'ipversion': nl_constants.IPVERSION_SOCKET.get, - 'protocol': constants.IP_PROTOCOL_MAP.get, - 'code': int, - 'type': int, - 'id': libc.htons, - 'sport': libc.htons, - 'dport': libc.htons, } - - def list_entries(self): - entries = [] - raw_entry = ctypes.create_string_buffer(nl_constants.BUFFER) - - @NFCT_CALLBACK - def callback(type_, conntrack, data): - nfct.nfct_snprintf(raw_entry, nl_constants.BUFFER, - conntrack, type_, - nl_constants.NFCT_O_PLAIN, - nl_constants.NFCT_OF_TIME) - entries.append(raw_entry.value.decode('utf-8')) - return nl_constants.NFCT_CB_CONTINUE - - self._callback_register(nl_constants.NFCT_T_ALL, - callback, DATA_CALLBACK) - - data_ref = self._get_ref(self.family_socket or - nl_constants.IPVERSION_SOCKET[4]) - self._query(nl_constants.NFCT_Q_DUMP, data_ref) - return entries - - def delete_entries(self, entries): - conntrack = nfct.nfct_new() - try: - for entry in entries: - self._set_attributes(conntrack, entry) - self._query(nl_constants.NFCT_Q_DESTROY, conntrack) - except Exception as e: - msg = "Failed to delete conntrack entries %s" % e - LOG.critical(msg) - raise ConntrackOpenFailedExit(msg) - finally: - nfct.nfct_destroy(conntrack) - - def flush_entries(self): - data_ref = self._get_ref(self.family_socket or - nl_constants.IPVERSION_SOCKET[4]) - self._query(nl_constants.NFCT_Q_FLUSH, data_ref) - - def _query(self, query_type, query_data): - result = nfct.nfct_query(self.conntrack_handler, query_type, - query_data) - if result == nl_constants.NFCT_CB_FAILURE: - LOG.warning("Netlink query failed") - - def _convert_text_to_binary(self, source, addr_family): - dest = ctypes.create_string_buffer( - nl_constants.IPVERSION_BUFFER[addr_family]) - libc.inet_pton(nl_constants.IPVERSION_SOCKET[addr_family], - source.encode('utf-8'), dest) - return dest.raw - - def _set_attributes(self, conntrack, entry): - ipversion = entry.get('ipversion', 4) - for attr, value in entry.items(): - set_function = self.set_functions[attr][ipversion] - target = TARGET[attr][ipversion] - converter = self.converters[attr] - if attr in ['src', 'dst']: - # convert src and dst of IPv4 and IPv6 into same format - value = self._convert_text_to_binary(value, ipversion) - set_function(conntrack, target, converter(value)) - - def _callback_register(self, message_type, callback_func, data): - nfct.nfct_callback_register(self.conntrack_handler, - message_type, callback_func, data) - - def _get_ref(self, data): - return ctypes.byref(ctypes.c_int(data)) - - def __enter__(self): - self.conntrack_handler = nfct.nfct_open( - nl_constants.CONNTRACK, - nl_constants.NFNL_SUBSYS_CTNETLINK) - if not self.conntrack_handler: - msg = "Failed to open new conntrack handler" - LOG.critical(msg) - raise ConntrackOpenFailedExit(msg) - return self - - def __exit__(self, *args): - nfct.nfct_close(self.conntrack_handler) - - -def _parse_entry(entry, ipversion): - """Parse entry from text to Python tuple - - :param entry: conntrack entry in text - :param ipversion: ipversion 4 or 6 - :return: conntrack entry in Python tuple - example: (4, 'tcp', '1', '2', '1.1.1.1', '2.2.2.2') - The attributes are ordered to be easy to compare with other entries - and compare with firewall rule - """ - protocol = entry[1] - parsed_entry = [ipversion, protocol] - for attr, position in ATTR_POSITIONS[protocol]: - val = entry[position].partition('=')[2] - parsed_entry.append(int(val) if attr in ['sport', 'dport', 'type', - 'code', 'id'] else val) - return tuple(parsed_entry) - - -@privileged.default.entrypoint -def flush_entries(namespace=None): - """Delete all conntrack entries - - :param namespace: namespace to delete conntrack entries - :return: None - """ - with fwaas_utils.in_namespace(namespace): - for ipversion in IP_VERSIONS: - with ConntrackManager(nl_constants.IPVERSION_SOCKET[ipversion]) \ - as conntrack: - conntrack.flush_entries() - - -@privileged.default.entrypoint -def list_entries(namespace=None): - """List and parse all conntrack entries - - :param namespace: namespace to get conntrack entries - :return: sorted list of conntrack entries in Python tuple - example: [(4, 'icmp', '8', '0', '1.1.1.1', '2.2.2.2', '1234'), - (4, 'tcp', '1', '2', '1.1.1.1', '2.2.2.2')] - """ - parsed_entries = [] - with fwaas_utils.in_namespace(namespace): - for ipversion in IP_VERSIONS: - with ConntrackManager(nl_constants.IPVERSION_SOCKET[ipversion]) \ - as conntrack: - raw_entries = conntrack.list_entries() - for raw_entry in raw_entries: - parsed_entry = _parse_entry(raw_entry.split(), ipversion) - parsed_entries.append(parsed_entry) - return sorted(parsed_entries) - - -@privileged.default.entrypoint -def delete_entries(entries, namespace=None): - """Delete selected entries - - :param entries: list of parsed (as tuple) entries to delete - :param namespace: namespace to delete conntrack entries - :return: None - """ - entry_args = [] - for entry in entries: - entry_arg = {'ipversion': entry[0], 'protocol': entry[1]} - for idx, attr in enumerate(ATTR_POSITIONS[entry_arg['protocol']]): - entry_arg[attr[0]] = entry[idx + 2] - entry_args.append(entry_arg) - - with fwaas_utils.in_namespace(namespace): - with ConntrackManager() as conntrack: - conntrack.delete_entries(entry_args) diff --git a/neutron_fwaas/privileged/tests/__init__.py b/neutron_fwaas/privileged/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/privileged/tests/functional/__init__.py b/neutron_fwaas/privileged/tests/functional/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/privileged/tests/functional/dummy.py b/neutron_fwaas/privileged/tests/functional/dummy.py deleted file mode 100644 index fe0e85995..000000000 --- a/neutron_fwaas/privileged/tests/functional/dummy.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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. - -from oslo_utils import uuidutils -from pyroute2 import netns as pynetns - -from neutron_fwaas import privileged - - -# TODO(cby): move this method in neutron.tests.functional.privileged associated -# to a new privsep context. -@privileged.default.entrypoint -def dummy(): - """This method aim is to validate that we can use privsep in functests.""" - namespace = 'dummy-%s' % uuidutils.generate_uuid() - pynetns.create(namespace) - pynetns.remove(namespace) diff --git a/neutron_fwaas/privileged/tests/functional/utils.py b/neutron_fwaas/privileged/tests/functional/utils.py deleted file mode 100644 index 2e58a27d8..000000000 --- a/neutron_fwaas/privileged/tests/functional/utils.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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 pyroute2 - -from neutron_fwaas import privileged -from neutron_fwaas.privileged import utils - - -def _get_ifname(link): - attr_dict = dict(link['attrs']) - return attr_dict['IFLA_IFNAME'] - - -def list_interface_names(): - iproute = pyroute2.IPRoute() - result = iproute.get_links() - return [_get_ifname(link) for link in result] - - -@privileged.default.entrypoint -def get_in_namespace_interfaces(namespace): - before = list_interface_names() - with utils.in_namespace(namespace): - inside = list_interface_names() - after = list_interface_names() - return before, inside, after diff --git a/neutron_fwaas/privileged/utils.py b/neutron_fwaas/privileged/utils.py deleted file mode 100644 index f3edccbae..000000000 --- a/neutron_fwaas/privileged/utils.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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 os - -from oslo_log import log as logging -from pyroute2 import netns as pynetns - -from neutron_fwaas._i18n import _ - - -PROCESS_NETNS = '/proc/self/ns/net' - -LOG = logging.getLogger(__name__) - - -class BackInNamespaceExit(SystemExit): - """Raised if we fail to moved back process in its original namespace.""" - - -@contextlib.contextmanager -def in_namespace(namespace): - """Move current process in a specific namespace. - - This contextmanager moves current process in a specific namespace and - ensures to move it back in original namespace or kills it if we fail to - move back in original namespace. - """ - if not namespace: - yield - return - - org_netns_fd = os.open(PROCESS_NETNS, os.O_RDONLY) - pynetns.setns(namespace) - try: - yield - finally: - try: - # NOTE(cby): this code is not executed only if we fail to - # move in target namespace - pynetns.setns(org_netns_fd) - except Exception as e: - msg = _('Failed to move back in original netns: %s') % e - LOG.critical(msg) - raise BackInNamespaceExit(msg) diff --git a/neutron_fwaas/services/__init__.py b/neutron_fwaas/services/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/__init__.py b/neutron_fwaas/services/firewall/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/fwaas_plugin_v2.py b/neutron_fwaas/services/firewall/fwaas_plugin_v2.py deleted file mode 100644 index 1fa2dba72..000000000 --- a/neutron_fwaas/services/firewall/fwaas_plugin_v2.py +++ /dev/null @@ -1,429 +0,0 @@ -# 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. - -from neutron.db import servicetype_db as st_db -from neutron import service -from neutron.services import provider_configuration as provider_conf -from neutron.services import service_base -from neutron_lib.api.definitions import firewall_v2 -from neutron_lib.api.definitions import portbindings as pb_def -from neutron_lib.api import validators -from neutron_lib.callbacks import events -from neutron_lib.callbacks import registry -from neutron_lib.callbacks import resources -from neutron_lib import constants as nl_constants -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib.plugins import constants as plugin_const -from neutron_lib.plugins import directory -from oslo_log import helpers as log_helpers -from oslo_log import log as logging - -from neutron_fwaas.common import exceptions -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.extensions.firewall_v2 import Firewallv2PluginBase -from neutron_fwaas.services.firewall.service_drivers import driver_api -from neutron_fwaas.services.logapi.agents.drivers.iptables \ - import driver as logging_driver - -LOG = logging.getLogger(__name__) - - -@registry.has_registry_receivers -class FirewallPluginV2(Firewallv2PluginBase): - """Firewall v2 Neutron service plugin class""" - - supported_extension_aliases = [firewall_v2.ALIAS] - path_prefix = firewall_v2.API_PREFIX - - def __init__(self): - super(FirewallPluginV2, self).__init__() - """Do the initialization for the firewall service plugin here.""" - # Initialize the Firewall v2 service plugin - service_type_manager = st_db.ServiceTypeManager.get_instance() - service_type_manager.add_provider_configuration( - fwaas_constants.FIREWALL_V2, - provider_conf.ProviderConfiguration('neutron_fwaas')) - - # Load the default driver - drivers, default_provider = service_base.load_drivers( - fwaas_constants.FIREWALL_V2, self) - LOG.info("Firewall v2 Service Plugin using Service Driver: %s", - default_provider) - - if len(drivers) > 1: - LOG.warning("Multiple drivers configured for Firewall v2, " - "although running multiple drivers in parallel is " - "not yet supported") - - self.driver_name = default_provider - self.driver = drivers[default_provider] - - # start rpc listener if driver required - if isinstance(self.driver, driver_api.FirewallDriverRPCMixin): - rpc_worker = service.RpcWorker([self], worker_process_count=0) - self.add_worker(rpc_worker) - - log_plugin = directory.get_plugin(plugin_const.LOG_API) - logging_driver.register() - # If log_plugin was loaded before firewall plugin - if log_plugin: - # Register logging driver with LoggingServiceDriverManager again - log_plugin.driver_manager.register_driver(logging_driver.DRIVER) - - def start_rpc_listeners(self): - return self.driver.start_rpc_listener() - - @property - def _core_plugin(self): - return directory.get_plugin() - - def _ensure_update_firewall_group(self, context, fwg_id): - """Checks if the firewall group can be updated - - Raises FirewallGroupInPendingState if the firewall group is in pending - state. - :param context: neutron context - :param fwg_id: firewall group ID to check - :return: Firewall group dict - """ - fwg = self.get_firewall_group(context, fwg_id) - if fwg['status'] in [nl_constants.PENDING_CREATE, - nl_constants.PENDING_UPDATE, - nl_constants.PENDING_DELETE]: - raise f_exc.FirewallGroupInPendingState( - firewall_id=fwg_id, pending_state=fwg['status']) - return fwg - - def _ensure_update_firewall_policy(self, context, fwp_id): - """Checks if the firewall policy can be updated - - Fetch firewall group associated to the policy and checks if they can be - updated. - :param context: neutron context - :param fwp_id: firewall policy ID to check - """ - fwp = self.get_firewall_policy(context, fwp_id) - ing_fwg_ids, eg_fwg_ids = self._get_fwgs_with_policy(context, fwp) - for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)): - self._ensure_update_firewall_group(context, fwg_id) - - def _ensure_update_firewall_rule(self, context, fwr_id): - """Checks if the firewall rule can be updated - - Fetch firewall policy associated to the rule and checks if they can be - updated. - :param context: neutron context - :param fwr_id: firewall policy ID to check - """ - fwr = self.get_firewall_rule(context, fwr_id) - fwp_ids = self._get_policies_with_rule(context, fwr) - for fwp_id in fwp_ids: - self._ensure_update_firewall_policy(context, fwp_id) - - def _validate_firewall_policies_for_firewall_group(self, context, fwg): - """Validate firewall group and policy owner - - Check if the firewall policy is not shared, it have the same project - owner than the friewall group. - :param context: neutron context - :param fwg: firewall group to validate - """ - for policy_type in ['ingress_firewall_policy_id', - 'egress_firewall_policy_id']: - if fwg.get(policy_type): - fwp = self.get_firewall_policy(context, fwg[policy_type]) - if fwg['tenant_id'] != fwp['tenant_id'] and not fwp['shared']: - raise f_exc.FirewallPolicyConflict( - firewall_policy_id=fwg[policy_type]) - - def _validate_ports_for_firewall_group(self, context, tenant_id, - fwg_ports): - """Validate firewall group associated ports - - Check if the firewall group associated ports have the same project - owner and is router interface type or a compute layer 2 and supported - by the firewall driver - :param context: neutron context - :param tenant_id: firewall group project ID - :param fwg_ports: firewall group associated ports - """ - # TODO(sridar): elevated context and do we want to use public ? - for port_id in fwg_ports: - port = self._core_plugin.get_port(context, port_id) - - if port['tenant_id'] != tenant_id: - raise f_exc.FirewallGroupPortInvalidProject( - port_id=port_id, project_id=port['tenant_id']) - device_owner = port.get('device_owner', '') - if device_owner in nl_constants.ROUTER_INTERFACE_OWNERS: - if not self.driver.is_supported_l3_port(port): - raise exceptions.FirewallGroupPortNotSupported( - driver_name=self.driver_name, port_id=port_id) - elif device_owner.startswith( - nl_constants.DEVICE_OWNER_COMPUTE_PREFIX): - if not self._is_supported_l2_port(context, port_id): - raise exceptions.FirewallGroupPortNotSupported( - driver_name=self.driver_name, port_id=port_id) - else: - raise f_exc.FirewallGroupPortInvalid(port_id=port_id) - - def _is_supported_l2_port(self, context, port_id): - """Whether this l2 port is supported""" - - # Re-fetch to get up-to-date data from db - port = self._core_plugin.get_port(context, id=port_id) - - # Skip port binding is unbound or failed - if port[pb_def.VIF_TYPE] in [pb_def.VIF_TYPE_UNBOUND, - pb_def.VIF_TYPE_BINDING_FAILED]: - return False - - return self.driver.is_supported_l2_port(port) - - def _validate_if_firewall_group_on_ports(self, context, firewall_group, - id=None): - """Validate if ports are not associated with any firewall_group. - - If any of the ports in the list is already associated with - a firewall group, raise an exception else just return. - :param context: neutron context - :param fwg: firewall group to validate - """ - if 'ports' not in firewall_group or not firewall_group['ports']: - return - - filters = { - 'tenant_id': [firewall_group['tenant_id']], - 'ports': firewall_group['ports'], - } - ports_in_use = set() - for fwg in self.get_firewall_groups(context, filters=filters): - if id is not None and fwg['id'] == id: - continue - ports_in_use |= set(fwg.get('ports', [])) & \ - set(firewall_group['ports']) - if ports_in_use: - raise f_exc.FirewallGroupPortInUse(port_ids=list(ports_in_use)) - - def _get_fwgs_with_policy(self, context, firewall_policy): - """List firewall group IDs which use a firewall policy - - List all firewall group IDs which have the given firewall policy as - ingress or egress. - :param context: neutron context - :param firewall_policy: firewall policy to filter - """ - filters = { - 'tenant_id': [firewall_policy['tenant_id']], - 'ingress_firewall_policy_id': [firewall_policy['id']], - } - ingress_fwp_ids = [fwg['id'] - for fwg in self.get_firewall_groups( - context, filters=filters)] - - filters = { - 'tenant_id': [firewall_policy['tenant_id']], - 'egress_firewall_policy_id': [firewall_policy['id']], - } - egress_fwp_ids = [fwg['id'] - for fwg in self.get_firewall_groups( - context, filters=filters)] - - return ingress_fwp_ids, egress_fwp_ids - - def _get_policies_with_rule(self, context, firewall_rule): - filters = { - 'tenant_id': [firewall_rule['tenant_id']], - 'firewall_rules': [firewall_rule['id']], - } - return [fwp['id'] for fwp in self.get_firewall_policies( - context, filters=filters)] - - def _validate_insert_remove_rule_request(self, rule_info): - """Validate rule_info dict - - Check that all mandatory fields are present, otherwise raise - proper exception. - """ - if not rule_info or 'firewall_rule_id' not in rule_info: - raise f_exc.FirewallRuleInfoMissing() - # Validator doesn't return anything if the check passes - if validators.validate_uuid(rule_info['firewall_rule_id']): - raise f_exc.FirewallRuleNotFound( - firewall_rule_id=rule_info['firewall_rule_id']) - - @registry.receives(resources.PORT, [events.AFTER_UPDATE]) - def handle_update_port(self, resource, event, trigger, **kwargs): - updated_port = kwargs['port'] - if not updated_port['device_owner'].startswith( - nl_constants.DEVICE_OWNER_COMPUTE_PREFIX): - return - - if (kwargs.get('original_port')[pb_def.VIF_TYPE] != - pb_def.VIF_TYPE_UNBOUND): - # Checking newly vm port binding allows us to avoid call to DB - # when a port update_event like restart, setting name, etc... - # Moreover, that will help us in case of tenant admin wants to - # only attach security group to vm port. - return - - context = kwargs['context'] - port_id = updated_port['id'] - # Check port is supported by firewall driver - if not self._is_supported_l2_port(context, port_id): - return - - project_id = updated_port['project_id'] - fwgs = self.get_firewall_groups( - context, - filters={ - 'tenant_id': [project_id], - 'name': [fwaas_constants.DEFAULT_FWG], - }, - fields=['id', 'ports'], - ) - if len(fwgs) != 1: - # Cannot found default Firewall Group, abandon - LOG.warning("Cannot found default firewall group of project %s", - project_id) - return - default_fwg = fwgs[0] - - # Add default firewall group to the port - port_ids = default_fwg.get('ports', []) + [port_id] - try: - self.update_firewall_group(context, default_fwg['id'], - {'firewall_group': {'ports': port_ids}}) - except f_exc.FirewallGroupPortInUse: - LOG.warning("Port %s has been already associated with default " - "firewall group %s and skip association", port_id, - default_fwg['id']) - - # Firewall Group - @log_helpers.log_method_call - def create_firewall_group(self, context, firewall_group): - firewall_group = firewall_group['firewall_group'] - ports = firewall_group.get('ports', []) - - self._validate_firewall_policies_for_firewall_group(context, - firewall_group) - # Validate ports owner type and project - self._validate_ports_for_firewall_group(context, - firewall_group['tenant_id'], - ports) - - self._validate_if_firewall_group_on_ports(context, firewall_group) - - return self.driver.create_firewall_group(context, firewall_group) - - @log_helpers.log_method_call - def delete_firewall_group(self, context, id): - # if no such group exists -> don't raise an exception according to - # 80fe2ba1, return None - try: - fwg = self.get_firewall_group(context, id) - except f_exc.FirewallGroupNotFound: - return - - if fwg['status'] == nl_constants.ACTIVE: - raise f_exc.FirewallGroupInUse(firewall_id=id) - - self.driver.delete_firewall_group(context, id) - - @log_helpers.log_method_call - def get_firewall_group(self, context, id, fields=None): - return self.driver.get_firewall_group(context, id, fields=fields) - - @log_helpers.log_method_call - def get_firewall_groups(self, context, filters=None, fields=None): - return self.driver.get_firewall_groups(context, filters, fields) - - @log_helpers.log_method_call - def update_firewall_group(self, context, id, firewall_group): - firewall_group = firewall_group['firewall_group'] - ports = firewall_group.get('ports', []) - - old_firewall_group = self._ensure_update_firewall_group(context, id) - firewall_group['tenant_id'] = old_firewall_group['tenant_id'] - - self._validate_firewall_policies_for_firewall_group(context, - firewall_group) - # Validate ports owner type and project - self._validate_ports_for_firewall_group(context, - firewall_group['tenant_id'], - ports) - self._validate_if_firewall_group_on_ports(context, firewall_group, - id=id) - - return self.driver.update_firewall_group(context, id, firewall_group) - - # Firewall Policy - @log_helpers.log_method_call - def create_firewall_policy(self, context, firewall_policy): - firewall_policy = firewall_policy['firewall_policy'] - return self.driver.create_firewall_policy(context, firewall_policy) - - @log_helpers.log_method_call - def delete_firewall_policy(self, context, id): - self.driver.delete_firewall_policy(context, id) - - @log_helpers.log_method_call - def get_firewall_policy(self, context, id, fields=None): - return self.driver.get_firewall_policy(context, id, fields) - - @log_helpers.log_method_call - def get_firewall_policies(self, context, filters=None, fields=None): - return self.driver.get_firewall_policies(context, filters, fields) - - @log_helpers.log_method_call - def update_firewall_policy(self, context, id, firewall_policy): - firewall_policy = firewall_policy['firewall_policy'] - self._ensure_update_firewall_policy(context, id) - return self.driver.update_firewall_policy(context, id, firewall_policy) - - # Firewall Rule - @log_helpers.log_method_call - def create_firewall_rule(self, context, firewall_rule): - firewall_rule = firewall_rule['firewall_rule'] - return self.driver.create_firewall_rule(context, firewall_rule) - - @log_helpers.log_method_call - def delete_firewall_rule(self, context, id): - self.driver.delete_firewall_rule(context, id) - - @log_helpers.log_method_call - def get_firewall_rule(self, context, id, fields=None): - return self.driver.get_firewall_rule(context, id, fields) - - @log_helpers.log_method_call - def get_firewall_rules(self, context, filters=None, fields=None): - return self.driver.get_firewall_rules(context, filters, fields) - - @log_helpers.log_method_call - def update_firewall_rule(self, context, id, firewall_rule): - firewall_rule = firewall_rule['firewall_rule'] - self._ensure_update_firewall_rule(context, id) - return self.driver.update_firewall_rule(context, id, firewall_rule) - - @log_helpers.log_method_call - def insert_rule(self, context, policy_id, rule_info): - self._ensure_update_firewall_policy(context, policy_id) - self._validate_insert_remove_rule_request(rule_info) - return self.driver.insert_rule(context, policy_id, rule_info) - - @log_helpers.log_method_call - def remove_rule(self, context, policy_id, rule_info): - self._ensure_update_firewall_policy(context, policy_id) - self._validate_insert_remove_rule_request(rule_info) - return self.driver.remove_rule(context, policy_id, rule_info) diff --git a/neutron_fwaas/services/firewall/service_drivers/__init__.py b/neutron_fwaas/services/firewall/service_drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/agents.py b/neutron_fwaas/services/firewall/service_drivers/agents/agents.py deleted file mode 100644 index de7a9652e..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/agents.py +++ /dev/null @@ -1,373 +0,0 @@ -# Copyright (c) 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. - -from neutron_lib.api.definitions import portbindings as pb_def -from neutron_lib import constants as nl_constants -from neutron_lib import context as neutron_context -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib import rpc as n_rpc -from oslo_config import cfg -from oslo_log import helpers as log_helpers -from oslo_log import log as logging -import oslo_messaging - -from neutron_fwaas.common import fwaas_constants as constants -from neutron_fwaas.services.firewall.service_drivers import driver_api - - -LOG = logging.getLogger(__name__) - - -class FirewallAgentCallbacks(object): - target = oslo_messaging.Target(version='1.0') - - def __init__(self, firewall_db): - self.firewall_db = firewall_db - - @log_helpers.log_method_call - def set_firewall_group_status(self, context, fwg_id, status, **kwargs): - """Agent uses this to set a firewall_group's status.""" - # Sanitize status first - if status in (nl_constants.ACTIVE, nl_constants.DOWN, - nl_constants.INACTIVE): - to_update = status - else: - to_update = nl_constants.ERROR - # ignore changing status if firewall_group expects to be deleted - # That case means that while some pending operation has been - # performed on the backend, neutron server received delete request - # and changed firewall status to PENDING_DELETE - updated = self.firewall_db.update_firewall_group_status( - context, fwg_id, to_update, not_in=(nl_constants.PENDING_DELETE,)) - if updated: - LOG.debug("firewall %s status set: %s", fwg_id, to_update) - return updated and to_update != nl_constants.ERROR - - @log_helpers.log_method_call - def firewall_group_deleted(self, context, fwg_id, **kwargs): - """Agent uses this to indicate firewall is deleted.""" - try: - fwg = self.firewall_db.get_firewall_group(context, fwg_id) - # allow to delete firewalls in ERROR state - if fwg['status'] in (nl_constants.PENDING_DELETE, - nl_constants.ERROR): - self.firewall_db.delete_firewall_group(context, fwg_id) - return True - LOG.warning('Firewall %(fwg)s unexpectedly deleted by agent, ' - 'status was %(status)s', - {'fwg': fwg_id, 'status': fwg['status']}) - fwg['status'] = nl_constants.ERROR - self.firewall_db.update_firewall_group(context, fwg_id, fwg) - return False - except f_exc.FirewallGroupNotFound: - LOG.info('Firewall group %s already deleted', fwg_id) - return True - - @log_helpers.log_method_call - def get_firewall_groups_for_project(self, context, **kwargs): - """Gets all firewall_groups and rules on a project.""" - fwg_list = [] - for fwg in self.firewall_db.get_firewall_groups(context): - fwg_with_rules =\ - self.firewall_db.make_firewall_group_dict_with_rules( - context, fwg['id']) - if fwg['status'] == nl_constants.PENDING_DELETE: - fwg_with_rules['add-port-ids'] = [] - fwg_with_rules['del-port-ids'] = ( - self.firewall_db.get_ports_in_firewall_group( - context, fwg['id'])) - else: - fwg_with_rules['add-port-ids'] = ( - self.firewall_db.get_ports_in_firewall_group( - context, fwg['id'])) - fwg_with_rules['del-port-ids'] = [] - fwg_list.append(fwg_with_rules) - return fwg_list - - @log_helpers.log_method_call - def get_projects_with_firewall_groups(self, context, **kwargs): - """Get all projects that have firewall_groups.""" - ctx = neutron_context.get_admin_context() - fwg_list = self.firewall_db.get_firewall_groups(ctx) - fwg_project_list = list(set(fwg['tenant_id'] for fwg in fwg_list)) - return fwg_project_list - - @log_helpers.log_method_call - def get_firewall_group_for_port(self, context, **kwargs): - """Get firewall_group is associated with a port.""" - ctx = context.elevated() - # Only one Firewall Group can be associated to a port at a time - fwg_port_binding = self.firewall_db.get_firewall_groups( - ctx, filters={'ports': [kwargs.get('port_id')]}) - if len(fwg_port_binding) != 1: - return - fwg = fwg_port_binding[0] - - fwg['ingress_rule_list'] = [] - for rule_id in self.firewall_db.get_firewall_policy( - context, fwg['ingress_firewall_policy_id'], - fields=['firewall_rules'])['firewall_rules']: - fwg['ingress_rule_list'].append( - self.firewall_db.get_firewall_rule(context, rule_id)) - fwg['egress_rule_list'] = [] - for rule_id in self.firewall_db.get_firewall_policy( - context, fwg['egress_firewall_policy_id'], - fields=['firewall_rules'])['firewall_rules']: - fwg['egress_rule_list'].append( - self.firewall_db.get_firewall_rule(context, rule_id)) - return fwg - - -class FirewallAgentApi(object): - """Plugin side of plugin to agent RPC API""" - - def __init__(self, topic, host): - self.host = host - target = oslo_messaging.Target(topic=topic, version='1.0') - self.client = n_rpc.get_client(target) - - def create_firewall_group(self, context, firewall_group): - cctxt = self.client.prepare(fanout=True) - cctxt.cast(context, 'create_firewall_group', - firewall_group=firewall_group, host=self.host) - - def update_firewall_group(self, context, firewall_group): - cctxt = self.client.prepare(fanout=True) - cctxt.cast(context, 'update_firewall_group', - firewall_group=firewall_group, host=self.host) - - def delete_firewall_group(self, context, firewall_group): - cctxt = self.client.prepare(fanout=True) - cctxt.cast(context, 'delete_firewall_group', - firewall_group=firewall_group, host=self.host) - - -class FirewallAgentDriver(driver_api.FirewallDriverDB, - driver_api.FirewallDriverRPCMixin): - """Firewall driver to implement agent messages and callback methods - - Implement RPC Firewall v2 API and callback methods for agents based on - Neutron DB model. - """ - - def __init__(self, service_plugin): - super(FirewallAgentDriver, self).__init__(service_plugin) - self.agent_rpc = FirewallAgentApi(constants.FW_AGENT, cfg.CONF.host) - - def is_supported_l2_port(self, port): - if port[pb_def.VIF_TYPE] == pb_def.VIF_TYPE_OVS: - if not port['port_security_enabled']: - return True - - # TODO(annp): remove these lines after we fully support for hybrid - # port - if not port[pb_def.VIF_DETAILS][pb_def.OVS_HYBRID_PLUG]: - return True - LOG.warning("Doesn't support hybrid port at the moment") - else: - LOG.warning("Doesn't support vif type %s", port[pb_def.VIF_TYPE]) - return False - - def is_supported_l3_port(self, port): - return True - - def start_rpc_listener(self): - self.endpoints = [FirewallAgentCallbacks(self.firewall_db)] - self.rpc_connection = n_rpc.Connection() - self.rpc_connection.create_consumer(constants.FIREWALL_PLUGIN, - self.endpoints, fanout=False) - return self.rpc_connection.consume_in_threads() - - def _rpc_update_firewall_group(self, context, fwg_id): - status_update = {"status": nl_constants.PENDING_UPDATE} - self.update_firewall_group(context, fwg_id, status_update) - fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules( - context, fwg_id) - # this is triggered on an update to fwg rule or policy, no - # change in associated ports. - fwg_with_rules['add-port-ids'] = \ - self.firewall_db.get_ports_in_firewall_group(context, fwg_id) - fwg_with_rules['del-port-ids'] = [] - fwg_with_rules['port_details'] = self._get_fwg_port_details( - context, fwg_with_rules['add-port-ids']) - self.agent_rpc.update_firewall_group(context, fwg_with_rules) - - def _rpc_update_firewall_policy(self, context, firewall_policy_id): - firewall_policy = self.get_firewall_policy(context, firewall_policy_id) - if firewall_policy: - ing_fwg_ids, eg_fwg_ids = self.firewall_db.get_fwgs_with_policy( - context, firewall_policy_id) - for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)): - self._rpc_update_firewall_group(context, fwg_id) - - def _get_fwg_port_details(self, context, fwg_ports): - """Returns a dictionary list of port details. """ - port_details = {} - for port_id in fwg_ports: - port_db = self._core_plugin.get_port(context, port_id) - # Add more parameters below based on requirement. - device_owner = port_db['device_owner'] - port_details[port_id] = { - 'device_owner': device_owner, - 'device': port_db['id'], - 'network_id': port_db['network_id'], - 'fixed_ips': port_db['fixed_ips'], - 'allowed_address_pairs': - port_db.get('allowed_address_pairs', []), - 'port_security_enabled': - port_db.get('port_security_enabled', True), - 'id': port_db['id'], - 'status': port_db['status'], - } - if device_owner.startswith( - nl_constants.DEVICE_OWNER_COMPUTE_PREFIX): - port_details[port_id].update( - {'host': port_db[pb_def.HOST_ID]}) - return port_details - - def create_firewall_group_precommit(self, context, firewall_group): - ports = firewall_group['ports'] - - if (not ports or (not firewall_group['ingress_firewall_policy_id'] and - not firewall_group['egress_firewall_policy_id'])): - # no messaging to agent needed and fw needs to go to INACTIVE state - # as no associated ports and/or no policy configured. - status = nl_constants.INACTIVE - else: - status = (nl_constants.CREATED if cfg.CONF.router_distributed - else nl_constants.PENDING_CREATE) - firewall_group['status'] = status - - def create_firewall_group_postcommit(self, context, firewall_group): - if firewall_group['status'] != nl_constants.INACTIVE: - fwg_with_rules =\ - self.firewall_db.make_firewall_group_dict_with_rules( - context, firewall_group['id']) - fwg_with_rules['add-port-ids'] = firewall_group['ports'] - fwg_with_rules['del-ports-id'] = [] - fwg_with_rules['port_details'] = self._get_fwg_port_details( - context, firewall_group['ports']) - self.agent_rpc.create_firewall_group(context, fwg_with_rules) - - def delete_firewall_group_precommit(self, context, firewall_group): - if firewall_group['status'] == nl_constants.ACTIVE: - raise f_exc.FirewallGroupInUse(firewall_id=firewall_group['id']) - elif firewall_group['status'] != nl_constants.INACTIVE: - # Firewall group is in inconsistent state, remove it - return - if not firewall_group['ports']: - # No associated port, can safety remove it - return - - # Need to prevent agent to delete the firewall group before delete it - self.firewall_db.update_firewall_group_status( - context, firewall_group['id'], nl_constants.PENDING_DELETE) - firewall_group['status'] = nl_constants.PENDING_DELETE - - fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules( - context, firewall_group['id']) - fwg_with_rules['del-port-ids'] = firewall_group['ports'] - fwg_with_rules['add-port-ids'] = [] - # Reflect state change in fwg_with_rules - fwg_with_rules['status'] = nl_constants.PENDING_DELETE - fwg_with_rules['port_details'] = self._get_fwg_port_details( - context, fwg_with_rules['del-port-ids']) - self.agent_rpc.delete_firewall_group(context, fwg_with_rules) - - def _need_pending_update(self, old_firewall_group, new_firewall_group): - port_updated = (set(new_firewall_group['ports']) != - set(old_firewall_group['ports'])) - policies_updated = ( - new_firewall_group['ingress_firewall_policy_id'] != - old_firewall_group['ingress_firewall_policy_id'] or - new_firewall_group['egress_firewall_policy_id'] != - old_firewall_group['egress_firewall_policy_id'] - ) - if (port_updated and - (new_firewall_group['ingress_firewall_policy_id'] or - new_firewall_group['egress_firewall_policy_id'])): - return True - if policies_updated and new_firewall_group['ports']: - return True - return False - - def update_firewall_group_precommit(self, context, old_firewall_group, - new_firewall_group): - if self._need_pending_update(old_firewall_group, new_firewall_group): - new_firewall_group['status'] = nl_constants.PENDING_UPDATE - - def update_firewall_group_postcommit(self, context, old_firewall_group, - new_firewall_group): - if not self._need_pending_update(old_firewall_group, - new_firewall_group): - return - - fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules( - context, new_firewall_group['id']) - - # determine ports to add fw to and del from - fwg_with_rules['add-port-ids'] = list( - set(new_firewall_group['ports']) - set(old_firewall_group['ports']) - ) - fwg_with_rules['del-port-ids'] = list( - set(old_firewall_group['ports']) - set(new_firewall_group['ports']) - ) - - # last-port drives agent to ack with status to set state to INACTIVE - # Set last-port to True if there are no ports in the new group and - # the old group had the same number of ports that need to be deleted. - fwg_with_rules['last-port'] = (len(old_firewall_group['ports']) == len( - fwg_with_rules['del-port-ids']) and - not(new_firewall_group['ports'])) - - LOG.debug("update_firewall_group %s: Add Ports: %s, Del Ports: %s", - new_firewall_group['id'], - fwg_with_rules['add-port-ids'], - fwg_with_rules['del-port-ids']) - - fwg_with_rules['port_details'] = self._get_fwg_port_details( - context, fwg_with_rules['del-port-ids']) - fwg_with_rules['port_details'].update(self._get_fwg_port_details( - context, fwg_with_rules['add-port-ids'])) - - if (new_firewall_group['name'] == constants.DEFAULT_FWG and - len(fwg_with_rules['add-port-ids']) == 1 and - not fwg_with_rules['del-port-ids']): - port_id = fwg_with_rules['add-port-ids'][0] - if (fwg_with_rules['port_details'][port_id].get('status') != - nl_constants.ACTIVE): - # If port not yet active, just associate to default firewall - # group. When agent will set it to UP, it'll found FG - # association and enforce default policies - return - # Warn agents Firewall Group port list updated - self.agent_rpc.update_firewall_group(context, fwg_with_rules) - - def update_firewall_policy_postcommit(self, context, old_firewall_policy, - new_firewall_group): - self._rpc_update_firewall_policy(context, new_firewall_group['id']) - - def update_firewall_rule_postcommit(self, context, old_firewall_rule, - new_firewall_rule): - firewall_policy_ids = self.firewall_db.get_policies_with_rule( - context, new_firewall_rule['id']) - for firewall_policy_id in firewall_policy_ids: - self._rpc_update_firewall_policy(context, firewall_policy_id) - - def insert_rule_postcommit(self, context, policy_id, rule_info): - self._rpc_update_firewall_policy(context, policy_id) - - def remove_rule_postcommit(self, context, policy_id, rule_info): - self._rpc_update_firewall_policy(context, policy_id) diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/conntrack_base.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/conntrack_base.py deleted file mode 100644 index 536869632..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/conntrack_base.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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 abc - -import six - -from neutron_lib.utils import runtime -from oslo_config import cfg -from oslo_log import log as logging -from oslo_utils import excutils - -LOG = logging.getLogger(__name__) - - -def load_and_init_conntrack_driver(*args, **kwargs): - driver = cfg.CONF.fwaas.conntrack_driver - try: - conntrack_driver_cls = runtime.load_class_by_alias_or_classname( - 'neutron.agent.l3.firewall_drivers', driver) - except ImportError: - with excutils.save_and_reraise_exception(): - LOG.exception("Driver '%s' not found.", driver) - conntrack_driver = conntrack_driver_cls() - conntrack_driver.initialize(*args, **kwargs) - return conntrack_driver - - -@six.add_metaclass(abc.ABCMeta) -class ConntrackDriverBase(object): - """Base Driver for Conntrack""" - - @abc.abstractmethod - def initialize(self, *args, **kwargs): - """Initialize the driver""" - - @abc.abstractmethod - def delete_entries(self, rules, namespace): - """Delete conntrack entries specified by list of rules""" - - @abc.abstractmethod - def flush_entries(self, namespace): - """Delete all conntrack entries within namespace""" diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base.py deleted file mode 100644 index da8cf3006..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2013 Dell 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 abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class FwaasDriverBase(object): - """Firewall as a Service Driver base class. - - Using FwaasDriver Class, an instance of L3 perimeter Firewall - can be created. The firewall co-exists with the L3 agent. - - One instance is created for each tenant. One firewall policy - is associated with each tenant (in the Havana release). - - The Firewall can be visualized as having two zones (in Havana - release), trusted and untrusted. - - All the 'internal' interfaces of Neutron Router is treated as trusted. The - interface connected to 'external network' is treated as untrusted. - - The policy is applied on traffic ingressing/egressing interfaces on - the trusted zone. This implies that policy will be applied for traffic - passing from - - - trusted to untrusted zones - - untrusted to trusted zones - - trusted to trusted zones - - Policy WILL NOT be applied for traffic from untrusted to untrusted zones. - This is not a problem in Havana release as there is only one interface - connected to external network. - - Since the policy is applied on the internal interfaces, the traffic - will be not be NATed to floating IP. For incoming traffic, the - traffic will get NATed to internal IP address before it hits - the firewall rules. So, while writing the rules, care should be - taken if using rules based on floating IP. - - The firewall rule addition/deletion/insertion/update are done by the - management console. When the policy is sent to the driver, the complete - policy is sent and the whole policy has to be applied atomically. The - firewall rules will not get updated individually. This is to avoid problems - related to out-of-order notifications or inconsistent behaviour by partial - application of rules. Argument agent_mode indicates the l3 agent in DVR or - DVR_SNAT or LEGACY mode. - """ - # TODO(Margaret): Remove the first 3 methods and make the second three - # @abc.abstractmethod - def create_firewall(self, agent_mode, apply_list, firewall): - """Create the Firewall with default (drop all) policy. - - The default policy will be applied on all the interfaces of - trusted zone. - """ - pass - - def delete_firewall(self, agent_mode, apply_list, firewall): - """Delete firewall. - - Removes all policies created by this instance and frees up - all the resources. - """ - pass - - def update_firewall(self, agent_mode, apply_list, firewall): - """Apply the policy on all trusted interfaces. - - Remove previous policy and apply the new policy on all trusted - interfaces. - """ - pass - - def create_firewall_group(self, agent_mode, apply_list, firewall): - """Create the Firewall with default (drop all) policy. - - The default policy will be applied on all the interfaces of - trusted zone. - """ - pass - - def delete_firewall_group(self, agent_mode, apply_list, firewall): - """Delete firewall. - - Removes all policies created by this instance and frees up - all the resources. - """ - pass - - def update_firewall_group(self, agent_mode, apply_list, firewall): - """Apply the policy on all trusted interfaces. - - Remove previous policy and apply the new policy on all trusted - interfaces. - """ - pass - - @abc.abstractmethod - def apply_default_policy(self, agent_mode, apply_list, firewall): - """Apply the default policy on all trusted interfaces. - - Remove current policy and apply the default policy on all trusted - interfaces. - """ - pass diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base_v2.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base_v2.py deleted file mode 100644 index b50538b64..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/fwaas_base_v2.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2016 -# 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 abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class FwaasDriverBase(object): - """Firewall as a Service Driver base class. - - Using FwaasDriver Class, an instance of L3 perimeter Firewall - can be created. The firewall co-exists with the L3 agent. - - One instance is created for each tenant. One firewall policy - is associated with each tenant (in the Havana release). - - The Firewall can be visualized as having two zones (in Havana - release), trusted and untrusted. - - All the 'internal' interfaces of Neutron Router is treated as trusted. The - interface connected to 'external network' is treated as untrusted. - - The policy is applied on traffic ingressing/egressing interfaces on - the trusted zone. This implies that policy will be applied for traffic - passing from - - - trusted to untrusted zones - - untrusted to trusted zones - - trusted to trusted zones - - Policy WILL NOT be applied for traffic from untrusted to untrusted zones. - This is not a problem in Havana release as there is only one interface - connected to external network. - - Since the policy is applied on the internal interfaces, the traffic - will be not be NATed to floating IP. For incoming traffic, the - traffic will get NATed to internal IP address before it hits - the firewall rules. So, while writing the rules, care should be - taken if using rules based on floating IP. - - The firewall rule addition/deletion/insertion/update are done by the - management console. When the policy is sent to the driver, the complete - policy is sent and the whole policy has to be applied atomically. The - firewall rules will not get updated individually. This is to avoid problems - related to out-of-order notifications or inconsistent behaviour by partial - application of rules. Argument agent_mode indicates the l3 agent in DVR or - DVR_SNAT or LEGACY mode. - """ - @abc.abstractmethod - def create_firewall_group(self, agent_mode, apply_list, firewall): - """Create the Firewall with default (drop all) policy. - - The default policy will be applied on all the interfaces of - trusted zone. - """ - pass - - @abc.abstractmethod - def delete_firewall_group(self, agent_mode, apply_list, firewall): - """Delete firewall. - - Removes all policies created by this instance and frees up - all the resources. - """ - pass - - @abc.abstractmethod - def update_firewall_group(self, agent_mode, apply_list, firewall): - """Apply the policy on all trusted interfaces. - - Remove previous policy and apply the new policy on all trusted - interfaces. - """ - pass - - @abc.abstractmethod - def apply_default_policy(self, agent_mode, apply_list, firewall): - """Apply the default policy on all trusted interfaces. - - Remove current policy and apply the default policy on all trusted - interfaces. - """ - pass diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py deleted file mode 100644 index 60efcb7fe..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py +++ /dev/null @@ -1,546 +0,0 @@ -# Copyright (c) 2016 -# 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. - -from neutron.agent.linux import iptables_manager -from neutron.common import utils -from neutron_lib import constants -from neutron_lib.exceptions import firewall_v2 as fw_ext -from oslo_log import log as logging - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\ - conntrack_base -from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\ - fwaas_base_v2 - -LOG = logging.getLogger(__name__) -FWAAS_DRIVER_NAME = 'Fwaas iptables driver' -FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy' - -# Introduce these chain for future processing like firewall logging -ACCEPTED_CHAIN = 'accepted' -DROPPED_CHAIN = 'dropped' -REJECTED_CHAIN = 'rejected' - -FWAAS_TO_IPTABLE_ACTION_MAP = { - 'allow': ACCEPTED_CHAIN, - 'deny': DROPPED_CHAIN, - 'reject': REJECTED_CHAIN -} - -CHAIN_NAME_PREFIX = {constants.INGRESS_DIRECTION: 'i', - constants.EGRESS_DIRECTION: 'o'} - -""" Firewall rules are applied on internal-interfaces of Neutron router. - The packets ingressing tenant's network will be on the output - direction on internal-interfaces. -""" -IPTABLES_DIR = {constants.INGRESS_DIRECTION: '-o', - constants.EGRESS_DIRECTION: '-i'} -IPV4 = 'ipv4' -IPV6 = 'ipv6' -IP_VER_TAG = {IPV4: 'v4', - IPV6: 'v6'} - -INTERNAL_DEV_PREFIX = 'qr-' -SNAT_INT_DEV_PREFIX = 'sg-' -ROUTER_2_FIP_DEV_PREFIX = 'rfp-' - -MAX_INTF_NAME_LEN = 14 - - -class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): - """IPTables driver for Firewall As A Service.""" - - def __init__(self): - LOG.debug("Initializing fwaas iptables driver") - self.pre_firewall = None - self.conntrack = conntrack_base.load_and_init_conntrack_driver() - - def _get_intf_name(self, if_prefix, port_id): - _name = "%s%s" % (if_prefix, port_id) - return _name[:MAX_INTF_NAME_LEN] - - def create_firewall_group(self, agent_mode, apply_list, firewall): - LOG.debug('Creating firewall %(fw_id)s for tenant %(tid)s', - {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) - try: - if firewall['admin_state_up']: - self._setup_firewall(agent_mode, apply_list, firewall) - self._remove_conntrack_new_firewall(agent_mode, - apply_list, firewall) - self.pre_firewall = dict(firewall) - else: - self.apply_default_policy(agent_mode, apply_list, firewall) - except (LookupError, RuntimeError): - # catch known library exceptions and raise Fwaas generic exception - LOG.exception("Failed to create firewall: %s", firewall['id']) - raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) - - def _get_ipt_mgrs_with_if_prefix(self, agent_mode, ri): - """Gets the iptables manager along with the if prefix to apply rules. - - With DVR we can have differing namespaces depending on which agent - (on Network or Compute node). Also, there is an associated i/f for - each namespace. The iptables on the relevant namespace and matching - i/f are provided. On the Network node we could have both the snat - namespace and a fip so this is provided back as a list - so in that - scenario rules can be applied on both. - """ - if not ri.router.get('distributed'): - return [{'ipt': ri.iptables_manager, - 'if_prefix': INTERNAL_DEV_PREFIX}] - ipt_mgrs = [] - # TODO(sridar): refactor to get strings to a common location. - if agent_mode == 'dvr_snat': - if ri.snat_iptables_manager: - ipt_mgrs.append({'ipt': ri.snat_iptables_manager, - 'if_prefix': SNAT_INT_DEV_PREFIX}) - if ri.rtr_fip_connect: - # handle the fip case on n/w or compute node. - ipt_mgrs.append({'ipt': ri.iptables_manager, - 'if_prefix': ROUTER_2_FIP_DEV_PREFIX}) - return ipt_mgrs - - def delete_firewall_group(self, agent_mode, apply_list, firewall): - LOG.debug('Deleting firewall %(fw_id)s for tenant %(tid)s', - {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) - fwid = firewall['id'] - try: - for ri, router_fw_ports in apply_list: - ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( - agent_mode, ri) - for ipt_if_prefix in ipt_if_prefix_list: - ipt_mgr = ipt_if_prefix['ipt'] - self._remove_chains(fwid, ipt_mgr) - self._remove_default_chains(ipt_mgr) - # apply the changes immediately (no defer in firewall path) - ipt_mgr.defer_apply_off() - self.pre_firewall = None - except (LookupError, RuntimeError): - # catch known library exceptions and raise Fwaas generic exception - LOG.exception("Failed to delete firewall: %s", fwid) - raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) - - def update_firewall_group(self, agent_mode, apply_list, firewall): - LOG.debug('Updating firewall %(fw_id)s for tenant %(tid)s', - {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) - try: - if firewall['admin_state_up']: - self._setup_firewall(agent_mode, apply_list, firewall) - if self.pre_firewall: - self._remove_conntrack_updated_firewall(agent_mode, - apply_list, self.pre_firewall, firewall) - else: - self._remove_conntrack_new_firewall(agent_mode, - apply_list, firewall) - else: - self.apply_default_policy(agent_mode, apply_list, firewall) - self.pre_firewall = dict(firewall) - except (LookupError, RuntimeError): - # catch known library exceptions and raise Fwaas generic exception - LOG.exception("Failed to update firewall: %s", firewall['id']) - raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) - - def apply_default_policy(self, agent_mode, apply_list, firewall): - LOG.debug('Applying firewall %(fw_id)s for tenant %(tid)s', - {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) - fwid = firewall['id'] - try: - for ri, router_fw_ports in apply_list: - ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( - agent_mode, ri) - for ipt_if_prefix in ipt_if_prefix_list: - # the following only updates local memory; no hole in FW - ipt_mgr = ipt_if_prefix['ipt'] - self._remove_chains(fwid, ipt_mgr) - self._remove_default_chains(ipt_mgr) - - # Create accepted/dropped/rejected chain - self._add_accepted_chain_v4v6(ipt_mgr) - self._add_dropped_chain_v4v6(ipt_mgr) - self._add_rejected_chain_v4v6(ipt_mgr) - - # create default 'DROP ALL' policy chain - self._add_default_policy_chain_v4v6(ipt_mgr) - self._enable_policy_chain(fwid, ipt_if_prefix, - router_fw_ports) - - # apply the changes immediately (no defer in firewall path) - ipt_mgr.defer_apply_off() - except (LookupError, RuntimeError): - # catch known library exceptions and raise Fwaas generic exception - LOG.exception( - "Failed to apply default policy on firewall: %s", fwid) - raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) - - def _setup_firewall(self, agent_mode, apply_list, firewall): - fwid = firewall['id'] - for ri, router_fw_ports in apply_list: - ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( - agent_mode, ri) - for ipt_if_prefix in ipt_if_prefix_list: - ipt_mgr = ipt_if_prefix['ipt'] - # the following only updates local memory; no hole in FW - self._remove_chains(fwid, ipt_mgr) - self._remove_default_chains(ipt_mgr) - - # Create accepted/dropped/rejected chain - self._add_accepted_chain_v4v6(ipt_mgr) - self._add_dropped_chain_v4v6(ipt_mgr) - self._add_rejected_chain_v4v6(ipt_mgr) - - # create default 'DROP ALL' policy chain - self._add_default_policy_chain_v4v6(ipt_mgr) - # create chain based on configured policy - self._setup_chains(firewall, ipt_if_prefix, router_fw_ports) - - # apply the changes immediately (no defer in firewall path) - ipt_mgr.defer_apply_off() - - def _get_chain_name(self, fwid, ver, direction): - return '%s%s%s' % (CHAIN_NAME_PREFIX[direction], - IP_VER_TAG[ver], - fwid) - - def _setup_chains(self, firewall, ipt_if_prefix, router_fw_ports): - """Create Fwaas chain using the rules in the policy - """ - egress_rule_list = firewall['egress_rule_list'] - ingress_rule_list = firewall['ingress_rule_list'] - fwid = firewall['id'] - ipt_mgr = ipt_if_prefix['ipt'] - - # default rules for invalid packets and established sessions - invalid_rule = self._drop_invalid_packets_rule() - est_rule = self._allow_established_rule() - - for ver in [IPV4, IPV6]: - if ver == IPV4: - table = ipt_mgr.ipv4['filter'] - else: - table = ipt_mgr.ipv6['filter'] - ichain_name = self._get_chain_name( - fwid, ver, constants.INGRESS_DIRECTION) - ochain_name = self._get_chain_name( - fwid, ver, constants.EGRESS_DIRECTION) - for name in [ichain_name, ochain_name]: - table.add_chain(name) - table.add_rule(name, invalid_rule) - table.add_rule(name, est_rule) - - for rule in ingress_rule_list: - if not rule['enabled']: - continue - iptbl_rule = self._convert_fwaas_to_iptables_rule(rule) - if rule['ip_version'] == constants.IP_VERSION_4: - ver = IPV4 - table = ipt_mgr.ipv4['filter'] - else: - ver = IPV6 - table = ipt_mgr.ipv6['filter'] - ichain_name = self._get_chain_name( - fwid, ver, constants.INGRESS_DIRECTION) - table.add_rule(ichain_name, iptbl_rule) - - for rule in egress_rule_list: - if not rule['enabled']: - continue - iptbl_rule = self._convert_fwaas_to_iptables_rule(rule) - if rule['ip_version'] == constants.IP_VERSION_4: - ver = IPV4 - table = ipt_mgr.ipv4['filter'] - else: - ver = IPV6 - table = ipt_mgr.ipv6['filter'] - ochain_name = self._get_chain_name( - fwid, ver, constants.EGRESS_DIRECTION) - table.add_rule(ochain_name, iptbl_rule) - - self._enable_policy_chain(fwid, ipt_if_prefix, router_fw_ports) - - def _find_changed_rules(self, pre_firewall, firewall): - """Find the rules changed between the current firewall - and the updating rule - """ - changed_rules = [] - for fw_rule_list in ['egress_rule_list', 'ingress_rule_list']: - pre_fw_rules = pre_firewall[fw_rule_list] - fw_rules = firewall[fw_rule_list] - for pre_fw_rule in pre_fw_rules: - for fw_rule in fw_rules: - if (pre_fw_rule.get('id') == fw_rule.get('id') and - pre_fw_rule != fw_rule): - changed_rules.append(pre_fw_rule) - changed_rules.append(fw_rule) - return changed_rules - - def _find_removed_rules(self, pre_firewall, firewall): - removed_rules = [] - for fw_rule_list in ['egress_rule_list', 'ingress_rule_list']: - pre_fw_rules = pre_firewall[fw_rule_list] - fw_rules = firewall[fw_rule_list] - fw_rule_ids = [fw_rule['id'] for fw_rule in fw_rules] - removed_rules.extend([pre_fw_rule for pre_fw_rule in pre_fw_rules - if pre_fw_rule['id'] not in fw_rule_ids]) - return removed_rules - - def _find_new_rules(self, pre_firewall, firewall): - return self._find_removed_rules(firewall, pre_firewall) - - def _remove_conntrack_new_firewall(self, agent_mode, apply_list, firewall): - """Remove conntrack when create new firewall""" - routers_list = list(set([apply_info[0] for apply_info in apply_list])) - for ri in routers_list: - ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( - agent_mode, ri) - for ipt_if_prefix in ipt_if_prefix_list: - ipt_mgr = ipt_if_prefix['ipt'] - self.conntrack.flush_entries(ipt_mgr.namespace) - - def _remove_conntrack_updated_firewall(self, agent_mode, - apply_list, pre_firewall, firewall): - """Remove conntrack when updated firewall""" - routers_list = list(set([apply_info[0] for apply_info in apply_list])) - for ri in routers_list: - ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( - agent_mode, ri) - for ipt_if_prefix in ipt_if_prefix_list: - ipt_mgr = ipt_if_prefix['ipt'] - ch_rules = self._find_changed_rules(pre_firewall, - firewall) - i_rules = self._find_new_rules(pre_firewall, firewall) - r_rules = self._find_removed_rules(pre_firewall, firewall) - removed_conntrack_rules_list = ch_rules + i_rules + r_rules - self.conntrack.delete_entries(removed_conntrack_rules_list, - ipt_mgr.namespace) - - def _remove_default_chains(self, nsid): - """Remove fwaas default policy chain.""" - self._remove_chain_by_name(IPV4, FWAAS_DEFAULT_CHAIN, nsid) - self._remove_chain_by_name(IPV6, FWAAS_DEFAULT_CHAIN, nsid) - - def _remove_chains(self, fwid, ipt_mgr): - """Remove fwaas policy chain.""" - for ver in [IPV4, IPV6]: - for direction in [constants.INGRESS_DIRECTION, - constants.EGRESS_DIRECTION]: - chain_name = self._get_chain_name(fwid, ver, direction) - self._remove_chain_by_name(ver, chain_name, ipt_mgr) - - def _add_default_policy_chain_v4v6(self, ipt_mgr): - dropped_chain = self._get_action_chain(DROPPED_CHAIN) - ipt_mgr.ipv4['filter'].add_chain(FWAAS_DEFAULT_CHAIN) - ipt_mgr.ipv4['filter'].add_rule( - FWAAS_DEFAULT_CHAIN, '-j %s' % dropped_chain) - ipt_mgr.ipv6['filter'].add_chain(FWAAS_DEFAULT_CHAIN) - ipt_mgr.ipv6['filter'].add_rule( - FWAAS_DEFAULT_CHAIN, '-j %s' % dropped_chain) - - def _add_accepted_chain_v4v6(self, ipt_mgr): - v4rules_in_chain = \ - ipt_mgr.get_chain("filter", ACCEPTED_CHAIN, - ip_version=constants.IP_VERSION_4) - if not v4rules_in_chain: - ipt_mgr.ipv4['filter'].add_chain(ACCEPTED_CHAIN) - ipt_mgr.ipv4['filter'].add_rule(ACCEPTED_CHAIN, '-j ACCEPT') - - v6rules_in_chain = \ - ipt_mgr.get_chain("filter", ACCEPTED_CHAIN, - ip_version=constants.IP_VERSION_6) - if not v6rules_in_chain: - ipt_mgr.ipv6['filter'].add_chain(ACCEPTED_CHAIN) - ipt_mgr.ipv6['filter'].add_rule(ACCEPTED_CHAIN, '-j ACCEPT') - - def _add_dropped_chain_v4v6(self, ipt_mgr): - v4rules_in_chain = \ - ipt_mgr.get_chain("filter", DROPPED_CHAIN, - ip_version=constants.IP_VERSION_4) - if not v4rules_in_chain: - ipt_mgr.ipv4['filter'].add_chain(DROPPED_CHAIN) - ipt_mgr.ipv4['filter'].add_rule(DROPPED_CHAIN, '-j DROP') - - v6rules_in_chain = \ - ipt_mgr.get_chain("filter", DROPPED_CHAIN, - ip_version=constants.IP_VERSION_6) - if not v6rules_in_chain: - ipt_mgr.ipv6['filter'].add_chain(DROPPED_CHAIN) - ipt_mgr.ipv6['filter'].add_rule(DROPPED_CHAIN, '-j DROP') - - def _add_rejected_chain_v4v6(self, ipt_mgr): - v4rules_in_chain = \ - ipt_mgr.get_chain("filter", REJECTED_CHAIN, - ip_version=constants.IP_VERSION_4) - if not v4rules_in_chain: - ipt_mgr.ipv4['filter'].add_chain(REJECTED_CHAIN) - ipt_mgr.ipv4['filter'].add_rule(REJECTED_CHAIN, '-j REJECT') - - v6rules_in_chain = \ - ipt_mgr.get_chain("filter", REJECTED_CHAIN, - ip_version=constants.IP_VERSION_6) - if not v6rules_in_chain: - ipt_mgr.ipv6['filter'].add_chain(REJECTED_CHAIN) - ipt_mgr.ipv6['filter'].add_rule(REJECTED_CHAIN, '-j REJECT') - - def _remove_chain_by_name(self, ver, chain_name, ipt_mgr): - if ver == IPV4: - ipt_mgr.ipv4['filter'].remove_chain(chain_name) - else: - ipt_mgr.ipv6['filter'].remove_chain(chain_name) - - def _remove_chain_by_name_v4v6(self, chain_name, ipt_mgr): - ipt_mgr.ipv4['filter'].remove_chain(chain_name) - ipt_mgr.ipv6['filter'].remove_chain(chain_name) - - def _add_rules_to_chain(self, ipt_mgr, ver, chain_name, rules): - if ver == IPV4: - table = ipt_mgr.ipv4['filter'] - else: - table = ipt_mgr.ipv6['filter'] - for rule in rules: - table.add_rule(chain_name, rule) - - def _get_action_chain(self, name): - binary_name = iptables_manager.binary_name - chain_name = iptables_manager.get_chain_name(name) - return '%s-%s' % (binary_name, chain_name) - - def _enable_policy_chain(self, fwid, ipt_if_prefix, router_fw_ports): - bname = iptables_manager.binary_name - ipt_mgr = ipt_if_prefix['ipt'] - if_prefix = ipt_if_prefix['if_prefix'] - - for (ver, tbl) in [(IPV4, ipt_mgr.ipv4['filter']), - (IPV6, ipt_mgr.ipv6['filter'])]: - for direction in [constants.INGRESS_DIRECTION, - constants.EGRESS_DIRECTION]: - chain_name = self._get_chain_name(fwid, ver, direction) - chain_name = iptables_manager.get_chain_name(chain_name) - if chain_name in tbl.chains: - for router_fw_port in router_fw_ports: - intf_name = self._get_intf_name(if_prefix, - router_fw_port) - jump_rule = ['%s %s -j %s-%s' % ( - IPTABLES_DIR[direction], intf_name, - bname, chain_name)] - self._add_rules_to_chain(ipt_mgr, ver, - 'FORWARD', jump_rule) - - # jump to DROP_ALL policy - chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN) - for router_fw_port in router_fw_ports: - intf_name = self._get_intf_name(if_prefix, - router_fw_port) - jump_rule = ['-o %s -j %s-%s' % (intf_name, bname, chain_name)] - self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule) - self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule) - - # jump to DROP_ALL policy - chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN) - for router_fw_port in router_fw_ports: - intf_name = self._get_intf_name(if_prefix, - router_fw_port) - jump_rule = ['-i %s -j %s-%s' % (intf_name, bname, chain_name)] - self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule) - self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule) - - def _convert_fwaas_to_iptables_rule(self, rule): - action = FWAAS_TO_IPTABLE_ACTION_MAP[rule.get('action')] - - # Output ordering is important here as it must exactly match what - # is returned by iptables-save. If not we risk unnecessarily removing - # and readding rules. - args = [] - - args += self._protocol_arg(rule.get('protocol'), - rule.get('ip_version')) - - args += self._ip_prefix_arg('s', rule.get('source_ip_address')) - args += self._ip_prefix_arg('d', rule.get('destination_ip_address')) - - # iptables adds '-m protocol' when any source - # or destination port number is specified - if (rule.get('source_port') is not None or - rule.get('destination_port') is not None): - args += self._match_arg(rule.get('protocol')) - - args += self._port_arg('sport', - rule.get('protocol'), - rule.get('source_port')) - - args += self._port_arg('dport', - rule.get('protocol'), - rule.get('destination_port')) - - args += self._action_arg(action) - - iptables_rule = ' '.join(args) - return iptables_rule - - def _drop_invalid_packets_rule(self): - dropped_chain = self._get_action_chain(DROPPED_CHAIN) - return '-m state --state INVALID -j %s' % dropped_chain - - def _allow_established_rule(self): - return '-m state --state RELATED,ESTABLISHED -j ACCEPT' - - def _action_arg(self, action): - if not action: - return [] - - args = ['-j', self._get_action_chain(action)] - - return args - - def _protocol_arg(self, protocol, ip_version): - if not protocol: - return [] - - if (protocol == constants.PROTO_NAME_ICMP and - ip_version == constants.IP_VERSION_6): - protocol = constants.PROTO_NAME_IPV6_ICMP - - args = ['-p', protocol] - - return args - - def _match_arg(self, protocol): - if not protocol: - return [] - - protocol_modules = {constants.PROTO_NAME_UDP: 'udp', - constants.PROTO_NAME_TCP: 'tcp', - constants.PROTO_NAME_ICMP: 'icmp', - constants.PROTO_NAME_IPV6_ICMP: 'icmp6'} - # iptables adds '-m protocol' when the port number is specified - args = ['-m', protocol_modules[protocol]] - - return args - - def _port_arg(self, direction, protocol, port): - if protocol not in [constants.PROTO_NAME_UDP, - constants.PROTO_NAME_TCP] or port is None: - return [] - - args = ['--%s' % direction, '%s' % port] - - return args - - def _ip_prefix_arg(self, direction, ip_prefix): - - if not(ip_prefix): - return [] - - args = ['-%s' % direction, '%s' % utils.ip_to_cidr(ip_prefix)] - return args diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/driver_base.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/driver_base.py deleted file mode 100644 index 0ed15b4fa..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/driver_base.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) 2017 Fujitsu Limited -# -# 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 abc -import contextlib - -import six - - -@six.add_metaclass(abc.ABCMeta) -class FirewallL2DriverBase(object): - """Abstract firewall L2 driver base""" - - def __init__(self, integration_bridge, sg_enabled=False): - pass - - def filter_defer_apply_on(self): - """Defer application of filtering rule.""" - pass - - def filter_defer_apply_off(self): - """Turn off deferral of rules and apply the rules now.""" - pass - - @property - def ports(self): - """Returns filtered ports.""" - pass - - @contextlib.contextmanager - def defer_apply(self): - """Defer apply context.""" - self.filter_defer_apply_on() - try: - yield - finally: - self.filter_defer_apply_off() - - def create_firewall_group(self, ports, firewall_group): - """Called when a firewall group is created. - """ - raise NotImplementedError() - - def update_firewall_group(self, ports, firewall_group): - """Called when a firewall group is updated. - """ - raise NotImplementedError() - - def delete_firewall_group(self, ports, firewall_group): - """Called when a firewall group is deleted. - """ - raise NotImplementedError() diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/noop/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/noop/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/noop/noop_driver.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/noop/noop_driver.py deleted file mode 100644 index 41f581540..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/noop/noop_driver.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2017 Fujitsu Limited -# -# 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. - -from oslo_log import helpers as log_helpers - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2\ - import driver_base - - -class NoopFirewallL2Driver(driver_base.FirewallL2DriverBase): - - @log_helpers.log_method_call - def create_firewall_group(self, ports, firewall_group): - pass - - @log_helpers.log_method_call - def update_firewall_group(self, ports, firewall_group): - pass - - @log_helpers.log_method_call - def delete_firewall_group(self, ports, firewall_group): - pass - - @log_helpers.log_method_call - def process_trusted_ports(self, ports): - pass - - @log_helpers.log_method_call - def remove_trusted_ports(self, port_ids): - pass diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/__init__.py deleted file mode 100644 index 892e565fb..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2015 -# 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. - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import firewall - -OVSFirewallDriver = firewall.OVSFirewallDriver diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/constants.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/constants.py deleted file mode 100644 index b901d1086..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/constants.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2015 -# 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. - -from neutron_lib import constants - - -OF_STATE_NOT_TRACKED = "-trk" -OF_STATE_TRACKED = "+trk" -OF_STATE_NEW_NOT_ESTABLISHED = "+new-est" -OF_STATE_NOT_ESTABLISHED = "-est" -OF_STATE_ESTABLISHED = "+est" -OF_STATE_ESTABLISHED_NOT_REPLY = "+est-rel-rpl" -OF_STATE_ESTABLISHED_REPLY = "+est-rel+rpl" -OF_STATE_RELATED = "-new-est+rel-inv" -OF_STATE_INVALID = "+trk+inv" -OF_STATE_NEW = "+new" -OF_STATE_NOT_REPLY_NOT_NEW = "-new-rpl" - -CT_MARK_NORMAL = '0x0' -CT_MARK_INVALID = '0x1' - -REG_PORT = 5 -REG_NET = 6 - -FW_BASE_EGRESS_TABLE = 64 -FW_RULES_EGRESS_TABLE = 65 -FW_ACCEPT_OR_INGRESS_TABLE = 66 -FW_BASE_INGRESS_TABLE = 68 -FW_RULES_INGRESS_TABLE = 69 - -OVS_FIREWALL_TABLES = ( - FW_BASE_EGRESS_TABLE, - FW_RULES_EGRESS_TABLE, - FW_ACCEPT_OR_INGRESS_TABLE, - FW_BASE_INGRESS_TABLE, - FW_RULES_INGRESS_TABLE, -) - -PROTOCOLS_WITH_PORTS = (constants.PROTO_NAME_SCTP, - constants.PROTO_NAME_TCP, - constants.PROTO_NAME_UDP) - -# Only map protocols that need special handling -REVERSE_IP_PROTOCOL_MAP_WITH_PORTS = { - constants.IP_PROTOCOL_MAP[proto]: proto for proto in - PROTOCOLS_WITH_PORTS} - -ethertype_to_dl_type_map = { - constants.IPv4: constants.ETHERTYPE_IP, - constants.IPv6: constants.ETHERTYPE_IPV6, -} diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/exceptions.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/exceptions.py deleted file mode 100644 index bd7618cf9..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/exceptions.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2016, Red Hat, 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. - -from neutron_lib import exceptions - -from neutron_fwaas._i18n import _ - - -class OVSFWaaSPortNotFound(exceptions.NeutronException): - message = _("Port %(port_id)s is not managed by this agent.") - - -class OVSFWaaSTagNotFound(exceptions.NeutronException): - message = _("Cannot get vlan tag for port %(port_id)s.") diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/firewall.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/firewall.py deleted file mode 100644 index a317f9e4a..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/firewall.py +++ /dev/null @@ -1,1017 +0,0 @@ -# Copyright 2015 -# 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 netaddr - -from neutron_lib import constants as lib_const -from oslo_log import log as logging -from oslo_utils import netutils - -from neutron.agent import firewall -from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ - as ovs_consts - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2\ - import driver_base -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import constants as fwaas_ovs_consts -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import exceptions -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import rules - -LOG = logging.getLogger(__name__) - -ACTION_ALLOW = 'allow' - - -# NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver. -def _replace_register(flow_params, register_number, register_value): - """Replace value from flows to given register number - - 'register_value' key in dictionary will be replaced by register number - given by 'register_number' - - :param flow_params: Dictionary containing defined flows - :param register_number: The number of register where value will be stored - :param register_value: Key to be replaced by register number - - """ - try: - reg_port = flow_params[register_value] - del flow_params[register_value] - flow_params['reg{:d}'.format(register_number)] = reg_port - except KeyError: - pass - - -# NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver that -# differs only in constants REG_PORT/REG_NET. -def create_reg_numbers(flow_params): - """Replace reg_(port|net) values with defined register numbers""" - _replace_register(flow_params, fwaas_ovs_consts.REG_PORT, 'reg_port') - _replace_register(flow_params, fwaas_ovs_consts.REG_NET, 'reg_net') - - -class FirewallGroup(object): - def __init__(self, id_): - self.id = id_ - self.ingress_rules = [] - self.egress_rules = [] - self.members = {} - self.ports = set() - - def update_rules(self, ingress_rules, egress_rules): - """Update firewall group with ingress/egress rules. - - If a rule has a protocol field, it is normalized to a number - here in order to ease later processing. - """ - def _translate_protocol_to_number(rule): - protocol = rule.get('protocol') - if protocol is not None: - if protocol.isdigit(): - rule['protocol'] = int(protocol) - elif (rule.get('ethertype') == lib_const.IPv6 and - protocol == lib_const.PROTO_NAME_ICMP): - rule['protocol'] = lib_const.PROTO_NUM_IPV6_ICMP - else: - rule['protocol'] = lib_const.IP_PROTOCOL_MAP.get( - protocol, protocol) - return rule - - self.ingress_rules = [_translate_protocol_to_number(ir) - for ir in ingress_rules] - self.egress_rules = [_translate_protocol_to_number(er) - for er in egress_rules] - - def get_ethertype_filtered_addresses(self, ethertype, - exclude_addresses=None): - exclude_addresses = set(exclude_addresses if exclude_addresses else []) - group_addresses = set(self.members.get(ethertype, [])) - return list(group_addresses - exclude_addresses) - - -# NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver that -# differs only in firewall groups list field name -class OFPort(object): - def __init__(self, port_dict, ovs_port, vlan_tag): - self.id = port_dict['device'] - self.vlan_tag = vlan_tag - self.mac = ovs_port.vif_mac - self.lla_address = str(netutils.get_ipv6_addr_by_EUI64( - lib_const.IPv6_LLA_PREFIX, self.mac)) - self.ofport = ovs_port.ofport - self.fw_group = None - self.fixed_ips = port_dict.get('fixed_ips', []) - self.neutron_port_dict = port_dict.copy() - self.allowed_pairs_v4 = self._get_allowed_pairs(port_dict, version=4) - self.allowed_pairs_v6 = self._get_allowed_pairs(port_dict, version=6) - - @staticmethod - def _get_allowed_pairs(port_dict, version): - aap_dict = port_dict.get('allowed_address_pairs', set()) - return {(aap['mac_address'], aap['ip_address']) for aap in aap_dict - if netaddr.IPNetwork(aap['ip_address']).version == version} - - @property - def all_allowed_macs(self): - macs = {item[0] for item in self.allowed_pairs_v4.union( - self.allowed_pairs_v6)} - macs.add(self.mac) - return macs - - @property - def ipv4_addresses(self): - return [ip_addr for ip_addr in - [fixed_ip['ip_address'] for fixed_ip in self.fixed_ips] - if netaddr.IPAddress(ip_addr).version == 4] - - @property - def ipv6_addresses(self): - return [ip_addr for ip_addr in - [fixed_ip['ip_address'] for fixed_ip in self.fixed_ips] - if netaddr.IPAddress(ip_addr).version == 6] - - def update(self, port_dict): - self.allowed_pairs_v4 = self._get_allowed_pairs(port_dict, - version=4) - self.allowed_pairs_v6 = self._get_allowed_pairs(port_dict, - version=6) - # Neighbour discovery uses LLA - self.allowed_pairs_v6.add((self.mac, self.lla_address)) - self.fixed_ips = port_dict.get('fixed_ips', []) - self.neutron_port_dict = port_dict.copy() - - -# NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver that -# differs in methods name [s/sg/fwg] and update_rules method. -class FWGPortMap(object): - def __init__(self): - self.ports = {} - self.fw_groups = {} - # Maps port_id to ofport number - self.unfiltered = {} - - def get_fwg(self, fwg_id): - return self.fw_groups.get(fwg_id, None) - - def get_or_create_fwg(self, fwg_id): - fw_group = self.get_fwg(fwg_id) - if not fw_group: - fw_group = FirewallGroup(fwg_id) - self.fw_groups[fwg_id] = fw_group - return fw_group - - def delete_fwg(self, fwg_id): - del self.fw_groups[fwg_id] - - # XXX NOTE(ivasilevskaya) couldn't find any logical definition why - # firewall_group should come as 3rd argument instead of adding fwg_id - # to port_dict. Removed in favor of SG api - def create_port(self, port, port_dict): - self.ports[port.id] = port - self.update_port(port, port_dict) - - # XXX NOTE(ivasilevskaya) couldn't find any logical definition why - # firewall_group should come as 3rd argument instead of adding fwg_id - # to port_dict. Removed in favor of SG api - def update_port(self, port, port_dict): - for fw_group in self.fw_groups.values(): - fw_group.ports.discard(port) - - fw_group = self.get_or_create_fwg(port_dict['firewall_group']) - port.fw_group = fw_group - fw_group.ports.add(port) - port.update(port_dict) - - def remove_port(self, port): - if port.fw_group: - port.fw_group.ports.discard(port) - del self.ports[port.id] - - def update_rules(self, fwg_id, ingress_rules, egress_rules): - fw_group = self.get_or_create_fwg(fwg_id) - fw_group.update_rules(ingress_rules, egress_rules) - - def update_members(self, fwg_id, members): - fw_group = self.get_or_create_fwg(fwg_id) - fw_group.members = members - - -# NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver that -# doesn't have a conjunction manager because no remote_group_id concept is -# applicable to firewall groups -class OVSFirewallDriver(driver_base.FirewallL2DriverBase): - REQUIRED_PROTOCOLS = [ - ovs_consts.OPENFLOW10, - ovs_consts.OPENFLOW11, - ovs_consts.OPENFLOW12, - ovs_consts.OPENFLOW13, - ovs_consts.OPENFLOW14, - ] - - provides_arp_spoofing_protection = True - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver. - # This driver won't have any conj_manager logic because there is no concept - # of remote_group_id for firewall groups (that I know of at least) - def __init__(self, agent_api, sg_with_ovs=False): - """Initialize object""" - - integration_bridge = agent_api.request_int_br() - self.int_br = self.initialize_bridge(integration_bridge) - self.fwg_port_map = FWGPortMap() - self.fwg_to_delete = set() - self._deferred = False - self.sg_with_ovs = sg_with_ovs - self._drop_all_unmatched_flows() - self._initialize_third_party_tables() - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def _accept_flow(self, **flow): - for f in rules.create_accept_flows(flow, self.sg_with_ovs): - self._add_flow(**f) - - def _drop_flow(self, **flow): - for f in rules.create_drop_flows(flow): - self._add_flow(**f) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def _add_flow(self, **kwargs): - dl_type = kwargs.get('dl_type') - create_reg_numbers(kwargs) - if isinstance(dl_type, int): - kwargs['dl_type'] = "0x{:04x}".format(dl_type) - if self._deferred: - self.int_br.add_flow(**kwargs) - else: - self.int_br.br.add_flow(**kwargs) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def _delete_flows(self, **kwargs): - create_reg_numbers(kwargs) - if self._deferred: - self.int_br.delete_flows(**kwargs) - else: - self.int_br.br.delete_flows(**kwargs) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def _strict_delete_flow(self, **kwargs): - """Delete given flow right away even if bridge is deferred. - - Delete command will use strict delete. - """ - create_reg_numbers(kwargs) - self.int_br.br.delete_flows(strict=True, **kwargs) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - @staticmethod - def initialize_bridge(int_br): - int_br.add_protocols(*OVSFirewallDriver.REQUIRED_PROTOCOLS) - return int_br.deferred(full_ordered=True) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver, - # differs in constants - def _drop_all_unmatched_flows(self): - for table in fwaas_ovs_consts.OVS_FIREWALL_TABLES: - if (table == fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE and - self.sg_with_ovs): - continue - self.int_br.br.add_flow(table=table, priority=0, actions='drop') - - def _initialize_third_party_tables(self): - self.int_br.br.add_flow( - table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, - priority=1, - actions='normal') - for table in (ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE, - ovs_consts.DROPPED_TRAFFIC_TABLE): - self.int_br.br.add_flow( - table=table, priority=0, actions='drop') - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def get_ovs_port(self, port_id): - ovs_port = self.int_br.br.get_vif_port_by_id(port_id) - if not ovs_port: - raise exceptions.OVSFWaaSPortNotFound(port_id=port_id) - return ovs_port - - def _get_port_vlan_tag(self, port): - vlan_tag = port.get('lvlan', None) - if not vlan_tag: - raise exceptions.OVSFWaaSTagNotFound(port_id=port['device']) - return vlan_tag - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def get_ofport(self, port): - port_id = port['device'] - return self.fwg_port_map.ports.get(port_id) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver, - # self.sg_port_map -> self.fwg_port_map - def get_or_create_ofport(self, port): - """Get ofport specified by port['device'], checking and reflecting - ofport changes. - If ofport is nonexistent, create and return one. - """ - port_id = port['device'] - ovs_port = self.get_ovs_port(port_id) - try: - of_port = self.fwg_port_map.ports[port_id] - except KeyError: - port_vlan_id = self._get_port_vlan_tag(port) - of_port = OFPort(port, ovs_port, port_vlan_id) - self.fwg_port_map.create_port(of_port, port) - else: - if of_port.ofport != ovs_port.ofport: - self.fwg_port_map.remove_port(of_port) - of_port = OFPort(port, ovs_port, of_port.vlan_tag) - self.fwg_port_map.update_port(of_port, port) - - return of_port - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def is_port_managed(self, port): - return port['device'] in self.fwg_port_map.ports - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def prepare_port_filter(self, port): - # NOTE(annp): port no security should be handled by security group in - # co-existence mode, otherwise(standalone mode) fwg will handle it. - if not firewall.port_sec_enabled(port) and not self.sg_with_ovs: - self._initialize_egress_no_port_security(port) - return - old_of_port = self.get_ofport(port) - # Make sure delete old allow_address_pair MACs because - # allow_address_pair MACs will be updated in - # self.get_or_create_ofport(port) - if old_of_port: - LOG.error("Initializing port %s that was already " - "initialized.", - port['device']) - self.delete_all_port_flows(old_of_port) - of_port = self.get_or_create_ofport(port) - self.initialize_port_flows(of_port) - self.add_flows_from_rules(of_port) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def update_port_filter(self, port): - """Update rules for given port - - Current existing filtering rules are removed and new ones are generated - based on current loaded firewall group rules and members. - - Note: port no security should be handled by security group in - co-existence mode, otherwise fwg will handle it. - - """ - if not firewall.port_sec_enabled(port) and not self.sg_with_ovs: - self.remove_port_filter(port) - self._initialize_egress_no_port_security(port) - return - elif not self.is_port_managed(port): - if not self.sg_with_ovs: - self._remove_egress_no_port_security(port['device']) - self.prepare_port_filter(port) - return - - old_of_port = self.get_ofport(port) - of_port = self.get_or_create_ofport(port) - # TODO(jlibosva): Handle firewall blink - self.delete_all_port_flows(old_of_port) - self.initialize_port_flows(of_port) - self.add_flows_from_rules(of_port) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver, - # sg_port_map -> fwg_port_map - def remove_port_filter(self, port): - """Remove port from firewall - - All flows related to this port are removed from ovs. Port is also - removed from ports managed by this firewall. - - """ - if self.is_port_managed(port): - of_port = self.get_ofport(port) - self.delete_all_port_flows(of_port) - self.fwg_port_map.remove_port(of_port) - self._schedule_fwg_deletion_maybe(of_port.fw_group.id) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # with ingress\egress rules arguments instead of single rules - def update_firewall_group_rules(self, fwg_id, ingress_rules, egress_rules): - self.fwg_port_map.update_rules(fwg_id, ingress_rules, egress_rules) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # with sg_port_map -> fwg_port_map - def _schedule_fwg_deletion_maybe(self, fwg_id): - """Schedule possible deletion of the given firewall group. - - This function must be called when the number of ports - associated to fwg_id drops to zero, as it isn't possible - to know FWG deletions from agents due to RPC API design. - """ - fwg_group = self.fwg_port_map.get_or_create_fwg(fwg_id) - if not fwg_group.members or not fwg_group.ports: - self.fwg_to_delete.add(fwg_id) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # with sg_port_map -> fwg_port_map - def _cleanup_stale_fwg(self): - fwg_to_delete = self.fwg_to_delete - self.fwg_to_delete = set() - - for fwg_id in fwg_to_delete: - fw_group = self.fwg_port_map.get_fwg(fwg_id) - if fw_group.members and fw_group.ports: - # firewall group is still in use - continue - - self.fwg_port_map.delete_fwg(fwg_id) - - def process_trusted_ports(self, ports): - """Pass packets from these ports directly to ingress pipeline.""" - if self.sg_with_ovs: - return - - for port in ports: - self._initialize_egress_no_port_security(port) - - def remove_trusted_ports(self, port_ids): - if self.sg_with_ovs: - return - - for port_id in port_ids: - self._remove_egress_no_port_security(port_id) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def filter_defer_apply_on(self): - self._deferred = True - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - def filter_defer_apply_off(self): - if self._deferred: - self._cleanup_stale_fwg() - self.int_br.apply_flows() - self._deferred = False - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # with sg_port_map -> fwg_port_map - @property - def ports(self): - return {id_: port.neutron_port_dict - for id_, port in self.fwg_port_map.ports.items()} - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def initialize_port_flows(self, port): - """Set base flows for port - - :param port: OFPort instance - - """ - # Identify egress flow - self._add_flow( - table=ovs_consts.TRANSIENT_TABLE, - priority=105, - in_port=port.ofport, - actions='set_field:{:d}->reg{:d},' - 'set_field:{:d}->reg{:d},' - 'resubmit(,{:d})'.format( - port.ofport, - fwaas_ovs_consts.REG_PORT, - port.vlan_tag, - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.FW_BASE_EGRESS_TABLE) - ) - - # Identify ingress flows after egress filtering - for mac_addr in port.all_allowed_macs: - self._add_flow( - table=ovs_consts.TRANSIENT_TABLE, - priority=95, - dl_dst=mac_addr, - dl_vlan='0x%x' % port.vlan_tag, - actions='set_field:{:d}->reg{:d},' - 'set_field:{:d}->reg{:d},' - 'strip_vlan,resubmit(,{:d})'.format( - port.ofport, - fwaas_ovs_consts.REG_PORT, - port.vlan_tag, - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - ) - - self._initialize_egress(port) - self._initialize_ingress(port) - - def _fwaas_process_colocated_ingress(self, port): - for mac_addr in port.all_allowed_macs: - self._add_flow( - table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, - priority=105, - dl_dst=mac_addr, - reg_net=port.vlan_tag, - actions='set_field:{:d}->reg{:d},resubmit(,{:d})'.format( - port.ofport, - fwaas_ovs_consts.REG_PORT, - fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_egress_ipv6_icmp(self, port): - for icmp_type in firewall.ICMPV6_ALLOWED_EGRESS_TYPES: - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=95, - in_port=port.ofport, - reg_port=port.ofport, - dl_type=lib_const.ETHERTYPE_IPV6, - nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, - icmp_type=icmp_type, - actions='normal') - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) and exception classes - def _initialize_egress_no_port_security(self, port): - port_id = port['device'] - try: - ovs_port = self.get_ovs_port(port_id) - vlan_tag = self._get_port_vlan_tag(port) - except exceptions.OVSFWaaSTagNotFound: - # It's a patch port, don't set anything - return - except exceptions.OVSFWaaSPortNotFound as not_found_e: - LOG.error("Initializing unfiltered port %(port_id)s that does not " - "exist in ovsdb: %(err)s.", - {'port_id': port_id, - 'err': not_found_e}) - return - self.fwg_port_map.unfiltered[port_id] = ovs_port.ofport - self._add_flow( - table=ovs_consts.TRANSIENT_TABLE, - priority=100, - in_port=ovs_port.ofport, - actions='set_field:%d->reg%d,' - 'set_field:%d->reg%d,' - 'resubmit(,%d)' % ( - ovs_port.ofport, - fwaas_ovs_consts.REG_PORT, - vlan_tag, - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE) - ) - self._add_flow( - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE, - priority=80, - reg_port=ovs_port.ofport, - actions='normal', - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _remove_egress_no_port_security(self, port_id): - try: - ofport = self.fwg_port_map.unfiltered[port_id] - except KeyError: - LOG.debug("Port %s is not handled by the firewall.", port_id) - return - self._delete_flows( - table=ovs_consts.TRANSIENT_TABLE, - in_port=ofport - ) - self._delete_flows( - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE, - reg_port=ofport - ) - del self.fwg_port_map.unfiltered[port_id] - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_egress(self, port): - """Identify egress traffic and send it to egress base""" - self._initialize_egress_ipv6_icmp(port) - - # Apply mac/ip pairs for IPv4 - allowed_pairs = port.allowed_pairs_v4.union( - {(port.mac, ip_addr) for ip_addr in port.ipv4_addresses}) - for mac_addr, ip_addr in allowed_pairs: - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=95, - in_port=port.ofport, - reg_port=port.ofport, - dl_src=mac_addr, - dl_type=lib_const.ETHERTYPE_ARP, - arp_spa=ip_addr, - actions='normal' - ) - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=65, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_TRACKED, - dl_type=lib_const.ETHERTYPE_IP, - in_port=port.ofport, - dl_src=mac_addr, - nw_src=ip_addr, - actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( - fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - fwaas_ovs_consts.REG_NET) - ) - - # Apply mac/ip pairs for IPv6 - allowed_pairs = port.allowed_pairs_v6.union( - {(port.mac, ip_addr) for ip_addr in port.ipv6_addresses}) - for mac_addr, ip_addr in allowed_pairs: - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=65, - reg_port=port.ofport, - in_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_TRACKED, - dl_type=lib_const.ETHERTYPE_IPV6, - dl_src=mac_addr, - ipv6_src=ip_addr, - actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( - fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - fwaas_ovs_consts.REG_NET) - ) - - # DHCP discovery - accept_or_ingress = fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE - if self.sg_with_ovs: - accept_or_ingress = ovs_consts.ACCEPT_OR_INGRESS_TABLE - for dl_type, src_port, dst_port in ( - (lib_const.ETHERTYPE_IP, 68, 67), - (lib_const.ETHERTYPE_IPV6, 546, 547)): - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=80, - reg_port=port.ofport, - in_port=port.ofport, - dl_type=dl_type, - nw_proto=lib_const.PROTO_NUM_UDP, - tp_src=src_port, - tp_dst=dst_port, - actions='resubmit(,{:d})'.format(accept_or_ingress) - ) - # Ban dhcp service running on an instance - for dl_type, src_port, dst_port in ( - (lib_const.ETHERTYPE_IP, 67, 68), - (lib_const.ETHERTYPE_IPV6, 547, 546)): - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=70, - in_port=port.ofport, - reg_port=port.ofport, - dl_type=dl_type, - nw_proto=lib_const.PROTO_NUM_UDP, - tp_src=src_port, - tp_dst=dst_port, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - - # Drop Router Advertisements from instances - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=70, - in_port=port.ofport, - reg_port=port.ofport, - dl_type=lib_const.ETHERTYPE_IPV6, - nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, - icmp_type=lib_const.ICMPV6_TYPE_RA, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - - # Drop all remaining not tracked egress connections - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE, - priority=10, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_TRACKED, - in_port=port.ofport, - reg_port=port.ofport, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - - # Fill in accept_or_ingress table by checking that traffic is ingress - # and if not, accept it - if self.sg_with_ovs: - self._fwaas_process_colocated_ingress(port) - else: - for mac_addr in port.all_allowed_macs: - self._add_flow( - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE, - priority=100, - dl_dst=mac_addr, - reg_net=port.vlan_tag, - actions='set_field:{:d}->reg{:d},resubmit(,{:d})'.format( - port.ofport, - fwaas_ovs_consts.REG_PORT, - fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - ) - for ethertype in [lib_const.ETHERTYPE_IP, - lib_const.ETHERTYPE_IPV6]: - self._add_flow( - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE, - priority=90, - dl_type=ethertype, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED, - actions='ct(commit,zone=NXM_NX_REG{:d}[0..15]),' - 'resubmit(,{:d})'.format( - fwaas_ovs_consts.REG_NET, - ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) - ) - self._add_flow( - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE, - priority=80, - reg_port=port.ofport, - actions='normal' - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_tracked_egress(self, port): - # Drop invalid packets - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - priority=50, - ct_state=fwaas_ovs_consts.OF_STATE_INVALID, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - # Drop traffic for removed fwg rules - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - priority=50, - reg_port=port.ofport, - ct_mark=fwaas_ovs_consts.CT_MARK_INVALID, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - - for state in ( - fwaas_ovs_consts.OF_STATE_ESTABLISHED_REPLY, - fwaas_ovs_consts.OF_STATE_RELATED, - ): - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - priority=50, - ct_state=state, - ct_mark=fwaas_ovs_consts.CT_MARK_NORMAL, - reg_port=port.ofport, - ct_zone=port.vlan_tag, - actions='normal' - ) - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - priority=40, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_ESTABLISHED, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - for ethertype in [lib_const.ETHERTYPE_IP, lib_const.ETHERTYPE_IPV6]: - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - priority=40, - dl_type=ethertype, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_ESTABLISHED, - actions="ct(commit,zone=NXM_NX_REG{:d}[0..15]," - "exec(set_field:{:s}->ct_mark))".format( - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.CT_MARK_INVALID) - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_ingress_ipv6_icmp(self, port): - for icmp_type in firewall.ICMPV6_ALLOWED_INGRESS_TYPES: - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE, - priority=100, - reg_port=port.ofport, - dl_dst=port.mac, - dl_type=lib_const.ETHERTYPE_IPV6, - nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, - icmp_type=icmp_type, - actions='output:{:d}'.format(port.ofport) - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_ingress(self, port): - # Allow incoming ARPs - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE, - priority=100, - dl_type=lib_const.ETHERTYPE_ARP, - reg_port=port.ofport, - actions='output:{:d}'.format(port.ofport) - ) - self._initialize_ingress_ipv6_icmp(port) - - # DHCP offers - for dl_type, src_port, dst_port in ( - (lib_const.ETHERTYPE_IP, 67, 68), - (lib_const.ETHERTYPE_IPV6, 547, 546)): - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE, - priority=95, - reg_port=port.ofport, - dl_type=dl_type, - nw_proto=lib_const.PROTO_NUM_UDP, - tp_src=src_port, - tp_dst=dst_port, - actions='output:{:d}'.format(port.ofport) - ) - - # Track untracked - for dl_type in (lib_const.ETHERTYPE_IP, lib_const.ETHERTYPE_IPV6): - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE, - priority=90, - reg_port=port.ofport, - dl_type=dl_type, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_TRACKED, - actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( - fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - fwaas_ovs_consts.REG_NET) - ) - self._add_flow( - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE, - ct_state=fwaas_ovs_consts.OF_STATE_TRACKED, - priority=80, - reg_port=port.ofport, - actions='resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_RULES_INGRESS_TABLE) - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def _initialize_tracked_ingress(self, port): - # Drop invalid packets - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - priority=50, - ct_state=fwaas_ovs_consts.OF_STATE_INVALID, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - # Drop traffic for removed fwg rules - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - priority=50, - reg_port=port.ofport, - ct_mark=fwaas_ovs_consts.CT_MARK_INVALID, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - - # Allow established and related connections - for state in (fwaas_ovs_consts.OF_STATE_ESTABLISHED_REPLY, - fwaas_ovs_consts.OF_STATE_RELATED): - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - priority=50, - reg_port=port.ofport, - ct_state=state, - ct_mark=fwaas_ovs_consts.CT_MARK_NORMAL, - ct_zone=port.vlan_tag, - actions='output:{:d}'.format(port.ofport) - ) - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - priority=40, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NOT_ESTABLISHED, - actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - ) - for ethertype in [lib_const.ETHERTYPE_IP, lib_const.ETHERTYPE_IPV6]: - self._add_flow( - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - priority=40, - dl_type=ethertype, - reg_port=port.ofport, - ct_state=fwaas_ovs_consts.OF_STATE_ESTABLISHED, - actions="ct(commit,zone=NXM_NX_REG{:d}[0..15]," - "exec(set_field:{:s}->ct_mark))".format( - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.CT_MARK_INVALID) - ) - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) and rules_generator method - def add_flows_from_rules(self, port): - self._initialize_tracked_ingress(port) - self._initialize_tracked_egress(port) - LOG.debug('Creating flow rules for port %s that is port %d in OVS', - port.id, port.ofport) - for rule in self.create_rules_generator_for_port(port): - flows = rules.create_flows_from_rule_and_port(rule, port) - LOG.debug("RULGEN: Rules generated for flow %s are %s", - rule, flows) - for flow in flows: - if rule.get('action') == ACTION_ALLOW: - self._accept_flow(**flow) - else: - self._drop_flow(**flow) - - def create_rules_generator_for_port(self, port): - """Returns a generator emitting rules valid for further processing - - Injects necessary fields to feed one-by-one to rules module to - transform into valid openflow rules. - """ - - def inject_fields(rule, direction, offset=0): - """Add fields to rule dict to be able to utilize rules module - - Currently such fields are added: - 'offset', 'direction', 'ethertype', 'source_port_range_min', - 'source_port_range_max', 'port_range_min', 'port_range_max' - """ - # XXX NOTE(ivasilevskaya) maybe there's a clever way to do that - version_ethertype_map = {lib_const.IP_VERSION_4: lib_const.IPv4, - lib_const.IP_VERSION_6: lib_const.IPv6} - - rule['direction'] = direction - rule['ethertype'] = version_ethertype_map[rule['ip_version']] - rule['offset'] = offset - - # transfer destination_port into port_range_min/port_range_max - def add_range(range_key, key_min, key_max): - range_str = rule.get(range_key) - if not range_str: - return - ports = range_str.split(':', 1) - rule[key_min] = int(ports[0]) - rule['port_range_max'] = ( - int(ports[1]) if len(ports) == 2 else int(ports[0])) - - add_range('destination_port', 'port_range_min', 'port_range_max') - add_range('source_port', 'source_port_range_min', - 'source_port_range_max') - - # add direction field - offset = len(port.fw_group.ingress_rules) - 1 - for rule in port.fw_group.ingress_rules: - inject_fields(rule, lib_const.INGRESS_DIRECTION, offset) - offset -= 1 - yield rule - - offset = len(port.fw_group.egress_rules) - 1 - for rule in port.fw_group.egress_rules: - inject_fields(rule, lib_const.EGRESS_DIRECTION, offset) - offset -= 1 - yield rule - - # NOTE(ivasilevskaya) That's a copy-paste from neutron ovsfw driver - # which differs in constants (table numbers) - def delete_all_port_flows(self, port): - """Delete all flows for given port""" - accept_or_ingress = fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE - if self.sg_with_ovs: - accept_or_ingress = ovs_consts.ACCEPT_OR_INGRESS_TABLE - - for mac_addr in port.all_allowed_macs: - self._strict_delete_flow(priority=95, - table=ovs_consts.TRANSIENT_TABLE, - dl_dst=mac_addr, - dl_vlan=port.vlan_tag) - self._delete_flows( - table=accept_or_ingress, - dl_dst=mac_addr, reg_net=port.vlan_tag) - self._strict_delete_flow(priority=105, - table=ovs_consts.TRANSIENT_TABLE, - in_port=port.ofport) - self._delete_flows(reg_port=port.ofport) - - def create_firewall_group(self, ports_for_fwg, firewall_group): - egress_rules = firewall_group['egress_rule_list'] - ingress_rules = firewall_group['ingress_rule_list'] - fwg_id = firewall_group['id'] - - self.update_firewall_group_rules(fwg_id, ingress_rules, egress_rules) - for port in ports_for_fwg: - port['firewall_group'] = fwg_id - self.update_port_filter(port) - - def update_firewall_group(self, ports_for_fwg, firewall_group): - self.create_firewall_group(ports_for_fwg, firewall_group) - - def delete_firewall_group(self, ports_for_fwg, firewall_group): - for port in ports_for_fwg: - port['firewall_group'] = firewall_group['id'] - self.remove_port_filter(port) diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/rules.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/rules.py deleted file mode 100644 index 2fbe1bc49..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/rules.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright 2015 Red Hat, 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 netaddr - -from neutron.common import utils -from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ - as ovs_consts -from neutron_lib import constants as n_consts -from oslo_log import log as logging - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import constants as fwaas_ovs_consts - - -LOG = logging.getLogger(__name__) - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver, differs in -# constants -CT_STATES = [ - fwaas_ovs_consts.OF_STATE_ESTABLISHED_NOT_REPLY, - fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED] - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -FLOW_FIELD_FOR_IPVER_AND_DIRECTION = { - (n_consts.IP_VERSION_4, n_consts.EGRESS_DIRECTION): 'nw_dst', - (n_consts.IP_VERSION_6, n_consts.EGRESS_DIRECTION): 'ipv6_dst', - (n_consts.IP_VERSION_4, n_consts.INGRESS_DIRECTION): 'nw_src', - (n_consts.IP_VERSION_6, n_consts.INGRESS_DIRECTION): 'ipv6_src', -} - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -FORBIDDEN_PREFIXES = (n_consts.IPv4_ANY, n_consts.IPv6_ANY) - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -def is_valid_prefix(ip_prefix): - # IPv6 have multiple ways how to describe ::/0 network, converting to - # IPNetwork and back to string unifies it - return (ip_prefix and - str(netaddr.IPNetwork(ip_prefix)) not in FORBIDDEN_PREFIXES) - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -def create_flows_from_rule_and_port(rule, port): - ethertype = rule['ethertype'] - direction = rule['direction'] - dst_ip_prefix = rule.get('dest_ip_prefix') - src_ip_prefix = rule.get('source_ip_prefix') - offset = int(rule.get('offset', 0)) - - flow_template = { - 'priority': 70 + offset, - 'dl_type': fwaas_ovs_consts.ethertype_to_dl_type_map[ethertype], - 'reg_port': port.ofport, - } - - if is_valid_prefix(dst_ip_prefix): - flow_template[FLOW_FIELD_FOR_IPVER_AND_DIRECTION[( - utils.get_ip_version(dst_ip_prefix), n_consts.EGRESS_DIRECTION)] - ] = dst_ip_prefix - - if is_valid_prefix(src_ip_prefix): - flow_template[FLOW_FIELD_FOR_IPVER_AND_DIRECTION[( - utils.get_ip_version(src_ip_prefix), n_consts.INGRESS_DIRECTION)] - ] = src_ip_prefix - - flows = create_protocol_flows(direction, flow_template, port, rule) - - return flows - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver, differs in -# constants -def populate_flow_common(direction, flow_template, port): - """Initialize common flow fields.""" - if direction == n_consts.INGRESS_DIRECTION: - flow_template['table'] = fwaas_ovs_consts.FW_RULES_INGRESS_TABLE - flow_template['actions'] = "output:{:d}".format(port.ofport) - elif direction == n_consts.EGRESS_DIRECTION: - flow_template['table'] = fwaas_ovs_consts.FW_RULES_EGRESS_TABLE - # Traffic can be both ingress and egress, check that no ingress rules - # should be applied - flow_template['actions'] = 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE) - return flow_template - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -def create_protocol_flows(direction, flow_template, port, rule): - flow_template = populate_flow_common(direction, - flow_template.copy(), - port) - protocol = rule.get('protocol') - if protocol is not None: - flow_template['nw_proto'] = protocol - - if protocol in [n_consts.PROTO_NUM_ICMP, n_consts.PROTO_NUM_IPV6_ICMP]: - flows = create_icmp_flows(flow_template, rule) - else: - flows = create_port_range_flows(flow_template, rule) - return flows or [flow_template] - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver, differs only in -# constant -def create_port_range_flows(flow_template, rule): - protocol = fwaas_ovs_consts.REVERSE_IP_PROTOCOL_MAP_WITH_PORTS.get( - rule.get('protocol')) - if protocol is None: - return [] - flows = [] - src_port_match = '{:s}_src'.format(protocol) - src_port_min = rule.get('source_port_range_min') - src_port_max = rule.get('source_port_range_max') - dst_port_match = '{:s}_dst'.format(protocol) - dst_port_min = rule.get('port_range_min') - dst_port_max = rule.get('port_range_max') - - dst_port_range = [] - if dst_port_min and dst_port_max: - dst_port_range = utils.port_rule_masking(dst_port_min, dst_port_max) - - src_port_range = [] - if src_port_min and src_port_max: - src_port_range = utils.port_rule_masking(src_port_min, src_port_max) - for port in src_port_range: - flow = flow_template.copy() - flow[src_port_match] = port - if dst_port_range: - for port in dst_port_range: - dst_flow = flow.copy() - dst_flow[dst_port_match] = port - flows.append(dst_flow) - else: - flows.append(flow) - else: - for port in dst_port_range: - flow = flow_template.copy() - flow[dst_port_match] = port - flows.append(flow) - - return flows - - -# NOTE(ivasilevskaya) copy-paste from neutron ovsfw driver -def create_icmp_flows(flow_template, rule): - icmp_type = rule.get('port_range_min') - if icmp_type is None: - return - flow = flow_template.copy() - flow['icmp_type'] = icmp_type - - icmp_code = rule.get('port_range_max') - if icmp_code is not None: - flow['icmp_code'] = icmp_code - return [flow] - - -def resubmit_to_sg(flow): - if flow['table'] == fwaas_ovs_consts.FW_RULES_EGRESS_TABLE: - flow['actions'] = 'resubmit(,{:d})'.format( - ovs_consts.RULES_EGRESS_TABLE) - if flow['table'] == fwaas_ovs_consts.FW_RULES_INGRESS_TABLE: - flow['actions'] = 'resubmit(,{:d})'.format( - ovs_consts.RULES_INGRESS_TABLE) - - -def create_accept_flows(flow, sg_enabled=False): - flow['ct_state'] = CT_STATES[0] - if sg_enabled: - resubmit_to_sg(flow) - result = [flow.copy()] - flow['ct_state'] = CT_STATES[1] - if sg_enabled: - resubmit_to_sg(flow) - elif flow['table'] == fwaas_ovs_consts.FW_RULES_INGRESS_TABLE: - flow['actions'] = ( - 'ct(commit,zone=NXM_NX_REG{:d}[0..15]),{:s},' - 'resubmit(,{:d})'.format( - fwaas_ovs_consts.REG_NET, flow['actions'], - ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE) - ) - result.append(flow) - return result - - -def create_drop_flows(flow): - if flow['table'] in [fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - fwaas_ovs_consts.FW_RULES_EGRESS_TABLE]: - flow['actions'] = 'resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE - flow['ct_state'] = fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED - result = [flow.copy()] - flow['ct_state'] = fwaas_ovs_consts.OF_STATE_ESTABLISHED_NOT_REPLY - result.append(flow) - return result diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/legacy_conntrack.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/legacy_conntrack.py deleted file mode 100644 index aef7b2f42..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/legacy_conntrack.py +++ /dev/null @@ -1,233 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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. - -from neutron.agent.linux import utils as linux_utils -from neutron_lib import constants -from oslo_log import log as logging - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\ - conntrack_base - -LOG = logging.getLogger(__name__) - -IP_VERSIONS = [constants.IP_VERSION_4, constants.IP_VERSION_6] - -ATTR_POSITIONS = { - 'icmp': (('type', 5), ('code', 6), ('src', 3), ('dst', 4), ('id', 7)), - 'icmpv6': (('type', 5), ('code', 6), ('src', 3), ('dst', 4), ('id', 7)), - 'tcp': (('sport', 6), ('dport', 7), ('src', 4), ('dst', 5)), - 'udp': (('sport', 5), ('dport', 6), ('src', 3), ('dst', 4)) -} - - -def normalize_filters_tuple(rule_tuple): - new_rule = [] - for el in rule_tuple: - if el is None: - new_rule.append('') - else: - new_rule.append(el) - return tuple(new_rule) - - -class ConntrackLegacy(conntrack_base.ConntrackDriverBase): - def initialize(self, execute=None): - LOG.debug('Initialize Conntrack Legacy') - self.execute = execute or linux_utils.execute - - def flush_entries(self, namespace): - prefixcmd = ['ip', 'netns', 'exec', namespace] if namespace else [] - cmd = prefixcmd + ['conntrack', '-D'] - self._execute_command(cmd) - - def delete_entries(self, rules, namespace): - rule_filters = [self._get_filter_from_rule(r) for r in rules] - rule_filters.sort(key=normalize_filters_tuple) - - delete_entries = self._get_entries_to_delete( - rule_filters, self.list_entries(namespace)) - for delete_entry in delete_entries: - cmd = self._get_conntrack_cmd_from_entry(delete_entry, namespace) - self._execute_command(cmd) - - def _execute_command(self, cmd): - try: - output = self.execute(cmd, - run_as_root=True, - check_exit_code=True, - extra_ok_codes=[1]) - except RuntimeError: - msg = "Failed execute conntrack command %s" % cmd - raise RuntimeError(msg) - return output - - def list_entries(self, namespace): - """List and parse all conntrack entries - - :param namespace: namespace to get conntrack entries - :returns: sorted list of conntrack entries in Python tuple - for example: [(4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 1234), - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2')] - """ - parsed_entries = [] - prefixcmd = ['ip', 'netns', 'exec', namespace] if namespace else [] - for ip_version in IP_VERSIONS: - cmd = prefixcmd + ['conntrack', '-L', - '-f', 'ipv' + str(ip_version)] - raw_entries = self._execute_command(cmd).splitlines() - for raw_entry in raw_entries: - parsed_entry = self._parse_entry(raw_entry.split(), ip_version) - if parsed_entry is not None: - parsed_entries.append(parsed_entry) - return sorted(parsed_entries) - - def _get_conntrack_cmd_from_entry(self, entry, namespace): - prefixcmd = ['ip', 'netns', 'exec', namespace] if namespace else [] - cmd = ['conntrack', '-D'] - contrack_filter = ['-f', 'ipv' + str(entry[0]), '-p', entry[1]] - if entry[1] in ['icmp', 'icmpv6']: - contrack_filter.extend(['--icmp-type', entry[2], - '--icmp-code', entry[3], - '-s', entry[4], - '-d', entry[5], - '--icmp-id', entry[6]]) - else: - contrack_filter.extend(['--sport', entry[2], - '--dport', entry[3], - '-s', entry[4], - '-d', entry[5]]) - exec_cmd = prefixcmd + cmd + contrack_filter - return exec_cmd - - def _parse_entry(self, entry, ip_version): - """Parse entry from text to Python tuple - - :param entry: conntrack entry as a list of string - :param ip_version: ip version 4 or 6 - :returns: conntrack entry in Python tuple - for example: (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') - The attributes are ordered to be easy to compare with other entries - and compare with firewall rule - """ - protocol = entry[0] - if protocol not in ATTR_POSITIONS: - LOG.warning( - 'Skipping conntrack entry %s with unsupported protocol', entry) - return None - - parsed_entry = [ip_version, protocol] - for attr, position in ATTR_POSITIONS[protocol]: - val = entry[position].partition('=')[2] - parsed_entry.append(int(val) if attr in ['sport', 'dport', 'type', - 'code', 'id'] else val) - return tuple(parsed_entry) - - def _get_entries_to_delete(self, rule_filters, entries): - """Specify conntrack entries to delete - - :param rule_filters: List of filters parsed from firewall rules - :param entries: all entries within namespace - :returns: conntrack entries to delete - """ - # List all entries from namespace, they are already parsed - # to a list of tuples: - # [(4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 1234), - # (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2')] - delete_entries = [] - entry_index = 0 - entry_number = len(entries) - for rule_filter in rule_filters: - while entry_index < entry_number: - # Compare entry with rule - comp = self._compare_entry_and_rule_filter( - rule_filter, entries[entry_index]) - # Increase entry_index when entry is under rule - if comp < 0: - entry_index += 1 - # Append entry to delete_entry if it matches with rule - elif comp == 0: - delete_entries.append(entries[entry_index]) - entry_index += 1 - # Switch to new higher rule - else: - break - return delete_entries - - @staticmethod - def _get_filter_from_rule(rule): - """Parse the firewall rule to a tuple - - :param rule: firewall rule - :returns: a tuple of parsed information - """ - rule_filter = [] - keys = ('ip_version', 'protocol', - 'source_port', 'destination_port', - 'source_ip_address', 'destination_ip_address') - for key in keys: - if key in ('source_port', 'destination_port'): - port_range = rule.get(key, []) - if port_range: - port_lower, sep, port_upper = port_range.partition(':') - port_upper = port_upper if sep else port_lower - port_range = [port_lower, port_upper] - rule_filter.append(port_range or []) - else: - rule_filter.append(rule.get(key, [])) - return tuple(rule_filter) - - @staticmethod - def _compare_entry_and_rule_filter(rule_filter, entry): - """Define that the entry should be deleted or not - - :param rule_filter: filter that is parsed from a firewall rule - for example: (4, 'tcp', ['22', '33'], ['44', '55']) - :param entry: parsed conntrack entry, - for example: (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') - :returns: -1 if entry is lower than rule - 0 if entry matches rule, - 1 if entry is higher than rule - """ - ENTRY_IS_LOWER = -1 - ENTRY_MATCHES = 0 - ENTRY_IS_HIGHER = 1 - rule_ip_version = rule_filter[0] - if entry[0] < rule_ip_version: - return ENTRY_IS_LOWER - elif entry[0] > rule_ip_version: - return ENTRY_IS_HIGHER - rule_protocol = rule_filter[1] - if rule_protocol == constants.PROTO_NAME_IPV6_ICMP: - rule_protocol = constants.PROTO_NAME_IPV6_ICMP_LEGACY - if rule_protocol: - if entry[1] < rule_protocol: - return ENTRY_IS_LOWER - elif entry[1] > rule_protocol: - return ENTRY_IS_HIGHER - sport_range = rule_filter[2] - if sport_range: - sport_range = [int(port) for port in sport_range] - if entry[2] < min(sport_range[0], sport_range[-1]): - return ENTRY_IS_LOWER - elif entry[2] > max(sport_range[0], sport_range[-1]): - return ENTRY_IS_HIGHER - dport_range = rule_filter[3] - if dport_range: - dport_range = [int(port) for port in dport_range] - if entry[3] < min(dport_range[0], dport_range[-1]): - return ENTRY_IS_LOWER - elif entry[3] > max(dport_range[0], dport_range[-1]): - return ENTRY_IS_HIGHER - return ENTRY_MATCHES diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/netlink_conntrack.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/netlink_conntrack.py deleted file mode 100644 index a43cc5e39..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/netlink_conntrack.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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. - -from neutron_lib import constants -from oslo_log import log as logging - -from neutron_fwaas.privileged import netlink_lib as nl_lib -from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\ - conntrack_base - -LOG = logging.getLogger(__name__) - - -class ConntrackNetlink(conntrack_base.ConntrackDriverBase): - def initialize(self, *args, **kwargs): - LOG.debug('Conntrack Netlink loaded') - - def flush_entries(self, namespace): - """Flush all conntrack entries within the namespace - - :param namespace: namespace to flush - :return: None - """ - nl_lib.flush_entries(namespace) - - def delete_entries(self, rules, namespace): - rule_filters = (self._get_filter_from_rule(r) for r in rules) - rule_filters = sorted(rule_filters) - entries = nl_lib.list_entries(namespace) - delete_entries = self._get_entries_to_delete(rule_filters, entries) - if delete_entries: - nl_lib.delete_entries(delete_entries, namespace) - - def _get_entries_to_delete(self, rule_filters, entries): - """Specify conntrack entries to delete - - :param rule_filters: List of filters parsed from firewall rules - :param entries: all entries within namespace - :return: conntrack entries to delete - """ - # List all entries from namespace, they are already parsed - # to a list of tuples: - # [(4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 1234), - # (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2')] - delete_entries = [] - entry_index = 0 - entry_number = len(entries) - for rule_filter in rule_filters: - while entry_index < entry_number: - # Compare entry with rule - comp = self._compare_entry_and_rule(rule_filter, - entries[entry_index]) - # Increase entry_index when entry is under rule - if comp < 0: - entry_index += 1 - # Append entry to delete_entry if it matches with rule - elif comp == 0: - delete_entries.append(entries[entry_index]) - entry_index += 1 - # Switch to new higher rule - else: - break - return delete_entries - - @staticmethod - def _get_filter_from_rule(rule): - """Parse the firewall rule to a tuple - - :param rule: firewall rule - :return: a tuple of parsed information - """ - rule_filter = [] - keys = ['ip_version', 'protocol', - 'source_port', 'destination_port', - 'source_ip_address', 'destination_ip_address'] - for key in keys: - if key in ['source_port', 'destination_port']: - port_range = rule.get(key, []) - if port_range: - port_lower, sep, port_upper = port_range.partition(':') - port_upper = port_upper if sep else port_lower - port_range = [port_lower, port_upper] - rule_filter.append(port_range or []) - else: - rule_filter.append(rule.get(key, [])) - return tuple(rule_filter) - - @staticmethod - def _compare_entry_and_rule(rule_filter, entry): - """Define that the entry should be deleted or not - - :param rule_filter: filter that is parsed from a firewall rule - ex: (4, 'tcp', 1, 2) - :param entry: parsed conntrack entry, - ex: (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') - :return: -1 if entry is lower than rule, 0 if entry matches rule, - 1 if entry is higher than rule - """ - ENTRY_IS_LOWER = -1 - ENTRY_MATCHES = 0 - ENTRY_IS_HIGHER = 1 - rule_ipversion = rule_filter[0] - - if entry[0] < rule_ipversion: - return ENTRY_IS_LOWER - elif entry[0] > rule_ipversion: - return ENTRY_IS_HIGHER - rule_protocol = rule_filter[1] - - if rule_protocol: - if rule_protocol == constants.PROTO_NAME_IPV6_ICMP: - rule_protocol = constants.PROTO_NAME_IPV6_ICMP_LEGACY - if entry[1] < rule_protocol: - return ENTRY_IS_LOWER - elif entry[1] > rule_protocol: - return ENTRY_IS_HIGHER - - sport_range = rule_filter[2] - if sport_range: - sport_range = [int(port) for port in sport_range] - if entry[2] < min(sport_range[0], sport_range[-1]): - return ENTRY_IS_LOWER - elif entry[2] > max(sport_range[0], sport_range[-1]): - return ENTRY_IS_HIGHER - dport_range = rule_filter[3] - if dport_range: - dport_range = [int(port) for port in dport_range] - if entry[3] < min(dport_range[0], dport_range[-1]): - return ENTRY_IS_LOWER - elif entry[3] > max(dport_range[0], dport_range[-1]): - return ENTRY_IS_HIGHER - return ENTRY_MATCHES diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/firewall_agent_api.py b/neutron_fwaas/services/firewall/service_drivers/agents/firewall_agent_api.py deleted file mode 100644 index 9fb36113c..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/firewall_agent_api.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) 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. - -from neutron_lib import rpc as n_rpc -from oslo_config import cfg -import oslo_messaging - -from neutron_fwaas._i18n import _ - - -FWAAS_V1 = "v1" -FWAAS_V2 = "v2" -FW_L2_NOOP_DRIVER = 'noop' - -FWaaSOpts = [ - cfg.StrOpt( - 'driver', - default='', - help=_("Name of the FWaaS Driver")), - cfg.BoolOpt( - 'enabled', - default=False, - help=_("Enable FWaaS")), - cfg.StrOpt( - 'agent_version', - default=FWAAS_V2, - help=_("Firewall agent class")), - cfg.StrOpt( - 'conntrack_driver', - default='conntrack', - help=_("Name of the FWaaS Conntrack Driver")), - cfg.StrOpt( - 'firewall_l2_driver', - default=FW_L2_NOOP_DRIVER, - help=_("Name of the firewall l2 driver") - ) -] -cfg.CONF.register_opts(FWaaSOpts, 'fwaas') - - -class FWaaSPluginApiMixin(object): - """Agent side of the FWaaS agent to FWaaS Plugin RPC API.""" - - def __init__(self, topic, host): - # NOTE(annp): Mixin class should call super - super(FWaaSPluginApiMixin, self).__init__() - - self.host = host - target = oslo_messaging.Target(topic=topic, version='1.0') - self.client = n_rpc.get_client(target) - - def set_firewall_status(self, context, firewall_id, status): - """Make a RPC to set the status of a firewall.""" - cctxt = self.client.prepare() - return cctxt.call(context, 'set_firewall_status', host=self.host, - firewall_id=firewall_id, status=status) - - def firewall_deleted(self, context, firewall_id): - """Make a RPC to indicate that the firewall resources are deleted.""" - cctxt = self.client.prepare() - return cctxt.call(context, 'firewall_deleted', host=self.host, - firewall_id=firewall_id) - - -class FWaaSAgentRpcCallbackMixin(object): - """Mixin for FWaaS agent Implementations.""" - - def __init__(self, host): - - super(FWaaSAgentRpcCallbackMixin, self).__init__(host) - - def create_firewall(self, context, firewall, host): - """Handle RPC cast from plugin to create a firewall.""" - pass - - def update_firewall(self, context, firewall, host): - """Handle RPC cast from plugin to update a firewall.""" - pass - - def delete_firewall(self, context, firewall, host): - """Handle RPC cast from plugin to delete a firewall.""" - pass diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/firewall_service.py b/neutron_fwaas/services/firewall/service_drivers/agents/firewall_service.py deleted file mode 100644 index aa0f17d7a..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/firewall_service.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2014 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. - -from neutron.services import provider_configuration as provconf -from oslo_config import cfg -from oslo_log import log as logging -from oslo_utils import importutils - -from neutron_fwaas._i18n import _ - -LOG = logging.getLogger(__name__) - -FIREWALL_DRIVERS = 'firewall_drivers' - - -class FirewallService(object): - """Firewall Service observer.""" - - def load_device_drivers(self): - """Loads a single device driver for FWaaS.""" - device_driver = provconf.get_provider_driver_class( - cfg.CONF.fwaas.driver, FIREWALL_DRIVERS) - try: - driver = importutils.import_object(device_driver) - LOG.debug('Loaded FWaaS device driver: %s', device_driver) - return driver - except ImportError: - msg = _('Error importing FWaaS device driver: %s') - raise ImportError(msg % device_driver) - except ValueError: - msg = _('Configuration error - no FWaaS device_driver specified') - raise ValueError(msg) diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/l2/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/l2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/l2/fwaas_v2.py b/neutron_fwaas/services/firewall/service_drivers/agents/l2/fwaas_v2.py deleted file mode 100644 index f9b0394d2..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/l2/fwaas_v2.py +++ /dev/null @@ -1,493 +0,0 @@ -# Copyright 2017-2018 FUJITSU LIMITED -# -# 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. - -from oslo_concurrency import lockutils -from oslo_config import cfg -from oslo_log import log as logging -import six - -from neutron.agent import securitygroups_rpc -from neutron import manager -from neutron.plugins.ml2.drivers.openvswitch.agent import vlanmanager -from neutron_lib.agent import l2_extension -from neutron_lib import constants as nl_const -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib import rpc as n_rpc -from neutron_lib.utils import net as nl_net - -from neutron_fwaas._i18n import _ -from neutron_fwaas.common import fwaas_constants as consts -from neutron_fwaas.services.firewall.service_drivers.agents import\ - firewall_agent_api as api - -LOG = logging.getLogger(__name__) - -FWAAS_L2_DRIVER = 'neutron.agent.l2.firewall_drivers' -SG_OVS_DRIVER = 'openvswitch' - - -class FWaaSL2PluginApi(api.FWaaSPluginApiMixin): - """L2 agent side of FWaaS agent-to-plugin RPC API""" - - def get_firewall_group_for_port(self, context, port_id): - """Get firewall group is associated with a port""" - - LOG.debug("Get firewall group is associated with port %s", port_id) - cctxt = self.client.prepare() - return cctxt.call(context, 'get_firewall_group_for_port', - port_id=port_id) - - def set_firewall_group_status(self, context, fwg_id, status, host): - """Set the status of a group operation.""" - - LOG.debug("Fetch firewall group changing status") - cctxt = self.client.prepare() - return cctxt.call(context, 'set_firewall_group_status', - fwg_id=fwg_id, status=status, host=host) - - def firewall_group_deleted(self, context, fwg_id, host): - """Notifies the plugin that a firewall group has been deleted.""" - - LOG.debug("Notify to the plugin that firewall group has been deleted") - cctxt = self.client.prepare() - return cctxt.call(context, 'firewall_group_deleted', - fwg_id=fwg_id, host=host) - - -class FWaaSV2AgentExtension(l2_extension.L2AgentExtension): - - def initialize(self, connection, driver_type): - """Perform Agent Extension initialization""" - - self.conf = cfg.CONF - self.vlan_manager = vlanmanager.LocalVlanManager() - fw_l2_driver_cls = self._load_l2_driver_class(driver_type) - sg_enabled = securitygroups_rpc.is_firewall_enabled() - sg_firewall_driver = self.conf.SECURITYGROUP.firewall_driver - sg_with_ovs = sg_enabled and (sg_firewall_driver == SG_OVS_DRIVER) - self.driver = manager.NeutronManager.load_class_for_provider( - FWAAS_L2_DRIVER, fw_l2_driver_cls)(self.agent_api, sg_with_ovs) - self.plugin_rpc = FWaaSL2PluginApi( - consts.FIREWALL_PLUGIN, self.conf.host) - self.start_rpc_listeners() - self.fwg_map = PortFirewallGroupMap() - - def consume_api(self, agent_api): - self.agent_api = agent_api - - def start_rpc_listeners(self): - self.conn = n_rpc.Connection() - endpoints = [self] - self.conn.create_consumer(consts.FW_AGENT, endpoints, fanout=False) - return self.conn.consume_in_threads() - - def _load_l2_driver_class(self, driver_type): - driver = self.conf.fwaas.firewall_l2_driver or 'noop' - if driver == api.FW_L2_NOOP_DRIVER: - return driver - - if driver != driver_type: - raise Exception( - _("Firewall l2 driver: %s is not compatible"), driver_type) - return driver - - def _is_port_layer2(self, port): - """This function checks if a port belongs to a L2 case. - - Currently both DHCP and router ports are eliminated. - """ - - return port and port.get('device_owner', '').startswith( - nl_const.DEVICE_OWNER_COMPUTE_PREFIX) - - def _get_firewall_group_ports(self, fwg, host, to_delete=False): - port_list = [] - port_ids = fwg['del-port-ids'] if to_delete else fwg['add-port-ids'] - - LOG.debug("_get_fwg fwg=%(fwg)s ports=%(port)s to_delete=%(delete)s", - {'fwg': fwg, 'port': port_ids, 'delete': to_delete}) - for fw_port in port_ids: - port_detail = fwg['port_details'].get(fw_port) - if (self._is_port_layer2(port_detail) and - port_detail.get('host') == host): - port_list.append(port_detail) - return port_list - - @staticmethod - def _has_ports(fwg, event): - """Verifying fwg has ports or not - - This function verify applying firewall group on ports - :param fwg: a fwg object - :param event: create/update firewall group or - create/update/delete port - :return: True if applying firewall group is fine. Otherwise is False - """ - if event == consts.UPDATE_FWG and 'last-port' in fwg: - return not fwg['last-port'] - else: - return bool(fwg['ports']) - - @staticmethod - def _has_policy(fwg): - """Verifying fwg has policy or not""" - return bool(fwg['ingress_firewall_policy_id'] or - fwg['egress_firewall_policy_id']) - - def _compute_status(self, fwg, result, event=consts.CREATE_FWG): - """Compute a status of specified firewall group for update - - Validates 'ACTIVE', 'DOWN', 'INACTIVE', 'ERROR' and None as follows: - - "ERROR" : if result is not True - - "ACTIVE" : admin_state_up is True and exists ports - - "INACTIVE" : admin_state_up is True and with no ports - - "DOWN" : admin_state_up is False - - None : In case of 'delete_firewall_group' - """ - if not result: - return nl_const.ERROR - - if not fwg['admin_state_up']: - return nl_const.DOWN - - if event == consts.DELETE_FWG: - # This firewall_group will be deleted. No need to update status. - return - - if (self._has_ports(fwg, event) and self._has_policy(fwg)): - return nl_const.ACTIVE - - return nl_const.INACTIVE - - def _get_network_id(self, fwg_port): - port_id = fwg_port.get('port_id', fwg_port.get('id')) - port_details = fwg_port.get('port_details') - - if port_details: - target = port_details.get(port_id) - if target: - return target.get('network_id') - return - - return fwg_port.get('network_id') - - def _add_local_vlan_to_ports(self, fwg_ports): - """Add local VLAN to ports if found - - This function tries to add local VLAN related to ports. - """ - - ports_with_lvlan = [] - for fwg_port in fwg_ports: - try: - network_id = self._get_network_id(fwg_port) - l_vlan = self.vlan_manager.get(network_id).vlan - fwg_port['lvlan'] = int(l_vlan) - except vlanmanager.MappingNotFound: - LOG.warning("No Local VLAN found in network %s", network_id) - # NOTE(yushiro): We ignore this exception because we should send - # all selected ports to driver layer. It depends on driver's - # behavior whether it occurs an error with no local VLAN or not. - ports_with_lvlan.append(fwg_port) - - return ports_with_lvlan - - def _apply_fwg_rules(self, fwg, ports, event=consts.UPDATE_FWG): - """This function invokes the driver create/update routine. """ - # Set firewall group status; will be overwritten if call to driver - # fails. - if event in [consts.CREATE_FWG, consts.UPDATE_FWG]: - ports_for_driver = self._add_local_vlan_to_ports(ports) - else: - ports_for_driver = ports - - # apply firewall group to driver - try: - if event == consts.UPDATE_FWG: - self.driver.update_firewall_group(ports_for_driver, fwg) - elif event == consts.DELETE_FWG: - self.driver.delete_firewall_group(ports_for_driver, fwg) - elif event == consts.CREATE_FWG: - self.driver.create_firewall_group(ports_for_driver, fwg) - except f_exc.FirewallInternalDriverError: - msg = _("FWaaS driver error in %(event)s_firewall_group " - "for firewall group: %(fwg_id)s") - LOG.exception(msg, {'event': event, 'fwg_id': fwg['id']}) - return False - return True - - def _send_fwg_status(self, context, fwg_id, status, host): - """Send firewall group's status to plugin. - - :returns: True if no exception occurred otherwise False - :rtype: boolean - """ - try: - self.plugin_rpc.set_firewall_group_status( - context, fwg_id, status, host) - LOG.debug("Successfully sent status(%s) for firewall_group(%s)", - status, fwg_id) - except Exception: - msg = _("Failed to send status for firewall_group(%s)") - LOG.exception(msg, fwg_id) - - def _create_firewall_group(self, context, fwg, host, - event=consts.CREATE_FWG): - """Handles RPC from plugin to create a firewall group. """ - - add_ports = self._get_firewall_group_ports(fwg, host) - if not add_ports: - status = nl_const.INACTIVE - else: - ret = self._apply_fwg_rules(fwg, add_ports, event) - - # cleanup port_map - for port in add_ports: - self.fwg_map.remove_port(port) - - status = self._compute_status(fwg, ret, event) - for port in add_ports: - self.fwg_map.set_port_fwg(port, fwg) - # Update status of firewall group which is associated with ports - # after updating. - self._send_fwg_status(context, fwg['id'], status, host) - - def _delete_firewall_group(self, context, fwg, host, - event=consts.DELETE_FWG): - """Handles RPC from plugin to delete a firewall group. """ - - del_ports = self._get_firewall_group_ports(fwg, host, to_delete=True) - if not del_ports: - return - - # cleanup all flows of del_ports - ret = self._apply_fwg_rules(fwg, del_ports, event=consts.DELETE_FWG) - del_port_ids = [] - for port in del_ports: - del_port_ids.append(port['id']) - self.fwg_map.remove_port(port) - - if event == consts.DELETE_FWG: - self.fwg_map.remove_fwg(fwg) - self.plugin_rpc.firewall_group_deleted( - context, fwg['id'], host=self.conf.host) - else: - status = self._compute_status(fwg, ret, event) - self._send_fwg_status(context, fwg['id'], status, self.conf.host) - - @lockutils.synchronized('fwg') - def create_firewall_group(self, context, firewall_group, host): - """Handles create firewall group event""" - - # TODO(chandanc): Fix agent RPC endpoint to remove host arg - host = cfg.CONF.host - with self.driver.defer_apply(): - try: - self._create_firewall_group(context, firewall_group, host) - except Exception as exc: - LOG.exception( - "Exception caught in create_firewall_group %s", exc) - self._send_fwg_status(context, firewall_group['id'], - status=nl_const.ERROR, host=host) - - @lockutils.synchronized('fwg') - def delete_firewall_group(self, context, firewall_group, host): - """Handles delete firewall group event""" - - # TODO(chandanc): Fix agent RPC endpoint to remove host arg - host = cfg.CONF.host - with self.driver.defer_apply(): - try: - self._delete_firewall_group(context, firewall_group, host) - except Exception as exc: - LOG.exception( - "Exception caught in delete_firewall_group %s", exc) - self._send_fwg_status(context, firewall_group['id'], - status=nl_const.ERROR, host=host) - - @lockutils.synchronized('fwg') - def update_firewall_group(self, context, firewall_group, host): - """Handles update firewall group event""" - - # TODO(chandanc): Fix agent RPC endpoint to remove host arg - host = cfg.CONF.host - with self.driver.defer_apply(): - try: - self._delete_firewall_group( - context, firewall_group, host, event=consts.UPDATE_FWG) - self._create_firewall_group( - context, firewall_group, host, event=consts.UPDATE_FWG) - except Exception as exc: - LOG.exception( - "Exception caught in update_firewall_group %s", exc) - self._send_fwg_status(context, firewall_group['id'], - status=nl_const.ERROR, host=host) - - @lockutils.synchronized('fwg-port') - def handle_port(self, context, port): - """Handle port update event""" - - # Check if port is trusted and called at once. - if nl_net.is_port_trusted(port) and not self.fwg_map.get_port(port): - self._add_rule_for_trusted_port(port) - self.fwg_map.set_port(port) - return - - if not self._is_port_layer2(port): - return - - # check if port is already assigned to a fwg - if self.fwg_map.get_port_fwg(port): - return - - fwg = self.plugin_rpc.get_firewall_group_for_port( - context, port.get('port_id')) - if not fwg: - LOG.info("Firewall group applied to port %s is " - "not available on server.", port['port_id']) - return - - ret = self._apply_fwg_rules(fwg, [port]) - status = self._compute_status(fwg, ret, event=consts.HANDLE_PORT) - self.fwg_map.set_port_fwg(port, fwg) - self._send_fwg_status( - context, fwg_id=fwg['id'], status=status, host=self.conf.host) - - def _add_rule_for_trusted_port(self, port): - self._add_local_vlan_to_ports([port]) - self.driver.process_trusted_ports([port]) - - def _delete_rule_for_trusted_port(self, port): - self.driver.remove_trusted_ports([port['port_id']]) - - def delete_port(self, context, port): - """This is being called when a port is deleted by the agent. """ - - # delete_port should be handled only unbound timing for a port. - # If 'vif_port' is included in the port dict, this is called after - # deleted the port and should be ignored. - if 'vif_port' in port: - return - - port = self.fwg_map.get_port(port) - - if port and nl_net.is_port_trusted(port): - self._delete_rule_for_trusted_port(port) - self.fwg_map.remove_port(port) - return - - if not self._is_port_layer2(port): - return - - fwg = self.fwg_map.get_port_fwg(port) - if not fwg: - LOG.info("Firewall group associated to port %(port_id)s is " - "not available on server.", {'port_id': port['port_id']}) - return - - ret = self._apply_fwg_rules(fwg, [port], event=consts.DELETE_FWG) - - port_id = self.fwg_map.port_id(port) - if port_id in fwg['ports']: - fwg['ports'].remove(port_id) - - # update the fwg dict to known_fwgs - self.fwg_map.set_fwg(fwg) - self.fwg_map.remove_port(port) - status = self._compute_status(fwg, ret, event=consts.DELETE_PORT) - self._send_fwg_status(context, fwg['id'], status, self.conf.host) - - -class PortFirewallGroupMap(object): - """Store relations between Port and Firewall Group and trusted port - - This map is used in deleting firewall_group because the firewall_group has - been deleted at that time. Therefore, it is impossible to refer 'ports'. - This map enables to refer 'ports' for specified firewall_group. - Furthermore, it is necessary to check 'device_owner' for trusted port, this - Map also stores trusted port data. - """ - def __init__(self): - self.known_fwgs = {} - self.port_fwg = {} - self.port_detail = {} - # TODO(yushiro): If agent is restarted, this map doesn't have any - # information. Need to consider map initialization in __init__() - - def port_id(self, port): - return (port if isinstance(port, six.string_types) - else port.get('port_id', port.get('id'))) - - def get_fwg(self, fwg_id): - return self.known_fwgs.get(fwg_id) - - def set_fwg(self, fwg): - self.known_fwgs[fwg['id']] = fwg - - def get_port(self, port): - return self.port_detail.get(self.port_id(port)) - - def get_port_fwg(self, port): - fwg_id = self.port_fwg.get(self.port_id(port)) - if fwg_id: - return self.get_fwg(fwg_id) - - def set_port(self, port): - """Add a new port into port_detail""" - port_id = self.port_id(port) - self.port_detail[port_id] = port - - def set_port_fwg(self, port, fwg): - """Add a new port into fwg['ports']""" - port_id = self.port_id(port) - # Update fwg['ports'] data - fwg['ports'] = list(set(fwg['ports'] + [port_id])) - # Update fwg_id -> firewall_group data - self.known_fwgs[fwg['id']] = fwg - # Update port_id -> port data - self.port_detail[port_id] = port - # Update port_id -> firewall_group_id relation - self.port_fwg[port_id] = fwg['id'] - - def remove_port(self, port): - """Remove port from fwg['ports'] and port_fwg dictionary - - When removing 'port' from several cases, the port should be removed - from this map. - """ - port_id = self.port_id(port) - # Check if 'port_id' has registered in port_fwg dictionary. - # Update firewall_group - if port_id in self.port_fwg: - fwg_id = self.port_fwg.get(port_id) - if not fwg_id: - # This case is trusted port. Try to delete port_detail dict - try: - del self.port_detail[port_id] - except KeyError: - pass - return - new_fwg = self.known_fwgs[fwg_id] - new_fwg['ports'] = [p for p in new_fwg['ports'] if p != port_id] - self.known_fwgs[fwg_id] = new_fwg - del self.port_fwg[port_id] - del self.port_detail[port_id] - - def remove_fwg(self, fwg): - """Remove firewall_group from known_fwgs dictionary - - When removing firewall_group, it should be removed from this map - """ - if fwg['id'] in self.known_fwgs: - del self.known_fwgs[fwg['id']] diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/l3reference/__init__.py b/neutron_fwaas/services/firewall/service_drivers/agents/l3reference/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/l3reference/firewall_l3_agent_v2.py b/neutron_fwaas/services/firewall/service_drivers/agents/l3reference/firewall_l3_agent_v2.py deleted file mode 100644 index 3fac9f9d0..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/agents/l3reference/firewall_l3_agent_v2.py +++ /dev/null @@ -1,549 +0,0 @@ -# Copyright (c) 2016 -# 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. - -from neutron.agent.linux import ip_lib -from neutron_lib.agent import l3_extension -from neutron_lib import constants as nl_constants -from neutron_lib import context -from neutron_lib.exceptions import firewall_v2 as fw_ext -from neutron_lib import rpc as n_rpc -from oslo_config import cfg -from oslo_log import helpers as log_helpers -from oslo_log import log as logging - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.common import resources as f_resources -from neutron_fwaas.services.firewall.service_drivers.agents import\ - firewall_agent_api as api -from neutron_fwaas.services.firewall.service_drivers.agents import\ - firewall_service - - -LOG = logging.getLogger(__name__) - - -class FWaaSL3PluginApi(api.FWaaSPluginApiMixin): - """Agent side of the FWaaS agent-to-plugin RPC API.""" - def __init__(self, topic, host): - super(FWaaSL3PluginApi, self).__init__(topic, host) - - def get_firewall_groups_for_project(self, context, **kwargs): - """Fetches a project's firewall groups from the plugin.""" - LOG.debug("Fetch firewall groups from plugin") - cctxt = self.client.prepare() - return cctxt.call(context, 'get_firewall_groups_for_project', - host=self.host) - - def get_projects_with_firewall_groups(self, context, **kwargs): - """Fetches from the plugin all projects that have firewall groups - configured. - """ - LOG.debug("Fetch from plugin projects that have firewall groups " - "configured") - cctxt = self.client.prepare() - return cctxt.call(context, - 'get_projects_with_firewall_groups', host=self.host) - - def firewall_group_deleted(self, context, fwg_id, **kwargs): - """Notifies the plugin that a firewall group has been deleted.""" - LOG.debug("Notify plugin that firewall group has been deleted") - cctxt = self.client.prepare() - return cctxt.call(context, 'firewall_group_deleted', fwg_id=fwg_id, - host=self.host) - - def set_firewall_group_status(self, context, fwg_id, status, **kwargs): - """Sets firewall group's status on the plugin.""" - LOG.debug("Set firewall groups from plugin") - cctxt = self.client.prepare() - return cctxt.call(context, 'set_firewall_group_status', - fwg_id=fwg_id, status=status, host=self.host) - - -class FWaaSL3AgentExtension(l3_extension.L3AgentExtension): - """FWaaS agent extension.""" - - SUPPORTED_RESOURCE_TYPES = [f_resources.FIREWALL_GROUP, - f_resources.FIREWALL_POLICY, - f_resources.FIREWALL_RULE] - - def initialize(self, connection, driver_type): - self._register_rpc_consumers(connection) - - def consume_api(self, agent_api): - LOG.debug("FWaaS consume_api call occurred with %s", agent_api) - self.agent_api = agent_api - - def _register_rpc_consumers(self, connection): - #TODO(njohnston): Add RPC consumer connection loading here. - pass - - def start_rpc_listeners(self, host, conf): - self.endpoints = [self] - - self.conn = n_rpc.Connection() - self.conn.create_consumer( - fwaas_constants.FW_AGENT, self.endpoints, fanout=False) - return self.conn.consume_in_threads() - - def __init__(self, host, conf): - LOG.debug("Initializing firewall group agent") - self.agent_api = None - self.neutron_service_plugins = None - self.conf = conf - self.fwaas_enabled = cfg.CONF.fwaas.enabled - - self.start_rpc_listeners(host, conf) - # None means l3-agent has no information on the server - # configuration due to the lack of RPC support. - if self.neutron_service_plugins is not None: - fwaas_plugin_configured = (fwaas_constants.FIREWALL - in self.neutron_service_plugins) - if fwaas_plugin_configured and not self.fwaas_enabled: - msg = ("FWaaS plugin is configured in the server side, but " - "FWaaS is disabled in L3-agent.") - LOG.error(msg) - raise SystemExit(1) - self.fwaas_enabled = self.fwaas_enabled and fwaas_plugin_configured - - if self.fwaas_enabled: - # NOTE: Temp location for creating service and loading driver - self.fw_service = firewall_service.FirewallService() - self.fwaas_driver = self.fw_service.load_device_drivers() - - self.services_sync_needed = False - self.fwplugin_rpc = FWaaSL3PluginApi(fwaas_constants.FIREWALL_PLUGIN, - host) - super(FWaaSL3AgentExtension, self).__init__() - - @property - def _local_namespaces(self): - local_ns_list = ip_lib.list_network_namespaces() - return local_ns_list - - def _has_port_insertion_fields(self, firewall_group): - """The presence of the 'add-port-ids' key in the firewall group dict - shows we are using the current version of the plugin. If this key - is absent, we are in an upgrade and message is from an older - version of the plugin. - """ - return 'add-port-ids' in firewall_group - - def _get_firewall_group_ports(self, context, firewall_group, - to_delete=False, require_new_plugin=False): - """Returns in-namespace ports, either from firewall group dict if ports - update or from project routers otherwise if only policies update. - - NOTE: Vernacular move from "tenant" to "project" doesn't yet appear - as a key in router or firewall group objects. - """ - fwg_port_ids = [] - if self._has_port_insertion_fields(firewall_group): - if to_delete: - fwg_port_ids = firewall_group['del-port-ids'] - else: - fwg_port_ids = firewall_group['add-port-ids'] - if not require_new_plugin and not fwg_port_ids: - routers = self.agent_api.get_routers_in_project( - firewall_group['tenant_id']) - for router in routers: - if router.router['tenant_id'] == firewall_group['tenant_id']: - fwg_port_ids.extend([p['id'] for p in - router.internal_ports]) - - # Return in-namespace port objects. - return self._get_in_ns_ports(fwg_port_ids) - - def _get_in_ns_ports(self, port_ids): - """Get ports in namespace by their IDs. - - Returns port objects in the local namespace, along with their - router_info. - - :param port_ids: IDs of router ports (set, list or tuple) - """ - in_ns_ports = {} # This will be converted to a list later. - if port_ids and self.agent_api: - for port_id in port_ids: - # This fetched router_info is guaranteed to be in_namespace. - router_info = self.agent_api.get_router_hosting_port(port_id) - if router_info: - if router_info in in_ns_ports: - in_ns_ports[router_info].append(port_id) - else: - in_ns_ports[router_info] = [port_id] - return list(in_ns_ports.items()) - - def _invoke_driver_for_sync_from_plugin(self, ctx, ports, firewall_group): - """Call driver to sync firewall group. - - Calls the FWaaS driver's delete_firewall_group method if firewall - group has status of PENDING_DELETE; calls driver's - update_firewall_group method for all other statuses. Both of these - methods are idempotent. - - :param ctx: RPC context - :param ports: IDs of ports associated with a firewall group - (set, list or tuple) - :param firewall_group: Dictionary describing the firewall group object - - """ - port_list = self._get_in_ns_ports(ports) - if firewall_group['status'] == nl_constants.PENDING_DELETE: - try: - self.fwaas_driver.delete_firewall_group( - self.conf.agent_mode, port_list, firewall_group) - self.fwplugin_rpc.firewall_group_deleted( - ctx, firewall_group['id']) - except fw_ext.FirewallInternalDriverError: - msg = ("FWaaS driver error on %(status)s " - "for firewall group: %(fwg_id)s") - LOG.exception(msg, {'status': firewall_group['status'], - 'fwg_id': firewall_group['id']}) - self.fwplugin_rpc.set_firewall_group_status( - ctx, firewall_group['id'], nl_constants.ERROR) - else: # PENDING_UPDATE, PENDING_CREATE, ... - - # Prepare firewall group status to return to plugin; may be - # overwritten if call to driver fails. - if firewall_group['admin_state_up']: - status = nl_constants.ACTIVE - else: - status = nl_constants.DOWN - - # Call the driver. - try: - self.fwaas_driver.update_firewall_group( - self.conf.agent_mode, port_list, firewall_group) - except fw_ext.FirewallInternalDriverError: - msg = ("FWaaS driver error on %(status)s for firewall " - "group: %(fwg_id)s") - LOG.exception(msg, {'status': firewall_group['status'], - 'fwg_id': firewall_group['id']}) - status = nl_constants.ERROR - - # Notify the plugin of firewall group's status. - self.fwplugin_rpc.set_firewall_group_status( - ctx, firewall_group['id'], status) - - def _process_router_update(self, updated_router): - """If a new or existing router in the local namespace is updated, - queries the plugin to get the firewall groups for the project in - question and then sees if the router has any ports for any firewall - group that is configured for that project. If so, installs firewall - group rules on the requested ports on this router. - """ - LOG.debug("Process router update, router_id: %s tenant: %s.", - updated_router['id'], updated_router['tenant_id']) - router_id = updated_router['id'] - if not self.agent_api.is_router_in_namespace(router_id): - return - - # Get the firewall groups for the new router's project. - # NOTE: Vernacular move from "tenant" to "project" doesn't yet appear - # as a key in router or firewall group objects. - ctx = context.Context('', updated_router['tenant_id']) - fwg_list = self.fwplugin_rpc.get_firewall_groups_for_project(ctx) - - if nl_constants.INTERFACE_KEY not in updated_router: - return - - # Apply a firewall group, as requested, to ports on the new router. - all_router_ports = set( - p['id'] for p in updated_router[nl_constants.INTERFACE_KEY] - ) - processed_ports = set() - for firewall_group in fwg_list: - if not self._has_port_insertion_fields(firewall_group): - continue - - ports_to_process = (set(firewall_group['add-port-ids'] + - firewall_group['del-port-ids']) & - all_router_ports) - # ensure no port in router is associated with the firewall group - if not ports_to_process: - continue - # A port can have at most one firewall group. - port_ids_to_exclude = ports_to_process & processed_ports - if port_ids_to_exclude: - LOG.warning("Port(s) %s is associated with " - "more than one firewall group(s).", - port_ids_to_exclude) - ports_to_process -= port_ids_to_exclude - self._invoke_driver_for_sync_from_plugin( - ctx, ports_to_process, firewall_group) - processed_ports |= ports_to_process - - def add_router(self, context, new_router): - """Handles agent restart and router add. Fetches firewall groups from - plugin and updates driver. - """ - if not self.fwaas_enabled: - return - - try: - self._process_router_update(new_router) - except Exception: - LOG.exception("FWaaS router add RPC info call failed for %s", - new_router['id']) - self.services_sync_needed = True - - def update_router(self, context, updated_router): - """Handles agent restart and router update. Fetches firewall groups - from plugin and updates driver. - """ - if not self.fwaas_enabled: - return - - try: - self._process_router_update(updated_router) - except Exception: - #TODO(njohnston): This repr should be replaced. - LOG.exception( - "FWaaS router update RPC info call failed for %s", - repr(updated_router)) - self.services_sync_needed = True - - def delete_router(self, context, new_router): - """Handles router deletion. There is basically nothing to do for this - in the context of FWaaS with an IPTables driver; the namespace will - already have been deleted, taking the IPTables rules with it. - """ - #TODO(njohnston): When another firewall driver is implemented, look at - # expanding this out so that the driver can handle deletion calls. - pass - - def process_services_sync(self, ctx): - """Syncs with plugin and applies the sync data. - """ - - if not self.services_sync_needed or not self.fwaas_enabled: - return - - try: - # Fetch from the plugin the list of projects with firewall groups. - project_ids = \ - self.fwplugin_rpc.get_projects_with_firewall_groups(ctx) - LOG.debug("Projects with firewall groups: %s", - ', '.join(project_ids)) - for project_id in project_ids: - ctx = context.Context('', project_id) - fwg_list = \ - self.fwplugin_rpc.get_firewall_groups_for_project(ctx) - for firewall_group in fwg_list: - if firewall_group['status'] == nl_constants.PENDING_DELETE: - self.delete_firewall_group(ctx, firewall_group, - self.host) - # No need to apply sync data for ACTIVE firewall group. - elif firewall_group['status'] != nl_constants.ACTIVE: - self.update_firewall_group(ctx, firewall_group, - self.host) - self.services_sync_needed = False - except Exception: - LOG.exception("Failed FWaaS process services sync.") - self.services_sync_needed = True - - @log_helpers.log_method_call - def create_firewall_group(self, context, firewall_group, host): - """Handles RPC from plugin to create a firewall group. - """ - - # Get the in-namespace ports to which to add the firewall group. - ports_for_fwg = self._get_firewall_group_ports(context, firewall_group) - if not ports_for_fwg: - return - - LOG.debug("Create firewall group %(fwg_id)s on ports: %(ports)s", - {'fwg_id': firewall_group['id'], - 'ports': ', '.join([p for ri_ports in ports_for_fwg - for p in ri_ports[1]])}) - - # Set firewall group status; will be overwritten if call to driver - # fails. - if firewall_group['admin_state_up']: - status = nl_constants.ACTIVE - else: - status = nl_constants.DOWN - - # Call the driver. - try: - self.fwaas_driver.create_firewall_group(self.conf.agent_mode, - ports_for_fwg, - firewall_group) - except fw_ext.FirewallInternalDriverError: - msg = ("FWaaS driver error in create_firewall_group " - "for firewall group: %(fwg_id)s") - LOG.exception(msg, {'fwg_id': firewall_group['id']}) - status = nl_constants.ERROR - - # Send firewall group's status to plugin. - try: - self.fwplugin_rpc.set_firewall_group_status(context, - firewall_group['id'], status) - except Exception: - msg = ("FWaaS RPC failure in create_firewall_group " - "for firewall group: %(fwg_id)s") - LOG.exception(msg, {'fwg_id': firewall_group['id']}) - self.services_sync_needed = True - - @log_helpers.log_method_call - def update_firewall_group(self, context, firewall_group, host): - """Handles RPC from plugin to update a firewall group. - """ - - # Initialize firewall group status. - status = "" - - # Get the list of in-namespace ports from which to delete the firewall - # group. - del_fwg_ports = self._get_firewall_group_ports( - context, firewall_group, to_delete=True, require_new_plugin=True) - add_fwg_ports = self._get_firewall_group_ports(context, firewall_group) - - port_ids = (firewall_group.get('del-port-ids') + - firewall_group.get('add-port-ids')) - - if port_ids and not (del_fwg_ports or add_fwg_ports): - LOG.debug("All ports are not router port." - "No need to update firewall driver.") - return - - # Remove firewall group from ports if requested. - if del_fwg_ports: - fw_ports = [p for ri_port in del_fwg_ports for p in ri_port[1]] - LOG.debug("Update (delete) firewall group %(fwg_id)s on ports: " - "%(ports)s", - {'fwg_id': firewall_group['id'], - 'ports': ', '.join(fw_ports)}) - - # Set firewall group's status; will be overwritten if call to - # driver fails. - - if firewall_group['admin_state_up']: - status = nl_constants.ACTIVE - if firewall_group['last-port']: - status = nl_constants.INACTIVE - else: - status = nl_constants.DOWN - - # Call the driver. - try: - self.fwaas_driver.delete_firewall_group(self.conf.agent_mode, - del_fwg_ports, - firewall_group) - except fw_ext.FirewallInternalDriverError: - msg = ("FWaaS driver error in update_firewall_group " - "(add) for firewall group: %s") - LOG.exception(msg, firewall_group['id']) - status = nl_constants.ERROR - - # Handle the add router and/or rule, policy, firewall group attribute - # updates. - if status not in (nl_constants.ERROR, nl_constants.INACTIVE): - if add_fwg_ports: - fw_ports = [p for ri_port in add_fwg_ports - for p in ri_port[1]] - LOG.debug("Update (create) firewall group %(fwg_id)s on " - "ports: %(ports)s", - {'fwg_id': firewall_group['id'], - 'ports': ', '.join(fw_ports)}) - - # Set firewall group status, which will be overwritten if call - # to driver fails. - if firewall_group['admin_state_up']: - status = nl_constants.ACTIVE - else: - status = nl_constants.DOWN - - # Call the driver. - try: - self.fwaas_driver.update_firewall_group( - self.conf.agent_mode, add_fwg_ports, - firewall_group) - except fw_ext.FirewallInternalDriverError: - msg = ("FWaaS driver error in update_firewall_group " - "for firewall group: %s") - LOG.exception(msg, firewall_group['id']) - status = nl_constants.ERROR - elif not status: - # if status not set by now, set it to INACTIVE - status = nl_constants.INACTIVE - - # Return status to plugin. - try: - self.fwplugin_rpc.set_firewall_group_status(context, - firewall_group['id'], status) - except Exception: - LOG.exception("FWaaS RPC failure in update_firewall_group " - "for firewall group: %s", firewall_group['id']) - self.services_sync_needed = True - - @log_helpers.log_method_call - def delete_firewall_group(self, context, firewall_group, host): - """Handles RPC from plugin to delete a firewall group. - """ - - ports_for_fwg = self._get_firewall_group_ports(context, firewall_group, - to_delete=True) - - if not ports_for_fwg: - return - - fw_ports = [p for ri_ports in ports_for_fwg for p in ri_ports[1]] - LOG.debug("Delete firewall group %(fwg_id)s on ports: %(ports)s", - {'fwg_id': firewall_group['id'], - 'ports': ', '.join(fw_ports)}) - - # Set the firewall group's status to return to plugin; status may be - # overwritten if call to driver fails. - if firewall_group['admin_state_up']: - status = nl_constants.ACTIVE - else: - status = nl_constants.DOWN - try: - self.fwaas_driver.delete_firewall_group(self.conf.agent_mode, - ports_for_fwg, - firewall_group) - # Call the driver. - except fw_ext.FirewallInternalDriverError: - LOG.exception("FWaaS driver error in delete_firewall_group " - "for firewall group: %s", firewall_group['id']) - status = nl_constants.ERROR - - # Notify plugin of deletion or return firewall group's status to - # plugin, as appropriate. - try: - if status in [nl_constants.ACTIVE, nl_constants.DOWN]: - self.fwplugin_rpc.firewall_group_deleted(context, - firewall_group['id']) - else: - self.fwplugin_rpc.set_firewall_group_status(context, - firewall_group['id'], status) - except Exception: - LOG.exception("FWaaS RPC failure in delete_firewall_group " - "for firewall group: %s", firewall_group['id']) - self.services_sync_needed = True - - def ha_state_change(self, context, data): - pass - - -class L3WithFWaaS(FWaaSL3AgentExtension): - - def __init__(self, conf=None): - if conf: - self.conf = conf - else: - self.conf = cfg.CONF - super(L3WithFWaaS, self).__init__(host=self.conf.host, conf=self.conf) diff --git a/neutron_fwaas/services/firewall/service_drivers/driver_api.py b/neutron_fwaas/services/firewall/service_drivers/driver_api.py deleted file mode 100644 index eae09177f..000000000 --- a/neutron_fwaas/services/firewall/service_drivers/driver_api.py +++ /dev/null @@ -1,532 +0,0 @@ -# Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. -# 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 abc -import copy - -import six - -from neutron_lib.callbacks import events -from neutron_lib.callbacks import registry -from neutron_lib import constants as nl_constants -from neutron_lib.plugins import directory -from oslo_log import log as logging - -from neutron_fwaas.common import fwaas_constants as const -from neutron_fwaas.db.firewall.v2 import firewall_db_v2 - - -LOG = logging.getLogger(__name__) - - -@six.add_metaclass(abc.ABCMeta) -class FirewallDriver(object): - """Firewall v2 interface for driver - - That driver interface does not persist Firewall v2 data in any database. - The driver needs to do it by itself. - """ - - def __init__(self, service_plugin): - self.service_plugin = service_plugin - - @property - def _core_plugin(self): - return directory.get_plugin() - - def is_supported_l2_port(self, port): - return False - - def is_supported_l3_port(self, port): - return False - - # Firewall Group - @abc.abstractmethod - def create_firewall_group(self, context, firewall_group): - pass - - @abc.abstractmethod - def delete_firewall_group(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_group(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_groups(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_group(self, context, id, firewall_group): - pass - - # Firewall Policy - @abc.abstractmethod - def create_firewall_policy(self, context, firewall_policy): - pass - - @abc.abstractmethod - def delete_firewall_policy(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_policy(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_policies(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_policy(self, context, id, firewall_policy): - pass - - # Firewall Rule - @abc.abstractmethod - def create_firewall_rule(self, context, firewall_rule): - pass - - @abc.abstractmethod - def delete_firewall_rule(self, context, id): - pass - - @abc.abstractmethod - def get_firewall_rule(self, context, id, fields=None): - pass - - @abc.abstractmethod - def get_firewall_rules(self, context, filters=None, fields=None): - pass - - @abc.abstractmethod - def update_firewall_rule(self, context, id, firewall_rule): - pass - - @abc.abstractmethod - def insert_rule(self, context, policy_id, rule_info): - pass - - @abc.abstractmethod - def remove_rule(self, context, policy_id, rule_info): - pass - - -@six.add_metaclass(abc.ABCMeta) -class FirewallDriverDBMixin(FirewallDriver): - """FirewallDriverDB mixin to provision the database on behalf of the driver - - That driver interface persists Firewall data in its database and forwards - the result to pre and post commit methods. - """ - - def __init__(self, *args, **kwargs): - super(FirewallDriverDBMixin, self).__init__(*args, **kwargs) - self.firewall_db = firewall_db_v2.FirewallPluginDb() - - @staticmethod - def _update_resource_status(context, resource_type, resource_dict): - with context.session.begin(subtransactions=True): - context.session.query(resource_type).\ - filter_by(id=resource_dict['id']).\ - update({'status': resource_dict['status']}) - - # Firewall Group - def create_firewall_group(self, context, firewall_group): - request_body = firewall_group - with context.session.begin(subtransactions=True): - firewall_group = self.firewall_db.create_firewall_group( - context, firewall_group) - self.create_firewall_group_precommit(context, firewall_group) - self._update_resource_status(context, firewall_db_v2.FirewallGroup, - firewall_group) - self.create_firewall_group_postcommit(context, firewall_group) - - payload = events.DBEventPayload(context=context, - resource_id=firewall_group['id'], - request_body=request_body, - states=(firewall_group,)) - registry.publish( - const.FIREWALL_GROUP, events.AFTER_CREATE, self, payload=payload) - return firewall_group - - @abc.abstractmethod - def create_firewall_group_precommit(self, context, firewall_group): - pass - - @abc.abstractmethod - def create_firewall_group_postcommit(self, context, firewall_group): - pass - - def delete_firewall_group(self, context, id): - firewall_group = self.firewall_db.get_firewall_group(context, id) - if firewall_group['status'] == nl_constants.PENDING_DELETE: - firewall_group['status'] = nl_constants.ERROR - self.delete_firewall_group_precommit(context, firewall_group) - if firewall_group['status'] != nl_constants.PENDING_DELETE: - # lets driver deleting firewall group later - self.firewall_db.delete_firewall_group(context, id) - self.delete_firewall_group_postcommit(context, firewall_group) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(firewall_group,)) - registry.publish( - const.FIREWALL_GROUP, events.AFTER_DELETE, self, payload=payload) - - @abc.abstractmethod - def delete_firewall_group_precommit(self, context, firewall_group): - pass - - @abc.abstractmethod - def delete_firewall_group_postcommit(self, context, firewall_group): - pass - - def get_firewall_group(self, context, id, fields=None): - return self.firewall_db.get_firewall_group(context, id, fields=fields) - - def get_firewall_groups(self, context, filters=None, fields=None): - return self.firewall_db.get_firewall_groups(context, filters, fields) - - def update_firewall_group(self, context, id, firewall_group_delta): - old_firewall_group = self.firewall_db.get_firewall_group(context, id) - new_firewall_group = copy.deepcopy(old_firewall_group) - new_firewall_group.update(firewall_group_delta) - self.update_firewall_group_precommit(context, old_firewall_group, - new_firewall_group) - firewall_group_delta['status'] = new_firewall_group['status'] - firewall_group = self.firewall_db.update_firewall_group( - context, id, firewall_group_delta) - self.update_firewall_group_postcommit(context, old_firewall_group, - firewall_group) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(old_firewall_group, - new_firewall_group)) - registry.publish( - const.FIREWALL_GROUP, events.AFTER_UPDATE, self, payload=payload) - - return firewall_group - - @abc.abstractmethod - def update_firewall_group_precommit(self, context, old_firewall_group, - new_firewall_group): - pass - - @abc.abstractmethod - def update_firewall_group_postcommit(self, context, old_firewall_group, - new_firewall_group): - pass - - # Firewall Policy - def create_firewall_policy(self, context, firewall_policy): - request_body = firewall_policy - with context.session.begin(subtransactions=True): - firewall_policy = self.firewall_db.create_firewall_policy( - context, firewall_policy) - self.create_firewall_policy_precommit(context, firewall_policy) - self.create_firewall_policy_postcommit(context, firewall_policy) - - payload = events.DBEventPayload(context=context, - resource_id=firewall_policy['id'], - request_body=request_body, - states=(firewall_policy,)) - registry.publish( - const.FIREWALL_POLICY, events.AFTER_CREATE, self, payload=payload) - return firewall_policy - - @abc.abstractmethod - def create_firewall_policy_precommit(self, context, firewall_policy): - pass - - @abc.abstractmethod - def create_firewall_policy_postcommit(self, context, firewall_policy): - pass - - def delete_firewall_policy(self, context, id): - firewall_policy = self.firewall_db.get_firewall_policy(context, id) - self.delete_firewall_policy_precommit(context, firewall_policy) - self.firewall_db.delete_firewall_policy(context, id) - self.delete_firewall_policy_postcommit(context, firewall_policy) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(firewall_policy,)) - registry.publish( - const.FIREWALL_POLICY, events.AFTER_UPDATE, self, payload=payload) - - @abc.abstractmethod - def delete_firewall_policy_precommit(self, context, firewall_policy): - pass - - @abc.abstractmethod - def delete_firewall_policy_postcommit(self, context, firewall_policy): - pass - - def get_firewall_policy(self, context, id, fields=None): - return self.firewall_db.get_firewall_policy(context, id, fields) - - def get_firewall_policies(self, context, filters=None, fields=None): - return self.firewall_db.get_firewall_policies(context, filters, fields) - - def update_firewall_policy(self, context, id, firewall_policy_delta): - old_firewall_policy = self.firewall_db.get_firewall_policy(context, id) - new_firewall_policy = copy.deepcopy(old_firewall_policy) - new_firewall_policy.update(firewall_policy_delta) - self.update_firewall_policy_precommit(context, old_firewall_policy, - new_firewall_policy) - firewall_policy = self.firewall_db.update_firewall_policy( - context, id, firewall_policy_delta) - self.update_firewall_policy_postcommit(context, old_firewall_policy, - firewall_policy) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(firewall_policy,)) - registry.publish( - const.FIREWALL_POLICY, events.AFTER_UPDATE, self, payload=payload) - return firewall_policy - - @abc.abstractmethod - def update_firewall_policy_precommit(self, context, old_firewall_policy, - new_firewall_policy): - pass - - @abc.abstractmethod - def update_firewall_policy_postcommit(self, context, old_firewall_policy, - new_firewall_policy): - pass - - # Firewall Rule - def create_firewall_rule(self, context, firewall_rule): - request_body = firewall_rule - with context.session.begin(subtransactions=True): - firewall_rule = self.firewall_db.create_firewall_rule( - context, firewall_rule) - self.create_firewall_rule_precommit(context, firewall_rule) - self.create_firewall_rule_postcommit(context, firewall_rule) - - payload = events.DBEventPayload(context=context, - resource_id=firewall_rule['id'], - request_body=request_body, - states=(firewall_rule,)) - registry.publish( - const.FIREWALL_RULE, events.AFTER_CREATE, self, payload=payload) - return firewall_rule - - @abc.abstractmethod - def create_firewall_rule_precommit(self, context, firewall_rule): - pass - - @abc.abstractmethod - def create_firewall_rule_postcommit(self, context, firewall_rule): - pass - - def delete_firewall_rule(self, context, id): - firewall_rule = self.firewall_db.get_firewall_rule(context, id) - self.delete_firewall_rule_precommit(context, firewall_rule) - self.firewall_db.delete_firewall_rule(context, id) - self.delete_firewall_rule_postcommit(context, firewall_rule) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(firewall_rule,)) - registry.publish( - const.FIREWALL_RULE, events.AFTER_DELETE, self, payload=payload) - - @abc.abstractmethod - def delete_firewall_rule_precommit(self, context, firewall_rule): - pass - - @abc.abstractmethod - def delete_firewall_rule_postcommit(self, context, firewall_rule): - pass - - def get_firewall_rule(self, context, id, fields=None): - return self.firewall_db.get_firewall_rule(context, id, fields) - - def get_firewall_rules(self, context, filters=None, fields=None): - return self.firewall_db.get_firewall_rules(context, filters, fields) - - def update_firewall_rule(self, context, id, firewall_rule_delta): - old_firewall_rule = self.firewall_db.get_firewall_rule(context, id) - new_firewall_rule = copy.deepcopy(old_firewall_rule) - new_firewall_rule.update(firewall_rule_delta) - self.update_firewall_rule_precommit(context, old_firewall_rule, - new_firewall_rule) - firewall_rule = self.firewall_db.update_firewall_rule( - context, id, firewall_rule_delta) - self.update_firewall_rule_postcommit(context, old_firewall_rule, - firewall_rule) - - payload = events.DBEventPayload(context=context, - resource_id=id, - states=(firewall_rule,)) - registry.publish( - const.FIREWALL_RULE, events.AFTER_UPDATE, self, payload=payload) - - return firewall_rule - - @abc.abstractmethod - def update_firewall_rule_precommit(self, context, old_firewall_rule, - new_firewall_rule): - pass - - @abc.abstractmethod - def update_firewall_rule_postcommit(self, context, old_firewall_rule, - new_firewall_rule): - pass - - def insert_rule(self, context, policy_id, rule_info): - self.insert_rule_precommit(context, policy_id, rule_info) - firewall_policy = self.firewall_db.insert_rule(context, policy_id, - rule_info) - self.insert_rule_postcommit(context, policy_id, rule_info) - payload = events.DBEventPayload(context=context, - resource_id=policy_id, - states=(firewall_policy,)) - registry.publish( - const.FIREWALL_POLICY, events.AFTER_UPDATE, self, payload=payload) - - return firewall_policy - - @abc.abstractmethod - def insert_rule_precommit(self, context, policy_id, rule_info): - pass - - @abc.abstractmethod - def insert_rule_postcommit(self, context, policy_id, rule_info): - pass - - def remove_rule(self, context, policy_id, rule_info): - self.remove_rule_precommit(context, policy_id, rule_info) - firewall_policy = self.firewall_db.remove_rule(context, policy_id, - rule_info) - self.remove_rule_postcommit(context, policy_id, rule_info) - payload = events.DBEventPayload(context=context, - resource_id=policy_id, - states=(firewall_policy,)) - - registry.publish( - const.FIREWALL_POLICY, events.AFTER_UPDATE, self, payload=payload) - return firewall_policy - - @abc.abstractmethod - def remove_rule_precommit(self, context, policy_id, rule_info): - pass - - @abc.abstractmethod - def remove_rule_postcommit(self, context, policy_id, rule_info): - pass - - -class FirewallDriverDB(FirewallDriverDBMixin): - """FirewallDriverDBMixin interface for driver with database. - - Each firewall backend driver that needs a database persistency should - inherit from this driver. - It can overload needed methods from the following pre/postcommit methods. - Any exception raised during a precommit method will result in not having - related records in the databases. - """ - - #Firewal Group - def create_firewall_group_precommit(self, context, firewall_group): - pass - - def create_firewall_group_postcommit(self, context, firewall_group): - pass - - def update_firewall_group_precommit(self, context, old_firewall_group, - new_firewall_group): - pass - - def update_firewall_group_postcommit(self, context, old_firewall_group, - new_firewall_group): - pass - - def delete_firewall_group_precommit(self, context, firewall_group): - pass - - def delete_firewall_group_postcommit(self, context, firewall_group): - pass - - #Firewall Policy - def create_firewall_policy_precommit(self, context, firewall_policy): - pass - - def create_firewall_policy_postcommit(self, context, firewall_policy): - pass - - def update_firewall_policy_precommit(self, context, old_firewall_policy, - new_firewall_policy): - pass - - def update_firewall_policy_postcommit(self, context, old_firewall_policy, - new_firewall_policy): - pass - - def delete_firewall_policy_precommit(self, context, firewall_policy): - pass - - def delete_firewall_policy_postcommit(self, context, firewall_policy): - pass - - #Firewall Rule - def create_firewall_rule_precommit(self, context, firewall_rule): - pass - - def create_firewall_rule_postcommit(self, context, firewall_rule): - pass - - def update_firewall_rule_precommit(self, context, old_firewall_rule, - new_firewall_rule): - pass - - def update_firewall_rule_postcommit(self, context, old_firewall_rule, - new_firewall_rule): - pass - - def delete_firewall_rule_precommit(self, context, firewall_rule): - pass - - def delete_firewall_rule_postcommit(self, context, firewall_rule): - pass - - def insert_rule_precommit(self, context, policy_id, rule_info): - pass - - def insert_rule_postcommit(self, context, policy_id, rule_info): - pass - - def remove_rule_precommit(self, context, policy_id, rule_info): - pass - - def remove_rule_postcommit(self, context, policy_id, rule_info): - pass - - -@six.add_metaclass(abc.ABCMeta) -class FirewallDriverRPCMixin(object): - """FirewallAgent interface for driver with rpc callback listener. - - Each firewall backend driver that needs a rpc callback listener should - inherit from this driver. - """ - - @abc.abstractmethod - def start_rpc_listener(self): - pass diff --git a/neutron_fwaas/services/logapi/__init__.py b/neutron_fwaas/services/logapi/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/agents/__init__.py b/neutron_fwaas/services/logapi/agents/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/agents/drivers/__init__.py b/neutron_fwaas/services/logapi/agents/drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/agents/drivers/iptables/__init__.py b/neutron_fwaas/services/logapi/agents/drivers/iptables/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/agents/drivers/iptables/driver.py b/neutron_fwaas/services/logapi/agents/drivers/iptables/driver.py deleted file mode 100644 index 417168358..000000000 --- a/neutron_fwaas/services/logapi/agents/drivers/iptables/driver.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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. - -from neutron.services.logapi.drivers import base -from neutron.services.logapi.drivers import manager -from neutron_lib.callbacks import resources -from neutron_lib.services.logapi import constants as log_const -from oslo_log import log as logging -from oslo_utils import importutils - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.services.logapi.common import fwg_callback -from neutron_fwaas.services.logapi.common import port_callback -from neutron_fwaas.services.logapi import constants as fw_const -from neutron_fwaas.services.logapi.rpc import log_server as rpc_server - -LOG = logging.getLogger(__name__) - -DRIVER = None - -SUPPORTED_LOGGING_TYPES = [fw_const.FIREWALL_GROUP] - - -class IptablesLoggingDriver(base.DriverBase): - - @staticmethod - def create(): - return IptablesLoggingDriver( - name='iptables', - vif_types=[], - vnic_types=[], - supported_logging_types=SUPPORTED_LOGGING_TYPES, - requires_rpc=True) - - -def register(): - """Register iptables-based logging driver for FWaaS.""" - - global DRIVER - if not DRIVER: - DRIVER = IptablesLoggingDriver.create() - # Register RPC methods - if DRIVER.requires_rpc: - rpc_methods = [ - {resources.PORT: rpc_server.get_fwg_log_info_for_port}, - {log_const.LOG_RESOURCE: rpc_server. - get_fwg_log_info_for_log_resources} - ] - DRIVER.register_rpc_methods(fw_const.FIREWALL_GROUP, rpc_methods) - - # Trigger fwg validator - importutils.import_module('neutron_fwaas.services.logapi.fwg_validate') - # Register resource callback handler - manager.register( - fwaas_constants.FIREWALL_GROUP, fwg_callback.FirewallGroupCallBack) - # Register resource callback handler for Neutron ports - manager.register(resources.PORT, port_callback.NeutronPortCallBack) - - LOG.debug('FWaaS L3 Logging driver based iptables registered') diff --git a/neutron_fwaas/services/logapi/agents/drivers/iptables/log.py b/neutron_fwaas/services/logapi/agents/drivers/iptables/log.py deleted file mode 100644 index 0ceeba409..000000000 --- a/neutron_fwaas/services/logapi/agents/drivers/iptables/log.py +++ /dev/null @@ -1,521 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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. - -from collections import defaultdict -import signal -import uuid - -from neutron.agent.linux import utils -from neutron.services.logapi.agent import log_extension as log_ext -from neutron_lib import constants -from neutron_lib.services.logapi import constants as log_const -from oslo_config import cfg -from oslo_log import formatters -from oslo_log import handlers -from oslo_log import log as logging - -from neutron_fwaas.privileged.netfilter_log import libnetfilter_log as libnflog - -LOG = logging.getLogger(__name__) - -UINT64_BITMASK = (1 << 64) - 1 - -MAX_INTF_NAME_LEN = 14 -INTERNAL_DEV_PREFIX = 'qr-' -SNAT_INT_DEV_PREFIX = 'sg-' -ROUTER_2_FIP_DEV_PREFIX = 'rfp-' - -IPTABLES_DIRECTION_DEVICE = { - constants.INGRESS_DIRECTION: 'i', - constants.EGRESS_DIRECTION: 'o' -} - - -def setup_logging(): - - log_file = cfg.CONF.network_log.local_output_log_base - if log_file: - from logging import handlers as watch_handler - log_file_handler = watch_handler.WatchedFileHandler(log_file) - log_file_handler.setLevel( - logging.DEBUG if cfg.CONF.debug else logging.INFO) - LOG.logger.addHandler(log_file_handler) - log_file_handler.setFormatter( - formatters.ContextFormatter( - fmt=cfg.CONF.logging_default_format_string, - datefmt=cfg.CONF.log_date_format)) - elif cfg.CONF.use_journal: - journal_handler = handlers.OSJournalHandler() - LOG.logger.addHandler(journal_handler) - else: - syslog_handler = handlers.OSSysLogHandler() - LOG.logger.addHandler(syslog_handler) - - -class LogPrefix(object): - """LogPrefix could be used as prefix in NFLOG rules - Each of a couple (port_id, event) has its own LogPrefix object - """ - - def __init__(self, port_id, event, project_id): - self.id = self._generate_prefix_id() - self.port_id = port_id - self.action = event - # A list of log objects that referenced to this prefix - self.log_object_refs = set() - self.project_id = project_id - - def __eq__(self, other): - return (self.id == other.id and - self.action == other.action and - self.port_id == other.port_id) - - def __hash__(self): - return hash(self.id) - - def _generate_prefix_id(self): - return uuid.uuid4().int & UINT64_BITMASK - - def add_log_obj_ref(self, log_id): - self.log_object_refs.add(log_id) - - def remove_log_obj_ref(self, log_id): - self.log_object_refs.discard(log_id) - - @property - def is_empty(self): - return not self.log_object_refs - - -class FWGPortLog(object): - """A firewall group port log per log_object""" - - def __init__(self, port_id, log_info): - self.port_id = port_id - self.log_id = log_info['id'] - self.project_id = log_info['project_id'] - self.event = log_info['event'] - - -class IptablesLoggingDriver(log_ext.LoggingDriver): - - SUPPORTED_LOGGING_TYPES = ['firewall_group'] - - def __init__(self, agent_api): - self.agent_api = agent_api - self.conf = cfg.CONF - self.rate_limit = self.conf.network_log.rate_limit - if self.rate_limit: - self.burst_limit = self.conf.network_log.burst_limit - self.ipt_mgr_list = defaultdict(dict) - # A list of fwg port logs that are being logged - self.fwg_port_logs = defaultdict(set) - # A list of prefixes that are being used in iptables - self.prefixes_table = {} - self.cleanup_table = defaultdict(set) - # Handle NFLOG processing - self.nflog_proc_map = {} - # A list of unused ports - self.unused_port_ids = set() - - def initialize(self, resource_rpc, **kwargs): - self.resource_rpc = resource_rpc - setup_logging() - self.log_app = libnflog.NFLogApp() - self.log_app.register_packet_handler(self.log_packet) - self.log_app.start() - - def log_packet(self, ev): - prefix = ev['prefix'] - pkt = ev['msg'] - prefix_entry = self._get_prefix_by_id(prefix) - if prefix_entry: - logs_id = [str(id) for id in prefix_entry.log_object_refs] - LOG.info("action=%s, project_id=%s, log_resource_ids=%s, port=%s, " - "pkt=%s", prefix_entry.action, - prefix_entry.project_id, logs_id, - prefix_entry.port_id, pkt) - else: - LOG.warning("Unknown cookie packet_in pkt=%s", pkt) - return 0 - - def _get_prefix(self, port_id, action): - if port_id in self.prefixes_table: - for prefix in self.prefixes_table[port_id]: - if prefix.action == action: - return prefix - return None - - def _get_prefix_by_id(self, prefix_id): - for port, prefixes in self.prefixes_table.items(): - for prefix in prefixes: - if str(prefix.id) == str(prefix_id): - return prefix - return None - - def _add_to_cleanup(self, port_id, prefix_id): - if port_id not in self.cleanup_table: - self.cleanup_table[port_id] = set() - self.cleanup_table[port_id].add(prefix_id) - - def _add_to_prefixes_table(self, port_id, prefix): - if port_id not in self.prefixes_table: - self.prefixes_table[port_id] = [] - self.prefixes_table[port_id].append(prefix) - - def _cleanup_nflog_process(self, router_info): - LOG.debug("Delete router_info %s", router_info) - if router_info in self.nflog_proc_map: - pid = self.nflog_proc_map[router_info] - try: - # A process started by a root helper will be running as - # root and need to be killed via the same helper. - LOG.debug('Trying to kill NFLOG process %d', pid) - utils.kill_process(pid, signal.SIGKILL, run_as_root=True) - del self.nflog_proc_map[router_info] - except Exception: - LOG.exception( - 'An error occurred while killing process %d', pid) - - def _cleanup_prefix_by_router(self, router_id): - - ipt_mgr_per_port = set() - for port_id in self.ipt_mgr_list[router_id]: - ipt_mgr = self.ipt_mgr_list[router_id][port_id] - ipt_mgr_per_port.add(ipt_mgr) - # Cleanup prefix - if port_id in self.prefixes_table: - for prefix in self.prefixes_table[port_id]: - self._add_to_cleanup(port_id, prefix.id) - del self.prefixes_table[port_id] - self.unused_port_ids.add(port_id) - return ipt_mgr_per_port - - def _cleanup_unused_ipt_mgrs(self): - - need_cleanup = set() - for port_id in self.unused_port_ids: - for router_id in self.ipt_mgr_list: - if port_id in self.ipt_mgr_list[router_id]: - del self.ipt_mgr_list[router_id][port_id] - if not self.ipt_mgr_list[router_id]: - need_cleanup.add(router_id) - - for router_id in need_cleanup: - del self.ipt_mgr_list[router_id] - - self.unused_port_ids.clear() - - def start_logging(self, context, **kwargs): - LOG.debug("Start logging: %s", str(kwargs)) - - for resource_type in self.SUPPORTED_LOGGING_TYPES: - router_info = kwargs.get('router_info') - if router_info: - # Handle router updated or L3 agent restart - router_id = router_info.router_id - internal_ports = router_info.internal_ports - self._create_firewall_group_log(context, resource_type, - ports=internal_ports, - router_id=router_id) - - # Start libnetfilter_log after router starting up - pid = libnflog.run_nflog(router_info.ns_name) - LOG.debug("NFLOG process ID %s for router %s has started", - pid, router_info.router_id) - self.nflog_proc_map[router_id] = pid - else: - # Handle the log request - self._create_firewall_group_log(context, resource_type, - **kwargs) - - def stop_logging(self, context, **kwargs): - LOG.debug("Stop logging: %s", str(kwargs)) - - # Delete router - router_info = kwargs.get('router_info') - if router_info: - self._cleanup_nflog_process(router_info) - - if kwargs.get('log_resources'): - # Handle incoming log request - self._delete_firewall_group_log(context, **kwargs) - - def _create_firewall_group_log(self, context, resource_type, **kwargs): - ports = kwargs.get('ports') - log_resources = kwargs.get('log_resources') - applied_ipt_mgrs = set() - logs_info = [] - - port_ids = [] - # Get log objects from database via RPC - if ports: - port_ids = [port['id'] for port in ports] - logs_info = self.resource_rpc. \ - get_sg_log_info_for_port(context, resource_type, - port_id=port_ids) - elif log_resources: - logs_info = self.resource_rpc.\ - get_sg_log_info_for_log_resources(context, resource_type, - log_resources=log_resources) - # Handle logs_info - for log_info in logs_info: - log_id = log_info['id'] - old_fwg_port_logs = self.fwg_port_logs.get(log_id, []) - new_ports_log = log_info.get('ports_log') - self.fwg_port_logs[log_id] = set() - for port in new_ports_log: - self._add_fwg_port_log(log_id, port, log_info) - - for port in old_fwg_port_logs: - if port.port_id not in new_ports_log: - # Remove port not bound by log_id - self._cleanup_prefixes_table(port.port_id, log_id) - - for fwg_port_log in self.fwg_port_logs[log_id]: - self._setup_chains(applied_ipt_mgrs, fwg_port_log) - - router_id = kwargs.get("router_id") - if router_id: - if not port_ids: - ipt_mgrs = self._cleanup_prefix_by_router(router_id) - applied_ipt_mgrs.update(ipt_mgrs) - - for port_id in port_ids: - try: - ipt_mgr = self.ipt_mgr_list[router_id][port_id] - applied_ipt_mgrs.add(ipt_mgr) - except KeyError: - pass - - # Clean up NFLOG rules - self._cleanup_nflog_rules(applied_ipt_mgrs) - - # Apply NFLOG rules into iptables managers - for ipt_mgr in applied_ipt_mgrs: - LOG.debug('Apply NFLOG rules in namespace %s', ipt_mgr.namespace) - ipt_mgr.defer_apply_off() - - # Clean up unused iptables managers from ports - self._cleanup_unused_ipt_mgrs() - - def _cleanup_prefixes_table(self, port_id, log_id): - - # Each a port has at most 2 prefix - for index in [1, 0]: - try: - prefix = self.prefixes_table[port_id][index] - prefix.remove_log_obj_ref(log_id) - if prefix.is_empty: - self._add_to_cleanup(port_id, prefix.id) - self.prefixes_table[port_id].remove(prefix) - except Exception: - pass - - if port_id in self.prefixes_table: - if not self.prefixes_table[port_id]: - del self.prefixes_table[port_id] - self.unused_port_ids.add(port_id) - - def _cleanup_nflog_rules(self, applied_ipt_mgrs): - for port_id, prefix_ids in self.cleanup_table.items(): - ipt_mgr = self._get_ipt_mgr_by_port(port_id) - for prefix_id in prefix_ids: - self._clear_rules_from_tag_v4v6(ipt_mgr, tag=prefix_id) - applied_ipt_mgrs.add(ipt_mgr) - self.cleanup_table.clear() - - def _delete_firewall_group_log(self, context, **kwargs): - log_resources = kwargs.get('log_resources') - applied_ipt_mgrs = set() - - for log_resource in log_resources: - log_id = log_resource.get('id') - fwg_port_logs = self.fwg_port_logs[log_id] - for port in fwg_port_logs: - self._cleanup_prefixes_table(port.port_id, log_id) - del self.fwg_port_logs[log_id] - - # Clean NFLOG rules: - self._cleanup_nflog_rules(applied_ipt_mgrs) - - # Apply NFLOG rules into iptables managers - for ipt_mgr in applied_ipt_mgrs: - ipt_mgr.defer_apply_off() - - # Clean up unused iptables managers - self._cleanup_unused_ipt_mgrs() - - def _get_if_prefix(self, agent_mode, router): - """Get the if prefix from router""" - if not router.router.get('distributed'): - return INTERNAL_DEV_PREFIX - - if agent_mode == 'dvr_snat': - return SNAT_INT_DEV_PREFIX - - if router.rtr_fip_connect: - return ROUTER_2_FIP_DEV_PREFIX - - def _get_intf_name(self, port_id): - agent_mode = self.conf.agent_mode - router = self.agent_api.get_router_hosting_port(port_id) - if_prefix = self._get_if_prefix(agent_mode, router) - return (if_prefix + port_id)[:constants.LINUX_DEV_LEN] - - def _get_ipt_mgr_by_port(self, port_id): - - router = self.agent_api.get_router_hosting_port(port_id) - if router: - try: - ipt_mgr = self.ipt_mgr_list[router.router_id][port_id] - return ipt_mgr - except KeyError: - pass - - ipt_mgr = router.iptables_manager - self.ipt_mgr_list[router.router_id][port_id] = ipt_mgr - return ipt_mgr - - for router_id in self.ipt_mgr_list: - if port_id in self.ipt_mgr_list[router_id]: - return self.ipt_mgr_list[router_id][port_id] - - def _setup_chains(self, applied_ipt_mgrs, fwg_port_log): - # Add NFLOG rules by log event - event = fwg_port_log.event - if event in [log_const.ACCEPT_EVENT, log_const.ALL_EVENT]: - self._add_nflog_rules_accepted(applied_ipt_mgrs, fwg_port_log) - if event in [log_const.DROP_EVENT, log_const.ALL_EVENT]: - self._add_log_rules_dropped(applied_ipt_mgrs, fwg_port_log) - - def _add_nflog_rules_accepted(self, applied_ipt_mgrs, fwg_port_log): - """Add NFLOG rules to the accepted chain into iptables""" - action = log_const.ACCEPT_EVENT - port_id = fwg_port_log.port_id - prefix = self._get_prefix(port_id, action) - if not prefix: - # Generate a new prefix from port and action - project_id = fwg_port_log.project_id - prefix = LogPrefix(port_id, action, project_id) - self._add_to_prefixes_table(port_id, prefix) - - # Get iptables manager from router port - ipt_mgr = self._get_ipt_mgr_by_port(port_id) - if ipt_mgr: - applied_ipt_mgrs.add(ipt_mgr) - - device = self._get_intf_name(port_id) - - # Add the NFLOG rules to the dropped chain into iptables - ipv4_rules, ipv6_rules = \ - self._generate_nflog_rules_v4v6(device, prefix=prefix.id) - self._add_rules_to_chain_v4v6(ipt_mgr, - 'accepted', ipv4_rules, ipv6_rules, - wrap=True, top=True, tag=prefix.id) - - prefix.add_log_obj_ref(fwg_port_log.log_id) - - def _add_log_rules_dropped(self, applied_ipt_mgrs, fwg_port_log): - """Add NFLOG rules to the dropped chain into iptables""" - - action = log_const.DROP_EVENT - port_id = fwg_port_log.port_id - prefix = self._get_prefix(port_id, action) - if not prefix: - # Generate a new prefix from port and action - project_id = fwg_port_log.project_id - prefix = LogPrefix(port_id, action, project_id) - self._add_to_prefixes_table(port_id, prefix) - device = self._get_intf_name(port_id) - - # Get iptables manager from router port - ipt_mgr = self._get_ipt_mgr_by_port(port_id) - if ipt_mgr: - applied_ipt_mgrs.add(ipt_mgr) - - # Add the NFLOG rules to the dropped chain into iptables - ipv4_rules, ipv6_rules = \ - self._generate_nflog_rules_v4v6(device, prefix=prefix.id) - self._add_rules_to_chain_v4v6(ipt_mgr, - 'dropped', ipv4_rules, ipv6_rules, - wrap=True, top=True, tag=prefix.id) - # Add the NFLOG rules to the rejected chain in iptables - self._add_rules_to_chain_v4v6(ipt_mgr, - 'rejected', ipv4_rules, ipv6_rules, - wrap=True, top=True, tag=prefix.id) - prefix.add_log_obj_ref(fwg_port_log.log_id) - - def _add_rules_to_chain_v4v6(self, ipt_mgr, chain_name, v4_rules, v6_rules, - wrap=False, comment=None, - top=False, tag=None): - """Add rules to filter table in iptables and ip6tables""" - - for rule in v4_rules: - ipt_mgr.ipv4['filter'].add_rule(chain_name, rule, wrap=wrap, - comment=comment, top=top, tag=tag) - for rule in v6_rules: - ipt_mgr.ipv6['filter'].add_rule(chain_name, rule, wrap=wrap, - comment=comment, top=top, tag=tag) - - def _add_fwg_port_log(self, log_id, port_id, log_info): - - self.fwg_port_logs[log_id].add(FWGPortLog(port_id, log_info)) - - # Add log ID into the corresponding LogPrefix object - if log_info['event'] == log_const.ALL_EVENT: - events = [log_const.ACCEPT_EVENT, log_const.DROP_EVENT] - else: - events = [log_info['event']] - for event in events: - prefix = self._get_prefix(port_id, event) - if prefix: - prefix.add_log_obj_ref(log_id) - - def _generate_nflog_rules_v4v6(self, device, prefix): - iptables_rules = [] - added_rules = set() - for direction in constants.VALID_DIRECTIONS: - args = self._generate_iptables_args(direction, device, prefix) - rule = ' '.join(args) - if rule in added_rules: - # Since these rules are already added to iptables, - # so we ignore them here - continue - added_rules.add(rule) - iptables_rules.append(rule) - LOG.debug("iptables-nflog-rules %r", iptables_rules) - return iptables_rules, iptables_rules - - def _generate_iptables_args(self, direction, device, prefix=None): - - direction_config = ['-%s %s' % - (IPTABLES_DIRECTION_DEVICE[direction], device)] - match_rule = [] - if self.rate_limit: - match_rule += ['-m', 'limit', '--limit', '%s/s' % self.rate_limit] - if self.burst_limit: - match_rule += ['--limit-burst %s' % self.burst_limit] - target = ['-j', 'NFLOG'] - if prefix: - target += ['--nflog-prefix', '%s' % prefix] - - args = direction_config + match_rule + target - return args - - def _clear_rules_from_tag_v4v6(self, ipt_mgt, tag): - """Remove rules from filter table in iptables and ip6tables""" - ipt_mgt.ipv4['filter'].clear_rules_by_tag(tag) - ipt_mgt.ipv6['filter'].clear_rules_by_tag(tag) diff --git a/neutron_fwaas/services/logapi/agents/l3/__init__.py b/neutron_fwaas/services/logapi/agents/l3/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/agents/l3/fwg_log.py b/neutron_fwaas/services/logapi/agents/l3/fwg_log.py deleted file mode 100644 index eae0ee288..000000000 --- a/neutron_fwaas/services/logapi/agents/l3/fwg_log.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.services.logapi.agent.l3 import base -from neutron.services.logapi.agent import log_extension as log_ext -from neutron.services.logapi.rpc import agent as agent_rpc -from neutron_lib.agent import l3_extension - -#TODO(annp) move to neutron-lib -FIREWALL_LOG_DRIVER_NAME = 'fwaas_v2_log' - - -class FWaaSL3LoggingExtension(base.L3LoggingExtensionBase, - l3_extension.L3AgentExtension): - - def initialize(self, connection, driver_type): - """Initialize L3 logging agent extension""" - - fw_log_cls = self._load_driver_cls( - log_ext.LOGGING_DRIVERS_NAMESPACE, FIREWALL_LOG_DRIVER_NAME) - self.log_driver = fw_log_cls(self.agent_api) - self.resource_rpc = agent_rpc.LoggingApiStub() - self._register_rpc_consumers() - self.log_driver.initialize(self.resource_rpc) diff --git a/neutron_fwaas/services/logapi/common/__init__.py b/neutron_fwaas/services/logapi/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/common/fwg_callback.py b/neutron_fwaas/services/logapi/common/fwg_callback.py deleted file mode 100644 index f7a463345..000000000 --- a/neutron_fwaas/services/logapi/common/fwg_callback.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.objects import ports as port_objects -from neutron.services.logapi.drivers import manager -from neutron_lib.callbacks import events -from neutron_lib import constants as nl_const -from neutron_lib.services.logapi import constants as log_const - -from neutron_fwaas.services.logapi.common import log_db_api - - -class FirewallGroupCallBack(manager.ResourceCallBackBase): - - def handle_event(self, resource, event, trigger, **kwargs): - payload = kwargs.get('payload') - context = payload.context - ports_delta = [] - if event == events.AFTER_CREATE: - # Update log when a new firewall group is created with ports - ports_delta = payload.latest_state['ports'] - - elif event == events.AFTER_UPDATE: - old_ports = payload.states[0]['ports'] - new_ports = payload.states[1]['ports'] - - # Check whether port is updated from firewall group or not - ports_delta = \ - set(new_ports).symmetric_difference(set(old_ports)) - - if self.need_to_notify(context, ports_delta): - self.trigger_logging(context, payload.resource_id, ports_delta) - - def trigger_logging(self, context, fwg_id, ports_delta): - log_resources = log_db_api.get_logs_for_fwg( - context, fwg_id, ports_delta) - if log_resources: - self.resource_push_api( - log_const.RESOURCE_UPDATE, context, log_resources) - - def need_to_notify(self, context, ports): - notify = False - for port_id in ports: - port = port_objects.Port.get_object(context, id=port_id) - device_owner = port.get('device_owner', '') - if device_owner in nl_const.ROUTER_INTERFACE_OWNERS: - notify = True - break - return notify diff --git a/neutron_fwaas/services/logapi/common/log_db_api.py b/neutron_fwaas/services/logapi/common/log_db_api.py deleted file mode 100644 index d188413c3..000000000 --- a/neutron_fwaas/services/logapi/common/log_db_api.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.objects.logapi import logging_resource as log_object -from neutron.objects import ports as port_objects -from neutron_lib import constants as nl_const -from neutron_lib.plugins import directory - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.services.logapi import constants - -fw_plugin_db = None - - -# TODO(longkb): We will support L2 port. Currently, this method returns only -# router ports. -def _get_ports_being_logged(context, log_obj): - """Return a list of ports being logged with a given log_obj""" - - target_id = log_obj['target_id'] - resource_id = log_obj['resource_id'] - - # If 'target_id' (port_id) is specified in a log_obj - if target_id: - fwg_id = fw_plugin_db.get_fwg_attached_to_port(context, target_id) - if fwg_id: - port_ids = [target_id] - else: - port_ids = [] - # If 'resource_id' (fwg_id) is specified in a log_obj - elif resource_id: - port_ids = \ - fw_plugin_db.get_ports_in_firewall_group(context, resource_id) - # Both 'resource_id' and 'target_id' aren't specified in a log_resource - else: - tenant_id = log_obj['project_id'] - port_ids = fw_plugin_db.get_fwg_ports_in_tenant(context, tenant_id) - - filtered_port_ids = [] - for port_id in port_ids: - port = port_objects.Port.get_object(context, id=port_id) - device_owner = port.get('device_owner', '') - # TODO(longkb): L2 ports will be supported in the future - # Check whether a port is router port or not. - if device_owner in nl_const.ROUTER_INTERFACE_OWNERS: - # Checking port status - if port.get('status') == nl_const.PORT_STATUS_ACTIVE: - # Check whether a port is attached to firewall group or not - fwg = fw_plugin_db.get_fwg_attached_to_port(context, port_id) - if fwg: - filtered_port_ids.append(port_id) - return filtered_port_ids - - -def _make_log_info_dict(log_obj, port_ids): - log_info = { - 'id': log_obj['id'], - 'ports_log': port_ids, - 'event': log_obj['event'], - 'project_id': log_obj['project_id'] - } - return log_info - - -def get_logs_for_port(context, port_id): - """Return a list of log_resources bound to a given port_id""" - - global fw_plugin_db - if not fw_plugin_db: - fw_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - - # NOTE(longkb): check whether fw plugin was loaded or not. - if not fw_plugin: - return [] - fw_plugin_db = fw_plugin.driver.firewall_db - - logs_bounded = [] - port = port_objects.Port.get_object(context, id=port_id) - - if not port: - return logs_bounded - # Ignore if a given port_id is not belong to router port - device_owner = port.get('device_owner', '') - if device_owner not in nl_const.ROUTER_INTERFACE_OWNERS: - return logs_bounded - - # Ignore if a given port does not attach to any fwg - fwg_id = fw_plugin_db.get_fwg_attached_to_port(context, port_id) - if not fwg_id: - return logs_bounded - - project_id = port['project_id'] - log_objs = log_object.Log.get_objects( - context, project_id=project_id, - resource_type=constants.FIREWALL_GROUP, enabled=True) - - for log_obj in log_objs: - if log_obj.resource_id == fwg_id: - logs_bounded.append(log_obj) - elif log_obj.target_id == port['id']: - logs_bounded.append(log_obj) - elif not log_obj.target_id and not log_obj.resource_id: - logs_bounded.append(log_obj) - return logs_bounded - - -def get_logs_for_fwg(context, fwg_id, ports_delta): - """Return a list of log_resources bound to a firewall group""" - - global fw_plugin_db - if not fw_plugin_db: - fw_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - - # NOTE(longkb): check whether fw plugin was loaded or not. - if not fw_plugin: - return [] - fw_plugin_db = fw_plugin.driver.firewall_db - - project_id = context.tenant_id - log_objs = log_object.Log.get_objects( - context, project_id=project_id, - resource_type=constants.FIREWALL_GROUP, enabled=True) - - log_resources = [] - for log_obj in log_objs: - if log_obj.resource_id == fwg_id: - log_resources.append(log_obj) - elif log_obj.target_id in ports_delta: - log_resources.append(log_obj) - elif not log_obj.resource_id and not log_obj.target_id: - log_resources.append(log_obj) - return log_resources - - -def get_fwg_log_info_for_port(context, port_ids): - """Return a list of firewall group log info for a given port - The list has format as below: - - [ - { - 'event': u'ALL', - 'id': '733e0499-e69e-4106-a84a-635fbc5fbbc0', - 'project_id': u'46f70361-ba71-4bd0-9769-3573fd227c4b', - 'ports_log': - [ - port1_id, - port2_id, - ] - }, - ] - :param context: current running context information - :param port_ids: list of ports which needed to get firewall group log info - - """ - - global fw_plugin_db - if not fw_plugin_db: - fw_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - - # NOTE(longkb): check whether fw plugin was loaded or not. - if not fw_plugin: - return [] - fw_plugin_db = fw_plugin.driver.firewall_db - - logs_info = [] - log_bounds = set() - for port_id in port_ids: - log_objs = get_logs_for_port(context, port_id) - if log_objs: - log_bounds |= set(log_objs) - if log_bounds: - for log_resource in log_bounds: - port_ids = _get_ports_being_logged(context, log_resource) - log_info = _make_log_info_dict(log_resource, port_ids) - logs_info.append(log_info) - return logs_info - - -def get_fwg_log_info_for_log_resources(context, log_resources): - """Return a list of firewall group log info for list of log_resources - The list has format as below: - - [ - { - 'event': u'ALL', - 'id': '733e0499-e69e-4106-a84a-635fbc5fbbc0', - 'project_id': u'46f70361-ba71-4bd0-9769-3573fd227c4b', - 'ports_log': - [ - port1_id, - port2_id, - ] - }, - ] - :param context: current running context information - :param log_resources: list of log_resources, which needed to get firewall - groups log info - - """ - - global fw_plugin_db - if not fw_plugin_db: - fw_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - - # NOTE(longkb): check whether fw plugin was loaded or not. - if not fw_plugin: - return [] - fw_plugin_db = fw_plugin.driver.firewall_db - - logs_info = [] - for log_resource in log_resources: - ports_id = _get_ports_being_logged(context, log_resource) - log_info = _make_log_info_dict(log_resource, ports_id) - logs_info.append(log_info) - - return logs_info diff --git a/neutron_fwaas/services/logapi/common/port_callback.py b/neutron_fwaas/services/logapi/common/port_callback.py deleted file mode 100644 index c609a7bae..000000000 --- a/neutron_fwaas/services/logapi/common/port_callback.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.services.logapi.drivers import manager -from neutron_lib.callbacks import events -from neutron_lib import constants as nl_const -from neutron_lib.services.logapi import constants as log_const - -from neutron_fwaas.services.logapi.common import log_db_api - - -class NeutronPortCallBack(manager.ResourceCallBackBase): - - def handle_event(self, resource, event, trigger, **kwargs): - if event == events.AFTER_UPDATE: - context = kwargs.get('context') - original_port = kwargs.get('original_port') - port = kwargs.get('port') - - if port['device_owner'] in nl_const.ROUTER_INTERFACE_OWNERS: - if original_port['status'] != port['status']: - self.trigger_logging(context, port) - - def trigger_logging(self, context, port): - log_resources = log_db_api.get_logs_for_port(context, port['id']) - if log_resources: - self.resource_push_api( - log_const.RESOURCE_UPDATE, context, log_resources) diff --git a/neutron_fwaas/services/logapi/constants.py b/neutron_fwaas/services/logapi/constants.py deleted file mode 100644 index fc82767b0..000000000 --- a/neutron_fwaas/services/logapi/constants.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - - -# Firewall group logging resource type -FIREWALL_GROUP = 'firewall_group' - -# Target logging resource type -TARGET_RESOURCE = 'port which is associated with the firewall group' diff --git a/neutron_fwaas/services/logapi/exceptions.py b/neutron_fwaas/services/logapi/exceptions.py deleted file mode 100644 index c7af753c0..000000000 --- a/neutron_fwaas/services/logapi/exceptions.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron._i18n import _ -from neutron_lib import exceptions as n_exc - -# TODO(annp or longkb): move to neutron-lib - - -class FWGIsNotReadyForLogging(n_exc.InvalidInput): - message = _("Firewall group %(fwg_id)s is not ready for logging " - "because of %(fwg_status)s status.") - - -class TargetResourceNotAssociated(n_exc.InvalidInput): - message = _("Target resource %(target_id)s is not associated with " - "any firewall group.") - - -class PortIsNotReadyForLogging(n_exc.InvalidInput): - message = _("Target resource %(target_id)s is not ready for logging " - "because of %(port_status)s status.") diff --git a/neutron_fwaas/services/logapi/fwg_validate.py b/neutron_fwaas/services/logapi/fwg_validate.py deleted file mode 100644 index ea3f3b0e0..000000000 --- a/neutron_fwaas/services/logapi/fwg_validate.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.objects import ports -from neutron.services.logapi.common import exceptions as log_exc -from neutron.services.logapi.common import validators -from neutron_lib import constants as nl_const -from neutron_lib.plugins import directory -from sqlalchemy.orm import exc as orm_exc - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.services.logapi import constants as log_const -from neutron_fwaas.services.logapi import exceptions as fwg_log_exc - -fwg_plugin = None - - -def _check_fwg(context, fwg_id): - try: - fwg = fwg_plugin.get_firewall_group(context, id=fwg_id) - except orm_exc.NoResultFound: - raise log_exc.ResourceNotFound(resource_id=fwg_id) - - if fwg['status'] != nl_const.ACTIVE: - raise fwg_log_exc.FWGIsNotReadyForLogging( - fwg_id=fwg_id, fwg_status=fwg['status']) - - -def _check_fwg_port(context, port_id): - - # Checking port exists - port = ports.Port.get_object(context, id=port_id) - if not port: - raise log_exc.TargetResourceNotFound(target_id=port_id) - - device_owner = port.get('device_owner', '') - # Checking supported firewall group logging for vm port - if device_owner.startswith(nl_const.DEVICE_OWNER_COMPUTE_PREFIX): - if not validators.validate_log_type_for_port( - log_const.FIREWALL_GROUP, port): - raise log_exc.LoggingTypeNotSupported( - log_type=log_const.FIREWALL_GROUP, - port_id=port_id) - # Checking supported firewall group for router interface, DVR interface, - # and HA replicated interface - elif device_owner not in nl_const.ROUTER_INTERFACE_OWNERS: - raise log_exc.LoggingTypeNotSupported( - log_type=log_const.FIREWALL_GROUP, port_id=port_id) - - # Checking port status - port_status = port.get('status') - if port_status != nl_const.PORT_STATUS_ACTIVE: - raise fwg_log_exc.PortIsNotReadyForLogging(target_id=port_id, - port_status=port_status) - - # Checking whether router port or vm port binding with any firewall group - fwg_id = fwg_plugin.driver.firewall_db.get_fwg_attached_to_port( - context, port_id=port_id) - - if not fwg_id: - raise fwg_log_exc.TargetResourceNotAssociated(target_id=port_id) - - fwg = fwg_plugin.get_firewall_group(context, id=fwg_id) - - if fwg['status'] != nl_const.ACTIVE: - raise fwg_log_exc.FWGIsNotReadyForLogging(fwg_id=fwg_id, - fwg_status=fwg['status']) - - -def _check_target_resource_bound_fwg(context, fwg_id, target_id): - ports = fwg_plugin.driver.firewall_db.get_ports_in_firewall_group( - context=context, firewall_group_id=fwg_id) - if target_id not in ports: - raise log_exc.InvalidResourceConstraint( - resource=log_const.FIREWALL_GROUP, - resource_id=fwg_id, - target_resource=log_const.TARGET_RESOURCE, - target_id=target_id) - - -@validators.ResourceValidateRequest.register(log_const.FIREWALL_GROUP) -def validate_firewall_group_request(context, log_data): - """Validate a log request - - This method validates log request is satisfied or not. - - A ResourceNotFound will be raised if resource_id in log_data not exists or - a TargetResourceNotFound will be raised if target_id in log_data not - exists. Beside, FWGIsNotReadyForLogging will be raised in the case of - queried firewall group is not in ACTIVE state. PortIsNotReadyForLogging - exception will be raised if port is not in ACTIVE status. Besides, - TargetResourceNotAssociated exception will be raised if a given port does - not have any firewall group attach to. This method will also raise a - LoggingTypeNotSupported, if there is no log_driver supporting for - resource_type in log_data. - - In addition, if log_data specify both resource_id and target_id. A - InvalidResourceConstraint will be raised if there is no constraint between - resource_id and target_id. - - """ - - global fwg_plugin - if not fwg_plugin: - fwg_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - resource_id = log_data.get('resource_id') - target_id = log_data.get('target_id') - if resource_id and target_id: - _check_target_resource_bound_fwg(context, resource_id, target_id) - if resource_id: - _check_fwg(context, resource_id) - if target_id: - _check_fwg_port(context, target_id) diff --git a/neutron_fwaas/services/logapi/rpc/__init__.py b/neutron_fwaas/services/logapi/rpc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/services/logapi/rpc/log_server.py b/neutron_fwaas/services/logapi/rpc/log_server.py deleted file mode 100644 index ca5e2e244..000000000 --- a/neutron_fwaas/services/logapi/rpc/log_server.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2018 Fujitsu Limited -# 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. - -from neutron_fwaas.services.logapi.common import log_db_api - - -# Use this when register log driver with -# "register_rpc_methods" function -def get_fwg_log_info_for_port(context, port_id): - return log_db_api.get_fwg_log_info_for_port(context, port_id) - - -# Use this when register log driver with -# "register_rpc_methods" function -def get_fwg_log_info_for_log_resources(context, log_resources): - return log_db_api.get_fwg_log_info_for_log_resources( - context, - log_resources) diff --git a/neutron_fwaas/tests/__init__.py b/neutron_fwaas/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/base.py b/neutron_fwaas/tests/base.py deleted file mode 100644 index 10b2490b9..000000000 --- a/neutron_fwaas/tests/base.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2014 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. -# - -from neutron.tests import base as n_base - - -class BaseTestCase(n_base.BaseTestCase): - pass diff --git a/neutron_fwaas/tests/contrib/README b/neutron_fwaas/tests/contrib/README deleted file mode 100644 index a73d75af9..000000000 --- a/neutron_fwaas/tests/contrib/README +++ /dev/null @@ -1,3 +0,0 @@ -The files in this directory are intended for use by the -Neutron infra jobs that run the various functional test -suites in the gate. diff --git a/neutron_fwaas/tests/contrib/filters.template b/neutron_fwaas/tests/contrib/filters.template deleted file mode 100644 index 78189d760..000000000 --- a/neutron_fwaas/tests/contrib/filters.template +++ /dev/null @@ -1,20 +0,0 @@ -# neutron-rootwrap command filters to support functional testing. It -# is NOT intended to be used outside of a test environment. -# -# This file should be owned by (and only-writeable by) the root user - -[Filters] -# '$BASE_PATH' is intended to be replaced with the expected tox path -# (e.g. /opt/stack/new/neutron/.tox/dsvm-functional) by the neutron -# functional jenkins job. This ensures that tests can kill the -# processes that they launch with their containing tox environment's -# python. -kill_tox_python: KillFilter, root, $BASE_PATH/bin/python, -9 - -# enable ping from namespace -ping_filter: CommandFilter, ping, root - -# enable curl from namespace -curl_filter: CommandFilter, curl, root -tee_filter: CommandFilter, tee, root -tee_kill: KillFilter, root, tee, -9 diff --git a/neutron_fwaas/tests/contrib/functional-testing.filters b/neutron_fwaas/tests/contrib/functional-testing.filters deleted file mode 100644 index 23fbc9b73..000000000 --- a/neutron_fwaas/tests/contrib/functional-testing.filters +++ /dev/null @@ -1,10 +0,0 @@ -# neutron-rootwrap command filters to support functional testing. It -# is NOT intended to be used outside of a test environment. -# -# This file should be owned by (and only-writeable by) the root user - -[Filters] -# enable ping from namespace -ping_filter: CommandFilter, ping, root -ping6_filter: CommandFilter, ping6, root -ping_kill: KillFilter, root, ping, -2 diff --git a/neutron_fwaas/tests/contrib/gate_hook.sh b/neutron_fwaas/tests/contrib/gate_hook.sh deleted file mode 100644 index 4ce09dd83..000000000 --- a/neutron_fwaas/tests/contrib/gate_hook.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -set -ex - -VENV=${1:-"dsvm-functional"} - -GATE_DEST=$BASE/new -FWAAS_PATH=$GATE_DEST/neutron-fwaas -DEVSTACK_PATH=$GATE_DEST/devstack - - -case $VENV in - "dsvm-functional"|"dsvm-fullstack") - # The following need to be set before sourcing - # configure_for_fwaas_func_testing. - GATE_STACK_USER=stack - PROJECT_NAME=neutron-fwaas - IS_GATE=True - - source $FWAAS_PATH/tools/configure_for_fwaas_func_testing.sh - - configure_host_for_func_testing - if is_ubuntu || is_suse; then - install_package libnetfilter-log1 - elif is_fedora; then - install_package libnetfilter-log - fi - ;; -esac diff --git a/neutron_fwaas/tests/contrib/gate_hook_tempest.sh b/neutron_fwaas/tests/contrib/gate_hook_tempest.sh deleted file mode 100755 index 99f1afe35..000000000 --- a/neutron_fwaas/tests/contrib/gate_hook_tempest.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -ex - -FWAAS_VERSION=$1 - -GATE_DEST=$BASE/new -GATE_HOOKS=$GATE_DEST/neutron-fwaas/neutron_fwaas/tests/contrib/hooks -DEVSTACK_PATH=$GATE_DEST/devstack -LOCAL_CONF=$DEVSTACK_PATH/late-local.conf -DSCONF=/tmp/devstack-tools/bin/dsconf - -# Install devstack-tools used to produce local.conf; we can't rely on -# test-requirements.txt because the gate hook is triggered before neutron-fwaas -# is installed -sudo -H pip install virtualenv -virtualenv /tmp/devstack-tools -/tmp/devstack-tools/bin/pip install -U devstack-tools==0.4.0 - -# Inject config from hook into localrc -function load_rc_hook { - local hook="$1" - local tmpfile - local config - tmpfile=$(tempfile) - config=$(cat $GATE_HOOKS/$hook) - echo "[[local|localrc]]" > $tmpfile - $DSCONF setlc_raw $tmpfile "$config" - $DSCONF merge_lc $LOCAL_CONF $tmpfile - rm -f $tmpfile -} - -LOCAL_CONF=$DEVSTACK_PATH/local.conf -load_rc_hook api_extensions-base -load_rc_hook api_extensions-${FWAAS_VERSION} - -export DEVSTACK_LOCALCONF=$(cat $LOCAL_CONF) -$BASE/new/devstack-gate/devstack-vm-gate.sh diff --git a/neutron_fwaas/tests/contrib/hooks/api_extensions-base b/neutron_fwaas/tests/contrib/hooks/api_extensions-base deleted file mode 100644 index 02be81851..000000000 --- a/neutron_fwaas/tests/contrib/hooks/api_extensions-base +++ /dev/null @@ -1 +0,0 @@ -NETWORK_API_EXTENSIONS=agent,binding,dhcp_agent_scheduler,external-net,ext-gw-mode,extra_dhcp_opts,quotas,router,security-group,subnet_allocation,network-ip-availability,auto-allocated-topology,timestamp_core,tag,service-type,rbac-policies,standard-attr-description,pagination,sorting,project-id diff --git a/neutron_fwaas/tests/contrib/hooks/api_extensions-legacy b/neutron_fwaas/tests/contrib/hooks/api_extensions-legacy deleted file mode 100644 index 98c9f4adc..000000000 --- a/neutron_fwaas/tests/contrib/hooks/api_extensions-legacy +++ /dev/null @@ -1 +0,0 @@ -NETWORK_API_EXTENSIONS+=,fwaas,fwaasrouterinsertion diff --git a/neutron_fwaas/tests/contrib/hooks/api_extensions-v1 b/neutron_fwaas/tests/contrib/hooks/api_extensions-v1 deleted file mode 100644 index 98c9f4adc..000000000 --- a/neutron_fwaas/tests/contrib/hooks/api_extensions-v1 +++ /dev/null @@ -1 +0,0 @@ -NETWORK_API_EXTENSIONS+=,fwaas,fwaasrouterinsertion diff --git a/neutron_fwaas/tests/contrib/hooks/api_extensions-v2 b/neutron_fwaas/tests/contrib/hooks/api_extensions-v2 deleted file mode 100644 index 7a7e7f950..000000000 --- a/neutron_fwaas/tests/contrib/hooks/api_extensions-v2 +++ /dev/null @@ -1 +0,0 @@ -NETWORK_API_EXTENSIONS+=,fwaas_v2 diff --git a/neutron_fwaas/tests/contrib/hooks/iptables_verify b/neutron_fwaas/tests/contrib/hooks/iptables_verify deleted file mode 100644 index 72cbd1aeb..000000000 --- a/neutron_fwaas/tests/contrib/hooks/iptables_verify +++ /dev/null @@ -1,4 +0,0 @@ -[[post-config|/etc/neutron/neutron.conf]] - -[AGENT] -debug_iptables_rules=True diff --git a/neutron_fwaas/tests/contrib/post_test_hook.sh b/neutron_fwaas/tests/contrib/post_test_hook.sh deleted file mode 100644 index fabac5bf4..000000000 --- a/neutron_fwaas/tests/contrib/post_test_hook.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -set -xe - -FWAAS_DIR="$BASE/new/neutron-fwaas" -NEUTRON_DIR="$BASE/new/neutron" -TEMPEST_DIR="$BASE/new/tempest" -SCRIPTS_DIR="/usr/os-testr-env/bin" - -venv=${1:-"dsvm-functional"} - -function generate_testr_results { - # Give job user rights to access tox logs - sudo -H -u $owner chmod o+rw . - sudo -H -u $owner chmod o+rw -R .stestr - if [ -f ".stestr/0" ] ; then - .tox/$venv/bin/subunit-1to2 < .stestr/0 > ./stestr.subunit - $SCRIPTS_DIR/subunit2html ./stestr.subunit testr_results.html - gzip -9 ./stestr.subunit - gzip -9 ./testr_results.html - sudo mv ./*.gz /opt/stack/logs/ - fi -} - -function dsvm_functional_prep_func { - : -} - -if [[ "$venv" == dsvm-functional* ]] -then - owner=stack - sudo_env= - # Set owner permissions according to job's requirements. - cd $FWAAS_DIR - sudo chown -R $owner:stack $FWAAS_DIR - sudo chown -R $owner:stack $NEUTRON_DIR - # Prep the environment according to job's requirements. - $prep_func - - # Run tests - echo "Running neutron-fwaas $venv test suite" - set +e - sudo -H -u $owner $sudo_env tox -e $venv - testr_exit_code=$? - set -e - - # Collect and parse results - generate_testr_results - exit $testr_exit_code -fi diff --git a/neutron_fwaas/tests/fullstack/README b/neutron_fwaas/tests/fullstack/README deleted file mode 100644 index cf1b7111f..000000000 --- a/neutron_fwaas/tests/fullstack/README +++ /dev/null @@ -1 +0,0 @@ -Please see neutron/TESTING.rst for more information about what Fullstack tests are. diff --git a/neutron_fwaas/tests/fullstack/__init__.py b/neutron_fwaas/tests/fullstack/__init__.py deleted file mode 100644 index 5c53d8822..000000000 --- a/neutron_fwaas/tests/fullstack/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - -from neutron.common import eventlet_utils - - -eventlet_utils.monkey_patch() diff --git a/neutron_fwaas/tests/fullstack/base.py b/neutron_fwaas/tests/fullstack/base.py deleted file mode 100644 index f8894a57d..000000000 --- a/neutron_fwaas/tests/fullstack/base.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import os - -from neutron_lib.tests import tools -from oslo_config import cfg - -from neutron.tests import base as tests_base -from neutron.tests.fullstack.resources import client as client_resource -from neutron.tests.unit import testlib_api - - -# This is the directory from which infra fetches log files for fullstack tests -DEFAULT_LOG_DIR = os.path.join('/opt/stack/logs/neutron-fwaas/', - 'dsvm-fullstack-logs') - - -class BaseFullStackTestCase(testlib_api.MySQLTestCaseMixin, - testlib_api.SqlTestCase): - """Base test class for full-stack tests.""" - - BUILD_WITH_MIGRATIONS = True - - def setUp(self, environment): - super(BaseFullStackTestCase, self).setUp() - - tests_base.setup_test_logging( - cfg.CONF, DEFAULT_LOG_DIR, '%s.txt' % self.get_name()) - - # NOTE(zzzeek): the opportunistic DB fixtures have built for - # us a per-test (or per-process) database. Set the URL of this - # database in CONF as the full stack tests need to actually run a - # neutron server against this database. - _orig_db_url = cfg.CONF.database.connection - cfg.CONF.set_override( - 'connection', str(self.engine.url), group='database') - self.addCleanup( - cfg.CONF.set_override, - "connection", _orig_db_url, group="database" - ) - - # NOTE(ihrachys): seed should be reset before environment fixture below - # since the latter starts services that may rely on generated port - # numbers - tools.reset_random_seed() - self.environment = environment - self.environment.test_name = self.get_name() - self.useFixture(self.environment) - self.client = self.environment.neutron_server.client - self.safe_client = self.useFixture( - client_resource.ClientFixture(self.client)) - - def get_name(self): - class_name, test_name = self.id().split(".")[-2:] - return "%s.%s" % (class_name, test_name) diff --git a/neutron_fwaas/tests/fullstack/resources/__init__.py b/neutron_fwaas/tests/fullstack/resources/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/fullstack/resources/client.py b/neutron_fwaas/tests/fullstack/resources/client.py deleted file mode 100644 index d97675fd0..000000000 --- a/neutron_fwaas/tests/fullstack/resources/client.py +++ /dev/null @@ -1,247 +0,0 @@ -# Copyright (c) 2015 Thales Services SAS -# -# 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 functools - -import netaddr - -import fixtures -from neutron_lib import constants -from neutronclient.common import exceptions - -from neutron.common import utils -from neutron.extensions import portbindings - - -def _safe_method(f): - @functools.wraps(f) - def delete(*args, **kwargs): - try: - return f(*args, **kwargs) - except exceptions.NotFound: - pass - return delete - - -class ClientFixture(fixtures.Fixture): - """Manage and cleanup neutron resources.""" - - def __init__(self, client): - super(ClientFixture, self).__init__() - self.client = client - - def _create_resource(self, resource_type, spec): - create = getattr(self.client, 'create_%s' % resource_type) - delete = getattr(self.client, 'delete_%s' % resource_type) - - body = {resource_type: spec} - resp = create(body=body) - data = resp[resource_type] - self.addCleanup(_safe_method(delete), data['id']) - return data - - def create_router(self, tenant_id, name=None, ha=False, - external_network=None): - resource_type = 'router' - - name = name or utils.get_rand_name(prefix=resource_type) - spec = {'tenant_id': tenant_id, 'name': name, 'ha': ha} - if external_network: - spec['external_gateway_info'] = {"network_id": external_network} - - return self._create_resource(resource_type, spec) - - def create_network(self, tenant_id, name=None, external=False): - resource_type = 'network' - - name = name or utils.get_rand_name(prefix=resource_type) - spec = {'tenant_id': tenant_id, 'name': name} - spec['router:external'] = external - return self._create_resource(resource_type, spec) - - def create_subnet(self, tenant_id, network_id, - cidr, gateway_ip=None, name=None, enable_dhcp=True, - ipv6_address_mode='slaac', ipv6_ra_mode='slaac'): - resource_type = 'subnet' - - name = name or utils.get_rand_name(prefix=resource_type) - ip_version = netaddr.IPNetwork(cidr).version - spec = {'tenant_id': tenant_id, 'network_id': network_id, 'name': name, - 'cidr': cidr, 'enable_dhcp': enable_dhcp, - 'ip_version': ip_version} - if ip_version == constants.IP_VERSION_6: - spec['ipv6_address_mode'] = ipv6_address_mode - spec['ipv6_ra_mode'] = ipv6_ra_mode - - if gateway_ip: - spec['gateway_ip'] = gateway_ip - - return self._create_resource(resource_type, spec) - - def create_port(self, tenant_id, network_id, hostname=None, - qos_policy_id=None, **kwargs): - spec = { - 'network_id': network_id, - 'tenant_id': tenant_id, - } - spec.update(kwargs) - if hostname is not None: - spec[portbindings.HOST_ID] = hostname - if qos_policy_id: - spec['qos_policy_id'] = qos_policy_id - return self._create_resource('port', spec) - - def create_floatingip(self, tenant_id, floating_network_id, - fixed_ip_address, port_id): - spec = { - 'floating_network_id': floating_network_id, - 'tenant_id': tenant_id, - 'fixed_ip_address': fixed_ip_address, - 'port_id': port_id - } - - return self._create_resource('floatingip', spec) - - def add_router_interface(self, router_id, subnet_id): - body = {'subnet_id': subnet_id} - router_interface_info = self.client.add_interface_router( - router=router_id, body=body) - self.addCleanup(_safe_method(self.client.remove_interface_router), - router=router_id, body=body) - return router_interface_info - - def create_qos_policy(self, tenant_id, name, description, shared): - policy = self.client.create_qos_policy( - body={'policy': {'name': name, - 'description': description, - 'shared': shared, - 'tenant_id': tenant_id}}) - - def detach_and_delete_policy(): - qos_policy_id = policy['policy']['id'] - ports_with_policy = self.client.list_ports( - qos_policy_id=qos_policy_id)['ports'] - for port in ports_with_policy: - self.client.update_port( - port['id'], - body={'port': {'qos_policy_id': None}}) - self.client.delete_qos_policy(qos_policy_id) - - # NOTE: We'll need to add support for detaching from network once - # create_network() supports qos_policy_id. - self.addCleanup(_safe_method(detach_and_delete_policy)) - - return policy['policy'] - - def create_bandwidth_limit_rule(self, tenant_id, qos_policy_id, limit=None, - burst=None): - rule = {'tenant_id': tenant_id} - if limit: - rule['max_kbps'] = limit - if burst: - rule['max_burst_kbps'] = burst - rule = self.client.create_bandwidth_limit_rule( - policy=qos_policy_id, - body={'bandwidth_limit_rule': rule}) - - self.addCleanup(_safe_method(self.client.delete_bandwidth_limit_rule), - rule['bandwidth_limit_rule']['id'], - qos_policy_id) - - return rule['bandwidth_limit_rule'] - - def create_dscp_marking_rule(self, tenant_id, qos_policy_id, dscp_mark=0): - rule = {'tenant_id': tenant_id} - if dscp_mark: - rule['dscp_mark'] = dscp_mark - rule = self.client.create_dscp_marking_rule( - policy=qos_policy_id, - body={'dscp_marking_rule': rule}) - - self.addCleanup(_safe_method(self.client.delete_dscp_marking_rule), - rule['dscp_marking_rule']['id'], - qos_policy_id) - - return rule['dscp_marking_rule'] - - def create_trunk(self, tenant_id, port_id, name=None, - admin_state_up=None, sub_ports=None): - """Create a trunk via API. - - :param tenant_id: ID of the tenant. - :param port_id: Parent port of trunk. - :param name: Name of the trunk. - :param admin_state_up: Admin state of the trunk. - :param sub_ports: List of subport dictionaries in format - {'port_id': , - 'segmentation_type': 'vlan', - 'segmentation_id': } - - :return: Dictionary with trunk's data returned from Neutron API. - """ - spec = { - 'port_id': port_id, - 'tenant_id': tenant_id, - } - if name is not None: - spec['name'] = name - if sub_ports is not None: - spec['sub_ports'] = sub_ports - if admin_state_up is not None: - spec['admin_state_up'] = admin_state_up - - trunk = self.client.create_trunk({'trunk': spec})['trunk'] - - if sub_ports: - self.addCleanup( - _safe_method(self.trunk_remove_subports), - tenant_id, trunk['id'], trunk['sub_ports']) - self.addCleanup(_safe_method(self.client.delete_trunk), trunk['id']) - - return trunk - - def trunk_add_subports(self, tenant_id, trunk_id, sub_ports): - """Add subports to the trunk. - - :param tenant_id: ID of the tenant. - :param trunk_id: ID of the trunk. - :param sub_ports: List of subport dictionaries to be added in format - {'port_id': , - 'segmentation_type': 'vlan', - 'segmentation_id': } - """ - spec = { - 'tenant_id': tenant_id, - 'sub_ports': sub_ports, - } - trunk = self.client.trunk_add_subports(trunk_id, spec) - - sub_ports_to_remove = [ - sub_port for sub_port in trunk['sub_ports'] - if sub_port in sub_ports] - self.addCleanup( - _safe_method(self.trunk_remove_subports), tenant_id, trunk_id, - sub_ports_to_remove) - - def trunk_remove_subports(self, tenant_id, trunk_id, sub_ports): - """Remove subports from the trunk. - - :param trunk_id: ID of the trunk. - :param sub_ports: List of subport port IDs. - """ - spec = { - 'tenant_id': tenant_id, - 'sub_ports': sub_ports, - } - return self.client.trunk_remove_subports(trunk_id, spec) diff --git a/neutron_fwaas/tests/fullstack/resources/config.py b/neutron_fwaas/tests/fullstack/resources/config.py deleted file mode 100644 index 60b2114ef..000000000 --- a/neutron_fwaas/tests/fullstack/resources/config.py +++ /dev/null @@ -1,290 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import tempfile - -import fixtures -from neutron_lib import constants - -from neutron.common import utils -from neutron.plugins.ml2.extensions import qos as qos_ext -from neutron.tests.common import config_fixtures -from neutron.tests.common.exclusive_resources import port -from neutron.tests.common import helpers as c_helpers - - -class ConfigFixture(fixtures.Fixture): - """A fixture that holds an actual Neutron configuration. - - Note that 'self.config' is intended to only be updated once, during - the constructor, so if this fixture is re-used (setUp is called twice), - then the dynamic configuration values won't change. The correct usage - is initializing a new instance of the class. - """ - def __init__(self, env_desc, host_desc, temp_dir, base_filename): - super(ConfigFixture, self).__init__() - self.config = config_fixtures.ConfigDict() - self.env_desc = env_desc - self.host_desc = host_desc - self.temp_dir = temp_dir - self.base_filename = base_filename - - def _setUp(self): - cfg_fixture = config_fixtures.ConfigFileFixture( - self.base_filename, self.config, self.temp_dir) - self.useFixture(cfg_fixture) - self.filename = cfg_fixture.filename - - -class NeutronConfigFixture(ConfigFixture): - - def __init__(self, env_desc, host_desc, temp_dir, - connection, rabbitmq_environment): - super(NeutronConfigFixture, self).__init__( - env_desc, host_desc, temp_dir, base_filename='neutron.conf') - - service_plugins = ['router', 'trunk'] - if env_desc.qos: - service_plugins.append('qos') - - self.config.update({ - 'DEFAULT': { - 'host': self._generate_host(), - 'state_path': self._generate_state_path(self.temp_dir), - 'api_paste_config': self._generate_api_paste(), - 'core_plugin': 'ml2', - 'service_plugins': ','.join(service_plugins), - 'auth_strategy': 'noauth', - 'debug': 'True', - 'transport_url': - 'rabbit://%(user)s:%(password)s@%(host)s:5672/%(vhost)s' % - {'user': rabbitmq_environment.user, - 'password': rabbitmq_environment.password, - 'host': rabbitmq_environment.host, - 'vhost': rabbitmq_environment.vhost}, - }, - 'database': { - 'connection': connection, - }, - 'oslo_concurrency': { - 'lock_path': '$state_path/lock', - }, - 'oslo_policy': { - 'policy_file': self._generate_policy_json(), - }, - }) - - def _setUp(self): - self.config['DEFAULT'].update({ - 'bind_port': self.useFixture( - port.ExclusivePort(constants.PROTO_NAME_TCP)).port - }) - super(NeutronConfigFixture, self)._setUp() - - def _generate_host(self): - return utils.get_rand_name(prefix='host-') - - def _generate_state_path(self, temp_dir): - # Assume that temp_dir will be removed by the caller - self.state_path = tempfile.mkdtemp(prefix='state_path', dir=temp_dir) - return self.state_path - - def _generate_api_paste(self): - return c_helpers.find_sample_file('api-paste.ini') - - def _generate_policy_json(self): - return c_helpers.find_sample_file('policy.json') - - -class ML2ConfigFixture(ConfigFixture): - - def __init__(self, env_desc, host_desc, temp_dir, tenant_network_types): - super(ML2ConfigFixture, self).__init__( - env_desc, host_desc, temp_dir, base_filename='ml2_conf.ini') - - mechanism_drivers = self.env_desc.mech_drivers - if self.env_desc.l2_pop: - mechanism_drivers += ',l2population' - - self.config.update({ - 'ml2': { - 'tenant_network_types': tenant_network_types, - 'mechanism_drivers': mechanism_drivers, - }, - 'ml2_type_vlan': { - 'network_vlan_ranges': 'physnet1:1000:2999', - }, - 'ml2_type_gre': { - 'tunnel_id_ranges': '1:1000', - }, - 'ml2_type_vxlan': { - 'vni_ranges': '1001:2000', - }, - }) - - if env_desc.qos: - self.config['ml2']['extension_drivers'] =\ - qos_ext.QOS_EXT_DRIVER_ALIAS - - -class OVSConfigFixture(ConfigFixture): - - def __init__(self, env_desc, host_desc, temp_dir, local_ip): - super(OVSConfigFixture, self).__init__( - env_desc, host_desc, temp_dir, - base_filename='openvswitch_agent.ini') - - self.tunneling_enabled = self.env_desc.tunneling_enabled - self.config.update({ - 'ovs': { - 'local_ip': local_ip, - 'integration_bridge': self._generate_integration_bridge(), - 'of_interface': host_desc.of_interface, - 'ovsdb_interface': host_desc.ovsdb_interface, - }, - 'securitygroup': { - 'firewall_driver': 'noop', - }, - 'agent': { - 'l2_population': str(self.env_desc.l2_pop), - 'arp_responder': str(self.env_desc.arp_responder), - } - }) - - if self.tunneling_enabled: - self.config['agent'].update({ - 'tunnel_types': self.env_desc.network_type}) - self.config['ovs'].update({ - 'tunnel_bridge': self._generate_tunnel_bridge(), - 'int_peer_patch_port': self._generate_int_peer(), - 'tun_peer_patch_port': self._generate_tun_peer()}) - else: - self.config['ovs']['bridge_mappings'] = ( - self._generate_bridge_mappings()) - - if env_desc.qos: - self.config['agent']['extensions'] = 'qos' - - def _setUp(self): - if self.config['ovs']['of_interface'] == 'native': - self.config['ovs'].update({ - 'of_listen_port': self.useFixture( - port.ExclusivePort(constants.PROTO_NAME_TCP)).port - }) - super(OVSConfigFixture, self)._setUp() - - def _generate_bridge_mappings(self): - return 'physnet1:%s' % utils.get_rand_device_name(prefix='br-eth') - - def _generate_integration_bridge(self): - return utils.get_rand_device_name(prefix='br-int') - - def _generate_tunnel_bridge(self): - return utils.get_rand_device_name(prefix='br-tun') - - def _generate_int_peer(self): - return utils.get_rand_device_name(prefix='patch-tun') - - def _generate_tun_peer(self): - return utils.get_rand_device_name(prefix='patch-int') - - def get_br_int_name(self): - return self.config.ovs.integration_bridge - - def get_br_phys_name(self): - return self.config.ovs.bridge_mappings.split(':')[1] - - def get_br_tun_name(self): - return self.config.ovs.tunnel_bridge - - -class LinuxBridgeConfigFixture(ConfigFixture): - - def __init__(self, env_desc, host_desc, temp_dir, local_ip, - physical_device_name): - super(LinuxBridgeConfigFixture, self).__init__( - env_desc, host_desc, temp_dir, - base_filename="linuxbridge_agent.ini" - ) - self.config.update({ - 'VXLAN': { - 'enable_vxlan': str(self.env_desc.tunneling_enabled), - 'local_ip': local_ip, - 'l2_population': str(self.env_desc.l2_pop), - } - }) - if env_desc.qos: - self.config.update({ - 'AGENT': { - 'extensions': 'qos' - } - }) - if self.env_desc.tunneling_enabled: - self.config.update({ - 'LINUX_BRIDGE': { - 'bridge_mappings': self._generate_bridge_mappings( - physical_device_name - ) - } - }) - else: - self.config.update({ - 'LINUX_BRIDGE': { - 'physical_interface_mappings': - self._generate_bridge_mappings( - physical_device_name - ) - } - }) - - def _generate_bridge_mappings(self, device_name): - return 'physnet1:%s' % device_name - - -class L3ConfigFixture(ConfigFixture): - - def __init__(self, env_desc, host_desc, temp_dir, integration_bridge=None): - super(L3ConfigFixture, self).__init__( - env_desc, host_desc, temp_dir, base_filename='l3_agent.ini') - if host_desc.l2_agent_type == constants.AGENT_TYPE_OVS: - self._prepare_config_with_ovs_agent(integration_bridge) - elif host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE: - self._prepare_config_with_linuxbridge_agent() - self.config['DEFAULT'].update({ - 'debug': 'True', - 'test_namespace_suffix': self._generate_namespace_suffix(), - }) - - def _prepare_config_with_ovs_agent(self, integration_bridge): - self.config.update({ - 'DEFAULT': { - 'interface_driver': ('neutron.agent.linux.interface.' - 'OVSInterfaceDriver'), - 'ovs_integration_bridge': integration_bridge, - } - }) - - def _prepare_config_with_linuxbridge_agent(self): - self.config.update({ - 'DEFAULT': { - 'interface_driver': ('neutron.agent.linux.interface.' - 'BridgeInterfaceDriver'), - } - }) - - def _generate_external_bridge(self): - return utils.get_rand_device_name(prefix='br-ex') - - def _generate_namespace_suffix(self): - return utils.get_rand_name(prefix='test') diff --git a/neutron_fwaas/tests/fullstack/resources/environment.py b/neutron_fwaas/tests/fullstack/resources/environment.py deleted file mode 100644 index 454502a7f..000000000 --- a/neutron_fwaas/tests/fullstack/resources/environment.py +++ /dev/null @@ -1,362 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import fixtures -from neutron_lib import constants -from neutronclient.common import exceptions as nc_exc -from oslo_config import cfg - -from neutron.agent.linux import ip_lib -from neutron.common import utils as common_utils -from neutron.plugins.ml2.drivers.linuxbridge.agent import \ - linuxbridge_neutron_agent as lb_agent -from neutron.tests.common.exclusive_resources import ip_address -from neutron.tests.common.exclusive_resources import ip_network -from neutron.tests.common import net_helpers -from neutron.tests.fullstack.resources import config -from neutron.tests.fullstack.resources import process - - -class EnvironmentDescription(object): - """A set of characteristics of an environment setup. - - Does the setup, as a whole, support tunneling? How about l2pop? - """ - def __init__(self, network_type='vxlan', l2_pop=True, qos=False, - mech_drivers='openvswitch,linuxbridge', arp_responder=False): - self.network_type = network_type - self.l2_pop = l2_pop - self.qos = qos - self.network_range = None - self.mech_drivers = mech_drivers - self.arp_responder = arp_responder - - @property - def tunneling_enabled(self): - return self.network_type in ('vxlan', 'gre') - - -class HostDescription(object): - """A set of characteristics of an environment Host. - - What agents should the host spawn? What mode should each agent operate - under? - """ - def __init__(self, l3_agent=False, of_interface='ovs-ofctl', - ovsdb_interface='vsctl', - l2_agent_type=constants.AGENT_TYPE_OVS): - self.l2_agent_type = l2_agent_type - self.l3_agent = l3_agent - self.of_interface = of_interface - self.ovsdb_interface = ovsdb_interface - - -class Host(fixtures.Fixture): - """The Host class models a physical host running agents, all reporting with - the same hostname. - - OpenStack installers or administrators connect compute nodes to the - physical tenant network by connecting the provider bridges to their - respective physical NICs. Or, if using tunneling, by configuring an - IP address on the appropriate physical NIC. The Host class does the same - with the connect_* methods. - - TODO(amuller): Add start/stop/restart methods that will start/stop/restart - all of the agents on this host. Add a kill method that stops all agents - and disconnects the host from other hosts. - """ - - def __init__(self, env_desc, host_desc, - test_name, neutron_config, - central_data_bridge, central_external_bridge): - self.env_desc = env_desc - self.host_desc = host_desc - self.test_name = test_name - self.neutron_config = neutron_config - self.central_data_bridge = central_data_bridge - self.central_external_bridge = central_external_bridge - self.host_namespace = None - self.agents = {} - # we need to cache already created "per network" bridges if linuxbridge - # agent is used on host: - self.network_bridges = {} - - def _setUp(self): - self.local_ip = self.allocate_local_ip() - - if self.host_desc.l2_agent_type == constants.AGENT_TYPE_OVS: - self.setup_host_with_ovs_agent() - elif self.host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE: - self.setup_host_with_linuxbridge_agent() - if self.host_desc.l3_agent: - self.l3_agent = self.useFixture( - process.L3AgentFixture( - self.env_desc, self.host_desc, - self.test_name, - self.neutron_config, - self.l3_agent_cfg_fixture)) - - def setup_host_with_ovs_agent(self): - agent_cfg_fixture = config.OVSConfigFixture( - self.env_desc, self.host_desc, self.neutron_config.temp_dir, - self.local_ip) - self.useFixture(agent_cfg_fixture) - - br_phys = self.useFixture( - net_helpers.OVSBridgeFixture( - agent_cfg_fixture.get_br_phys_name())).bridge - if self.env_desc.tunneling_enabled: - self.useFixture( - net_helpers.OVSBridgeFixture( - agent_cfg_fixture.get_br_tun_name())).bridge - self.connect_to_internal_network_via_tunneling() - else: - self.connect_to_internal_network_via_vlans(br_phys) - - self.ovs_agent = self.useFixture( - process.OVSAgentFixture( - self.env_desc, self.host_desc, - self.test_name, self.neutron_config, agent_cfg_fixture)) - - if self.host_desc.l3_agent: - self.l3_agent_cfg_fixture = self.useFixture( - config.L3ConfigFixture( - self.env_desc, self.host_desc, - self.neutron_config.temp_dir, - self.ovs_agent.agent_cfg_fixture.get_br_int_name())) - - def setup_host_with_linuxbridge_agent(self): - #First we need to provide connectivity for agent to prepare proper - #bridge mappings in agent's config: - self.host_namespace = self.useFixture( - net_helpers.NamespaceFixture(prefix="host-") - ).name - - self.connect_namespace_to_control_network() - - agent_cfg_fixture = config.LinuxBridgeConfigFixture( - self.env_desc, self.host_desc, - self.neutron_config.temp_dir, - self.local_ip, - physical_device_name=self.host_port.name - ) - self.useFixture(agent_cfg_fixture) - - self.linuxbridge_agent = self.useFixture( - process.LinuxBridgeAgentFixture( - self.env_desc, self.host_desc, - self.test_name, self.neutron_config, agent_cfg_fixture, - namespace=self.host_namespace - ) - ) - - if self.host_desc.l3_agent: - self.l3_agent_cfg_fixture = self.useFixture( - config.L3ConfigFixture( - self.env_desc, self.host_desc, - self.neutron_config.temp_dir)) - - def _connect_ovs_port(self, cidr_address): - ovs_device = self.useFixture( - net_helpers.OVSPortFixture( - bridge=self.central_data_bridge, - namespace=self.host_namespace)).port - # NOTE: This sets an IP address on the host's root namespace - # which is cleaned up when the device is deleted. - ovs_device.addr.add(cidr_address) - return ovs_device - - def connect_namespace_to_control_network(self): - self.host_port = self._connect_ovs_port( - common_utils.ip_to_cidr(self.local_ip, 24) - ) - self.host_port.link.set_up() - - def connect_to_internal_network_via_tunneling(self): - veth_1, veth_2 = self.useFixture( - net_helpers.VethFixture()).ports - - # NOTE: This sets an IP address on the host's root namespace - # which is cleaned up when the device is deleted. - veth_1.addr.add(common_utils.ip_to_cidr(self.local_ip, 32)) - - veth_1.link.set_up() - veth_2.link.set_up() - - def connect_to_internal_network_via_vlans(self, host_data_bridge): - # If using VLANs as a segmentation device, it's needed to connect - # a provider bridge to a centralized, shared bridge. - net_helpers.create_patch_ports( - self.central_data_bridge, host_data_bridge) - - def connect_to_external_network(self, host_external_bridge): - net_helpers.create_patch_ports( - self.central_external_bridge, host_external_bridge) - - def allocate_local_ip(self): - if not self.env_desc.network_range: - return str(self.useFixture( - ip_address.ExclusiveIPAddress( - '240.0.0.1', '240.255.255.254')).address) - return str(self.useFixture( - ip_address.ExclusiveIPAddress( - str(self.env_desc.network_range[2]), - str(self.env_desc.network_range[-2]))).address) - - def get_bridge(self, network_id): - if "ovs" in self.agents.keys(): - return self.ovs_agent.br_int - elif "linuxbridge" in self.agents.keys(): - bridge = self.network_bridges.get(network_id, None) - if not bridge: - br_prefix = lb_agent.LinuxBridgeManager.get_bridge_name( - network_id) - bridge = self.useFixture( - net_helpers.LinuxBridgeFixture( - prefix=br_prefix, - namespace=self.host_namespace, - prefix_is_full_name=True)).bridge - self.network_bridges[network_id] = bridge - return bridge - - @property - def hostname(self): - return self.neutron_config.config.DEFAULT.host - - @property - def l3_agent(self): - return self.agents['l3'] - - @l3_agent.setter - def l3_agent(self, agent): - self.agents['l3'] = agent - - @property - def ovs_agent(self): - return self.agents['ovs'] - - @ovs_agent.setter - def ovs_agent(self, agent): - self.agents['ovs'] = agent - - @property - def linuxbridge_agent(self): - return self.agents['linuxbridge'] - - @linuxbridge_agent.setter - def linuxbridge_agent(self, agent): - self.agents['linuxbridge'] = agent - - -class Environment(fixtures.Fixture): - """Represents a deployment topology. - - Environment is a collection of hosts. It starts a Neutron server - and a parametrized number of Hosts, each a collection of agents. - The Environment accepts a collection of HostDescription, each describing - the type of Host to create. - """ - - def __init__(self, env_desc, hosts_desc): - """ - :param env_desc: An EnvironmentDescription instance. - :param hosts_desc: A list of HostDescription instances. - """ - - super(Environment, self).__init__() - self.env_desc = env_desc - self.hosts_desc = hosts_desc - self.hosts = [] - - def wait_until_env_is_up(self): - common_utils.wait_until_true(self._processes_are_ready) - - def _processes_are_ready(self): - try: - running_agents = self.neutron_server.client.list_agents()['agents'] - agents_count = sum(len(host.agents) for host in self.hosts) - return len(running_agents) == agents_count - except nc_exc.NeutronClientException: - return False - - def _create_host(self, host_desc): - temp_dir = self.useFixture(fixtures.TempDir()).path - neutron_config = config.NeutronConfigFixture( - self.env_desc, host_desc, temp_dir, - cfg.CONF.database.connection, self.rabbitmq_environment) - self.useFixture(neutron_config) - - return self.useFixture( - Host(self.env_desc, - host_desc, - self.test_name, - neutron_config, - self.central_data_bridge, - self.central_external_bridge)) - - def _setUp(self): - self.temp_dir = self.useFixture(fixtures.TempDir()).path - - #we need this bridge before rabbit and neutron service will start - self.central_data_bridge = self.useFixture( - net_helpers.OVSBridgeFixture('cnt-data')).bridge - self.central_external_bridge = self.useFixture( - net_helpers.OVSBridgeFixture('cnt-ex')).bridge - - #Get rabbitmq address (and cnt-data network) - rabbitmq_ip_address = self._configure_port_for_rabbitmq() - self.rabbitmq_environment = self.useFixture( - process.RabbitmqEnvironmentFixture(host=rabbitmq_ip_address) - ) - - plugin_cfg_fixture = self.useFixture( - config.ML2ConfigFixture( - self.env_desc, self.hosts_desc, self.temp_dir, - self.env_desc.network_type)) - neutron_cfg_fixture = self.useFixture( - config.NeutronConfigFixture( - self.env_desc, None, self.temp_dir, - cfg.CONF.database.connection, self.rabbitmq_environment)) - self.neutron_server = self.useFixture( - process.NeutronServerFixture( - self.env_desc, None, - self.test_name, neutron_cfg_fixture, plugin_cfg_fixture)) - - self.hosts = [self._create_host(desc) for desc in self.hosts_desc] - - self.wait_until_env_is_up() - - def _configure_port_for_rabbitmq(self): - self.env_desc.network_range = self._get_network_range() - if not self.env_desc.network_range: - return "127.0.0.1" - rabbitmq_ip = str(self.env_desc.network_range[1]) - rabbitmq_port = ip_lib.IPDevice(self.central_data_bridge.br_name) - rabbitmq_port.addr.add(common_utils.ip_to_cidr(rabbitmq_ip, 24)) - rabbitmq_port.link.set_up() - - return rabbitmq_ip - - def _get_network_range(self): - #NOTE(slaweq): We need to choose IP address on which rabbitmq will be - # available because LinuxBridge agents are spawned in their own - # namespaces and need to know where the rabbitmq server is listening. - # For ovs agent it is not necessary because agents are spawned in - # globalscope together with rabbitmq server so default localhost - # address is fine for them - for desc in self.hosts_desc: - if desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE: - return self.useFixture( - ip_network.ExclusiveIPNetwork( - "240.0.0.0", "240.255.255.255", "24")).network diff --git a/neutron_fwaas/tests/fullstack/resources/machine.py b/neutron_fwaas/tests/fullstack/resources/machine.py deleted file mode 100644 index e9eaecc1e..000000000 --- a/neutron_fwaas/tests/fullstack/resources/machine.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import itertools - -import netaddr - -from neutron_lib import constants - -from neutron.agent.linux import ip_lib -from neutron.common import utils -from neutron.extensions import portbindings as pbs -from neutron.tests.common import machine_fixtures -from neutron.tests.common import net_helpers - - -class FakeFullstackMachinesList(list): - """A list of items implementing the FakeFullstackMachine interface.""" - - def block_until_all_boot(self): - for vm in self: - vm.block_until_boot() - - def ping_all(self): - # Generate an iterable of all unique pairs. For example: - # itertools.combinations(range(3), 2) results in: - # ((0, 1), (0, 2), (1, 2)) - for vm_1, vm_2 in itertools.combinations(self, 2): - vm_1.block_until_ping(vm_2.ip) - - -class FakeFullstackMachine(machine_fixtures.FakeMachineBase): - - def __init__(self, host, network_id, tenant_id, safe_client, - neutron_port=None, bridge_name=None): - super(FakeFullstackMachine, self).__init__() - self.host = host - self.tenant_id = tenant_id - self.network_id = network_id - self.safe_client = safe_client - self.neutron_port = neutron_port - self.bridge_name = bridge_name - - def _setUp(self): - super(FakeFullstackMachine, self)._setUp() - - self.bridge = self._get_bridge() - - if not self.neutron_port: - self.neutron_port = self.safe_client.create_port( - network_id=self.network_id, - tenant_id=self.tenant_id, - hostname=self.host.hostname) - mac_address = self.neutron_port['mac_address'] - hybrid_plug = self.neutron_port[pbs.VIF_DETAILS].get( - pbs.OVS_HYBRID_PLUG, False) - - self.bind_port_if_needed() - self.port = self.useFixture( - net_helpers.PortFixture.get( - self.bridge, self.namespace, mac_address, - self.neutron_port['id'], hybrid_plug)).port - - for fixed_ip in self.neutron_port['fixed_ips']: - self._configure_ipaddress(fixed_ip) - - def bind_port_if_needed(self): - if self.neutron_port[pbs.VIF_TYPE] == pbs.VIF_TYPE_UNBOUND: - self.safe_client.client.update_port( - self.neutron_port['id'], - {'port': {pbs.HOST_ID: self.host.hostname}}) - self.addCleanup(self.safe_client.client.update_port, - self.neutron_port['id'], - {'port': {pbs.HOST_ID: ''}}) - - def _get_bridge(self): - if self.bridge_name is None: - return self.host.get_bridge(self.network_id) - agent_type = self.host.host_desc.l2_agent_type - if agent_type == constants.AGENT_TYPE_OVS: - new_bridge = self.useFixture( - net_helpers.OVSTrunkBridgeFixture(self.bridge_name)).bridge - else: - raise NotImplementedError( - "Support for %s agent is not implemented." % agent_type) - - return new_bridge - - def _configure_ipaddress(self, fixed_ip): - if (netaddr.IPAddress(fixed_ip['ip_address']).version == - constants.IP_VERSION_6): - # v6Address/default_route is auto-configured. - self._ipv6 = fixed_ip['ip_address'] - else: - self._ip = fixed_ip['ip_address'] - subnet_id = fixed_ip['subnet_id'] - subnet = self.safe_client.client.show_subnet(subnet_id) - prefixlen = netaddr.IPNetwork(subnet['subnet']['cidr']).prefixlen - self._ip_cidr = '%s/%s' % (self._ip, prefixlen) - - # TODO(amuller): Support DHCP - self.port.addr.add(self.ip_cidr) - - self.gateway_ip = subnet['subnet']['gateway_ip'] - if self.gateway_ip: - net_helpers.set_namespace_gateway(self.port, self.gateway_ip) - - @property - def ipv6(self): - return self._ipv6 - - @property - def ip(self): - return self._ip - - @property - def ip_cidr(self): - return self._ip_cidr - - def block_until_boot(self): - utils.wait_until_true( - lambda: (self.safe_client.client.show_port(self.neutron_port['id']) - ['port']['status'] == 'ACTIVE'), - sleep=3) - - def destroy(self): - """Destroy this fake machine. - - This should simulate deletion of a vm. It doesn't call cleanUp(). - """ - self.safe_client.client.update_port( - self.neutron_port['id'], - {'port': {pbs.HOST_ID: ''}} - ) - # All associated vlan interfaces are deleted too - self.bridge.delete_port(self.port.name) - - ip_wrap = ip_lib.IPWrapper(self.namespace) - ip_wrap.netns.delete(self.namespace) - - -class FakeFullstackTrunkMachine(FakeFullstackMachine): - def __init__(self, trunk, *args, **kwargs): - super(FakeFullstackTrunkMachine, self).__init__(*args, **kwargs) - self.trunk = trunk - - def add_vlan_interface(self, mac_address, ip_address, segmentation_id): - """Add VLAN interface to VM's namespace. - - :param mac_address: MAC address to be set on VLAN interface. - :param ip_address: The IPNetwork instance containing IP address - assigned to the interface. - :param segmentation_id: VLAN tag added to the interface. - """ - net_helpers.create_vlan_interface( - self.namespace, self.port.name, mac_address, ip_address, - segmentation_id) diff --git a/neutron_fwaas/tests/fullstack/resources/process.py b/neutron_fwaas/tests/fullstack/resources/process.py deleted file mode 100644 index 0f98c888e..000000000 --- a/neutron_fwaas/tests/fullstack/resources/process.py +++ /dev/null @@ -1,235 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import datetime -from distutils import spawn -import os -import signal - -import fixtures -from neutronclient.common import exceptions as nc_exc -from neutronclient.v2_0 import client - -from neutron.agent.common import async_process -from neutron.agent.linux import utils -from neutron.common import utils as common_utils -from neutron.tests import base -from neutron.tests.common import net_helpers -from neutron.tests.fullstack import base as fullstack_base - - -class ProcessFixture(fixtures.Fixture): - def __init__(self, test_name, process_name, exec_name, config_filenames, - namespace=None, kill_signal=signal.SIGKILL): - super(ProcessFixture, self).__init__() - self.test_name = test_name - self.process_name = process_name - self.exec_name = exec_name - self.config_filenames = config_filenames - self.process = None - self.kill_signal = kill_signal - self.namespace = namespace - - def _setUp(self): - self.start() - self.addCleanup(self.stop) - - def start(self): - test_name = base.sanitize_log_path(self.test_name) - - log_dir = os.path.join(fullstack_base.DEFAULT_LOG_DIR, test_name) - common_utils.ensure_dir(log_dir) - - timestamp = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S-%f") - log_file = "%s--%s.log" % (self.process_name, timestamp) - cmd = [spawn.find_executable(self.exec_name), - '--log-dir', log_dir, - '--log-file', log_file] - for filename in self.config_filenames: - cmd += ['--config-file', filename] - run_as_root = bool(self.namespace) - self.process = async_process.AsyncProcess( - cmd, run_as_root=run_as_root, namespace=self.namespace - ) - self.process.start(block=True) - - def stop(self): - self.process.stop(block=True, kill_signal=self.kill_signal) - - -class RabbitmqEnvironmentFixture(fixtures.Fixture): - - def __init__(self, host="127.0.0.1"): - super(RabbitmqEnvironmentFixture, self).__init__() - self.host = host - - def _setUp(self): - self.user = common_utils.get_rand_name(prefix='user') - self.password = common_utils.get_rand_name(prefix='pass') - self.vhost = common_utils.get_rand_name(prefix='vhost') - - self._execute('add_user', self.user, self.password) - self.addCleanup(self._execute, 'delete_user', self.user) - - self._execute('add_vhost', self.vhost) - self.addCleanup(self._execute, 'delete_vhost', self.vhost) - - self._execute('set_permissions', '-p', self.vhost, self.user, - '.*', '.*', '.*') - - def _execute(self, *args): - cmd = ['rabbitmqctl'] - cmd.extend(args) - utils.execute(cmd, run_as_root=True) - - -class NeutronServerFixture(fixtures.Fixture): - - NEUTRON_SERVER = "neutron-server" - - def __init__(self, env_desc, host_desc, - test_name, neutron_cfg_fixture, plugin_cfg_fixture): - super(NeutronServerFixture, self).__init__() - self.env_desc = env_desc - self.host_desc = host_desc - self.test_name = test_name - self.neutron_cfg_fixture = neutron_cfg_fixture - self.plugin_cfg_fixture = plugin_cfg_fixture - - def _setUp(self): - config_filenames = [self.neutron_cfg_fixture.filename, - self.plugin_cfg_fixture.filename] - - self.process_fixture = self.useFixture(ProcessFixture( - test_name=self.test_name, - process_name=self.NEUTRON_SERVER, - exec_name=self.NEUTRON_SERVER, - config_filenames=config_filenames, - kill_signal=signal.SIGTERM)) - - common_utils.wait_until_true(self.server_is_live) - - def server_is_live(self): - try: - self.client.list_networks() - return True - except nc_exc.NeutronClientException: - return False - - @property - def client(self): - url = ("http://127.0.0.1:%s" % - self.neutron_cfg_fixture.config.DEFAULT.bind_port) - return client.Client(auth_strategy="noauth", endpoint_url=url) - - -class OVSAgentFixture(fixtures.Fixture): - - NEUTRON_OVS_AGENT = "neutron-openvswitch-agent" - - def __init__(self, env_desc, host_desc, - test_name, neutron_cfg_fixture, agent_cfg_fixture): - super(OVSAgentFixture, self).__init__() - self.env_desc = env_desc - self.host_desc = host_desc - self.test_name = test_name - self.neutron_cfg_fixture = neutron_cfg_fixture - self.neutron_config = self.neutron_cfg_fixture.config - self.agent_cfg_fixture = agent_cfg_fixture - self.agent_config = agent_cfg_fixture.config - - def _setUp(self): - self.br_int = self.useFixture( - net_helpers.OVSBridgeFixture( - self.agent_cfg_fixture.get_br_int_name())).bridge - - config_filenames = [self.neutron_cfg_fixture.filename, - self.agent_cfg_fixture.filename] - - self.process_fixture = self.useFixture(ProcessFixture( - test_name=self.test_name, - process_name=self.NEUTRON_OVS_AGENT, - exec_name=spawn.find_executable( - 'ovs_agent.py', - path=os.path.join(base.ROOTDIR, 'common', 'agents')), - config_filenames=config_filenames, - kill_signal=signal.SIGTERM)) - - -class LinuxBridgeAgentFixture(fixtures.Fixture): - - NEUTRON_LINUXBRIDGE_AGENT = "neutron-linuxbridge-agent" - - def __init__(self, env_desc, host_desc, test_name, - neutron_cfg_fixture, agent_cfg_fixture, - namespace=None): - super(LinuxBridgeAgentFixture, self).__init__() - self.env_desc = env_desc - self.host_desc = host_desc - self.test_name = test_name - self.neutron_cfg_fixture = neutron_cfg_fixture - self.neutron_config = self.neutron_cfg_fixture.config - self.agent_cfg_fixture = agent_cfg_fixture - self.agent_config = agent_cfg_fixture.config - self.namespace = namespace - - def _setUp(self): - config_filenames = [self.neutron_cfg_fixture.filename, - self.agent_cfg_fixture.filename] - - self.process_fixture = self.useFixture( - ProcessFixture( - test_name=self.test_name, - process_name=self.NEUTRON_LINUXBRIDGE_AGENT, - exec_name=self.NEUTRON_LINUXBRIDGE_AGENT, - config_filenames=config_filenames, - namespace=self.namespace - ) - ) - - -class L3AgentFixture(fixtures.Fixture): - - NEUTRON_L3_AGENT = "neutron-l3-agent" - - def __init__(self, env_desc, host_desc, test_name, - neutron_cfg_fixture, l3_agent_cfg_fixture, - namespace=None): - super(L3AgentFixture, self).__init__() - self.env_desc = env_desc - self.host_desc = host_desc - self.test_name = test_name - self.neutron_cfg_fixture = neutron_cfg_fixture - self.l3_agent_cfg_fixture = l3_agent_cfg_fixture - self.namespace = namespace - - def _setUp(self): - self.plugin_config = self.l3_agent_cfg_fixture.config - - config_filenames = [self.neutron_cfg_fixture.filename, - self.l3_agent_cfg_fixture.filename] - self.process_fixture = self.useFixture( - ProcessFixture( - test_name=self.test_name, - process_name=self.NEUTRON_L3_AGENT, - exec_name=spawn.find_executable( - 'l3_agent.py', - path=os.path.join(base.ROOTDIR, 'common', 'agents')), - config_filenames=config_filenames, - namespace=self.namespace - ) - ) - - def get_namespace_suffix(self): - return self.plugin_config.DEFAULT.test_namespace_suffix diff --git a/neutron_fwaas/tests/fullstack/test_l3_agent.py b/neutron_fwaas/tests/fullstack/test_l3_agent.py deleted file mode 100644 index 58d1ea02c..000000000 --- a/neutron_fwaas/tests/fullstack/test_l3_agent.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import functools - -import netaddr - -from neutron_lib import constants -from oslo_utils import uuidutils - -from neutron.agent.l3 import agent as l3_agent -from neutron.agent.l3 import namespaces -from neutron.agent.linux import ip_lib -from neutron.common import utils as common_utils -from neutron.tests.common.exclusive_resources import ip_network -from neutron.tests.common import machine_fixtures -from neutron.tests.fullstack import base -from neutron.tests.fullstack.resources import environment -from neutron.tests.fullstack.resources import machine -from neutron.tests.unit import testlib_api - -load_tests = testlib_api.module_load_tests - - -class TestL3Agent(base.BaseFullStackTestCase): - - def _create_external_network_and_subnet(self, tenant_id): - network = self.safe_client.create_network( - tenant_id, name='public', external=True) - cidr = self.useFixture( - ip_network.ExclusiveIPNetwork( - "240.0.0.0", "240.255.255.255", "24")).network - subnet = self.safe_client.create_subnet( - tenant_id, network['id'], cidr, - enable_dhcp=False) - return network, subnet - - def block_until_port_status_active(self, port_id): - def is_port_status_active(): - port = self.client.show_port(port_id) - return port['port']['status'] == 'ACTIVE' - common_utils.wait_until_true(lambda: is_port_status_active(), sleep=1) - - def _create_net_subnet_and_vm(self, tenant_id, subnet_cidrs, host, router): - network = self.safe_client.create_network(tenant_id) - for cidr in subnet_cidrs: - # For IPv6 subnets, enable_dhcp should be set to true. - enable_dhcp = (netaddr.IPNetwork(cidr).version == - constants.IP_VERSION_6) - subnet = self.safe_client.create_subnet( - tenant_id, network['id'], cidr, enable_dhcp=enable_dhcp) - - router_interface_info = self.safe_client.add_router_interface( - router['id'], subnet['id']) - self.block_until_port_status_active( - router_interface_info['port_id']) - - vm = self.useFixture( - machine.FakeFullstackMachine( - host, network['id'], tenant_id, self.safe_client)) - vm.block_until_boot() - return vm - - -class TestLegacyL3Agent(TestL3Agent): - - def setUp(self): - host_descriptions = [ - environment.HostDescription(l3_agent=True), - environment.HostDescription()] - env = environment.Environment( - environment.EnvironmentDescription( - network_type='vlan', l2_pop=False), - host_descriptions) - super(TestLegacyL3Agent, self).setUp(env) - - def _get_namespace(self, router_id): - return namespaces.build_ns_name(l3_agent.NS_PREFIX, router_id) - - def _assert_namespace_exists(self, ns_name): - ip = ip_lib.IPWrapper(ns_name) - common_utils.wait_until_true(lambda: ip.netns.exists(ns_name)) - - def test_namespace_exists(self): - tenant_id = uuidutils.generate_uuid() - - router = self.safe_client.create_router(tenant_id) - network = self.safe_client.create_network(tenant_id) - subnet = self.safe_client.create_subnet( - tenant_id, network['id'], '20.0.0.0/24', gateway_ip='20.0.0.1') - self.safe_client.add_router_interface(router['id'], subnet['id']) - - namespace = "%s@%s" % ( - self._get_namespace(router['id']), - self.environment.hosts[0].l3_agent.get_namespace_suffix(), ) - self._assert_namespace_exists(namespace) - - def test_east_west_traffic(self): - tenant_id = uuidutils.generate_uuid() - router = self.safe_client.create_router(tenant_id) - - vm1 = self._create_net_subnet_and_vm( - tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'], - self.environment.hosts[0], router) - vm2 = self._create_net_subnet_and_vm( - tenant_id, ['21.0.0.0/24', '2001:db8:bbbb::/64'], - self.environment.hosts[1], router) - - vm1.block_until_ping(vm2.ip) - # Verify ping6 from vm2 to vm1 IPv6 Address - vm2.block_until_ping(vm1.ipv6) - - def test_snat_and_floatingip(self): - # This function creates external network and boots an extrenal vm - # on it with gateway ip and connected to central_external_bridge. - # Later it creates a tenant vm on tenant network, with tenant router - # connected to tenant network and external network. - # To test snat and floatingip, try ping between tenant and external vms - tenant_id = uuidutils.generate_uuid() - ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) - external_vm = self.useFixture( - machine_fixtures.FakeMachine( - self.environment.central_external_bridge, - common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) - - router = self.safe_client.create_router(tenant_id, - external_network=ext_net['id']) - vm = self._create_net_subnet_and_vm( - tenant_id, ['20.0.0.0/24'], - self.environment.hosts[1], router) - - # ping external vm to test snat - vm.block_until_ping(external_vm.ip) - - fip = self.safe_client.create_floatingip( - tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id']) - - # ping floating ip from external vm - external_vm.block_until_ping(fip['floating_ip_address']) - - -class TestHAL3Agent(base.BaseFullStackTestCase): - - def setUp(self): - host_descriptions = [ - environment.HostDescription(l3_agent=True) for _ in range(2)] - env = environment.Environment( - environment.EnvironmentDescription( - network_type='vxlan', l2_pop=True), - host_descriptions) - super(TestHAL3Agent, self).setUp(env) - - def _is_ha_router_active_on_one_agent(self, router_id): - agents = self.client.list_l3_agent_hosting_routers(router_id) - return ( - agents['agents'][0]['ha_state'] != agents['agents'][1]['ha_state']) - - def test_ha_router(self): - # TODO(amuller): Test external connectivity before and after a - # failover, see: https://review.openstack.org/#/c/196393/ - - tenant_id = uuidutils.generate_uuid() - router = self.safe_client.create_router(tenant_id, ha=True) - agents = self.client.list_l3_agent_hosting_routers(router['id']) - self.assertEqual(2, len(agents['agents']), - 'HA router must be scheduled to both nodes') - - common_utils.wait_until_true( - functools.partial( - self._is_ha_router_active_on_one_agent, - router['id']), - timeout=90) diff --git a/neutron_fwaas/tests/fullstack/utils.py b/neutron_fwaas/tests/fullstack/utils.py deleted file mode 100644 index 5a0f9623c..000000000 --- a/neutron_fwaas/tests/fullstack/utils.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - - -def get_ovs_interface_scenarios(): - return [ - ('openflow-cli_ovsdb-cli', {'of_interface': 'ovs-ofctl', - 'ovsdb_interface': 'vsctl'}), - ('openflow-native_ovsdb-cli', {'of_interface': 'native', - 'ovsdb_interface': 'vsctl'}), - ('openflow-cli_ovsdb-native', {'of_interface': 'ovs-ofctl', - 'ovsdb_interface': 'native'}), - ('openflow-native_ovsdb-native', {'of_interface': 'native', - 'ovsdb_interface': 'native'}), - ] diff --git a/neutron_fwaas/tests/functional/__init__.py b/neutron_fwaas/tests/functional/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/db/__init__.py b/neutron_fwaas/tests/functional/db/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/db/test_migrations.py b/neutron_fwaas/tests/functional/db/test_migrations.py deleted file mode 100644 index 9b3fcb3f0..000000000 --- a/neutron_fwaas/tests/functional/db/test_migrations.py +++ /dev/null @@ -1,100 +0,0 @@ -# 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. - -from alembic import script as alembic_script -from neutron.db.migration.alembic_migrations import external -from neutron.db.migration import cli as migration -from neutron.tests.functional.db import test_migrations -from neutron.tests.unit import testlib_api -from oslo_config import cfg -import sqlalchemy - -from neutron_fwaas.db.models import head - -# EXTERNAL_TABLES should contain all names of tables that are not related to -# current repo. -EXTERNAL_TABLES = set(external.TABLES) -# Model moved to vendor repo -EXTERNAL_TABLES.update({'cisco_firewall_associations'}) -EXTERNAL_TABLES.update({'firewall_router_associations'}) - -VERSION_TABLE = 'alembic_version_fwaas' - - -class _TestModelsMigrationsFWaaS(test_migrations._TestModelsMigrations): - - def db_sync(self, engine): - cfg.CONF.set_override('connection', engine.url, group='database') - for conf in migration.get_alembic_configs(): - self.alembic_config = conf - self.alembic_config.neutron_config = cfg.CONF - migration.do_alembic_command(conf, 'upgrade', 'heads') - - def get_metadata(self): - return head.get_metadata() - - def include_object(self, object_, name, type_, reflected, compare_to): - if type_ == 'table' and (name.startswith('alembic') or - name == VERSION_TABLE or - name in EXTERNAL_TABLES): - return False - if type_ == 'index' and reflected and name.startswith("idx_autoinc_"): - return False - return True - - -class TestModelsMigrationsMysql(testlib_api.MySQLTestCaseMixin, - _TestModelsMigrationsFWaaS, - testlib_api.SqlTestCaseLight): - pass - - -class TestModelsMigrationsPostgresql(testlib_api.PostgreSQLTestCaseMixin, - _TestModelsMigrationsFWaaS, - testlib_api.SqlTestCaseLight): - pass - - -class TestSanityCheck(testlib_api.SqlTestCaseLight): - BUILD_SCHEMA = False - - def setUp(self): - super(TestSanityCheck, self).setUp() - - for conf in migration.get_alembic_configs(): - self.alembic_config = conf - self.alembic_config.neutron_config = cfg.CONF - - def _drop_table(self, table): - with self.engine.begin() as conn: - table.drop(conn) - - def test_check_sanity_f24e0d5e5bff(self): - current_revision = "f24e0d5e5bff" - fwg_port_association = sqlalchemy.Table( - 'firewall_group_port_associations_v2', sqlalchemy.MetaData(), - sqlalchemy.Column('firewall_group_id', sqlalchemy.String(36)), - sqlalchemy.Column('port_id', sqlalchemy.String(36))) - - with self.engine.connect() as conn: - fwg_port_association.create(conn) - self.addCleanup(self._drop_table, fwg_port_association) - conn.execute(fwg_port_association.insert(), [ - {'firewall_group_id': '1234', 'port_id': '12345'}, - {'firewall_group_id': '12343', 'port_id': '12345'} - ]) - script_dir = alembic_script.ScriptDirectory.from_config( - self.alembic_config) - script = script_dir.get_revision(current_revision).module - self.assertRaises( - script.DuplicatePortRecordinFirewallGroupPortAssociation, - script.check_sanity, conn) diff --git a/neutron_fwaas/tests/functional/privileged/__init__.py b/neutron_fwaas/tests/functional/privileged/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/privileged/test_dummy.py b/neutron_fwaas/tests/functional/privileged/test_dummy.py deleted file mode 100644 index cdcb0ff6b..000000000 --- a/neutron_fwaas/tests/functional/privileged/test_dummy.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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. - -from neutron.tests.functional import base - -from neutron_fwaas.privileged.tests.functional import dummy - - -class DummyTest(base.BaseSudoTestCase): - - def test_dummy(self): - dummy.dummy() diff --git a/neutron_fwaas/tests/functional/privileged/test_netlink_lib.py b/neutron_fwaas/tests/functional/privileged/test_netlink_lib.py deleted file mode 100644 index 90024d479..000000000 --- a/neutron_fwaas/tests/functional/privileged/test_netlink_lib.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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. - -from neutron.agent.linux import utils as linux_utils -from neutron.tests.common import net_helpers -from neutron.tests.functional import base as functional_base -from oslo_log import log as logging - -import neutron_fwaas.privileged.netlink_lib as nl_lib - -LOG = logging.getLogger(__name__) - - -def check_nf_conntrack_ipv6_is_loaded(): - try: - output = linux_utils.execute(['lsmod']) - except RuntimeError: - msg = "Failed execute command lsmod!" - raise RuntimeError(msg) - if 'nf_conntrack_ipv6' in output: - return True - return False - - -def _create_entries(namespace, conntrack_cmds): - for cmd in conntrack_cmds: - exec_cmd = ['ip', 'netns', 'exec', namespace] + cmd - try: - linux_utils.execute(exec_cmd, - run_as_root=True, - check_exit_code=True, - extra_ok_codes=[1]) - except RuntimeError: - raise Exception('Error while creating entry') - - -class NetlinkLibTestCase(functional_base.BaseSudoTestCase): - """Functional test for netlink_lib: List, delete, flush conntrack entries. - - For each function, first we add a specific namespace, then create real - conntrack entries. netlink_lib function will do list, delete and flush - these entries. This class will test this netlink_lib function work - as expected. - """ - - CONNTRACK_CMDS = ( - ['conntrack', '-I', '-p', 'tcp', - '-s', '1.1.1.1', '-d', '2.2.2.2', - '--sport', '1', '--dport', '2', - '--state', 'ESTABLISHED', '--timeout', '1234'], - ['conntrack', '-I', '-p', 'udp', - '-s', '1.1.1.1', '-d', '2.2.2.2', - '--sport', '1', '--dport', '2', - '--timeout', '1234'], - ['conntrack', '-I', '-p', 'icmp', - '-s', '1.1.1.1', '-d', '2.2.2.2', - '--icmp-type', '8', '--icmp-code', '0', '--icmp-id', '3333', - '--timeout', '1234'], - ['conntrack', '-I', '-p', 'icmp', - '-s', '1.1.1.1', '-d', '2.2.2.2', - '--icmp-type', '8', '--icmp-code', '0', '--icmp-id', '3333', - '--timeout', '1234'], - ) - - def test_list_entries(self): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - expected = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - ) - entries_list = nl_lib.list_entries(namespace=namespace) - self.assertEqual(expected, entries_list) - - def _delete_entry(self, delete_entries, remain_entries): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - nl_lib.delete_entries(namespace=namespace, entries=delete_entries) - entries_list = nl_lib.list_entries(namespace) - self.assertEqual(remain_entries, entries_list) - - def test_delete_icmp_entry(self): - icmp_entry = [(4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333)] - remain_entries = ( - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2'), - ) - self._delete_entry(icmp_entry, remain_entries) - - def test_delete_tcp_entry(self): - tcp_entry = [(4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2')] - remain_entries = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - ) - self._delete_entry(tcp_entry, remain_entries) - - def test_delete_udp_entry(self): - udp_entry = [(4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2')] - remain_entries = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') - ) - self._delete_entry(udp_entry, remain_entries) - - def test_delete_multiple_entries(self): - delete_entries = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - ) - remain_entries = () - self._delete_entry(delete_entries, remain_entries) - - def test_flush_entries(self): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - nl_lib.flush_entries(namespace) - entries_list = nl_lib.list_entries(namespace) - self.assertEqual((), entries_list) - - -class NetlinkLibTestCaseIPv6(functional_base.BaseSudoTestCase): - - CONNTRACK_CMDS = ( - ['conntrack', '-I', '-p', 'icmp', - '-s', '1.1.1.1', '-d', '2.2.2.2', - '--icmp-type', '8', '--icmp-code', '0', '--icmp-id', '3333', - '--timeout', '1234'], - ['conntrack', '-I', '-p', 'icmpv6', - '-s', '10::10', '-d', '20::20', - '--icmpv6-type', '128', '--icmpv6-code', '0', '--icmpv6-id', '3456', - '--timeout', '1234'], - ) - - def setUp(self): - super(NetlinkLibTestCaseIPv6, self).setUp() - if not check_nf_conntrack_ipv6_is_loaded(): - self.skipTest( - "nf_conntrack_ipv6 module wasn't loaded. Please load" - "this module into your system if you want to use " - "netlink conntrack with ipv6" - ) - - def test_list_entries(self): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - expected = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - (6, 'icmpv6', 128, 0, '10::10', '20::20', 3456), - ) - entries_list = nl_lib.list_entries(namespace=namespace) - self.assertEqual(expected, entries_list) - - def _delete_entry(self, delete_entries, remain_entries): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - nl_lib.delete_entries(namespace=namespace, entries=delete_entries) - entries_list = nl_lib.list_entries(namespace) - self.assertEqual(remain_entries, entries_list) - - def test_delete_icmpv6_entry(self): - icmp_entry = [(6, 'icmpv6', 128, 0, '10::10', '20::20', 3456)] - remain_entries = ( - (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', 3333), - ) - self._delete_entry(icmp_entry, remain_entries) - - def test_flush_entries(self): - namespace = self.useFixture(net_helpers.NamespaceFixture()).name - _create_entries(namespace, self.CONNTRACK_CMDS) - nl_lib.flush_entries(namespace) - entries_list = nl_lib.list_entries(namespace) - self.assertEqual((), entries_list) diff --git a/neutron_fwaas/tests/functional/privileged/test_utils.py b/neutron_fwaas/tests/functional/privileged/test_utils.py deleted file mode 100644 index 3d62d4473..000000000 --- a/neutron_fwaas/tests/functional/privileged/test_utils.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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. - -from neutron.agent.linux import ip_lib -from neutron.common import utils as neutron_utils -from neutron.tests.common import net_helpers -from neutron.tests.functional import base - -from neutron_fwaas.privileged.tests.functional import utils - - -class InNamespaceTest(base.BaseSudoTestCase): - - def setUp(self): - super(InNamespaceTest, self).setUp() - self.namespace = self.useFixture(net_helpers.NamespaceFixture()).name - - ip = ip_lib.IPWrapper() - root_dev_name = neutron_utils.get_rand_device_name() - netns_dev_name = neutron_utils.get_rand_device_name() - self.root_dev, self.netns_dev = ip.add_veth( - root_dev_name, netns_dev_name, namespace2=self.namespace) - self.addCleanup(self.root_dev.link.delete) - - def test_in_namespace(self): - before, observed, after = utils.get_in_namespace_interfaces( - self.namespace) - expected = ['lo', self.netns_dev.name] - self.assertItemsEqual(expected, observed) - # Other tests can create/delete devices, so we just checks - # self.root_dev_name is included in the root namespace result. - self.assertIn(self.root_dev.name, before) - self.assertIn(self.root_dev.name, after) - - def test_in_no_namespace(self): - before, observed, after = utils.get_in_namespace_interfaces(None) - # Other tests can create/delete devices, so we just checks - # self.root_dev_name is included in the root namespace result. - self.assertIn(self.root_dev.name, observed) - self.assertIn(self.root_dev.name, before) - self.assertIn(self.root_dev.name, after) diff --git a/neutron_fwaas/tests/functional/services/__init__.py b/neutron_fwaas/tests/functional/services/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/services/logapi/__init__.py b/neutron_fwaas/tests/functional/services/logapi/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/services/logapi/agents/__init__.py b/neutron_fwaas/tests/functional/services/logapi/agents/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/services/logapi/agents/drivers/__init__.py b/neutron_fwaas/tests/functional/services/logapi/agents/drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/services/logapi/agents/drivers/iptables/__init__.py b/neutron_fwaas/tests/functional/services/logapi/agents/drivers/iptables/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/functional/services/logapi/agents/drivers/iptables/test_log.py b/neutron_fwaas/tests/functional/services/logapi/agents/drivers/iptables/test_log.py deleted file mode 100644 index 7e03e2d18..000000000 --- a/neutron_fwaas/tests/functional/services/logapi/agents/drivers/iptables/test_log.py +++ /dev/null @@ -1,567 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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 time - -import mock -from neutron.agent.l3 import l3_agent_extension_api as l3_ext_api -from neutron.agent.linux import utils as linux_utils -from neutron.tests.functional.agent.l3 import framework -from neutron_lib import constants -from neutron_lib import context as neutron_context -from neutron_lib.services.logapi import constants as log_const -from oslo_config import cfg -from oslo_log import log as logging - -from neutron_fwaas.services.logapi.agents.drivers.iptables import log - -LOG = logging.getLogger(__name__) - -FAKE_LOG_ID = 'fake_log_id' -FAKE_PROJECT_ID = 'fake_project_id' -FAKE_RESOURCE_TYPE = 'firewall_group' - -# Default chain name -ACCEPTED_CHAIN = 'accepted' -DROPPED_CHAIN = 'dropped' -REJECTED_CHAIN = 'rejected' - -ACCEPT = 'ACCEPT' -DROP = 'DROP' -REJECT = 'REJECT' -ALL = 'ALL' - -CHAIN_NAME_POSTFIX_MAP = { - ACCEPT: ACCEPTED_CHAIN, - DROP: DROPPED_CHAIN, - REJECT: REJECTED_CHAIN -} - -FWAAS_V2_LOG_OPTS = [ - cfg.StrOpt('extensions', default=['fwaas_v2', 'fwaas_v2_log']), -] - -AGENT_MODE_OPTS = [ - cfg.StrOpt('agent_mode', default='legacy', - choices=['legacy', 'dvr', 'dvr_snat', 'dvr_no_external']), -] - - -class FWLoggingTestBase(framework.L3AgentTestFramework): - - def setUp(self): - super(FWLoggingTestBase, self).setUp() - self.conf.register_opts(FWAAS_V2_LOG_OPTS, 'fwaas') - self.conf.register_opts(AGENT_MODE_OPTS, group='DEFAULT') - self._set_agent_mode(self.conf) - self.if_prefix = 'qr-' - - self.context = neutron_context.get_admin_context() - self.context.tenant_id = FAKE_PROJECT_ID - self.resource_rpc = mock.patch( - 'neutron.services.logapi.rpc.agent.LoggingApiStub').start() - # Initialize logging driver - self.log_driver = self._initialize_iptables_log() - # Prepare router_info - self._prepare_router_info(n_ports=2) - - def _prepare_router_info(self, n_ports=0): - router_data = self.generate_router_info(enable_ha=False, - num_internal_ports=n_ports) - - self.router_info = self.manage_router(self.agent, router_data) - self.log_driver.agent_api._router_info = { - self.router_info.router_id: self.router_info - } - - def _initialize_iptables_log(self): - self.agent_api = l3_ext_api.L3AgentExtensionAPI({}, None) - log_driver = log.IptablesLoggingDriver(self.agent_api) - log_driver.initialize(self.resource_rpc) - log_driver.conf = self.conf - return log_driver - - def _refresh_logging_config(self, ipt_mgr): - # Reset configuration for the next testing EVENT - self.log_driver.ipt_mgr_list.clear() - self.log_driver.fwg_port_logs.clear() - self.log_driver.prefixes_table.clear() - self.log_driver.cleanup_table.clear() - self.log_driver.nflog_proc_map.clear() - self.log_driver.unused_port_ids.clear() - # Empty default chains - self._empty_default_chains_v4v6(ipt_mgr=ipt_mgr) - - def _set_agent_mode(self, cfg, agent_mode='legacy'): - cfg.agent_mode = agent_mode - - def _config_default_chains_v4v6(self, ipt_mgr): - # Config default chains in iptables and ip6tables - for action, chain in CHAIN_NAME_POSTFIX_MAP.items(): - v4rules_in_chain = \ - ipt_mgr.get_chain("filter", chain, ip_version=4) - if not v4rules_in_chain: - ipt_mgr.ipv4['filter'].add_chain(chain) - ipt_mgr.ipv4['filter'].add_rule(chain, '-j %s' % action) - - v6rules_in_chain = \ - ipt_mgr.get_chain("filter", chain, ip_version=6) - if not v6rules_in_chain: - ipt_mgr.ipv6['filter'].add_chain(chain) - ipt_mgr.ipv6['filter'].add_rule(chain, '-j %s' % action) - - def _empty_default_chains_v4v6(self, ipt_mgr): - # Empty default chains in iptables and ip6tables - for action, chain in CHAIN_NAME_POSTFIX_MAP.items(): - ipt_mgr.ipv4['filter'].empty_chain(chain=chain) - ipt_mgr.ipv6['filter'].empty_chain(chain=chain) - - def _fake_log_resource(self, tenant_id, resource_id=None, - target_id=None, event='ALL', enabled=True): - log_resource = { - 'id': FAKE_LOG_ID, - 'name': 'fake_log_name', - 'resource_type': FAKE_RESOURCE_TYPE, - 'project_id': tenant_id, - 'event': event, - 'enabled': True} - if resource_id: - log_resource['resource_id'] = resource_id - if target_id: - log_resource['target_id'] = target_id - if not enabled: - log_resource['enabled'] = enabled - return log_resource - - def _fake_log_info(self, log_id, port_ids, event='ALL'): - return { - 'event': event, - 'id': log_id, - 'project_id': FAKE_PROJECT_ID, - 'ports_log': port_ids - } - - def _get_expected_nflog_rule(self, wrap_name, if_prefix, logs_info): - # Generate an expected NFLOG rules from given log_info - rules = set() - limit = 'limit --limit %s/sec --limit-burst %s' % \ - (self.log_driver.rate_limit, self.log_driver.burst_limit) - - accept_chain = wrap_name + '-' + ACCEPTED_CHAIN - drop_chain = wrap_name + '-' + DROPPED_CHAIN - reject_chain = wrap_name + '-' + REJECTED_CHAIN - for log_info in logs_info: - event = log_info['event'] - ports_log = log_info['ports_log'] - - for port_id in ports_log: - device = (if_prefix + port_id)[:constants.LINUX_DEV_LEN] - if event in [ACCEPT, ALL]: - # Generate iptables rules for ACCEPT action - prefix = self._get_log_prefix(port_id, ACCEPT) - rules.add('-A %s -i %s -m %s -j NFLOG --nflog-prefix %s' - % (accept_chain, device, limit, prefix.id)) - rules.add('-A %s -o %s -m %s -j NFLOG --nflog-prefix %s' - % (accept_chain, device, limit, prefix.id)) - - if event in [DROP, ALL]: - # Generate iptables rules for DROP action - prefix = self._get_log_prefix(port_id, DROP) - rules.add('-A %s -i %s -m %s -j NFLOG --nflog-prefix %s' - % (drop_chain, device, limit, prefix.id)) - rules.add('-A %s -o %s -m %s -j NFLOG --nflog-prefix %s' - % (drop_chain, device, limit, prefix.id)) - - # Generate iptables rules for REJECT action - rules.add('-A %s -i %s -m %s -j NFLOG --nflog-prefix %s' - % (reject_chain, device, limit, prefix.id)) - rules.add('-A %s -o %s -m %s -j NFLOG --nflog-prefix %s' - % (reject_chain, device, limit, prefix.id)) - return rules - - def _get_log_prefix(self, port_id, action): - prefix_table = self.log_driver.prefixes_table - if port_id in prefix_table: - for prefix in prefix_table[port_id]: - if prefix.action == action: - return prefix - return None - - def _get_nflog_entries(self, namespace, table='iptables', chain_name=None): - # Get NFLOG entries from iptables and ip6tables - exec_cmd = ['ip', 'netns', 'exec', namespace, table, '-S'] - if chain_name: - exec_cmd += [chain_name] - while True: - try: - output = linux_utils.execute(exec_cmd, - run_as_root=True, - check_exit_code=True, - extra_ok_codes=[1]) - nflog_rules = [rule for rule in output.splitlines() - if 'NFLOG' in rule] - return nflog_rules - except RuntimeError: - time.sleep(1) - - def assert_logging_results(self, ipt_mgr, log_info): - # Comparing between expected NFLOG rules and NFLOG rules from iptables - v4_rules = v6_rules = self._get_expected_nflog_rule( - ipt_mgr.wrap_name, self.if_prefix, log_info) - - v4_actual = self._get_nflog_entries(ipt_mgr.namespace, - table='iptables') - v6_actual = self._get_nflog_entries(ipt_mgr.namespace, - table='ip6tables') - - self.assertEqual(sorted(v4_rules), sorted(v4_actual)) - self.assertEqual(sorted(v6_rules), sorted(v6_actual)) - - def run_start_logging(self, ipt_mgr, log_info, **kwargs): - # Run start logging function with a give log_info - router_info = kwargs.get('router_info') - log_resources = kwargs.get('log_resources') - - self._config_default_chains_v4v6(ipt_mgr) - if router_info: - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - return_value=log_info): - self.log_driver.start_logging(self.context, - router_info=router_info) - elif log_resources: - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_log_resources', - return_value=log_info): - self.log_driver.start_logging(self.context, - log_resources=log_resources) - - -class FWLoggingTestCase(FWLoggingTestBase): - - def test_start_logging_when_l3_starting(self): - # Get router information - ipt_mgr = self.router_info.iptables_manager - port_ids = [port['id'] for port in self.router_info.internal_ports] - - for event in log_const.LOG_EVENTS: - # Test start_logging with single log resource - f_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - self.run_start_logging(ipt_mgr, - log_info=f_log_info, - router_info=self.router_info) - - # Test start_logging with multiple log resources - f_log_info = [ - self._fake_log_info(log_id='fake_log_id_1', - port_ids=[port_ids[0]], - event=event), - self._fake_log_info(log_id='fake_log_id_2', - port_ids=[port_ids[1]], - event=event) - ] - self.run_start_logging(ipt_mgr, - log_info=f_log_info, - router_info=self.router_info) - - self.assert_logging_results(ipt_mgr, f_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_create_log(self): - # Get router information - ipt_mgr = self.router_info.iptables_manager - port_ids = [port['id'] for port in self.router_info.internal_ports] - - for event in log_const.LOG_EVENTS: - log_resources = [self._fake_log_resource(FAKE_PROJECT_ID, - event=event)] - f_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - self.run_start_logging(ipt_mgr, - log_info=f_log_info, - log_resources=log_resources) - - self.assert_logging_results(ipt_mgr, f_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_add_router_port(self): - ipt_mgr = self.router_info.iptables_manager - - for event in log_const.LOG_EVENTS: - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Making log_info when there is only one port - added_port_id = port_ids.pop() - initial_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - # Make log_info with new adding port - port_ids.append(added_port_id) - add_port_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - side_effect=[initial_log_info, - add_port_log_info]): - # Start logging with a single port as normal to get initial - # NFLOG rules into iptables - self.log_driver.start_logging(self.context, - router_info=self.router_info) - # Start logging with the new port - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - self.assert_logging_results(ipt_mgr, add_port_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_remove_port(self): - ipt_mgr = self.router_info.iptables_manager - - for event in log_const.LOG_EVENTS: - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Making log_info when there are two ports on router - initial_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - # Make log_info when a port is removed from router - port_ids.pop() - remove_port_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - side_effect=[initial_log_info, - remove_port_log_info]): - # Start logging with a single port as normal to get initial - # NFLOG rules into iptables - self.log_driver.start_logging(self.context, - router_info=self.router_info) - # Start logging with the new port - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - self.assert_logging_results(ipt_mgr, remove_port_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_attach_port_to_fwg(self): - ipt_mgr = self.router_info.iptables_manager - - for event in log_const.LOG_EVENTS: - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Making log_info when there is only one port - attached_port_id = port_ids.pop() - initial_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - # Make log_info with a new port that attached to fwg - port_ids.append(attached_port_id) - - attached_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - log_resources = [ - self._fake_log_resource(FAKE_PROJECT_ID, - resource_id=attached_port_id, - event=event) - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - return_value=initial_log_info): - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_log_resources', - return_value=attached_log_info): - # Start logging with a single port as normal to get initial - # NFLOG rules into iptables - self.log_driver.start_logging(self.context, - router_info=self.router_info) - # Start logging with the new port attach to fwg - self.log_driver.start_logging(self.context, - log_resources=log_resources) - - self.assert_logging_results(ipt_mgr, attached_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_detach_port_from_fwg(self): - ipt_mgr = self.router_info.iptables_manager - - for event in log_const.LOG_EVENTS: - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Making log_info when there are two ports attached to fwg - initial_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - # Make log_info when a port is detached from fwg - detached_port_id = port_ids.pop() - detached_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=event) - ] - log_resources = [ - self._fake_log_resource(FAKE_PROJECT_ID, - resource_id=detached_port_id, - event=event) - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - return_value=initial_log_info): - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_log_resources', - return_value=detached_log_info): - # Start logging with a single port as normal to get initial - # NFLOG rules into iptables - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - # Start logging with the new port attach to fwg - self.log_driver.start_logging(self.context, - log_resources=log_resources) - - self.assert_logging_results(ipt_mgr, detached_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_start_logging_when_enable_router(self): - ipt_mgr = self.router_info.iptables_manager - port_ids = [port['id'] for port in self.router_info.internal_ports] - for event in log_const.LOG_EVENTS: - # Log info to initialize NFLOG rules - f_log_info = [ - self._fake_log_info(log_id=FAKE_LOG_ID, - port_ids=port_ids, - event=ALL) - ] - # Initialize NFLOG rules with start_logging - self.run_start_logging(ipt_mgr, - log_info=f_log_info, - router_info=self.router_info) - # Fake disable router by running stop_logging with router_info - self.log_driver.stop_logging( - self.context, router_info=self.router_info.router_id) - # Fake enable router by running start_logging with router_info - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - self.assert_logging_results(ipt_mgr, f_log_info) - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_stop_logging_when_delete_log(self): - ipt_mgr = self.router_info.iptables_manager - - for event in log_const.LOG_EVENTS: - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Initialize log_info to start logging - log_info_1 = self._fake_log_info(log_id='fake_log_id_1', - port_ids=port_ids, - event=event) - log_info_2 = self._fake_log_info(log_id='fake_log_id_2', - port_ids=[port_ids[0]], - event=event) - initial_log_info = [ - log_info_1, - log_info_2 - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - return_value=initial_log_info): - # Start logging to get initial NFLOG rules - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - # Stop logging by deleting fake_log_id_1 - deleted_log_1 = [{'id': 'fake_log_id_1'}] - self.log_driver.stop_logging(self.context, - log_resources=deleted_log_1) - self.assert_logging_results(ipt_mgr, [log_info_2]) - - # Stop logging by deleting fake_log_id_2 - deleted_log_2 = [{'id': 'fake_log_id_2'}] - self.log_driver.stop_logging(self.context, - log_resources=deleted_log_2) - self.assert_logging_results(ipt_mgr, []) - - self._refresh_logging_config(ipt_mgr=ipt_mgr) - - def test_stop_logging_when_delete_log_with_event_combination(self): - ipt_mgr = self.router_info.iptables_manager - - port_ids = [port['id'] for port in self.router_info.internal_ports] - - # Initial log_info to start logging - log_info_1 = self._fake_log_info(log_id='accept_log_id', - port_ids=port_ids, - event=ACCEPT) - log_info_2 = self._fake_log_info(log_id='all_log_id', - port_ids=[port_ids[0]], - event=ALL) - initial_log_info = [ - log_info_1, - log_info_2 - ] - - self._config_default_chains_v4v6(ipt_mgr) - with mock.patch.object(self.resource_rpc, - 'get_sg_log_info_for_port', - return_value=initial_log_info): - # Start logging to get initial NFLOG rules - self.log_driver.start_logging(self.context, - router_info=self.router_info) - - # Stop logging by deleting accept_log_id - accepted_log = [{'id': 'accept_log_id'}] - self.log_driver.stop_logging(self.context, - log_resources=accepted_log) - self.assert_logging_results(ipt_mgr, [log_info_2]) - - # Stop logging by deleting all_log_id - all_log = [{'id': 'all_log_id'}] - self.log_driver.stop_logging(self.context, - log_resources=all_log) - self.assert_logging_results(ipt_mgr, []) diff --git a/neutron_fwaas/tests/unit/__init__.py b/neutron_fwaas/tests/unit/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/cmd/__init__.py b/neutron_fwaas/tests/unit/cmd/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/cmd/upgrade_checks/__init__.py b/neutron_fwaas/tests/unit/cmd/upgrade_checks/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/cmd/upgrade_checks/test_checks.py b/neutron_fwaas/tests/unit/cmd/upgrade_checks/test_checks.py deleted file mode 100644 index 41b47d2a2..000000000 --- a/neutron_fwaas/tests/unit/cmd/upgrade_checks/test_checks.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2019 Red Hat 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. - -import mock -from oslo_config import cfg -from oslo_upgradecheck.upgradecheck import Code - -from neutron_fwaas.cmd.upgrade_checks import checks -from neutron_fwaas.tests import base - - -class TestChecks(base.BaseTestCase): - - def setUp(self): - super(TestChecks, self).setUp() - self.checks = checks.Checks() - - def test_get_checks_list(self): - self.assertIsInstance(self.checks.get_checks(), list) - - def test_fwaas_v1_check_sucess(self): - cfg.CONF.set_override('service_plugins', ['l3', 'qos']) - check_result = checks.Checks.fwaas_v1_check(mock.Mock()) - self.assertEqual(Code.SUCCESS, check_result.code) - - def test_fwaas_v1_check_warning(self): - plugins_to_check = [ - ['l3', 'firewall', 'qos'], - ['l3', - 'neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin', - 'qos']] - for plugins in plugins_to_check: - cfg.CONF.set_override('service_plugins', plugins) - check_result = checks.Checks.fwaas_v1_check(mock.Mock()) - self.assertEqual(Code.FAILURE, check_result.code) diff --git a/neutron_fwaas/tests/unit/db/__init__.py b/neutron_fwaas/tests/unit/db/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/db/firewall/__init__.py b/neutron_fwaas/tests/unit/db/firewall/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/db/firewall/v2/__init__.py b/neutron_fwaas/tests/unit/db/firewall/v2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/db/firewall/v2/test_firewall_db_v2.py b/neutron_fwaas/tests/unit/db/firewall/v2/test_firewall_db_v2.py deleted file mode 100644 index 41c21db5d..000000000 --- a/neutron_fwaas/tests/unit/db/firewall/v2/test_firewall_db_v2.py +++ /dev/null @@ -1,1739 +0,0 @@ -# Copyright (c) 2016 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import six -import testtools -import webob.exc - -from neutron_lib import constants as nl_constants -from neutron_lib.exceptions import firewall_v2 as f_exc -from oslo_config import cfg -from oslo_utils import uuidutils - -from neutron_fwaas.common import fwaas_constants as constants -from neutron_fwaas.tests.unit.services.firewall import test_fwaas_plugin_v2 - - -class TestFirewallDBPluginV2(test_fwaas_plugin_v2.FirewallPluginV2TestCase): - - def setUp(self): - super(TestFirewallDBPluginV2, self).setUp() - self.db = self.plugin.driver.firewall_db - - def test_get_policy_ordered_rules(self): - with self.firewall_rule(name='alone'), \ - self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr3') as fwr3, \ - self.firewall_rule(name='fwr2') as fwr2: - fwrs = fwr1, fwr2, fwr3 - expected_ids = [fwr['firewall_rule']['id'] for fwr in fwrs] - with self.firewall_policy(firewall_rules=expected_ids) as fwp: - ctx = self._get_admin_context() - fwp_id = fwp['firewall_policy']['id'] - observeds = self.db._get_policy_ordered_rules(ctx, fwp_id) - observed_ids = [r['id'] for r in observeds] - self.assertEqual(expected_ids, observed_ids) - - def test_create_firewall_policy(self): - name = "firewall_policy1" - attrs = self._get_test_firewall_policy_attrs(name) - - with self.firewall_policy(name=name, shared=self.SHARED, - firewall_rules=None, audited=self.AUDITED - ) as firewall_policy: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_policy['firewall_policy'][k]) - - def test_create_firewall_policy_with_rules(self): - name = "firewall_policy1" - attrs = self._get_test_firewall_policy_attrs(name) - - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3: - fr = [fwr1, fwr2, fwr3] - fw_rule_ids = [r['firewall_rule']['id'] for r in fr] - attrs['firewall_rules'] = fw_rule_ids - with self.firewall_policy(name=name, shared=self.SHARED, - firewall_rules=fw_rule_ids, - audited=self.AUDITED) as fwp: - for k, v in six.iteritems(attrs): - self.assertEqual(v, fwp['firewall_policy'][k]) - - def test_create_firewall_policy_with_previously_associated_rule(self): - with self.firewall_rule() as fwr: - fw_rule_ids = [fwr['firewall_rule']['id']] - with self.firewall_policy(firewall_rules=fw_rule_ids): - with self.firewall_policy(shared=self.SHARED, - firewall_rules=fw_rule_ids) as fwp2: - self.assertEqual( - fwr['firewall_rule']['id'], - fwp2['firewall_policy']['firewall_rules'][0]) - - def test_show_firewall_policy(self): - name = "firewall_policy1" - attrs = self._get_test_firewall_policy_attrs(name) - - with self.firewall_policy(name=name, shared=self.SHARED, - firewall_rules=None, - audited=self.AUDITED) as fwp: - res = self._show_req('firewall_policies', - fwp['firewall_policy']['id']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - def test_list_firewall_policies(self): - with self.firewall_policy(name='fwp1', description='fwp') as fwp1, \ - self.firewall_policy(name='fwp2', description='fwp') as fwp2, \ - self.firewall_policy(name='fwp3', description='fwp') as fwp3: - fw_policies = [fwp1, fwp2, fwp3] - self._test_list_resources('firewall_policy', - fw_policies, - query_params='description=fwp') - - def test_update_firewall_policy(self): - name = "new_firewall_policy1" - attrs = self._get_test_firewall_policy_attrs(name, audited=False) - - with self.firewall_policy(shared=self.SHARED, firewall_rules=None, - audited=self.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 six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - def _test_update_firewall_policy(self, with_audited): - with self.firewall_policy(name='firewall_policy1', description='fwp', - audited=self.AUDITED) as fwp: - attrs = self._get_test_firewall_policy_attrs(audited=with_audited) - data = {'firewall_policy': - {'description': 'fw_p1'}} - if with_audited: - data['firewall_policy']['audited'] = 'True' - - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - attrs['description'] = 'fw_p1' - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - def test_update_firewall_policy_set_audited_false(self): - self._test_update_firewall_policy(with_audited=False) - - def test_update_firewall_policy_with_audited_set_true(self): - self._test_update_firewall_policy(with_audited=True) - - def test_update_firewall_policy_with_rules(self): - attrs = self._get_test_firewall_policy_attrs() - - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3: - with self.firewall_policy() as fwp: - fr = [fwr1, fwr2, fwr3] - fw_rule_ids = [r['firewall_rule']['id'] for r in fr] - attrs['firewall_rules'] = fw_rule_ids - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - attrs['audited'] = False - attrs['firewall_rules'] = sorted(attrs['firewall_rules']) - # TODO(sridar): set it so that the ordering is maintained - res['firewall_policy']['firewall_rules'] = sorted( - res['firewall_policy']['firewall_rules']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - def test_update_firewall_policy_replace_rules(self): - attrs = self._get_test_firewall_policy_attrs() - - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3, \ - self.firewall_rule(name='fwr4') as fwr4: - frs = [fwr1, fwr2, fwr3, fwr4] - fr1 = frs[0:2] - fr2 = frs[2:4] - with self.firewall_policy() as fwp: - fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - req.get_response(self.ext_api) - - fw_rule_ids = [r['firewall_rule']['id'] for r in fr2] - attrs['firewall_rules'] = fw_rule_ids - new_data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', new_data, - fwp['firewall_policy']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - attrs['audited'] = False - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - @testtools.skip('bug/1614673') - def test_update_firewall_policy_reorder_rules(self): - attrs = self._get_test_firewall_policy_attrs() - - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3, \ - self.firewall_rule(name='fwr4') as fwr4: - fr = [fwr1, fwr2, fwr3, fwr4] - with self.firewall_policy() as fwp: - fw_rule_ids = [fr[2]['firewall_rule']['id'], - fr[3]['firewall_rule']['id']] - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - req.get_response(self.ext_api) - # shuffle the rules, add more rules - fw_rule_ids = [fr[1]['firewall_rule']['id'], - fr[3]['firewall_rule']['id'], - fr[2]['firewall_rule']['id'], - fr[0]['firewall_rule']['id']] - attrs['firewall_rules'] = fw_rule_ids - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - rules = [] - for rule_id in fw_rule_ids: - res = self._show_req('firewall_rules', rule_id) - rules.append(res['firewall_rule']) - self.assertEqual(1, rules[0]['position']) - self.assertEqual(fr[1]['firewall_rule']['id'], rules[0]['id']) - self.assertEqual(2, rules[1]['position']) - self.assertEqual(fr[3]['firewall_rule']['id'], rules[1]['id']) - self.assertEqual(3, rules[2]['position']) - self.assertEqual(fr[2]['firewall_rule']['id'], rules[2]['id']) - self.assertEqual(4, rules[3]['position']) - self.assertEqual(fr[0]['firewall_rule']['id'], rules[3]['id']) - - def test_update_firewall_policy_with_non_existing_rule(self): - attrs = self._get_test_firewall_policy_attrs() - - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2: - fr = [fwr1, fwr2] - with self.firewall_policy() as fwp: - fw_rule_ids = [r['firewall_rule']['id'] for r in fr] - # appending non-existent rule - fw_rule_ids.append(uuidutils.generate_uuid()) - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - # check that the firewall_rule was not found - self.assertEqual(404, res.status_int) - # check if none of the rules got added to the policy - res = self._show_req('firewall_policies', - fwp['firewall_policy']['id']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_policy'][k]) - - def test_update_shared_firewall_policy_with_nonshared_rule(self): - with self.firewall_rule(name='fwr1', shared=False) as fr: - with self.firewall_policy() as fwp: - fw_rule_ids = [fr['firewall_rule']['id']] - # update shared policy with nonshared rule - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int) - - def test_update_firewall_policy_with_shared_attr_nonshared_rule(self): - with self.firewall_rule(name='fwr1', shared=False) as fr: - with self.firewall_policy(shared=False) as fwp: - fw_rule_ids = [fr['firewall_rule']['id']] - # update shared policy with shared attr and nonshared rule - data = {'firewall_policy': {'shared': self.SHARED, - 'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int) - - def test_update_firewall_policy_with_shared_attr_exist_unshared_rule(self): - with self.firewall_rule(name='fwr1', shared=False) as fwr: - fwr_ids = [fwr['firewall_rule']['id']] - with self.firewall_policy(shared=False, - firewall_rules=fwr_ids) as fwp: - # Update policy with shared attr - data = {'firewall_policy': {'shared': self.SHARED}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_firewall_policy_with_shared_and_shared_rules(self): - with self.firewall_rule(name='fwr1', shared=self.SHARED) as fwr: - fwr_ids = [fwr['firewall_rule']['id']] - with self.firewall_policy(shared=False, - firewall_rules=fwr_ids) as fwp: - # Update policy with shared attr - data = {'firewall_policy': {'shared': self.SHARED}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPOk.code, res.status_int) - - def test_update_firewall_policy_assoc_with_other_tenant_firewall(self): - with self.firewall_policy(shared=self.SHARED, - tenant_id='tenant1') as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id): - data = {'firewall_policy': {'shared': False}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_firewall_policy_from_shared_to_unshared(self): - with self.firewall_policy(shared=True) as fwp: - # update policy with public attr - data = {'firewall_policy': {'shared': False}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPOk.code, res.status_int) - - def test_update_from_shared_to_unshared_associated_as_ingress_fwp(self): - with self.firewall_policy(shared=True, tenant_id='here') as fwp: - # update policy with public attr - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(tenant_id='another', - ingress_firewall_policy_id=fwp_id): - data = {'firewall_policy': {'shared': False}} - req = self.new_update_request('firewall_policies', data, - fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_from_shared_to_unshared_associated_as_egress_fwp(self): - with self.firewall_policy(shared=True, tenant_id='here') as fwp: - # update policy with public attr - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(tenant_id='another', - egress_firewall_policy_id=fwp_id): - data = {'firewall_policy': {'shared': False}} - req = self.new_update_request('firewall_policies', data, - fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_from_shared_to_unshared_associated_as_ingress_egress(self): - with self.firewall_policy(shared=True, tenant_id='here') as fwp: - # update policy with public attr - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(tenant_id='another', - egress_firewall_policy_id=fwp_id, - ingress_firewall_policy_id=fwp_id): - data = {'firewall_policy': {'shared': False}} - req = self.new_update_request('firewall_policies', data, - fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_default_fwg_policy(self): - """ - Make sure that neither admin nor non-admin can update policy - associated with default firewall group - """ - ctx_admin = self._get_admin_context() - ctx_nonadmin = self._get_nonadmin_context() - for ctx in [ctx_admin, ctx_nonadmin]: - self._build_default_fwg(ctx=ctx) - policies = self._list_req('firewall_policies') - for p in policies: - data = {'firewall_policy': - {'firewall_rules': []}} - req = self.new_update_request('firewall_policies', - data, p['id']) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_delete_firewall_policy(self): - ctx = self._get_admin_context() - with self.firewall_policy(do_delete=False) as fwp: - fwp_id = fwp['firewall_policy']['id'] - req = self.new_delete_request('firewall_policies', fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(204, res.status_int) - self.assertRaises(f_exc.FirewallPolicyNotFound, - self.plugin.get_firewall_policy, - ctx, fwp_id) - - @testtools.skip('bug/1614673') - def test_delete_firewall_policy_with_rule(self): - ctx = self._get_admin_context() - attrs = self._get_test_firewall_policy_attrs() - with self.firewall_policy(do_delete=False) as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_rule(name='fwr1') as fr: - fr_id = fr['firewall_rule']['id'] - fw_rule_ids = [fr_id] - attrs['firewall_rules'] = fw_rule_ids - data = {'firewall_policy': - {'firewall_rules': fw_rule_ids}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - req.get_response(self.ext_api) - fw_rule = self.plugin.get_firewall_rule(ctx, fr_id) - self.assertEqual(fwp_id, fw_rule['ingress_firewall_policy_id']) - req = self.new_delete_request('firewall_policies', fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(204, res.status_int) - self.assertRaises(f_exc.FirewallPolicyNotFound, - self.plugin.get_firewall_policy, - ctx, fwp_id) - fw_rule = self.plugin.get_firewall_rule(ctx, fr_id) - self.assertIsNone(fw_rule['ingress_firewall_policy_id']) - - def test_delete_firewall_policy_with_firewall_group_association(self): - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - ingress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP): - req = self.new_delete_request('firewall_policies', fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_create_firewall_rule(self): - attrs = self._get_test_firewall_rule_attrs() - - with self.firewall_rule() as firewall_rule: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_rule['firewall_rule'][k]) - - attrs['source_port'] = None - attrs['destination_port'] = None - with self.firewall_rule(source_port=None, - destination_port=None) as firewall_rule: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_rule['firewall_rule'][k]) - - attrs['source_port'] = '10000' - attrs['destination_port'] = '80' - with self.firewall_rule(source_port=10000, - destination_port=80) as firewall_rule: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_rule['firewall_rule'][k]) - - attrs['source_port'] = '10000' - attrs['destination_port'] = '80' - with self.firewall_rule(source_port='10000', - destination_port='80') as firewall_rule: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_rule['firewall_rule'][k]) - - def test_create_firewall_src_port_illegal_range(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['source_port'] = '65535:1024' - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_dest_port_illegal_range(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['destination_port'] = '65535:1024' - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_rule_icmp_with_port(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['protocol'] = 'icmp' - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_rule_icmp_without_port(self): - attrs = self._get_test_firewall_rule_attrs() - - attrs['protocol'] = 'icmp' - attrs['source_port'] = None - attrs['destination_port'] = None - with self.firewall_rule(source_port=None, - destination_port=None, - protocol='icmp') as firewall_rule: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_rule['firewall_rule'][k]) - - def test_create_firewall_without_source(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['source_ip_address'] = None - attrs['expected_res_status'] = 201 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_rule_without_destination(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['destination_ip_address'] = None - attrs['expected_res_status'] = 201 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_rule_without_protocol_with_dport(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['protocol'] = None - attrs['source_port'] = None - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_create_firewall_rule_without_protocol_with_sport(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['protocol'] = None - attrs['destination_port'] = None - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_show_firewall_rule_with_fw_policy_not_associated(self): - attrs = self._get_test_firewall_rule_attrs() - with self.firewall_rule() as fw_rule: - res = self._show_req('firewall_rules', - fw_rule['firewall_rule']['id']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - @testtools.skip('bug/1614673') - def test_show_firewall_rule_with_fw_policy_associated(self): - attrs = self._get_test_firewall_rule_attrs() - with self.firewall_rule() as fw_rule: - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - attrs['ingress_firewall_policy_id'] = fwp_id - data = {'firewall_policy': - {'firewall_rules': - [fw_rule['firewall_rule']['id']]}} - req = self.new_update_request('firewall_policies', data, - fwp['firewall_policy']['id']) - req.get_response(self.ext_api) - res = self._show_req('firewall_rules', - fw_rule['firewall_rule']['id']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - def test_create_firewall_rule_with_ipv6_addrs_and_wrong_ip_version(self): - attrs = self._get_test_firewall_rule_attrs() - attrs['source_ip_address'] = '::/0' - attrs['destination_ip_address'] = '2001:db8:3::/64' - attrs['ip_version'] = 4 - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - attrs = self._get_test_firewall_rule_attrs() - attrs['source_ip_address'] = None - attrs['destination_ip_address'] = '2001:db8:3::/64' - attrs['ip_version'] = 4 - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - attrs = self._get_test_firewall_rule_attrs() - attrs['source_ip_address'] = '::/0' - attrs['destination_ip_address'] = None - attrs['ip_version'] = 4 - attrs['expected_res_status'] = 400 - self._create_firewall_rule(self.fmt, **attrs) - - def test_list_firewall_rules(self): - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3: - fr = [fwr1, fwr2, fwr3] - query_params = 'protocol=tcp' - self._test_list_resources('firewall_rule', fr, - query_params=query_params) - - def test_update_firewall_rule(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, - 'protocol': self.PROTOCOL, - '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 six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - attrs['source_port'] = '10000' - attrs['destination_port'] = '80' - with self.firewall_rule() as fwr: - data = {'firewall_rule': {'name': name, - 'protocol': self.PROTOCOL, - '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 six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - attrs['source_port'] = '10000' - attrs['destination_port'] = '80' - with self.firewall_rule() as fwr: - data = {'firewall_rule': {'name': name, - 'protocol': self.PROTOCOL, - '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 six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - 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 six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - def test_update_firewall_rule_with_port_and_no_proto(self): - with self.firewall_rule() as fwr: - data = {'firewall_rule': {'protocol': None, - 'destination_port': 80}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(400, res.status_int) - - def test_update_firewall_rule_without_ports_and_no_proto(self): - with self.firewall_rule() as fwr: - data = {'firewall_rule': {'protocol': None, - 'destination_port': None, - 'source_port': None}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_update_firewall_rule_with_port(self): - with self.firewall_rule(source_port=None, - destination_port=None, - protocol=None) as fwr: - data = {'firewall_rule': {'destination_port': 80}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(400, res.status_int) - - def test_update_firewall_rule_with_port_illegal_range(self): - with self.firewall_rule() as fwr: - data = {'firewall_rule': {'destination_port': '65535:1024'}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(400, res.status_int) - - def test_update_firewall_rule_with_port_and_protocol(self): - with self.firewall_rule(source_port=None, - destination_port=None, - protocol=None) as fwr: - data = {'firewall_rule': {'destination_port': 80, - 'protocol': 'tcp'}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_update_firewall_rule_icmp_with_port(self): - with self.firewall_rule(source_port=None, - destination_port=None, - protocol=None) as fwr: - data = {'firewall_rule': {'destination_port': 80, - 'protocol': 'icmp'}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(400, res.status_int) - - with self.firewall_rule(source_port=None, - destination_port=None, - protocol='icmp') as fwr: - data = {'firewall_rule': {'destination_port': 80}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(400, res.status_int) - - def test_update_firewall_rule_protocol_icmp(self): - with self.firewall_rule(source_port=10000) as fwr: - data = {'firewall_rule': {'protocol': 'icmp'}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int) - - def test_update_firewall_rule_protocol_none(self): - with self.firewall_rule(source_port=10000) as fwr: - data = {'firewall_rule': {'protocol': None}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int) - - def test_update_firewall_rule_with_policy_associated(self): - name = "new_firewall_rule1" - attrs = self._get_test_firewall_rule_attrs(name) - with self.firewall_rule() as fwr: - with self.firewall_policy() as fwp: - 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)) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - res = self._show_req('firewall_policies', - fwp['firewall_policy']['id']) - self.assertEqual( - [fwr_id], - res['firewall_policy']['firewall_rules']) - self.assertFalse(res['firewall_policy']['audited']) - - @testtools.skip('bug/1614680') - def test_update_firewall_rule_associated_with_other_tenant_policy(self): - with self.firewall_rule(shared=self, tenant_id='tenant1') as fwr: - fwr_id = [fwr['firewall_rule']['id']] - with self.firewall_policy(shared=False, firewall_rules=fwr_id): - data = {'firewall_rule': {'shared': False}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_update_firewall_rule_with_ipv6_ipaddr(self): - with self.firewall_rule(source_ip_address="1::10", - destination_ip_address=None, - ip_version=6) as fwr_v6: - data = {'firewall_rule': { - 'destination_ip_address': "2::20"}} - req = self.new_update_request('firewall_rules', data, - fwr_v6['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_delete_firewall_rule(self): - ctx = self._get_admin_context() - with self.firewall_rule(do_delete=False) as fwr: - fwr_id = fwr['firewall_rule']['id'] - req = self.new_delete_request('firewall_rules', fwr_id) - res = req.get_response(self.ext_api) - self.assertEqual(204, res.status_int) - self.assertRaises(f_exc.FirewallRuleNotFound, - self.plugin.get_firewall_rule, - ctx, fwr_id) - - def test_delete_firewall_rule_with_policy_associated(self): - with self.firewall_rule() as fwr: - with self.firewall_policy() as fwp: - 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']) - res = req.get_response(self.ext_api) - req = self.new_delete_request('firewall_rules', fwr_id) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_create_firewall_group(self): - attrs = self._get_test_firewall_group_attrs("firewall1") - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_router_port(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF) as port: - attrs = self._get_test_firewall_group_attrs("fwg1") - attrs['ports'] = [port['port']['id']] - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_dvr_port(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_DVR_INTERFACE) as port: - attrs = self._get_test_firewall_group_attrs("fwg1") - attrs['ports'] = [port['port']['id']] - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_router_port_l3ha(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_HA_REPLICATED_INT) as port: - attrs = self._get_test_firewall_group_attrs("fwg1") - attrs['ports'] = [port['port']['id']] - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_empty_ports(self): - attrs = self._get_test_firewall_group_attrs("fwg1") - attrs['ports'] = [] - self._test_create_firewall_group(attrs) - - def test_create_default_firewall_group_multiple_times_diff_tenants(self): - ctx_admin = self._get_admin_context() - fwg_admin = self._build_default_fwg(ctx=ctx_admin) - res = self._build_default_fwg(ctx=ctx_admin, is_one=False) - # check that only 1 group has been created - self.assertEqual(1, len(res)) - ctx = self._get_nonadmin_context() - fwg_na = self._build_default_fwg(ctx=ctx) - res = self._build_default_fwg(ctx=ctx, is_one=False) - # check that only 1 group has been created - self.assertEqual(1, len(res)) - # make sure that admin default_fwg and non_admin don't match - self.assertNotEqual(fwg_na['id'], fwg_admin['id']) - # make sure that admin can see default groups for admin and non-admin - res = self._list_req('firewall_groups', ctx=ctx_admin) - self.assertEqual(2, len(res)) - self.assertEqual(set([ctx_admin.tenant_id, ctx.tenant_id]), - set([r['tenant_id'] for r in res])) - - def test_create_default_firewall_group_from_config(self): - group = 'default_fwg_rules' - - cfg.CONF.set_override('shared', True, group) - cfg.CONF.set_override('protocol', 'tcp', group) - cfg.CONF.set_override('enabled', False, group) - cfg.CONF.set_override('ingress_action', 'allow', group) - cfg.CONF.set_override('egress_action', 'deny', group) - cfg.CONF.set_override('ingress_source_port', '7777', group) - cfg.CONF.set_override('egress_source_port', '8888', group) - cfg.CONF.set_override('ingress_destination_port', '6666', group) - cfg.CONF.set_override('egress_destination_port', '5555', group) - cfg.CONF.set_override('ingress_source_ipv4_address', '1.2.3.4', group) - cfg.CONF.set_override('ingress_source_ipv6_address', '1:2:3:4:5:6:7:8', - group) - cfg.CONF.set_override('egress_source_ipv4_address', '4.3.2.1', group) - cfg.CONF.set_override('egress_source_ipv6_address', '8:7:6:5:4:3:2:1', - group) - cfg.CONF.set_override('ingress_destination_ipv4_address', - '251.252.253.254', group) - cfg.CONF.set_override('ingress_destination_ipv6_address', - '88:99:aa:bb:cc:dd:ee:ff', group) - cfg.CONF.set_override('egress_destination_ipv4_address', - '255.254.253.252', group) - cfg.CONF.set_override('egress_destination_ipv6_address', - 'ff:ee:dd:cc:bb:aa:99:88', group) - - self._build_default_fwg() - results = self._list_req('firewall_rules') - for res in results: - res.pop('id') - - base = { - 'shared': True, - 'protocol': 'tcp', - 'enabled': False, - 'tenant_id': 'admin-tenant', - 'project_id': 'admin-tenant', - 'firewall_policy_id': None - } - - ingress_base = dict(base, **{ - 'source_port': '7777', - 'destination_port': '6666', - 'action': 'allow' - }) - - egress_base = dict(base, **{ - 'source_port': '8888', - 'destination_port': '5555', - 'action': 'deny' - }) - - expected = [dict(ingress_base, **{ - 'name': 'default ingress ipv4', - 'description': 'default ingress rule for IPv4', - 'ip_version': 4, - 'source_ip_address': '1.2.3.4', - 'destination_ip_address': '251.252.253.254', - }), dict(ingress_base, **{ - 'name': 'default ingress ipv6', - 'description': 'default ingress rule for IPv6', - 'ip_version': 6, - 'source_ip_address': '1:2:3:4:5:6:7:8', - 'destination_ip_address': '88:99:aa:bb:cc:dd:ee:ff', - }), dict(egress_base, **{ - 'name': 'default egress ipv4', - 'description': 'default egress rule for IPv4', - 'ip_version': 4, - 'source_ip_address': '4.3.2.1', - 'destination_ip_address': '255.254.253.252', - }), dict(egress_base, **{ - 'name': 'default egress ipv6', - 'description': 'default egress rule for IPv6', - 'ip_version': 6, - 'source_ip_address': '8:7:6:5:4:3:2:1', - 'destination_ip_address': 'ff:ee:dd:cc:bb:aa:99:88', - })] - - self.assertEqual(expected, results) - - def test_create_default_firewall_group(self): - self._build_default_fwg() - result_map = { - 'firewall_groups': {"keys": ["description", "name"], - "data": [("Default firewall group", - constants.DEFAULT_FWG)] - }, - 'firewall_policies': { - "keys": ["description", "name"], - "data": [("Ingress firewall policy", - constants.DEFAULT_FWP_INGRESS), - ("Egress firewall policy", - constants.DEFAULT_FWP_EGRESS)]}, - 'firewall_rules': { - "keys": ["description", "action", "protocol", "enabled", - "ip_version", "name"], - "data": [ - ("default ingress rule for IPv4", "deny", None, True, 4, - "default ingress ipv4"), - ("default egress rule for IPv4", "allow", None, True, 4, - "default egress ipv4"), - ("default ingress rule for IPv6", "deny", None, True, 6, - "default ingress ipv6"), - ("default egress rule for IPv6", "allow", None, True, 6, - "default egress ipv6")] - } - } - - def _check_rules_match_policies(policy, direction): - if direction in policy["description"].lower(): - for rule_id in policy['firewall_rules']: - rule = self._show_req( - 'firewall_rules', rule_id)['firewall_rule'] - self.assertTrue(direction in rule["description"]) - - for obj in result_map: - res = self._list_req(obj) - check_keys = result_map[obj]["keys"] - expected = result_map[obj]["data"] - self.assertEqual(len(expected), len(res)) - - # an attempt to check that rules match policies - if obj == 'firewall_policies': - for p in res: - _check_rules_match_policies(p, "ingress") - _check_rules_match_policies(p, "egress") - - # check that a rule with given params is present in actual - # data by comparing expected/actual tuples - actual = [] - for r in res: - actual.append(tuple(r[key] for key in check_keys)) - self.assertEqual(set(expected), set(actual)) - - def test_create_firewall_group_exists_default(self): - self._build_default_fwg()['id'] - attrs = self._get_test_firewall_group_attrs("firewall1") - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_fwp_does_not_exist(self): - fmt = self.fmt - fwg_name = "firewall1" - description = "my_firewall1" - not_found_fwp_id = uuidutils.generate_uuid() - self._create_firewall_group(fmt, fwg_name, - description, not_found_fwp_id, - not_found_fwp_id, ports=None, - admin_state_up=self.ADMIN_STATE_UP, - expected_res_status=404) - - def test_create_firewall_group_with_fwp_on_different_tenant(self): - fmt = self.fmt - fwg_name = "firewall1" - description = "my_firewall1" - with self.firewall_policy(shared=False, tenant_id='tenant2') as fwp: - fwp_id = fwp['firewall_policy']['id'] - ctx = self._get_nonadmin_context() - self._create_firewall_group(fmt, fwg_name, - description, - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - context=ctx, - expected_res_status=404) - - def test_create_firewall_group_with_admin_and_fwp_different_tenant(self): - fmt = self.fmt - fwg_name = "firewall1" - description = "my_firewall1" - with self.firewall_policy(shared=False, tenant_id='tenant2') as fwp: - fwp_id = fwp['firewall_policy']['id'] - ctx = self._get_admin_context() - self._create_firewall_group(fmt, fwg_name, - description, fwp_id, fwp_id, - tenant_id="admin-tenant", - context=ctx, - expected_res_status=404) - - def test_create_firewall_group_with_admin_and_fwp_is_shared(self): - fwg_name = "fw_with_shared_fwp" - with self.firewall_policy(tenant_id="tenantX") as fwp: - fwp_id = fwp['firewall_policy']['id'] - ctx = self._get_admin_context() - target_tenant = 'tenant1' - with self.firewall_group( - name=fwg_name, - ingress_firewall_policy_id=fwp_id, - tenant_id=target_tenant, - context=ctx, - admin_state_up=self.ADMIN_STATE_UP) as fwg: - self.assertEqual(target_tenant, - fwg['firewall_group']['tenant_id']) - - def _test_show_firewall_group(self, attrs): - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - attrs['ingress_firewall_policy_id'] = fwp_id - attrs['egress_firewall_policy_id'] = fwp_id - with self.firewall_group( - name=attrs['name'], - ports=attrs['ports'] if 'ports' in attrs else None, - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP) as firewall_group: - res = self._show_req('firewall_groups', - firewall_group['firewall_group']['id']) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_group'][k]) - - def test_show_firewall_group(self): - attrs = self._get_test_firewall_group_attrs('fwg1') - self._test_show_firewall_group(attrs) - - def test_show_firewall_group_with_ports(self): - attrs = self._get_test_firewall_group_attrs('fwg1') - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF) as dummy_port: - attrs['ports'] = [dummy_port['port']['id']] - self._test_show_firewall_group(attrs) - - def test_show_firewall_group_with_empty_ports(self): - attrs = self._get_test_firewall_group_attrs('fwg1') - attrs['ports'] = [] - self._test_show_firewall_group(attrs) - - def test_list_firewall_groups(self): - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(name='fwg1', tenant_id='tenant1', - ingress_firewall_policy_id=fwp_id, - description='fwg') as fwg1, \ - self.firewall_group(name='fwg2', tenant_id='tenant2', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - description='fwg') as fwg2, \ - self.firewall_group(name='fwg3', tenant_id='tenant3', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - description='fwg') as fwg3: - fwgrps = [fwg1, fwg2, fwg3] - self._test_list_resources('firewall_group', fwgrps, - query_params='description=fwg') - - def test_update_firewall_group(self): - name = "new_firewall1" - attrs = self._get_test_firewall_group_attrs(name) - - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - ingress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP) as firewall: - data = {'firewall_group': {'name': name}} - req = self.new_update_request('firewall_groups', data, - firewall['firewall_group']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_group'][k]) - - def test_existing_default_create_default_firewall_group(self): - self._build_default_fwg() - self._create_firewall_group(fmt=None, - name=constants.DEFAULT_FWG, - description="", - ingress_firewall_policy_id=None, - egress_firewall_policy_id=None, - expected_res_status=409) - - def test_update_default_firewall_group_with_non_admin_success(self): - ctx = self._get_nonadmin_context() - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF, - tenant_id=ctx.project_id) as dummy_port: - port_id = dummy_port['port']['id'] - success_cases = [ - {'ports': [port_id]}, - {'ports': []}, - {'ports': None}, - {}, - ] - for attr in success_cases: - data = {'firewall_group': attr} - req = self.new_update_request( - 'firewall_groups', data, def_fwg_id) - req.environ['neutron.context'] = ctx - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_update_default_firewall_group_with_non_admin_failure(self): - ctx = self._get_nonadmin_context() - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF, - tenant_id=ctx.project_id) as dummy_port: - port_id = dummy_port['port']['id'] - conflict_cases = [ - {'name': ''}, - {'name': 'default'}, - {'name': 'non-default'}, - {'ingress_firewall_policy_id': None}, - {'egress_firewall_policy_id': None}, - {'description': 'try to modify'}, - {'admin_state_up': True}, - {'ports': [port_id], 'name': ''}, - {'ports': [], 'name': 'default'}, - {'ports': None, 'name': 'non-default'}, - ] - for attr in conflict_cases: - data = {'firewall_group': attr} - req = self.new_update_request( - 'firewall_groups', data, def_fwg_id) - req.environ['neutron.context'] = ctx - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_update_default_firewall_group_with_admin_success(self): - ctx = self._get_admin_context() - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF, - tenant_id=ctx.project_id) as dummy_port: - port_id = dummy_port['port']['id'] - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - success_cases = [ - {'ports': [port_id]}, - {'ports': []}, - {'ports': None}, - {'ingress_firewall_policy_id': None}, - {'egress_firewall_policy_id': None}, - {'description': 'try to modify'}, - {'admin_state_up': True}, - {}, - ] - for attr in success_cases: - data = {'firewall_group': attr} - req = self.new_update_request( - 'firewall_groups', data, def_fwg_id) - req.environ['neutron.context'] = ctx - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_update_default_firewall_group_with_admin_failure(self): - ctx = self._get_admin_context() - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF, - tenant_id=ctx.project_id) as dummy_port: - port_id = dummy_port['port']['id'] - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - conflict_cases = [ - {'name': 'default'}, - {'name': 'non-default'}, - {'name': ''}, - {'ports': [port_id], 'name': ''}, - {'ports': [], 'name': 'default'}, - {'ports': None, 'name': 'non-default'}, - ] - for attr in conflict_cases: - data = {'firewall_group': attr} - req = self.new_update_request( - 'firewall_groups', data, def_fwg_id) - req.environ['neutron.context'] = ctx - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_update_firewall_group_with_fwp(self): - ctx = self._get_nonadmin_context() - with self.firewall_policy(name='p1', tenant_id=ctx.tenant_id, - shared=False) as fwp1, \ - self.firewall_policy(name='p2', tenant_id=ctx.tenant_id, - shared=False) as fwp2, \ - self.firewall_group( - ingress_firewall_policy_id=fwp1['firewall_policy']['id'], - egress_firewall_policy_id=fwp2['firewall_policy']['id'], - context=ctx) as fw: - fw_id = fw['firewall_group']['id'] - fwp2_id = fwp2['firewall_policy']['id'] - data = {'firewall_group': {'ingress_firewall_policy_id': fwp2_id}} - req = self.new_update_request('firewall_groups', data, fw_id, - context=ctx) - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_change_fwg_name_to_default(self): - """ - Make sure that neither admin nor non-admin can change name of - existing firewall group to default - """ - admin_ctx = self._get_admin_context() - nonadmin_ctx = self._get_nonadmin_context() - with self.firewall_group(context=nonadmin_ctx) as fwg: - data = {'firewall_group': {'name': constants.DEFAULT_FWG}} - fwg_id = fwg['firewall_group']['id'] - for ctx in [admin_ctx, nonadmin_ctx]: - req = self.new_update_request('firewall_groups', data, fwg_id, - context=ctx) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - @testtools.skip('bug/1614680') - def test_update_firewall_group_with_shared_fwp(self): - ctx = self._get_nonadmin_context() - with self.firewall_policy(name='p1', tenant_id=ctx.tenant_id, - shared=True) as fwp1, \ - self.firewall_policy(name='p2', tenant_id='tenant2', - shared=True) as fwp2, \ - self.firewall_group( - ingress_firewall_policy_id=fwp1['firewall_policy']['id'], - egress_firewall_policy_id=fwp1['firewall_policy']['id'], - context=ctx) as fw: - fw_id = fw['firewall_group']['id'] - fwp2_id = fwp2['firewall_policy']['id'] - data = {'firewall_group': {'ingress_firewall_policy_id': fwp2_id}} - req = self.new_update_request('firewall_groups', data, fw_id, - context=ctx) - res = req.get_response(self.ext_api) - self.assertEqual(200, res.status_int) - - def test_update_firewall_group_with_admin_and_fwp_different_tenant(self): - ctx = self._get_admin_context() - with self.firewall_policy() as fwp1, \ - self.firewall_policy(tenant_id='tenant2', - shared=False) as fwp2, \ - self.firewall_group( - ingress_firewall_policy_id=fwp1['firewall_policy']['id'], - egress_firewall_policy_id=fwp1['firewall_policy']['id'], - context=ctx) as fw: - fw_id = fw['firewall_group']['id'] - fwp2_id = fwp2['firewall_policy']['id'] - data = {'firewall_group': {'egress_firewall_policy_id': fwp2_id}} - req = self.new_update_request('firewall_groups', data, fw_id, - context=ctx) - res = req.get_response(self.ext_api) - self.assertEqual(404, res.status_int) - - def test_update_firewall_group_fwp_not_found_on_different_tenant(self): - ctx_tenant1 = self._get_nonadmin_context(tenant_id='tenant1') - ctx_tenant2 = self._get_nonadmin_context(tenant_id='tenant2') - - with self.firewall_policy(name='fwp1', context=ctx_tenant1, - shared=False, do_delete=False) as fwp1, \ - self.firewall_group( - ingress_firewall_policy_id=fwp1['firewall_policy']['id'], - context=ctx_tenant1, do_delete=False) as fwg: - fwg_id = fwg['firewall_group']['id'] - # fw_db = self.db._get_firewall_group(ctx_tenant1, fwg_id) - # fw_db['status'] = nl_constants.ACTIVE - - # update firewall from fwp1 to fwp2 (different tenant) - with self.firewall_policy(name='fwp2', context=ctx_tenant2, - shared=False) as fwp2: - data = { - 'firewall_group': { - 'ingress_firewall_policy_id': - fwp2['firewall_policy']['id'], - }, - } - req = self.new_update_request('firewall_groups', data, fwg_id, - context=ctx_tenant1) - res = req.get_response(self.ext_api) - self.assertEqual(404, res.status_int) - - def test_delete_firewall_group(self): - ctx = self._get_admin_context() - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group(ingress_firewall_policy_id=fwp_id, - do_delete=False) as fw: - fw_id = fw['firewall_group']['id'] - req = self.new_delete_request('firewall_groups', fw_id) - res = req.get_response(self.ext_api) - self.assertEqual(204, res.status_int) - self.assertRaises(f_exc.FirewallGroupNotFound, - self.plugin.get_firewall_group, - ctx, fw_id) - - def test_delete_firewall_group_already_deleted(self): - ctx = self._get_admin_context() - with self.firewall_group(do_delete=False, context=ctx) as fwg: - fwg_id = fwg['firewall_group']['id'] - self.assertIsNone(self.plugin.delete_firewall_group(ctx, fwg_id)) - # No error raise is fwg not found on delete - self.assertIsNone(self.plugin.delete_firewall_group(ctx, fwg_id)) - - def test_delete_default_firewall_group_with_admin(self): - ctx_a = self._get_admin_context() - ctx_na = self._get_nonadmin_context() - def_fwg_id = None - for ctx in [ctx_na, ctx_a]: - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - req = self.new_delete_request('firewall_groups', def_fwg_id) - req.environ['neutron.context'] = ctx_a - self.assertEqual(204, req.get_response(self.ext_api).status_int) - # check that policy has been deleted by listing as admin and getting 1 - # default fwg with a differnt id - res = self._list_req('firewall_groups', ctx=ctx_a) - self.assertEqual(1, len(res)) - self.assertNotEqual(def_fwg_id, res[0]['id']) - - def test_delete_default_firewall_group_with_non_admin(self): - ctx = self._get_nonadmin_context() - def_fwg_id = self._build_default_fwg(ctx=ctx)['id'] - req = self.new_delete_request('firewall_groups', def_fwg_id) - req.environ['neutron.context'] = ctx - self.assertEqual(409, req.get_response(self.ext_api).status_int) - - def test_insert_rule_in_policy_with_prior_rules_added_via_update(self): - attrs = self._get_test_firewall_policy_attrs() - attrs['audited'] = False - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3: - frs = [fwr1, fwr2, fwr3] - fr1 = frs[0:2] - fwr3 = frs[2] - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - attrs['id'] = fwp_id - 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) - self._rule_action('insert', fwp_id, fw_rule_ids[0], - insert_before=fw_rule_ids[0], - insert_after=None, - expected_code=webob.exc.HTTPConflict.code, - expected_body=None) - fwr3_id = fwr3['firewall_rule']['id'] - attrs['firewall_rules'].insert(0, fwr3_id) - self._rule_action('insert', fwp_id, fwr3_id, - insert_before=fw_rule_ids[0], - insert_after=None, - expected_code=webob.exc.HTTPOk.code, - expected_body=attrs) - - def test_insert_rule_in_policy_failures(self): - with self.firewall_rule(name='fwr1') as fr1: - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - fr1_id = fr1['firewall_rule']['id'] - fw_rule_ids = [fr1_id] - 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 inserting with empty request body - self._rule_action('insert', fwp_id, '123', - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None, body_data={}) - # test inserting when firewall_rule_id is missing in - # request body - insert_data = {'insert_before': '123', - 'insert_after': '456'} - self._rule_action('insert', fwp_id, '123', - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None, - body_data=insert_data) - # test inserting when firewall_rule_id is None - insert_data = {'firewall_rule_id': None, - 'insert_before': '123', - 'insert_after': '456'} - self._rule_action('insert', fwp_id, None, - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None, - body_data=insert_data) - # test inserting when firewall_policy_id is incorrect - self._rule_action('insert', '123', fr1_id, - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None) - # test inserting when firewall_policy_id is None - self._rule_action('insert', None, fr1_id, - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None) - - def test_insert_rule_and_already_associated(self): - with self.firewall_rule() as fwr: - fwr_id = fwr['firewall_rule']['id'] - with self.firewall_policy(firewall_rules=[fwr_id]) as fwp: - fwp_id = fwp['firewall_policy']['id'] - self._rule_action( - 'insert', fwp_id, fwr_id, - insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPConflict.code, - body_data={'firewall_rule_id': fwr_id}) - - def test_insert_rule_for_previously_associated_rule(self): - with self.firewall_rule() as fwr: - fwr_id = fwr['firewall_rule']['id'] - fw_rule_ids = [fwr_id] - with self.firewall_policy(firewall_rules=fw_rule_ids): - with self.firewall_policy(name='firewall_policy2') as fwp: - fwp_id = fwp['firewall_policy']['id'] - insert_data = {'firewall_rule_id': fwr_id} - self._rule_action( - 'insert', fwp_id, fwr_id, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPOk.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_for_previously_associated_rule_other_tenant(self): - with self.firewall_rule(tenant_id='tenant-2') as fwr: - fwr_id = fwr['firewall_rule']['id'] - fw_rule_ids = [fwr_id] - with self.firewall_policy(tenant_id='tenant-2', - firewall_rules=fw_rule_ids): - with self.firewall_policy(name='firewall_policy2') as fwp: - fwp_id = fwp['firewall_policy']['id'] - insert_data = {'firewall_rule_id': fwr_id} - self._rule_action( - 'insert', fwp_id, fwr_id, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPOk.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_for_prev_associated_ref_rule(self): - with self.firewall_rule(name='fwr0') as fwr0, \ - self.firewall_rule(name='fwr1') as fwr1: - fwr = [fwr0, fwr1] - fwr0_id = fwr[0]['firewall_rule']['id'] - fwr1_id = fwr[1]['firewall_rule']['id'] - with self.firewall_policy(name='fwp0') as fwp0, \ - self.firewall_policy(name='fwp1', - firewall_rules=[fwr1_id]) as fwp1: - fwp = [fwp0, fwp1] - fwp0_id = fwp[0]['firewall_policy']['id'] - # test inserting before a rule which - # is associated with different policy - self._rule_action('insert', fwp0_id, fwr0_id, - insert_before=fwr1_id, - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None) - # test inserting after a rule which - # is associated with different policy - self._rule_action('insert', fwp0_id, fwr0_id, - insert_after=fwr1_id, - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None) - - def test_insert_rule_for_policy_of_other_tenant(self): - with self.firewall_rule(tenant_id='tenant-2', shared=False) as fwr: - fwr_id = fwr['firewall_rule']['id'] - with self.firewall_policy(name='firewall_policy') as fwp: - fwp_id = fwp['firewall_policy']['id'] - insert_data = {'firewall_rule_id': fwr_id} - self._rule_action( - 'insert', fwp_id, fwr_id, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPConflict.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_missing_rule_id(self): - with self.firewall_rule(tenant_id='tenant-2', shared=False): - with self.firewall_policy(name='firewall_policy') as fwp: - fwp_id = fwp['firewall_policy']['id'] - insert_data = {} - self._rule_action( - 'insert', fwp_id, None, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_empty_rule_id(self): - with self.firewall_rule(tenant_id='tenant-2', shared=False): - with self.firewall_policy(name='firewall_policy') as fwp: - fwp_id = fwp['firewall_policy']['id'] - insert_data = {'firewall_rule_id': None} - self._rule_action( - 'insert', fwp_id, None, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_invalid_rule_id(self): - with self.firewall_rule(tenant_id='tenant-2', shared=False): - with self.firewall_policy(name='firewall_policy') as fwp: - fwp_id = fwp['firewall_policy']['id'] - fwr_id_fake = 'foo' - insert_data = {'firewall_rule_id': fwr_id_fake} - self._rule_action( - 'insert', fwp_id, fwr_id_fake, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_nonexistent_rule_id(self): - with self.firewall_rule(tenant_id='tenant-2', shared=False): - with self.firewall_policy(name='firewall_policy') as fwp: - fwp_id = fwp['firewall_policy']['id'] - fwr_id_fake = uuidutils.generate_uuid() - insert_data = {'firewall_rule_id': fwr_id_fake} - self._rule_action( - 'insert', fwp_id, fwr_id_fake, insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None, body_data=insert_data) - - def test_insert_rule_in_policy(self): - attrs = self._get_test_firewall_policy_attrs() - attrs['audited'] = False - with self.firewall_rule(name='fwr0') as fwr0, \ - self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3, \ - self.firewall_rule(name='fwr4') as fwr4, \ - self.firewall_rule(name='fwr5') as fwr5, \ - self.firewall_rule(name='fwr6') as fwr6: - fwr = [fwr0, fwr1, fwr2, fwr3, fwr4, fwr5, fwr6] - 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_remove_rule_and_not_associated(self): - with self.firewall_rule(name='fwr0') as fwr: - with self.firewall_policy(name='firewall_policy2') as fwp: - fwp_id = fwp['firewall_policy']['id'] - fwr_id = fwr['firewall_rule']['id'] - msg = "Firewall rule {0} is not associated with " \ - "firewall policy {1}.".format(fwr_id, fwp_id) - result = self._rule_action( - 'remove', fwp_id, fwr_id, - insert_before=None, - insert_after=None, - expected_code=webob.exc.HTTPBadRequest.code, - body_data={'firewall_rule_id': fwr_id}) - self.assertEqual(msg, result['NeutronError']['message']) - - def test_remove_rule_from_policy(self): - attrs = self._get_test_firewall_policy_attrs() - attrs['audited'] = False - with self.firewall_rule(name='fwr1') as fwr1, \ - self.firewall_rule(name='fwr2') as fwr2, \ - self.firewall_rule(name='fwr3') as fwr3: - fr1 = [fwr1, fwr2, fwr3] - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - attrs['id'] = fwp_id - 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_from_policy_failures(self): - with self.firewall_rule(name='fwr1') as fr1: - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - fw_rule_ids = [fr1['firewall_rule']['id']] - 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 rule that does not exist - self._rule_action('remove', fwp_id, '123', - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None) - # test removing rule with bad request - self._rule_action('remove', fwp_id, '123', - expected_code=webob.exc.HTTPBadRequest.code, - expected_body=None, body_data={}) - # test removing rule with firewall_rule_id set to None - self._rule_action('remove', fwp_id, '123', - expected_code=webob.exc.HTTPNotFound.code, - expected_body=None, - body_data={'firewall_rule_id': None}) - - def test_show_firewall_rule_by_name(self): - with self.firewall_rule(name='firewall_Rule1') as fw_rule: - res = self._show('firewall_rules', - fw_rule['firewall_rule']['id']) - self.assertEqual('firewall_Rule1', res['firewall_rule']['name']) - - def test_show_firewall_policy_by_name(self): - with self.firewall_policy(name='firewall_Policy1') as fw_policy: - res = self._show('firewall_policies', - fw_policy['firewall_policy']['id']) - self.assertEqual( - 'firewall_Policy1', res['firewall_policy']['name']) - - def test_show_firewall_group_by_name(self): - with self.firewall_group(name='fireWall1') as fw: - res = self._show('firewall_groups', fw['firewall_group']['id']) - self.assertEqual('fireWall1', res['firewall_group']['name']) - - def test_set_port_in_use_for_firewall_group(self): - fwg_db = {'id': 'fake_id'} - new_ports = {'ports': ['fake_port1', 'fake_port2']} - m_context = self._get_admin_context() - with mock.patch.object(m_context.session, 'add', - side_effect=[None, f_exc.FirewallGroupPortInUse( - port_ids=['fake_port2'])]): - self.assertRaises(f_exc.FirewallGroupPortInUse, - self.db._set_ports_for_firewall_group, - m_context, - fwg_db, - new_ports) - - def test_set_port_for_default_firewall_group(self): - ctx = self._get_nonadmin_context() - default_fwg = self._build_default_fwg(ctx=ctx) - port_args = { - 'tenant_id': ctx.tenant_id, - 'device_owner': 'compute:nova', - 'binding:vif_type': 'ovs', - } - self.plugin._is_supported_l2_port = mock.Mock( - return_value=True) - with self.port(**port_args) as port1, self.port(**port_args) as port2: - port1_id = port1['port']['id'] - port2_id = port2['port']['id'] - port_ids = [port1_id, port2_id] - - self.plugin.update_firewall_group( - ctx, - default_fwg['id'], - {'firewall_group': {'ports': port_ids}}, - ) - default_fwg = self.plugin.get_firewall_group(ctx, - default_fwg['id']) - self.assertEqual(sorted(port_ids), sorted(default_fwg['ports'])) diff --git a/neutron_fwaas/tests/unit/privileged/__init__.py b/neutron_fwaas/tests/unit/privileged/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/privileged/netfilter_log/__init__.py b/neutron_fwaas/tests/unit/privileged/netfilter_log/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/privileged/netfilter_log/test_libnetfilter_log.py b/neutron_fwaas/tests/unit/privileged/netfilter_log/test_libnetfilter_log.py deleted file mode 100644 index 8b24090d6..000000000 --- a/neutron_fwaas/tests/unit/privileged/netfilter_log/test_libnetfilter_log.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 socket - -import cffi -import mock -from neutron.tests import base -from oslo_utils import importutils -import testtools - -# mock for dlopen -cffi.FFI = mock.Mock() -cffi.FFI.dlopen = mock.Mock(return_value=mock.Mock()) -lib_log = importutils.import_module( - 'neutron_fwaas.privileged.netfilter_log.libnetfilter_log' -) - - -class NFLogAppTestCase(base.BaseTestCase): - - def setUp(self): - - self.nflog_app = lib_log.NFLogApp() - self.spawn = mock.patch('eventlet.spawn').start() - super(NFLogAppTestCase, self).setUp() - - def test_register_packet_handler(self): - def fake_method(): - pass - self.nflog_app.register_packet_handler(fake_method) - self.assertEqual(fake_method, self.nflog_app.callback) - - def test_unregister_packet_handler(self): - def fake_method(): - pass - self.nflog_app.register_packet_handler(fake_method) - self.assertEqual(fake_method, self.nflog_app.callback) - self.nflog_app.unregister_packet_handler() - self.assertIsNone(self.nflog_app.callback) - - -class NFLogWrapper(base.BaseTestCase): - - def setUp(self): - super(NFLogWrapper, self).setUp() - lib_log.libnflog = mock.Mock() - lib_log.ffi = mock.Mock() - - def test_open_failed(self): - lib_log.libnflog.nflog_open.return_value = None - handle = lib_log.NFLogWrapper.get_instance() - with testtools.ExpectedException(Exception): - handle.open() - lib_log.libnflog.nflog_open.assert_called_once_with() - lib_log.libnflog.nflog_unbind_pf.assert_not_called() - lib_log.libnflog.nflog_bind_pf.assert_not_called() - handle.close() - - def test_bind_pf(self): - nflog_handle = mock.Mock() - lib_log.libnflog.nflog_open.return_value = nflog_handle - handle = lib_log.NFLogWrapper.get_instance() - handle.open() - lib_log.libnflog.nflog_open.assert_called_once_with() - calls = [mock.call(nflog_handle, socket.AF_INET), - mock.call(nflog_handle, socket.AF_INET6)] - lib_log.libnflog.nflog_unbind_pf.assert_has_calls( - calls, any_order=True) - lib_log.libnflog.nflog_bind_pf.assert_has_calls( - calls, any_order=True) - - def test_bind_group_set_mode_failed(self): - nflog_handle = mock.Mock() - g_handle = mock.Mock() - lib_log.libnflog.nflog_open.return_value = nflog_handle - lib_log.libnflog.nflog_bind_group.return_value = g_handle - lib_log.libnflog.nflog_set_mode.return_value = -1 - handle = lib_log.NFLogWrapper.get_instance() - with testtools.ExpectedException(Exception): - handle.open() - handle.bind_group(0) - lib_log.libnflog.nflog_open.assert_called_once_with() - lib_log.libnflog.nflog_bind_group.assert_called_once_with( - nflog_handle, 0) - lib_log.libnflog.nflog_set_mode.assert_called_once_with( - g_handle, 0x2, 0xffff) - lib_log.libnflog.nflog_callback_register.assert_not_called() - - def test_bind_group_set_callback_failed(self): - nflog_handle = mock.Mock() - g_handle = mock.Mock() - lib_log.libnflog.nflog_open.return_value = nflog_handle - lib_log.libnflog.nflog_bind_group.return_value = g_handle - lib_log.libnflog.nflog_set_mode.return_value = 0 - lib_log.libnflog.nflog_callback_register.return_value = -1 - handle = lib_log.NFLogWrapper.get_instance() - with testtools.ExpectedException(Exception): - handle.open() - handle.bind_group(0) - lib_log.libnflog.nflog_open.assert_called_once_with() - lib_log.libnflog.nflog_bind_group.assert_called_once_with( - nflog_handle, 0) - lib_log.libnflog.nflog_set_mode.assert_called_once_with( - g_handle, 0x2, 0xffff) - lib_log.libnflog.nflog_callback_register.assert_called_once_with( - g_handle, handle.cb, lib_log.ffi.NULL) - - def test_bind_group_pass(self): - nflog_handle = mock.Mock() - g_handle = mock.Mock() - lib_log.libnflog.nflog_open.return_value = nflog_handle - lib_log.libnflog.nflog_bind_group.return_value = g_handle - lib_log.libnflog.nflog_set_mode.return_value = 0 - lib_log.libnflog.nflog_callback_register.return_value = 0 - handle = lib_log.NFLogWrapper.get_instance() - handle.open() - handle.bind_group(0) - lib_log.libnflog.nflog_open.assert_called_once_with() - lib_log.libnflog.nflog_bind_group.assert_called_once_with( - nflog_handle, 0) - lib_log.libnflog.nflog_set_mode.assert_called_once_with( - g_handle, 0x2, 0xffff) - lib_log.libnflog.nflog_callback_register.assert_called_once_with( - g_handle, handle.cb, lib_log.ffi.NULL) diff --git a/neutron_fwaas/tests/unit/privileged/test_netlink_lib.py b/neutron_fwaas/tests/unit/privileged/test_netlink_lib.py deleted file mode 100644 index 8c96fa04e..000000000 --- a/neutron_fwaas/tests/unit/privileged/test_netlink_lib.py +++ /dev/null @@ -1,329 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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 mock -import testtools - -from neutron_lib import constants - -from neutron_fwaas.privileged import netlink_constants as nl_constants -from neutron_fwaas.privileged import netlink_lib as nl_lib -from neutron_fwaas.tests import base - - -FAKE_ENTRY = {'ipversion': 4, 'protocol': 'icmp', - 'type': '8', 'code': '0', 'id': 1234, - 'src': '1.1.1.1', 'dst': '2.2.2.2'} -FAKE_TCP_ENTRY = {'ipversion': 4, 'protocol': 'tcp', - 'sport': 1, 'dport': 2, - 'src': '1.1.1.1', 'dst': '2.2.2.2'} -FAKE_UDP_ENTRY = {'ipversion': 4, 'protocol': 'udp', - 'sport': 1, 'dport': 2, - 'src': '1.1.1.1', 'dst': '2.2.2.2'} -FAKE_ICMPV6_ENTRY = {'ipversion': 6, 'protocol': 'ipv6-icmp', - 'sport': 1, 'dport': 2, 'type': '8', 'code': '0', - 'id': 3456, 'src': '10::10', 'dst': '20::20'} - - -class NetlinkLibTestCase(base.BaseTestCase): - def setUp(self): - super(NetlinkLibTestCase, self).setUp() - nl_lib.nfct = mock.Mock() - nl_lib.libc = mock.Mock() - - def test_open_new_conntrack_handler_failed(self): - nl_lib.nfct.nfct_open.return_value = None - with testtools.ExpectedException(nl_lib.ConntrackOpenFailedExit): - with nl_lib.ConntrackManager(): - nl_lib.nfct.nfct_open.assert_called_once() - nl_lib.nfct.nfct_close.assert_not_called() - - def test_open_new_conntrack_handler_pass(self): - with nl_lib.ConntrackManager(): - nl_lib.nfct.nfct_open.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_list_entries(self): - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.list_entries() - nl_lib.nfct.nfct_callback_register.assert_called_once() - nl_lib.nfct.nfct_query.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_flush_entries(self): - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.flush_entries() - nl_lib.nfct.nfct_query.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_new_failed(self): - nl_lib.nfct.nfct_new.return_value = None - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_ENTRY]) - nl_lib.nfct.nfct_new.assert_called_once() - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_delete_icmp_entry(self): - conntrack_filter = mock.Mock() - nl_lib.nfct.nfct_new.return_value = conntrack_filter - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_ENTRY]) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['icmp']), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_CODE, - int(FAKE_ENTRY['code'])), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_TYPE, - int(FAKE_ENTRY['type'])) - ] - nl_lib.nfct.nfct_set_attr_u8.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_ID, - nl_lib.libc.htons(FAKE_ENTRY['id'])), - ] - nl_lib.nfct.nfct_set_attr_u16.assert_has_calls(calls) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_ENTRY['dst'], 4)), - ] - nl_lib.nfct.nfct_set_attr.assert_has_calls(calls, any_order=True) - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_delete_icmpv6_entry(self): - conntrack_filter = mock.Mock() - nl_lib.nfct.nfct_new.return_value = conntrack_filter - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_ICMPV6_ENTRY]) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[6]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['ipv6-icmp']), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_CODE, - int(FAKE_ICMPV6_ENTRY['code'])), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_TYPE, - int(FAKE_ICMPV6_ENTRY['type'])) - ] - nl_lib.nfct.nfct_set_attr_u8.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_ID, - nl_lib.libc.htons(FAKE_ICMPV6_ENTRY['id'])), - ] - nl_lib.nfct.nfct_set_attr_u16.assert_has_calls(calls) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_IPV6_SRC, - conntrack._convert_text_to_binary( - FAKE_ENTRY['src'], 6)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV6_DST, - conntrack._convert_text_to_binary( - FAKE_ENTRY['dst'], 6)), - ] - nl_lib.nfct.nfct_set_attr.assert_has_calls(calls, any_order=True) - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_delete_udp_entry(self): - conntrack_filter = mock.Mock() - nl_lib.nfct.nfct_new.return_value = conntrack_filter - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_UDP_ENTRY]) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['udp']) - ] - nl_lib.nfct.nfct_set_attr_u8.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_SRC, - nl_lib.libc.htons(FAKE_UDP_ENTRY['sport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_DST, - nl_lib.libc.htons(FAKE_UDP_ENTRY['dport'])) - ] - nl_lib.nfct.nfct_set_attr_u16.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_UDP_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_UDP_ENTRY['dst'], 4)), - ] - nl_lib.nfct.nfct_set_attr.assert_has_calls(calls, any_order=True) - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_delete_tcp_entry(self): - conntrack_filter = mock.Mock() - nl_lib.nfct.nfct_new.return_value = conntrack_filter - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_TCP_ENTRY]) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['tcp']) - ] - nl_lib.nfct.nfct_set_attr_u8.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_SRC, - nl_lib.libc.htons(FAKE_TCP_ENTRY['sport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_DST, - nl_lib.libc.htons(FAKE_TCP_ENTRY['dport'])) - ] - nl_lib.nfct.nfct_set_attr_u16.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_TCP_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_TCP_ENTRY['dst'], 4)), - ] - nl_lib.nfct.nfct_set_attr.assert_has_calls(calls, any_order=True) - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() - - def test_conntrack_delete_entries(self): - conntrack_filter = mock.Mock() - nl_lib.nfct.nfct_new.return_value = conntrack_filter - with nl_lib.ConntrackManager() as conntrack: - nl_lib.nfct.nfct_open.assert_called_once() - conntrack.delete_entries([FAKE_ENTRY, - FAKE_TCP_ENTRY, - FAKE_UDP_ENTRY]) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['tcp']), - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['udp']), - mock.call(conntrack_filter, - nl_constants.ATTR_L3PROTO, - nl_constants.IPVERSION_SOCKET[4]), - mock.call(conntrack_filter, - nl_constants.ATTR_L4PROTO, - constants.IP_PROTOCOL_MAP['icmp']), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_CODE, - int(FAKE_ENTRY['code'])), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_TYPE, - int(FAKE_ENTRY['type'])) - ] - nl_lib.nfct.nfct_set_attr_u8.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_SRC, - nl_lib.libc.htons(FAKE_TCP_ENTRY['sport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_DST, - nl_lib.libc.htons(FAKE_TCP_ENTRY['dport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_SRC, - nl_lib.libc.htons(FAKE_UDP_ENTRY['sport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_PORT_DST, - nl_lib.libc.htons(FAKE_UDP_ENTRY['dport'])), - mock.call(conntrack_filter, - nl_constants.ATTR_ICMP_ID, - nl_lib.libc.htons(FAKE_ENTRY['id'])), - ] - nl_lib.nfct.nfct_set_attr_u16.assert_has_calls(calls, - any_order=True) - calls = [ - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_TCP_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_TCP_ENTRY['dst'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_UDP_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_UDP_ENTRY['dst'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_SRC, - conntrack._convert_text_to_binary( - FAKE_ENTRY['src'], 4)), - mock.call(conntrack_filter, - nl_constants.ATTR_IPV4_DST, - conntrack._convert_text_to_binary( - FAKE_UDP_ENTRY['dst'], 4)), - ] - nl_lib.nfct.nfct_set_attr.assert_has_calls(calls, any_order=True) - nl_lib.nfct.nfct_destroy.assert_called_once() - nl_lib.nfct.nfct_close.assert_called_once() diff --git a/neutron_fwaas/tests/unit/privileged/test_utils.py b/neutron_fwaas/tests/unit/privileged/test_utils.py deleted file mode 100644 index 525df286c..000000000 --- a/neutron_fwaas/tests/unit/privileged/test_utils.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2017 Thales Services SAS -# 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 mock -import testtools - -from neutron_fwaas.privileged import utils -from neutron_fwaas.tests import base - - -class InNamespaceTest(base.BaseTestCase): - ORG_NETNS_FD = 124 - NEW_NETNS_FD = 421 - NEW_NETNS = 'newns' - - def setUp(self): - super(InNamespaceTest, self).setUp() - - # NOTE(cby): we should unmock os.open/close as early as possible - # because there are used in cleanups - open_patch = mock.patch('os.open', return_value=self.ORG_NETNS_FD) - self.open_mock = open_patch.start() - self.addCleanup(open_patch.stop) - - close_patch = mock.patch('os.close') - self.close_mock = close_patch.start() - self.addCleanup(close_patch.stop) - - self.setns_mock = mock.patch( - 'pyroute2.netns.setns').start() - - def test_in_namespace(self): - with utils.in_namespace(self.NEW_NETNS): - self.setns_mock.assert_called_once_with(self.NEW_NETNS) - - setns_calls = [mock.call(self.NEW_NETNS), mock.call(self.ORG_NETNS_FD)] - self.setns_mock.assert_has_calls(setns_calls) - - def test_in_no_namespace(self): - for namespace in ('', None): - with utils.in_namespace(namespace): - pass - self.setns_mock.assert_not_called() - self.close_mock.assert_not_called() - - def test_in_namespace_failed(self): - with testtools.ExpectedException(ValueError): - with utils.in_namespace(self.NEW_NETNS): - self.setns_mock.assert_called_once_with(self.NEW_NETNS) - raise ValueError - - setns_calls = [mock.call(self.NEW_NETNS), mock.call(self.ORG_NETNS_FD)] - self.setns_mock.assert_has_calls(setns_calls) - - def test_in_namespace_enter_failed(self): - self.setns_mock.side_effect = ValueError - with testtools.ExpectedException(ValueError): - with utils.in_namespace(self.NEW_NETNS): - self.fail('It should fail before we reach this code') - - self.setns_mock.assert_called_once_with(self.NEW_NETNS) - - def test_in_namespace_exit_failed(self): - self.setns_mock.side_effect = [self.NEW_NETNS_FD, ValueError] - with testtools.ExpectedException(utils.BackInNamespaceExit): - with utils.in_namespace(self.NEW_NETNS): - pass diff --git a/neutron_fwaas/tests/unit/services/__init__.py b/neutron_fwaas/tests/unit/services/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/__init__.py b/neutron_fwaas/tests/unit/services/firewall/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/noop/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/noop/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/noop/test_noop_driver.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/noop/test_noop_driver.py deleted file mode 100644 index fea3c29f3..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/noop/test_noop_driver.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2017 Mirantis 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 mock - -from neutron import manager -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - noop import noop_driver -from neutron_fwaas.tests import base - - -class TestNoopDriver(base.BaseTestCase): - def setUp(self): - super(TestNoopDriver, self).setUp() - mock_br = mock.Mock() - self.firewall = noop_driver.NoopFirewallL2Driver(mock_br) - - def test_basic_methods(self): - # just make sure it doesn't crash - fwg_mock = mock.Mock() - self.firewall.create_firewall_group(ports=[], firewall_group=fwg_mock) - self.firewall.update_firewall_group(ports=[], firewall_group=fwg_mock) - self.firewall.delete_firewall_group(ports=[], firewall_group=fwg_mock) - self.firewall.filter_defer_apply_on() - self.firewall.filter_defer_apply_off() - self.firewall.defer_apply() - self.firewall.ports - - def test_load_firewall_class(self): - res = manager.NeutronManager.load_class_for_provider( - 'neutron.agent.l2.firewall_drivers', 'noop') - self.assertEqual(res, noop_driver.NoopFirewallL2Driver) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_firewall.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_firewall.py deleted file mode 100644 index 156f00e4d..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_firewall.py +++ /dev/null @@ -1,694 +0,0 @@ -# Copyright 2017 Mirantis, 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. - -import mock -from neutron_lib import constants -import testtools - -from neutron.agent.common import ovs_lib -from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ - as ovs_consts -from neutron.plugins.ml2.drivers.openvswitch.agent import \ - ovs_agent_extension_api as ovs_ext_api -from neutron.tests import base - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import constants as fwaas_ovs_consts -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import exceptions -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import firewall as ovsfw - -TESTING_VLAN_TAG = 1 - - -def create_ofport(port_dict): - ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00', ofport=1, - port_name="port-name") - return ovsfw.OFPort(port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) - - -class TestCreateRegNumbers(base.BaseTestCase): - def test_no_registers_defined(self): - flow = {'foo': 'bar'} - ovsfw.create_reg_numbers(flow) - self.assertEqual({'foo': 'bar'}, flow) - - def test_both_registers_defined(self): - flow = {'foo': 'bar', 'reg_port': 1, 'reg_net': 2} - expected_flow = {'foo': 'bar', - 'reg{:d}'.format(fwaas_ovs_consts.REG_PORT): 1, - 'reg{:d}'.format(fwaas_ovs_consts.REG_NET): 2} - ovsfw.create_reg_numbers(flow) - self.assertEqual(expected_flow, flow) - - -class TestFirewallGroup(base.BaseTestCase): - def setUp(self): - super(TestFirewallGroup, self).setUp() - self.fwg = ovsfw.FirewallGroup('123') - self.fwg.members = {'type': [1, 2, 3, 4]} - - def test_update_rules(self): - ingress_rules = [{'foo-ingress': 'bar', 'rule': 'all'}, - {'bar-ingress': 'foo'}] - egress_rules = [{'foo-egress': '123456'}, {'bar-egress': 'bar'}] - self.fwg.update_rules(ingress_rules, egress_rules) - - self.assertEqual(ingress_rules, self.fwg.ingress_rules) - self.assertEqual(egress_rules, self.fwg.egress_rules) - - def test_update_rules_protocols(self): - # XXX FIXME(ivasilevskaya) figure out what this test does and fix - # appropriately - # leaving failing as it may be important - rules = [ - {'foo': 'bar', 'protocol': constants.PROTO_NAME_ICMP, - 'ethertype': constants.IPv4}, - {'foo': 'bar', 'protocol': constants.PROTO_NAME_ICMP, - 'ethertype': constants.IPv6}, - {'foo': 'bar', 'protocol': constants.PROTO_NAME_IPV6_ICMP_LEGACY, - 'ethertype': constants.IPv6}, - {'foo': 'bar', 'protocol': constants.PROTO_NAME_TCP}, - {'foo': 'bar', 'protocol': '94'}, - {'foo': 'bar', 'protocol': 'baz'}, - {'foo': 'no_proto'}] - self.fwg.update_rules(rules, []) - - self.assertEqual({'foo': 'no_proto'}, self.fwg.ingress_rules.pop()) - protos = [rule['protocol'] for rule in self.fwg.ingress_rules] - self.assertEqual([constants.PROTO_NUM_ICMP, - constants.PROTO_NUM_IPV6_ICMP, - constants.PROTO_NUM_IPV6_ICMP, - constants.PROTO_NUM_TCP, - 94, - 'baz'], protos) - - def test_get_ethertype_filtered_addresses(self): - addresses = self.fwg.get_ethertype_filtered_addresses('type') - expected_addresses = [1, 2, 3, 4] - self.assertEqual(expected_addresses, addresses) - - -class TestOFPort(base.BaseTestCase): - def setUp(self): - super(TestOFPort, self).setUp() - self.ipv4_addresses = ['10.0.0.1', '192.168.0.1'] - self.ipv6_addresses = ['fe80::f816:3eff:fe2e:1'] - port_dict = {'device': 1, - 'fixed_ips': [ - {'subnet_id': 's_%s' % ip, 'ip_address': ip} - for ip in self.ipv4_addresses + self.ipv6_addresses]} - self.port = create_ofport(port_dict) - - def test_ipv4_address(self): - ipv4_addresses = self.port.ipv4_addresses - self.assertEqual(self.ipv4_addresses, ipv4_addresses) - - def test_ipv6_address(self): - ipv6_addresses = self.port.ipv6_addresses - self.assertEqual(self.ipv6_addresses, ipv6_addresses) - - def test__get_allowed_pairs(self): - port = { - 'allowed_address_pairs': [ - {'mac_address': 'foo', 'ip_address': '10.0.0.1'}, - {'mac_address': 'bar', 'ip_address': '192.168.0.1'}, - {'mac_address': 'qux', 'ip_address': '169.254.0.0/16'}, - {'mac_address': 'baz', 'ip_address': '2003::f'}, - ]} - allowed_pairs_v4 = ovsfw.OFPort._get_allowed_pairs(port, version=4) - allowed_pairs_v6 = ovsfw.OFPort._get_allowed_pairs(port, version=6) - expected_aap_v4 = {('foo', '10.0.0.1'), ('bar', '192.168.0.1'), - ('qux', '169.254.0.0/16')} - expected_aap_v6 = {('baz', '2003::f')} - self.assertEqual(expected_aap_v4, allowed_pairs_v4) - self.assertEqual(expected_aap_v6, allowed_pairs_v6) - - def test__get_allowed_pairs_empty(self): - port = {} - allowed_pairs = ovsfw.OFPort._get_allowed_pairs(port, version=4) - self.assertFalse(allowed_pairs) - - def test_update(self): - old_port_dict = self.port.neutron_port_dict - new_port_dict = old_port_dict.copy() - added_ips = [1, 2, 3] - new_port_dict.update({ - 'fixed_ips': added_ips, - 'allowed_address_pairs': [ - {'mac_address': '00:00:00:00:00:01', - 'ip_address': '192.168.0.1'}, - {'mac_address': '00:00:00:00:00:01', - 'ip_address': '2003::f'}], - }) - self.port.update(new_port_dict) - self.assertEqual(new_port_dict, self.port.neutron_port_dict) - self.assertIsNot(new_port_dict, self.port.neutron_port_dict) - self.assertEqual(added_ips, self.port.fixed_ips) - self.assertEqual({('00:00:00:00:00:01', '192.168.0.1')}, - self.port.allowed_pairs_v4) - self.assertIn(('00:00:00:00:00:01', '2003::f'), - self.port.allowed_pairs_v6) - - -class TestFWGPortMap(base.BaseTestCase): - def setUp(self): - super(TestFWGPortMap, self).setUp() - self.map = ovsfw.FWGPortMap() - - def test_get_or_create_fwg_existing_fwg(self): - self.map.fw_groups['id'] = mock.sentinel - fwg = self.map.get_or_create_fwg('id') - self.assertIs(mock.sentinel, fwg) - - def test_get_or_create_fwg_nonexisting_fwg(self): - with mock.patch.object(ovsfw, 'FirewallGroup') as fwg_mock: - fwg = self.map.get_or_create_fwg('id') - self.assertEqual(fwg_mock.return_value, fwg) - - def _check_port(self, port_id, expected_id): - port = self.map.ports[port_id] - expected_fwg = self.map.fw_groups[expected_id] - self.assertEqual(expected_fwg, port.fw_group) - - def _check_fwg(self, fwg_id, expected_port_ids): - fwg = self.map.fw_groups[fwg_id] - expected_ports = {self.map.ports[port_id] - for port_id in expected_port_ids} - self.assertEqual(expected_ports, fwg.ports) - - def _create_ports_and_fwgs(self): - fwg_1 = ovsfw.FirewallGroup(1) - fwg_2 = ovsfw.FirewallGroup(2) - fwg_3 = ovsfw.FirewallGroup(3) - port_a = create_ofport({'device': 'a'}) - port_b = create_ofport({'device': 'b'}) - port_c = create_ofport({'device': 'c'}) - self.map.ports = {'a': port_a, 'b': port_b, 'c': port_c} - self.map.fw_groups = {1: fwg_1, 2: fwg_2, 3: fwg_3} - # XXX FIXME(ivasilevskaya) see note for OFPORT - port_a.fw_group = fwg_1 - port_b.fw_group = fwg_2 - port_c.fw_group = fwg_2 - fwg_1.ports = {port_a} - fwg_2.ports = {port_b, port_c} - - def test_create_port(self): - """Create a port and assign it to firewall group - - It is implied that 1 port can be assigned to one firewall group only - """ - port = create_ofport({'device': 'a'}) - port_dict = {'some-port-attributes-go-here': 42, - 'firewall_group': 1} - self.map.create_port(port, port_dict) - self._check_port('a', 1) - self._check_fwg(1, ['a']) - - def test_update_port_another_fwg_added(self): - """Update a port with new firewall group id - - It is implied that 1 port can be assigned to one firewall group only - """ - self._create_ports_and_fwgs() - self._check_port('b', 2) - port_dict = {'firewall_group': 3} - self.map.update_port(self.map.ports['b'], port_dict) - self._check_port('a', 1) - self._check_port('b', 3) - self._check_port('c', 2) - self._check_fwg(1, ['a']) - self._check_fwg(2, ['c']) - self._check_fwg(3, ['b']) - - def test_remove_port(self): - self._create_ports_and_fwgs() - self.map.remove_port(self.map.ports['c']) - self._check_port('b', 2) - self._check_fwg(1, ['a']) - self._check_fwg(2, ['b']) - self.assertNotIn('c', self.map.ports) - - def test_update_rules(self): - """Just make sure it doesn't crash""" - self.map.update_rules(42, [], []) - - def test_update_members(self): - """Just make sure it doesn't crash""" - self.map.update_members(42, []) - - -class FakeOVSPort(object): - def __init__(self, name, port, mac): - self.port_name = name - self.ofport = port - self.vif_mac = mac - - -class TestOVSFirewallDriver(base.BaseTestCase): - def setUp(self): - super(TestOVSFirewallDriver, self).setUp() - mock_bridge = mock.patch.object( - ovs_lib, 'OVSBridge', autospec=True).start() - mock_agent_api = mock.patch.object( - ovs_ext_api.OVSAgentExtensionAPI, 'request_int_br', - return_value=mock_bridge).start() - self.firewall = ovsfw.OVSFirewallDriver(mock_agent_api) - self.mock_bridge = self.firewall.int_br - self.mock_bridge.reset_mock() - self.fake_ovs_port = FakeOVSPort('port', 1, '00:00:00:00:00:00') - self.mock_bridge.br.get_vif_port_by_id.return_value = \ - self.fake_ovs_port - - def _prepare_firewall_group(self): - ingress_rules = [ - {'position': '1', - 'protocol': 'tcp', - 'ip_version': 4, - 'destination_port': '123', - 'enabled': True, - 'action': 'allow', - 'id': 'fake-fw-rule1'} - ] - egress_rules = [ - {'position': '2', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'allow', - 'id': 'fake-fw-rule2'}, - {'position': '3', - 'protocol': 'tcp', - 'ip_version': 6, - 'enabled': True, - 'action': 'allow', - 'id': 'fake-fw-rule3'}] - self.firewall.update_firewall_group_rules(1, ingress_rules, []) - self.firewall.update_firewall_group_rules(2, [], egress_rules) - - @property - def port_ofport(self): - return self.mock_bridge.br.get_vif_port_by_id.return_value.ofport - - @property - def port_mac(self): - return self.mock_bridge.br.get_vif_port_by_id.return_value.vif_mac - - def test_initialize_bridge(self): - br = self.firewall.initialize_bridge(self.mock_bridge) - self.assertEqual(br, self.mock_bridge.deferred.return_value) - - def test__add_flow_dl_type_formatted_to_string(self): - dl_type = 0x0800 - self.firewall._add_flow(dl_type=dl_type) - - def test__add_flow_registers_are_replaced(self): - self.firewall._add_flow(in_port=1, reg_port=1, reg_net=2) - expected_calls = {'in_port': 1, - 'reg{:d}'.format(fwaas_ovs_consts.REG_PORT): 1, - 'reg{:d}'.format(fwaas_ovs_consts.REG_NET): 2} - self.mock_bridge.br.add_flow.assert_called_once_with( - **expected_calls) - - def test__drop_all_unmatched_flows(self): - self.firewall._drop_all_unmatched_flows() - expected_calls = [ - mock.call(actions='drop', priority=0, - table=fwaas_ovs_consts.FW_BASE_EGRESS_TABLE), - mock.call(actions='drop', priority=0, - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE), - mock.call(actions='drop', priority=0, - table=fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - mock.call(actions='drop', priority=0, - table=fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - mock.call(actions='drop', priority=0, - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE)] - actual_calls = self.firewall.int_br.br.add_flow.call_args_list - self.assertEqual(expected_calls, actual_calls) - - def test_get_or_create_ofport_non_existing(self): - port_dict = { - 'device': 'port-id', - 'firewall_group': 123, - 'lvlan': TESTING_VLAN_TAG, - } - port = self.firewall.get_or_create_ofport(port_dict) - port_dict = { - 'device': 'port-id', - 'firewall_group': 456, - 'lvlan': TESTING_VLAN_TAG, - } - port = self.firewall.get_or_create_ofport(port_dict) - sg1, sg2 = sorted( - self.firewall.fwg_port_map.fw_groups.values(), - key=lambda x: x.id) - self.assertIn(port, self.firewall.fwg_port_map.ports.values()) - self.assertEqual(port.fw_group, sg2) - self.assertEqual(set(), sg1.ports) - self.assertIn(port, sg2.ports) - - def test_get_or_create_ofport_existing(self): - port_dict = { - 'device': 'port-id', - 'firewall_group': 123} - of_port = create_ofport(port_dict) - self.firewall.fwg_port_map.ports[of_port.id] = of_port - port = self.firewall.get_or_create_ofport(port_dict) - [sg1] = sorted(self.firewall.fwg_port_map.fw_groups.values(), - key=lambda x: x.id) - self.assertIs(of_port, port) - self.assertIn(port, self.firewall.fwg_port_map.ports.values()) - self.assertEqual(port.fw_group, sg1) - self.assertIn(port, sg1.ports) - - def test_get_or_create_ofport_changed(self): - port_dict = { - 'device': 'port-id', - 'firewall_group': 123} - of_port = create_ofport(port_dict) - self.firewall.fwg_port_map.ports[of_port.id] = of_port - fake_ovs_port = FakeOVSPort('port', 2, '00:00:00:00:00:00') - self.mock_bridge.br.get_vif_port_by_id.return_value = \ - fake_ovs_port - port = self.firewall.get_or_create_ofport(port_dict) - self.assertEqual(port.ofport, 2) - - def test_get_or_create_ofport_missing(self): - port_dict = { - 'device': 'port-id', - 'firewall_group': 123} - self.mock_bridge.br.get_vif_port_by_id.return_value = None - with testtools.ExpectedException(exceptions.OVSFWaaSPortNotFound): - self.firewall.get_or_create_ofport(port_dict) - - def test_get_or_create_ofport_missing_nocreate(self): - port_dict = { - 'device': 'port-id', - 'firewall_group': 123} - self.mock_bridge.br.get_vif_port_by_id.return_value = None - self.assertIsNone(self.firewall.get_ofport(port_dict)) - self.assertFalse(self.mock_bridge.br.get_vif_port_by_id.called) - - def test_is_port_managed_managed_port(self): - port_dict = {'device': 'port-id'} - self.firewall.fwg_port_map.ports[port_dict['device']] = object() - is_managed = self.firewall.is_port_managed(port_dict) - self.assertTrue(is_managed) - - def test_is_port_managed_not_managed_port(self): - port_dict = {'device': 'port-id'} - is_managed = self.firewall.is_port_managed(port_dict) - self.assertFalse(is_managed) - - def test_prepare_port_filter(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'fixed_ips': [{'subnet_id': "some_subnet_id_here", - 'ip_address': "10.0.0.1"}], - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.prepare_port_filter(port_dict) - exp_egress_classifier = mock.call( - actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' - 'resubmit(,{:d})'.format( - self.port_ofport, TESTING_VLAN_TAG, - fwaas_ovs_consts.FW_BASE_EGRESS_TABLE), - in_port=self.port_ofport, - priority=105, - table=ovs_consts.TRANSIENT_TABLE) - exp_ingress_classifier = mock.call( - actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' - 'strip_vlan,resubmit(,{:d})'.format( - self.port_ofport, TESTING_VLAN_TAG, - fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - dl_dst=self.port_mac, - dl_vlan='0x%x' % TESTING_VLAN_TAG, - priority=95, - table=ovs_consts.TRANSIENT_TABLE) - filter_rule = mock.call( - actions='ct(commit,zone=NXM_NX_REG6[0..15]),' - 'output:{:d},resubmit(,{:d})'.format( - self.port_ofport, - ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), - dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), - nw_proto=constants.PROTO_NUM_TCP, - priority=70, - reg5=self.port_ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED, - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - tcp_dst='0x007b') - calls = self.mock_bridge.br.add_flow.call_args_list - for call in exp_ingress_classifier, exp_egress_classifier, filter_rule: - self.assertIn(call, calls) - - def test_prepare_port_filter_in_coexistence_mode(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'fixed_ips': [{'subnet_id': "some_subnet_id_here", - 'ip_address': "10.0.0.1"}], - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.sg_with_ovs = True - self.firewall.prepare_port_filter(port_dict) - exp_egress_classifier = mock.call( - actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' - 'resubmit(,{:d})'.format( - self.port_ofport, TESTING_VLAN_TAG, - fwaas_ovs_consts.FW_BASE_EGRESS_TABLE), - in_port=self.port_ofport, - priority=105, - table=ovs_consts.TRANSIENT_TABLE) - exp_ingress_classifier = mock.call( - actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' - 'strip_vlan,resubmit(,{:d})'.format( - self.port_ofport, TESTING_VLAN_TAG, - fwaas_ovs_consts.FW_BASE_INGRESS_TABLE), - dl_dst=self.port_mac, - dl_vlan='0x%x' % TESTING_VLAN_TAG, - priority=95, - table=ovs_consts.TRANSIENT_TABLE) - filter_rule = mock.call( - actions='resubmit(,{:d})'.format(ovs_consts.RULES_INGRESS_TABLE), - dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), - nw_proto=constants.PROTO_NUM_TCP, - priority=70, - reg5=self.port_ofport, - ct_state=fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED, - table=fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - tcp_dst='0x007b') - calls = self.mock_bridge.br.add_flow.call_args_list - for call in exp_ingress_classifier, exp_egress_classifier, filter_rule: - self.assertIn(call, calls) - - def test_prepare_port_filter_port_security_disabled(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'port_security_enabled': False} - self._prepare_firewall_group() - with mock.patch.object( - self.firewall, 'initialize_port_flows') as m_init_flows: - self.firewall.prepare_port_filter(port_dict) - self.assertFalse(m_init_flows.called) - - def test_prepare_port_filter_initialized_port(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.prepare_port_filter(port_dict) - self.assertFalse(self.mock_bridge.br.delete_flows.called) - self.firewall.prepare_port_filter(port_dict) - self.assertTrue(self.mock_bridge.br.delete_flows.called) - - def test_update_port_filter(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.prepare_port_filter(port_dict) - port_dict['firewall_group'] = 2 - self.mock_bridge.reset_mock() - - self.firewall.update_port_filter(port_dict) - self.assertTrue(self.mock_bridge.br.delete_flows.called) - filter_rules = [ - mock.call( - actions='resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), - nw_proto=constants.PROTO_NUM_UDP, - priority=71, - ct_state=fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED, - reg5=self.port_ofport, - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE), - # XXX FIXME NOTE(ivasilevskaya) this test originally tested that - # flows for SG with remote_group=this group were generated with - # proper conjunction action. If the original idea that conj_manager - # isn't needed for firewall groups proves to be wrong this needs to - # be revizited and properly fixed/covered with tests - mock.call( - actions='resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - ct_state=fwaas_ovs_consts.OF_STATE_ESTABLISHED_NOT_REPLY, - dl_type=mock.ANY, - nw_proto=6, - priority=70, reg5=self.port_ofport, - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE)] - self.mock_bridge.br.add_flow.assert_has_calls(filter_rules, - any_order=True) - - def test_update_port_filter_in_coexistence_mode(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.sg_with_ovs = True - self.firewall.prepare_port_filter(port_dict) - port_dict['firewall_group'] = 2 - self.mock_bridge.reset_mock() - - self.firewall.update_port_filter(port_dict) - self.assertTrue(self.mock_bridge.br.delete_flows.called) - filter_rules = [ - mock.call( - actions='resubmit(,{:d})'.format( - ovs_consts.RULES_EGRESS_TABLE), - dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), - nw_proto=constants.PROTO_NUM_UDP, - priority=71, - ct_state=fwaas_ovs_consts.OF_STATE_NEW_NOT_ESTABLISHED, - reg5=self.port_ofport, - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE), - # XXX FIXME NOTE(ivasilevskaya) this test originally tested that - # flows for SG with remote_group=this group were generated with - # proper conjunction action. If the original idea that conj_manager - # isn't needed for firewall groups proves to be wrong this needs to - # be revizited and properly fixed/covered with tests - mock.call( - actions='resubmit(,{:d})'.format( - ovs_consts.RULES_EGRESS_TABLE), - ct_state=fwaas_ovs_consts.OF_STATE_ESTABLISHED_NOT_REPLY, - dl_type=mock.ANY, - nw_proto=6, - priority=70, reg5=self.port_ofport, - table=fwaas_ovs_consts.FW_RULES_EGRESS_TABLE)] - self.mock_bridge.br.add_flow.assert_has_calls(filter_rules, - any_order=True) - - def test_update_port_filter_create_new_port_if_not_present(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1} - self._prepare_firewall_group() - with mock.patch.object( - self.firewall, 'prepare_port_filter') as prepare_mock: - self.firewall.update_port_filter(port_dict) - self.assertTrue(prepare_mock.called) - - def test_update_port_filter_port_security_disabled(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.prepare_port_filter(port_dict) - port_dict['port_security_enabled'] = False - self.firewall.update_port_filter(port_dict) - self.assertTrue(self.mock_bridge.br.delete_flows.called) - - def test_remove_port_filter(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self._prepare_firewall_group() - self.firewall.prepare_port_filter(port_dict) - self.firewall.remove_port_filter(port_dict) - self.assertTrue(self.mock_bridge.br.delete_flows.called) - self.assertIn(1, self.firewall.fwg_to_delete) - - def test_remove_port_filter_port_security_disabled(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1} - self.firewall.remove_port_filter(port_dict) - self.assertFalse(self.mock_bridge.br.delete_flows.called) - - def test_update_firewall_group_rules(self): - """Just make sure it doesn't crash""" - new_rules_ingress = [ - {'ip_version': 4, - 'action': 'allow', - 'protocol': constants.PROTO_NAME_ICMP}, - {'ip_version': 4, - 'direction': 'deny'}] - self.firewall.update_firewall_group_rules(1, new_rules_ingress, []) - - def test__cleanup_stale_sg(self): - self._prepare_firewall_group() - self.firewall.fwg_to_delete = {1} - with mock.patch.object(self.firewall.fwg_port_map, - 'delete_fwg') as delete_fwg_mock: - self.firewall._cleanup_stale_fwg() - delete_fwg_mock.assert_called_once_with(1) - - def test_get_ovs_port(self): - ovs_port = self.firewall.get_ovs_port('port_id') - self.assertEqual(self.fake_ovs_port, ovs_port) - - def test_get_ovs_port_non_existent(self): - self.mock_bridge.br.get_vif_port_by_id.return_value = None - with testtools.ExpectedException(exceptions.OVSFWaaSPortNotFound): - self.firewall.get_ovs_port('port_id') - - def test__initialize_egress_no_port_security_sends_to_egress(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': TESTING_VLAN_TAG} - self.firewall._initialize_egress_no_port_security(port_dict) - expected_call = mock.call( - table=ovs_consts.TRANSIENT_TABLE, - priority=100, - in_port=self.fake_ovs_port.ofport, - actions='set_field:%d->reg%d,' - 'set_field:%d->reg%d,' - 'resubmit(,%d)' % ( - self.fake_ovs_port.ofport, - fwaas_ovs_consts.REG_PORT, - TESTING_VLAN_TAG, - fwaas_ovs_consts.REG_NET, - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE) - ) - calls = self.mock_bridge.br.add_flow.call_args_list - self.assertIn(expected_call, calls) - - def test__initialize_egress_no_port_security_no_tag(self): - port_dict = {'device': 'port-id', - 'firewall_group': 1, - 'lvlan': None} - self.firewall._initialize_egress_no_port_security(port_dict) - self.assertFalse(self.mock_bridge.br.add_flow.called) - - def test__remove_egress_no_port_security_deletes_flow(self): - self.mock_bridge.br.db_get_val.return_value = {'tag': TESTING_VLAN_TAG} - self.firewall.fwg_port_map.unfiltered['port_id'] = 1 - self.firewall._remove_egress_no_port_security('port_id') - expected_call = mock.call( - table=ovs_consts.TRANSIENT_TABLE, - in_port=self.fake_ovs_port.ofport, - ) - calls = self.mock_bridge.br.delete_flows.call_args_list - self.assertIn(expected_call, calls) - - def test__remove_egress_no_port_security_no_tag(self): - self.mock_bridge.br.db_get_val.return_value = {} - self.firewall._remove_egress_no_port_security('port_id') - self.assertFalse(self.mock_bridge.br.delete_flows.called) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_rules.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_rules.py deleted file mode 100644 index a376b394b..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/l2/openvswitch_firewall/test_rules.py +++ /dev/null @@ -1,334 +0,0 @@ -# Copyright 2015 Red Hat, 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. - -import mock -from neutron_lib import constants - -from neutron.tests import base - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import constants as fwaas_ovs_consts -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import firewall as ovsfw -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\ - openvswitch_firewall import rules - -TESTING_VLAN_TAG = 1 - - -class TestIsValidPrefix(base.BaseTestCase): - def test_valid_prefix_ipv4(self): - is_valid = rules.is_valid_prefix('10.0.0.0/0') - self.assertTrue(is_valid) - - def test_invalid_prefix_ipv4(self): - is_valid = rules.is_valid_prefix('0.0.0.0/0') - self.assertFalse(is_valid) - - def test_valid_prefix_ipv6(self): - is_valid = rules.is_valid_prefix('ffff::0/0') - self.assertTrue(is_valid) - - def test_invalid_prefix_ipv6(self): - is_valid = rules.is_valid_prefix('0000:0::0/0') - self.assertFalse(is_valid) - is_valid = rules.is_valid_prefix('::0/0') - self.assertFalse(is_valid) - is_valid = rules.is_valid_prefix('::/0') - self.assertFalse(is_valid) - - -class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): - def setUp(self): - super(TestCreateFlowsFromRuleAndPort, self).setUp() - ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00') - ovs_port.ofport = 1 - port_dict = {'device': 'port_id'} - self.port = ovsfw.OFPort( - port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) - - self.create_flows_mock = mock.patch.object( - rules, 'create_protocol_flows').start() - - @property - def passed_flow_template(self): - return self.create_flows_mock.call_args[0][1] - - def _test_create_flows_from_rule_and_port_helper( - self, rule, expected_template): - rules.create_flows_from_rule_and_port(rule, self.port) - - self.assertEqual(expected_template, self.passed_flow_template) - - def test_create_flows_from_rule_and_port_no_ip_ipv4(self): - rule = { - 'ethertype': constants.IPv4, - 'direction': constants.INGRESS_DIRECTION, - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IP, - 'reg_port': self.port.ofport, - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - def test_create_flows_from_rule_and_port_src_and_dst_ipv4(self): - rule = { - 'ethertype': constants.IPv4, - 'direction': constants.INGRESS_DIRECTION, - 'source_ip_prefix': '192.168.0.0/24', - 'dest_ip_prefix': '10.0.0.1/32', - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IP, - 'reg_port': self.port.ofport, - 'nw_src': '192.168.0.0/24', - 'nw_dst': '10.0.0.1/32', - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - def test_create_flows_from_rule_and_port_src_and_dst_with_zero_ipv4(self): - rule = { - 'ethertype': constants.IPv4, - 'direction': constants.INGRESS_DIRECTION, - 'source_ip_prefix': '192.168.0.0/24', - 'dest_ip_prefix': '0.0.0.0/0', - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IP, - 'reg_port': self.port.ofport, - 'nw_src': '192.168.0.0/24', - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - def test_create_flows_from_rule_and_port_no_ip_ipv6(self): - rule = { - 'ethertype': constants.IPv6, - 'direction': constants.INGRESS_DIRECTION, - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IPV6, - 'reg_port': self.port.ofport, - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - def test_create_flows_from_rule_and_port_src_and_dst_ipv6(self): - rule = { - 'ethertype': constants.IPv6, - 'direction': constants.INGRESS_DIRECTION, - 'source_ip_prefix': '2001:db8:bbbb::1/64', - 'dest_ip_prefix': '2001:db8:aaaa::1/64', - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IPV6, - 'reg_port': self.port.ofport, - 'ipv6_src': '2001:db8:bbbb::1/64', - 'ipv6_dst': '2001:db8:aaaa::1/64', - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - def test_create_flows_from_rule_and_port_src_and_dst_with_zero_ipv6(self): - rule = { - 'ethertype': constants.IPv6, - 'direction': constants.INGRESS_DIRECTION, - 'source_ip_prefix': '2001:db8:bbbb::1/64', - 'dest_ip_prefix': '::/0', - } - expected_template = { - 'priority': 70, - 'dl_type': constants.ETHERTYPE_IPV6, - 'reg_port': self.port.ofport, - 'ipv6_src': '2001:db8:bbbb::1/64', - } - self._test_create_flows_from_rule_and_port_helper(rule, - expected_template) - - -class TestCreateProtocolFlows(base.BaseTestCase): - def setUp(self): - super(TestCreateProtocolFlows, self).setUp() - ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00') - ovs_port.ofport = 1 - port_dict = {'device': 'port_id'} - self.port = ovsfw.OFPort( - port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) - - def _test_create_protocol_flows_helper(self, direction, rule, - expected_flows): - flow_template = {'some_settings': 'foo'} - for flow in expected_flows: - flow.update(flow_template) - flows = rules.create_protocol_flows( - direction, flow_template, self.port, rule) - self.assertEqual(expected_flows, flows) - - def test_create_protocol_flows_ingress(self): - rule = {'protocol': constants.PROTO_NUM_TCP} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_INGRESS_TABLE, - 'actions': 'output:1', - 'nw_proto': constants.PROTO_NUM_TCP - }] - self._test_create_protocol_flows_helper( - constants.INGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_egress(self): - rule = {'protocol': constants.PROTO_NUM_TCP} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - 'nw_proto': constants.PROTO_NUM_TCP, - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_no_protocol(self): - rule = {} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_icmp6(self): - rule = {'ethertype': constants.IPv6, - 'protocol': constants.PROTO_NUM_IPV6_ICMP} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - 'nw_proto': constants.PROTO_NUM_IPV6_ICMP, - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_port_range(self): - rule = {'ethertype': constants.IPv4, - 'protocol': constants.PROTO_NUM_TCP, - 'port_range_min': 22, - 'port_range_max': 23} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - 'nw_proto': constants.PROTO_NUM_TCP, - 'tcp_dst': '0x0016/0xfffe' - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_icmp(self): - rule = {'ethertype': constants.IPv4, - 'protocol': constants.PROTO_NUM_ICMP, - 'port_range_min': 0} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - 'nw_proto': constants.PROTO_NUM_ICMP, - 'icmp_type': 0 - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - def test_create_protocol_flows_ipv6_icmp(self): - rule = {'ethertype': constants.IPv6, - 'protocol': constants.PROTO_NUM_IPV6_ICMP, - 'port_range_min': 5, - 'port_range_max': 0} - expected_flows = [{ - 'table': fwaas_ovs_consts.FW_RULES_EGRESS_TABLE, - 'actions': 'resubmit(,{:d})'.format( - fwaas_ovs_consts.FW_ACCEPT_OR_INGRESS_TABLE), - 'nw_proto': constants.PROTO_NUM_IPV6_ICMP, - 'icmp_type': 5, - 'icmp_code': 0, - }] - self._test_create_protocol_flows_helper( - constants.EGRESS_DIRECTION, rule, expected_flows) - - -class TestCreatePortRangeFlows(base.BaseTestCase): - def _test_create_port_range_flows_helper(self, expected_flows, rule): - flow_template = {'some_settings': 'foo'} - for flow in expected_flows: - flow.update(flow_template) - port_range_flows = rules.create_port_range_flows(flow_template, rule) - self.assertEqual(expected_flows, port_range_flows) - - def test_create_port_range_flows_with_source_and_destination(self): - rule = { - 'protocol': constants.PROTO_NUM_TCP, - 'source_port_range_min': 123, - 'source_port_range_max': 124, - 'port_range_min': 10, - 'port_range_max': 11, - } - expected_flows = [ - {'tcp_src': '0x007b', 'tcp_dst': '0x000a/0xfffe'}, - {'tcp_src': '0x007c', 'tcp_dst': '0x000a/0xfffe'}, - ] - self._test_create_port_range_flows_helper(expected_flows, rule) - - def test_create_port_range_flows_with_source(self): - rule = { - 'protocol': constants.PROTO_NUM_TCP, - 'source_port_range_min': 123, - 'source_port_range_max': 124, - } - expected_flows = [ - {'tcp_src': '0x007b'}, - {'tcp_src': '0x007c'}, - ] - self._test_create_port_range_flows_helper(expected_flows, rule) - - def test_create_port_range_flows_with_destination(self): - rule = { - 'protocol': constants.PROTO_NUM_TCP, - 'port_range_min': 10, - 'port_range_max': 11, - } - expected_flows = [ - {'tcp_dst': '0x000a/0xfffe'}, - ] - self._test_create_port_range_flows_helper(expected_flows, rule) - - def test_create_port_range_flows_without_port_range(self): - rule = { - 'protocol': constants.PROTO_NUM_TCP, - } - expected_flows = [] - self._test_create_port_range_flows_helper(expected_flows, rule) - - def test_create_port_range_with_icmp_protocol(self): - # NOTE: such call is prevented by create_protocols_flows - rule = { - 'protocol': constants.PROTO_NUM_ICMP, - 'port_range_min': 10, - 'port_range_max': 11, - } - expected_flows = [] - self._test_create_port_range_flows_helper(expected_flows, rule) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py deleted file mode 100644 index c0770de2c..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py +++ /dev/null @@ -1,520 +0,0 @@ -# Copyright (c) 2016 -# 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 copy - -import mock -from neutron.tests import base -from neutron.tests.unit.api.v2 import test_base as test_api_v2 - -import neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.\ - iptables_fwaas_v2 as fwaas - - -_uuid = test_api_v2._uuid -FAKE_SRC_PREFIX = '10.0.0.0/24' -FAKE_DST_PREFIX = '20.0.0.0/24' -FAKE_PROTOCOL = 'tcp' -FAKE_SRC_PORT = 5000 -FAKE_DST_PORT = 22 -FAKE_FW_ID = 'fake-fw-uuid' -FAKE_PORT_IDS = ('1_fake-port-uuid', '2_fake-port-uuid') -FW_LEGACY = 'legacy' -MAX_INTF_NAME_LEN = 14 - - -class IptablesFwaasTestCase(base.BaseTestCase): - def setUp(self): - super(IptablesFwaasTestCase, self).setUp() - self.iptables_cls_p = mock.patch( - 'neutron.agent.linux.iptables_manager.IptablesManager') - self.iptables_cls_p.start() - self.firewall = fwaas.IptablesFwaasDriver() - self.firewall.conntrack.delete_entries = mock.Mock() - self.firewall.conntrack.flush_entries = mock.Mock() - - def _fake_rules_v4(self, fwid, apply_list): - rule_list = [] - rule1 = {'enabled': True, - 'action': 'allow', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '80', - 'source_ip_address': '10.24.4.2', - 'id': 'fake-fw-rule1'} - rule2 = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '22', - 'id': 'fake-fw-rule2'} - rule3 = {'enabled': True, - 'action': 'reject', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '23', - 'id': 'fake-fw-rule3'} - ingress_chain = ('iv4%s' % fwid)[:11] - egress_chain = ('ov4%s' % fwid)[:11] - for router_info_inst, port_ids in apply_list: - v4filter_inst = router_info_inst.iptables_manager.ipv4['filter'] - v4filter_inst.chains.append(ingress_chain) - v4filter_inst.chains.append(egress_chain) - rule_list.append(rule1) - rule_list.append(rule2) - rule_list.append(rule3) - return rule_list - - def _fake_rules_v6(self, fwid, apply_list): - rule_list = [] - rule1 = {'enabled': True, - 'action': 'allow', - 'ip_version': 6, - 'protocol': 'icmp', - 'destination_ip_address': '2001:db8::2', - 'id': 'fake-fw-rule1'} - ingress_chain = ('iv6%s' % fwid)[:11] - egress_chain = ('ov6%s' % fwid)[:11] - for router_info_inst, port_ids in apply_list: - v6filter_inst = router_info_inst.iptables_manager.ipv6['filter'] - v6filter_inst.chains.append(ingress_chain) - v6filter_inst.chains.append(egress_chain) - rule_list.append(rule1) - return rule_list - - def _fake_firewall_no_rule(self): - rule_list = [] - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'egress_rule_list': rule_list, - 'ingress_rule_list': rule_list} - return fw_inst - - def _fake_firewall(self, rule_list): - _rule_list = copy.deepcopy(rule_list) - for rule in _rule_list: - rule['position'] = str(_rule_list.index(rule)) - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'egress_rule_list': _rule_list, - 'ingress_rule_list': _rule_list} - return fw_inst - - def _fake_firewall_with_admin_down(self, rule_list): - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': False, - 'tenant_id': 'tenant-uuid', - 'egress_rule_list': rule_list, - 'ingress_rule_list': rule_list} - return fw_inst - - def _fake_apply_list(self, router_count=1, distributed=False, - distributed_mode=None): - apply_list = [] - while router_count > 0: - iptables_inst = mock.Mock() - if distributed: - router_inst = {'distributed': distributed} - else: - router_inst = {} - v4filter_inst = mock.Mock() - v6filter_inst = mock.Mock() - v4filter_inst.chains = [] - v6filter_inst.chains = [] - iptables_inst.ipv4 = {'filter': v4filter_inst} - iptables_inst.ipv6 = {'filter': v6filter_inst} - router_info_inst = mock.Mock() - router_info_inst.iptables_manager = iptables_inst - router_info_inst.snat_iptables_manager = iptables_inst - if distributed_mode == 'dvr': - router_info_inst.rtr_fip_connect = True - router_info_inst.router = router_inst - apply_list.append((router_info_inst, FAKE_PORT_IDS)) - router_count -= 1 - return apply_list - - def _get_intf_name(self, if_prefix, port_id): - _name = "%s%s" % (if_prefix, port_id) - return _name[:MAX_INTF_NAME_LEN] - - def _setup_firewall_with_rules(self, func, router_count=1, - distributed=False, distributed_mode=None): - apply_list = self._fake_apply_list(router_count=router_count, - distributed=distributed, distributed_mode=distributed_mode) - rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall(rule_list) - if distributed: - if distributed_mode == 'dvr_snat': - if_prefix = 'sg-' - if distributed_mode == 'dvr': - if_prefix = 'rfp-' - else: - if_prefix = 'qr-' - distributed_mode = 'legacy' - func(distributed_mode, apply_list, firewall) - binary_name = fwaas.iptables_manager.binary_name - dropped = '%s-dropped' % binary_name - accepted = '%s-accepted' % binary_name - rejected = '%s-rejected' % binary_name - invalid_rule = '-m state --state INVALID -j %s' % dropped - est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT' - rule1 = '-p tcp -s 10.24.4.2/32 -m tcp --dport 80 -j %s' % accepted - rule2 = '-p tcp -m tcp --dport 22 -j %s' % dropped - rule3 = '-p tcp -m tcp --dport 23 -j %s' % rejected - ingress_chain = 'iv4%s' % firewall['id'] - egress_chain = 'ov4%s' % firewall['id'] - ipt_mgr_ichain = '%s-%s' % (binary_name, ingress_chain[:11]) - ipt_mgr_echain = '%s-%s' % (binary_name, egress_chain[:11]) - for router_info_inst, port_ids in apply_list: - v4filter_inst = router_info_inst.iptables_manager.ipv4['filter'] - calls = [mock.call.remove_chain('iv4fake-fw-uuid'), - mock.call.remove_chain('ov4fake-fw-uuid'), - mock.call.remove_chain('fwaas-default-policy'), - mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule( - 'fwaas-default-policy', '-j %s' % dropped), - mock.call.add_chain(ingress_chain), - mock.call.add_rule(ingress_chain, invalid_rule), - mock.call.add_rule(ingress_chain, est_rule), - mock.call.add_chain(egress_chain), - mock.call.add_rule(egress_chain, invalid_rule), - mock.call.add_rule(egress_chain, est_rule), - mock.call.add_rule(ingress_chain, rule1), - mock.call.add_rule(ingress_chain, rule2), - mock.call.add_rule(ingress_chain, rule3), - mock.call.add_rule(egress_chain, rule1), - mock.call.add_rule(egress_chain, rule2), - mock.call.add_rule(egress_chain, rule3) - ] - - for port in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port) - calls.append(mock.call.add_rule('FORWARD', - '-o %s -j %s' % (intf_name, ipt_mgr_ichain))) - for port in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port) - calls.append(mock.call.add_rule('FORWARD', - '-i %s -j %s' % (intf_name, ipt_mgr_echain))) - - for direction in ['o', 'i']: - for port_id in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port_id) - calls.append(mock.call.add_rule('FORWARD', - '-%s %s -j %s-fwaas-defau' % (direction, - intf_name, binary_name))) - v4filter_inst.assert_has_calls(calls) - - def _setup_firewall_with_rules_v6(self, func, router_count=1, - distributed=False, distributed_mode=None): - apply_list = self._fake_apply_list(router_count=router_count, - distributed=distributed, distributed_mode=distributed_mode) - rule_list = self._fake_rules_v6(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall(rule_list) - if distributed: - if distributed_mode == 'dvr_snat': - if_prefix = 'sg-' - if distributed_mode == 'dvr': - if_prefix = 'rfp-' - else: - if_prefix = 'qr-' - distributed_mode = 'legacy' - func(distributed_mode, apply_list, firewall) - binary_name = fwaas.iptables_manager.binary_name - dropped = '%s-dropped' % binary_name - accepted = '%s-accepted' % binary_name - invalid_rule = '-m state --state INVALID -j %s' % dropped - est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT' - rule1 = '-p ipv6-icmp -d 2001:db8::2/128 -j %s' % accepted - ingress_chain = 'iv6%s' % firewall['id'] - egress_chain = 'ov6%s' % firewall['id'] - ipt_mgr_ichain = '%s-%s' % (binary_name, ingress_chain[:11]) - ipt_mgr_echain = '%s-%s' % (binary_name, egress_chain[:11]) - for router_info_inst, port_ids in apply_list: - v6filter_inst = router_info_inst.iptables_manager.ipv6['filter'] - calls = [mock.call.remove_chain('iv6fake-fw-uuid'), - mock.call.remove_chain('ov6fake-fw-uuid'), - mock.call.remove_chain('fwaas-default-policy'), - mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule( - 'fwaas-default-policy', '-j %s' % dropped), - mock.call.add_chain(ingress_chain), - mock.call.add_rule(ingress_chain, invalid_rule), - mock.call.add_rule(ingress_chain, est_rule), - mock.call.add_chain(egress_chain), - mock.call.add_rule(egress_chain, invalid_rule), - mock.call.add_rule(egress_chain, est_rule), - mock.call.add_rule(ingress_chain, rule1), - mock.call.add_rule(egress_chain, rule1) - ] - for port in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port) - calls.append(mock.call.add_rule('FORWARD', - '-o %s -j %s' % (intf_name, ipt_mgr_ichain))) - for port in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port) - calls.append(mock.call.add_rule('FORWARD', - '-i %s -j %s' % (intf_name, ipt_mgr_echain))) - - for direction in ['o', 'i']: - for port_id in FAKE_PORT_IDS: - intf_name = self._get_intf_name(if_prefix, port_id) - calls.append(mock.call.add_rule('FORWARD', - '-%s %s -j %s-fwaas-defau' % (direction, - intf_name, binary_name))) - - v6filter_inst.assert_has_calls(calls) - - def test_create_firewall_group_no_rules(self): - apply_list = self._fake_apply_list() - first_ri = apply_list[0][0] - firewall = self._fake_firewall_no_rule() - self.firewall.create_firewall_group('legacy', apply_list, firewall) - binary_name = fwaas.iptables_manager.binary_name - dropped = '%s-dropped' % binary_name - invalid_rule = '-m state --state INVALID -j %s' % dropped - est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT' - for ip_version in (4, 6): - ingress_chain = ('iv%s%s' % (ip_version, firewall['id'])) - egress_chain = ('ov%s%s' % (ip_version, firewall['id'])) - calls = [mock.call.remove_chain( - 'iv%sfake-fw-uuid' % ip_version), - mock.call.remove_chain( - 'ov%sfake-fw-uuid' % ip_version), - mock.call.remove_chain('fwaas-default-policy'), - mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule( - 'fwaas-default-policy', '-j %s' % dropped), - mock.call.add_chain(ingress_chain), - mock.call.add_rule(ingress_chain, invalid_rule), - mock.call.add_rule(ingress_chain, est_rule), - mock.call.add_chain(egress_chain), - mock.call.add_rule(egress_chain, invalid_rule), - mock.call.add_rule(egress_chain, est_rule)] - - for port_id in FAKE_PORT_IDS: - for direction in ['o', 'i']: - mock.call.add_rule('FORWARD', - '-%s qr-%s -j %s-fwaas-defau' % (port_id, - direction, - binary_name)) - if ip_version == 4: - v4filter_inst = first_ri.iptables_manager.ipv4['filter'] - v4filter_inst.assert_has_calls(calls) - else: - v6filter_inst = first_ri.iptables_manager.ipv6['filter'] - v6filter_inst.assert_has_calls(calls) - - def test_create_firewall_group_with_rules(self): - self._setup_firewall_with_rules(self.firewall.create_firewall_group) - - def test_create_firewall_group_with_rules_v6(self): - self._setup_firewall_with_rules_v6(self.firewall.create_firewall_group) - - def test_create_firewall_group_with_rules_without_distributed_attr(self): - self._setup_firewall_with_rules(self.firewall.create_firewall_group, - distributed=None) - - def test_create_firewall_group_with_rules_two_routers(self): - self._setup_firewall_with_rules(self.firewall.create_firewall_group, - router_count=2) - - def test_update_firewall_group_with_rules(self): - self._setup_firewall_with_rules(self.firewall.update_firewall_group) - - def test_update_firewall_group_with_rules_v6(self): - self._setup_firewall_with_rules_v6(self.firewall.update_firewall_group) - - def test_update_firewall_group_with_rules_without_distributed_attr(self): - self._setup_firewall_with_rules(self.firewall.update_firewall_group, - distributed=None) - - def _test_delete_firewall_group(self, distributed=False): - apply_list = self._fake_apply_list(distributed=distributed) - first_ri = apply_list[0][0] - firewall = self._fake_firewall_no_rule() - self.firewall.delete_firewall_group('legacy', apply_list, firewall) - ingress_chain = 'iv4%s' % firewall['id'] - egress_chain = 'ov4%s' % firewall['id'] - calls = [mock.call.remove_chain(ingress_chain), - mock.call.remove_chain(egress_chain), - mock.call.remove_chain('fwaas-default-policy')] - first_ri.iptables_manager.ipv4['filter'].assert_has_calls(calls) - - def test_delete_firewall_group(self): - self._test_delete_firewall_group() - - def test_delete_firewall_group_without_distributed_attr(self): - self._test_delete_firewall_group(distributed=None) - - def test_create_firewall_group_with_admin_down(self): - apply_list = self._fake_apply_list() - first_ri = apply_list[0][0] - rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall_with_admin_down(rule_list) - binary_name = fwaas.iptables_manager.binary_name - dropped = '%s-dropped' % binary_name - self.firewall.create_firewall_group('legacy', apply_list, firewall) - calls = [mock.call.remove_chain('iv4fake-fw-uuid'), - mock.call.remove_chain('ov4fake-fw-uuid'), - mock.call.remove_chain('fwaas-default-policy'), - mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule('fwaas-default-policy', '-j %s' % dropped)] - first_ri.iptables_manager.ipv4['filter'].assert_has_calls(calls) - - def test_create_firewall_group_with_rules_dvr_snat(self): - self._setup_firewall_with_rules(self.firewall.create_firewall_group, - distributed=True, distributed_mode='dvr_snat') - - def test_update_firewall_group_with_rules_dvr_snat(self): - self._setup_firewall_with_rules(self.firewall.update_firewall_group, - distributed=True, distributed_mode='dvr_snat') - - def test_create_firewall_group_with_rules_dvr(self): - self._setup_firewall_with_rules(self.firewall.create_firewall_group, - distributed=True, distributed_mode='dvr') - - def test_update_firewall_group_with_rules_dvr(self): - self._setup_firewall_with_rules(self.firewall.update_firewall_group, - distributed=True, distributed_mode='dvr') - - def test_remove_conntrack_new_firewall(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - self.firewall.create_firewall_group(FW_LEGACY, apply_list, firewall) - for router_info_inst, port_ids in apply_list: - namespace = router_info_inst.iptables_manager.namespace - calls = [mock.call(namespace)] - self.firewall.conntrack.flush_entries.assert_has_calls(calls) - - def test_remove_conntrack_inserted_rule(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall(rule_list) - self.firewall.create_firewall_group(FW_LEGACY, apply_list, firewall) - self.firewall.pre_firewall = dict(firewall) - insert_rule = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'icmp', - 'id': 'fake-fw-rule'} - rule_list.insert(2, insert_rule) - firewall = self._fake_firewall(rule_list) - self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall) - rules_changed = [ - {'destination_port': '23', - 'position': '2', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'}, - {'destination_port': '23', - 'position': '3', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'} - ] * 2 # Egress and ingress rule lists - rules_inserted = [ - {'id': 'fake-fw-rule', - 'protocol': 'icmp', - 'ip_version': 4, - 'enabled': True, - 'action': 'deny', - 'position': '2'} - ] * 2 # Egress and ingress rule lists - for router_info_inst, port_ids in apply_list: - namespace = router_info_inst.iptables_manager.namespace - self.firewall.conntrack.delete_entries.assert_called_once_with( - rules_changed + rules_inserted, namespace - ) - - def test_remove_conntrack_removed_rule(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall(rule_list) - self.firewall.create_firewall_group(FW_LEGACY, apply_list, firewall) - self.firewall.pre_firewall = dict(firewall) - remove_rule = rule_list[1] - rule_list.remove(remove_rule) - firewall = self._fake_firewall(rule_list) - self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall) - rules_changed = [ - {'destination_port': '23', - 'position': '2', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'}, - {'destination_port': '23', - 'position': '1', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'} - ] * 2 # Egress and ingress rule lists - rules_removed = [ - {'enabled': True, - 'position': '1', - 'protocol': 'tcp', - 'id': 'fake-fw-rule2', - 'ip_version': 4, - 'action': 'deny', - 'destination_port': '22'} - ] * 2 # Egress and ingress rule lists - for router_info_inst, port_ids in apply_list: - namespace = router_info_inst.iptables_manager.namespace - self.firewall.conntrack.delete_entries.assert_called_once_with( - rules_changed + rules_removed, namespace - ) - - def test_remove_conntrack_changed_rule(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) - firewall = self._fake_firewall(rule_list) - self.firewall.create_firewall_group(FW_LEGACY, apply_list, firewall) - income_rule = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'tcp', - 'id': 'fake-fw-rule3'} - rule_list[2] = income_rule - firewall = self._fake_firewall(rule_list) - self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall) - rules_changed = [ - {'id': 'fake-fw-rule3', - 'enabled': True, - 'action': 'reject', - 'position': '2', - 'destination_port': '23', - 'ip_version': 4, - 'protocol': 'tcp'}, - {'position': '2', - 'enabled': True, - 'action': 'deny', - 'id': 'fake-fw-rule3', - 'ip_version': 4, - 'protocol': 'tcp'} - ] * 2 # Egress and ingress rule lists - for router_info_inst, port_ids in apply_list: - namespace = router_info_inst.iptables_manager.namespace - self.firewall.conntrack.delete_entries.assert_called_once_with( - rules_changed, namespace - ) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_legacy_conntrack.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_legacy_conntrack.py deleted file mode 100644 index 7650a0ca5..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_legacy_conntrack.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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 mock -import testtools - -from neutron.tests import base -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \ - import legacy_conntrack -from neutron_lib import constants - - -FW_RULES = [ - {'position': '1', - 'protocol': 'icmp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule1'}, - {'source_port': '0:10', - 'destination_port': '0:10', - 'position': '2', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule2'}, - {'source_port': '0:10', - 'destination_port': '0:20', - 'position': '3', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'}, - {'source_port': '1', - 'destination_port': '0:10', - 'position': '4', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule5'}, - {'source_port': '0:10', - 'destination_port': None, - 'position': '5', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule5'}, - {'source_port': '1', - 'destination_port': '3', - 'position': '6', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule6'}, - {'source_port': '1', - 'destination_port': '2', - 'position': '7', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule7'}, -] - -ICMP_ENTRY = (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', '1234') -TCP_ENTRY = (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') -UDP_ENTRY = (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - -CONNTRACK_LIST = '''\ -icmp 1 27 src=1.1.1.1 dst=2.2.2.2 type=8 code=0 id=18127 src=2.2.2.2 dst=1.1.1.1 type=0 code=0 id=18127 mark=0 use=1 -tcp 6 88 SYN_SENT src=1.1.1.1 dst=2.2.2.2 sport=36567 dport=5000 [UNREPLIED] src=2.2.2.2 dst=1.1.1.1 sport=5000 dport=36567 mark=0 use=1 -unknown 2 551 src=0.0.0.0 dst=224.0.0.1 [UNREPLIED] src=224.0.0.1 dst=0.0.0.0 mark=0 use=1 -udp 17 28 src=0.0.0.0 dst=255.255.255.255 sport=68 dport=67 [UNREPLIED] src=255.255.255.255 dst=0.0.0.0 sport=67 dport=68 mark=0 use=1 -''' # nopep8 - -ROUTER_NAMESPACE = 'qrouter-fake-namespace' - - -class ConntrackLegacyTestCase(base.BaseTestCase): - def setUp(self): - super(ConntrackLegacyTestCase, self).setUp() - self.utils_exec = mock.Mock() - self.conntrack_driver = legacy_conntrack.ConntrackLegacy() - self.conntrack_driver.initialize(execute=self.utils_exec) - - def test_normalize_filters_tuple(self): - self.assertEqual( - (4, 'udp', [], [], '', ''), - legacy_conntrack.normalize_filters_tuple( - (4, 'udp', [], [], None, None))) - self.assertEqual( - (4, '', [], [], '', ''), - legacy_conntrack.normalize_filters_tuple( - (4, None, [], [], None, None))) - - def test_excecute_command_failed(self): - with testtools.ExpectedException(RuntimeError): - self.conntrack_driver._execute_command(['fake', 'command']) - raise RuntimeError("Failed execute conntrack command fake command") - - def test_flush_entries(self): - self.conntrack_driver.flush_entries(ROUTER_NAMESPACE) - self.utils_exec.assert_called_with( - ['ip', 'netns', 'exec', ROUTER_NAMESPACE, - 'conntrack', '-D'], - check_exit_code=True, - extra_ok_codes=[1], - run_as_root=True) - - def test_list_entries(self): - def get_contrack_entries(conntrack_cmd): - if 'ipv' + str(constants.IP_VERSION_4) in conntrack_cmd: - return CONNTRACK_LIST - return '' - - self.conntrack_driver._execute_command = mock.Mock( - side_effect=get_contrack_entries) - entries = self.conntrack_driver.list_entries(ROUTER_NAMESPACE) - protocols = set([entry[1] for entry in entries]) - supported_protocols = set(legacy_conntrack.ATTR_POSITIONS.keys()) - self.assertTrue(protocols.issubset(supported_protocols)) - - def test_delete_entries(self): - list_entries_mock = mock.patch( - 'neutron_fwaas.services.firewall.service_drivers.agents.drivers.' - 'linux.legacy_conntrack.ConntrackLegacy.list_entries') - self.list_entries = list_entries_mock.start() - - self.conntrack_driver.list_entries.return_value = [ - ICMP_ENTRY, TCP_ENTRY, UDP_ENTRY] - self.conntrack_driver.delete_entries(FW_RULES, ROUTER_NAMESPACE) - calls = [ - mock.call(['ip', 'netns', 'exec', ROUTER_NAMESPACE, - 'conntrack', '-D', '-f', 'ipv4', '-p', 'icmp', - '--icmp-type', 8, '--icmp-code', 0, - '-s', '1.1.1.1', '-d', '2.2.2.2', '--icmp-id', '1234'], - check_exit_code=True, - extra_ok_codes=[1], - run_as_root=True), - mock.call(['ip', 'netns', 'exec', ROUTER_NAMESPACE, - 'conntrack', '-D', '-f', 'ipv4', '-p', 'tcp', - '--sport', 1, '--dport', 2, - '-s', '1.1.1.1', '-d', '2.2.2.2'], - check_exit_code=True, - extra_ok_codes=[1], - run_as_root=True), - mock.call(['ip', 'netns', 'exec', ROUTER_NAMESPACE, - 'conntrack', '-D', '-f', 'ipv4', '-p', 'udp', - '--sport', 1, '--dport', 2, - '-s', '1.1.1.1', '-d', '2.2.2.2'], - check_exit_code=True, - extra_ok_codes=[1], - run_as_root=True), - - ] - self.utils_exec.assert_has_calls(calls) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_netlink_conntrack.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_netlink_conntrack.py deleted file mode 100644 index 0637459df..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_netlink_conntrack.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (c) 2017 Fujitsu Limited -# 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 mock - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \ - import netlink_conntrack -from neutron_fwaas.tests import base - -FW_RULES = [ - {'position': '1', - 'protocol': 'icmp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule1'}, - {'source_port': '0:10', - 'destination_port': '0:10', - 'position': '2', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule2'}, - {'source_port': '0:10', - 'destination_port': '0:20', - 'position': '3', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule3'}, - {'source_port': None, - 'destination_port': '0:10', - 'position': '2', - 'protocol': 'tcp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule5'}, - {'source_port': '0:10', - 'destination_port': None, - 'position': '3', - 'protocol': 'udp', - 'ip_version': 4, - 'enabled': True, - 'action': 'reject', - 'id': 'fake-fw-rule5'}, -] - -ICMP_ENTRY = (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', '1234') -TCP_ENTRY = (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') -UDP_ENTRY = (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - -ROUTER_NAMESPACE = 'qrouter-fake-namespace' - - -class ConntrackNetlinkTestCase(base.BaseTestCase): - def setUp(self): - super(ConntrackNetlinkTestCase, self).setUp() - self.conntrack_driver = netlink_conntrack.ConntrackNetlink() - self.conntrack_driver.initialize() - nl_flush_entries = mock.patch('neutron_fwaas.privileged.' - 'netlink_lib.flush_entries') - self.flush_entries = nl_flush_entries.start() - nl_list_entries = mock.patch('neutron_fwaas.privileged.' - 'netlink_lib.list_entries') - self.list_entries = nl_list_entries.start() - nl_delete_entries = mock.patch('neutron_fwaas.privileged.' - 'netlink_lib.delete_entries') - self.delete_entries = nl_delete_entries.start() - - def test_flush_entries(self): - self.conntrack_driver.flush_entries(ROUTER_NAMESPACE) - self.flush_entries.assert_called_with(ROUTER_NAMESPACE) - - def test_delete_with_empty_conntrack_entries(self): - self.list_entries.return_value = [] - self.conntrack_driver.delete_entries([], ROUTER_NAMESPACE) - self.list_entries.assert_called_with(ROUTER_NAMESPACE) - self.delete_entries.assert_not_called() - - def test_delete_icmp_entry(self): - """Testing delete an icmp entry - - The icmp entry can be deleted if there is an icmp conntrack entry - matched with an icmp firewall rule. - The information passing to nl_lib.kill_entry will include: - (ipversion, protocol, icmp_type, icmp_code, src_address, dst_addres, - icmp_ip) - """ - self.list_entries.return_value = [ICMP_ENTRY] - self.conntrack_driver.delete_entries(FW_RULES, ROUTER_NAMESPACE) - self.list_entries.assert_called_with(ROUTER_NAMESPACE) - self.delete_entries.assert_called_with([(4, 'icmp', 8, 0, - '1.1.1.1', '2.2.2.2', - '1234')], ROUTER_NAMESPACE) - - def test_delete_tcp_entry(self): - """Testing delete a tcp entry - - The tcp entry can be deleted if there is a tcp conntrack entry - matched with a tcp firewall rule. - The information passing to nl_lib.kill_entry will include: - (ipversion, protocol, src_port, dst_port, src_address, dst_addres) - """ - self.list_entries.return_value = [TCP_ENTRY] - self.conntrack_driver.delete_entries(FW_RULES, ROUTER_NAMESPACE) - self.list_entries.assert_called_with(ROUTER_NAMESPACE) - self.delete_entries.assert_called_with( - [(4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2')], ROUTER_NAMESPACE) - - def test_delete_udp_entry(self): - """Testing delete an udp entry - - The udp entry can be deleted if there is an udp conntrack entry - matched with an udp firewall rule. - The information passing to nl_lib.kill_entry will include: - (ipversion, protocol, src_port, dst_port, src_address, dst_addres) - """ - self.list_entries.return_value = [UDP_ENTRY] - self.conntrack_driver.delete_entries(FW_RULES, ROUTER_NAMESPACE) - self.list_entries.assert_called_with(ROUTER_NAMESPACE) - self.delete_entries.assert_called_with( - [(4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2')], ROUTER_NAMESPACE) - - def test_delete_multiple_entries(self): - self.list_entries.return_value = [ICMP_ENTRY, TCP_ENTRY, UDP_ENTRY] - self.conntrack_driver.delete_entries(FW_RULES, ROUTER_NAMESPACE) - self.list_entries.assert_called_with(ROUTER_NAMESPACE) - self.delete_entries.assert_called_with( - [(4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', '1234'), - (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2')], ROUTER_NAMESPACE) - - def _test_entry_to_delete(self, rule_filter, entry, expect_result): - is_entry_to_delete = ( - self.conntrack_driver._compare_entry_and_rule(rule_filter, entry)) - self.assertEqual(expect_result, is_entry_to_delete) - - def test_icmp_entry_match_rule(self): - entry = (4, 'icmp', 8, 0, '1.1.1.1', '2.2.2.2', '1234') - rule_filter = (4, 'icmp', None, None) - self._test_entry_to_delete(rule_filter, entry, 0) - - def test_tcp_entry_match_rule(self): - entry = (4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2') - rule_filters = [(4, 'tcp', None, None), - (4, 'tcp', [1], None), - (4, 'tcp', None, [2]), - (4, 'tcp', [1], [2]), - (4, 'tcp', ['0', '10'], ['0', '10']), ] - for rule_filter in rule_filters: - self._test_entry_to_delete(rule_filter, entry, 0) - - def test_udp_entry_match_rule(self): - entry = (4, 'udp', 1, 2, '1.1.1.1', '2.2.2.2') - rule_filters = [(4, 'udp', None, None), - (4, 'udp', [1], None), - (4, 'udp', None, [2]), - (4, 'udp', [1], [2]), - (4, 'udp', ['0', '10'], ['0', '10']), ] - for rule_filter in rule_filters: - self._test_entry_to_delete(rule_filter, entry, 0) - - def test_entry_unmatch_rule(self): - wrong_ipv = [(4, 'tcp', '1', '2', '1.1.1.1', '2.2.2.2'), - (6, 'tcp', None, None), -1] - wrong_proto = [(4, 'tcp', '1', '2', '1.1.1.1', '2.2.2.2'), - (4, 'udp', None, None), -1] - not_in_sport_range = [(4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'tcp', ['2', '100'], [2]), -1] - not_in_dport_range = [(4, 'tcp', 1, 2, '1.1.1.1', '2.2.2.2'), - (4, 'tcp', [1], ['3', '100']), -1] - for entry, rule_filter, expect in [ - wrong_ipv, wrong_proto, not_in_sport_range, not_in_dport_range]: - self._test_entry_to_delete(rule_filter, entry, expect) - - def test_get_filter_from_rules(self): - fw_rule_icmp = FW_RULES[0] - fw_rule_port_range = FW_RULES[1] - fw_rule_dest_port = FW_RULES[3] - fw_rule_source_port = FW_RULES[4] - - # filter format: - # ('ip_version', 'protocol', 'source_port', 'destination_port', - # 'source_ip_address', 'destination_ip_address') - - expected_icmp_filter = (4, 'icmp', [], [], [], []) - expected_port_range_filter = (4, 'tcp', ['0', '10'], ['0', '10'], - [], []) - expected_dest_port_filter = (4, 'tcp', [], ['0', '10'], [], []) - expected_source_port_filter = (4, 'udp', ['0', '10'], [], [], []) - - actual_icmp_filter = self.conntrack_driver._get_filter_from_rule( - fw_rule_icmp) - actual_port_range_filter = \ - self.conntrack_driver._get_filter_from_rule(fw_rule_port_range) - actual_dest_port_filter = \ - self.conntrack_driver._get_filter_from_rule(fw_rule_dest_port) - actual_source_port_filter = \ - self.conntrack_driver._get_filter_from_rule(fw_rule_source_port) - - self.assertEqual(expected_icmp_filter, actual_icmp_filter) - self.assertEqual(expected_port_range_filter, actual_port_range_filter) - self.assertEqual(expected_dest_port_filter, actual_dest_port_filter) - self.assertEqual(expected_source_port_filter, - actual_source_port_filter) - - def test_get_entries_to_delete(self): - rule_filters = sorted( - [(4, 'tcp', ['0', '10'], ['1', '10']), - (4, 'udp', ['0', '10'], ['0', '10']), - (4, 'icmp', None, None)]) - TCP_ENTRY_IN_RANGE = (4, 'tcp', 2, 3, '1.1.1.1', '2.2.2.2') - TCP_ENTRY_OUT_RANGE = (4, 'tcp', 22, 100, '1.1.1.1', '2.2.2.2') - UDP_ENTRY_IN_RANGE = (4, 'udp', 3, 4, '1.1.1.1', '2.2.2.2') - UDP_ENTRY_OUT_RANGE = (4, 'udp', 100, 200, '1.1.1.1', '2.2.2.2') - self.list_entries.return_value = sorted( - [ICMP_ENTRY, TCP_ENTRY, UDP_ENTRY, - TCP_ENTRY_IN_RANGE, TCP_ENTRY_OUT_RANGE, - UDP_ENTRY_IN_RANGE, UDP_ENTRY_OUT_RANGE]) - expected_delete_entries = sorted( - [ICMP_ENTRY, TCP_ENTRY, UDP_ENTRY, - TCP_ENTRY_IN_RANGE, UDP_ENTRY_IN_RANGE]) - actual_delete_entries = self.conntrack_driver._get_entries_to_delete( - rule_filters, self.list_entries()) - self.assertEqual(expected_delete_entries, actual_delete_entries) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/fake_data.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/fake_data.py deleted file mode 100644 index 33bfea013..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/fake_data.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright 2017 FUJITSU LIMITED -# 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 copy - -import mock -from neutron_lib import constants as nl_consts -from oslo_utils import uuidutils - -TENANT_UUID = uuidutils.generate_uuid() -TENANT_ID = TENANT_UUID -PROJECT_ID = TENANT_UUID -NETWORK_ID = uuidutils.generate_uuid() -SUBNET_ID = uuidutils.generate_uuid() -DEVICE_ID = uuidutils.generate_uuid() -PORT1 = uuidutils.generate_uuid() -PORT2 = uuidutils.generate_uuid() -PORT3 = uuidutils.generate_uuid() -PORT4 = uuidutils.generate_uuid() -HOST = 'fake_host' - - -class FakeFWaaSL2Agent(object): - - def __init__(self): - super(FakeFWaaSL2Agent, self).__init__() - - def create(self, resource, attrs=None, minimal=False): - """Create a fake fwaas v2 resources - - :param resource: A dictionary with all attributes - :type resource: string - :param attrs: A dictionary of each attribute you need to modify - :type attrs: dictionary - :param minimal: True if minimal port_detail is necessary - otherwise False - :type minimal: boolean - :return: - A OrderedDict faking the fwaas v2 resource - """ - target = getattr(self, "_" + resource) - return copy.deepcopy(target(attrs=attrs, minimal=minimal)) - - def _fwg(self, **kwargs): - - fwg = { - 'id': uuidutils.generate_uuid(), - 'name': 'my-group-' + uuidutils.generate_uuid(), - 'ingress_firewall_policy_id': uuidutils.generate_uuid(), - 'egress_firewall_policy_id': uuidutils.generate_uuid(), - 'description': 'my firewall group', - 'status': nl_consts.PENDING_CREATE, - 'ports': [PORT3, PORT4], - 'admin_state_up': True, - 'shared': False, - 'tenant_id': TENANT_ID, - 'project_id': PROJECT_ID - } - attrs = kwargs.get('attrs', None) - if attrs: - fwg.update(attrs) - return fwg - - def _fwg_with_rule(self, **kwargs): - - fwg_with_rule = self.create('fwg', attrs={'ports': [PORT1, PORT2]}) - rules = { - 'ingress_rule_list': [mock.Mock()], - 'egress_rule_list': [mock.Mock()], - 'add-port-ids': [PORT1], - 'del-port-ids': [PORT2], - 'port_details': { - PORT1: { - 'device': uuidutils.generate_uuid(), - 'device_owner': 'compute:nova', - 'host': HOST, - 'network_id': NETWORK_ID, - 'fixed_ips': [ - {'subnet_id': SUBNET_ID, 'ip_address': '172.24.4.5'}], - 'allowed_address_pairs': [], - 'port_security_enabled': True, - 'id': PORT1 - }, - PORT2: { - 'device': uuidutils.generate_uuid(), - 'device_owner': 'compute:nova', - 'host': HOST, - 'network_id': NETWORK_ID, - 'fixed_ips': [ - {'subnet_id': SUBNET_ID, 'ip_address': '172.24.4.6'}], - 'allowed_address_pairs': [], - 'port_security_enabled': True, - 'id': PORT2 - } - }, - } - fwg_with_rule.update(rules) - - if kwargs.get('minimal', None): - fwg_with_rule.update({'ports': []}) - fwg_with_rule.update({'add-port-ids': []}) - fwg_with_rule.update({'del-port-ids': []}) - fwg_with_rule.update({'port_details': {}}) - - attrs = kwargs.get('attrs', None) - if attrs: - fwg_with_rule.update(attrs) - return fwg_with_rule - - def _port(self, **kwargs): - - if kwargs.get('minimal', None): - return {'port_id': uuidutils.generate_uuid()} - - port_detail = { - 'profile': {}, - 'network_qos_policy_id': None, - 'qos_policy_id': None, - 'allowed_address_pairs': [], - 'admin_state_up': True, - 'network_id': NETWORK_ID, - 'segmentation_id': None, - 'fixed_ips': [ - {'subnet_id': SUBNET_ID, 'ip_address': '172.24.4.5'}], - 'vif_port': mock.Mock(), - 'device_owner': 'compute:node', - 'physical_network': 'physnet', - 'mac_address': 'fa:16:3e:8a:80:2b', - 'device': DEVICE_ID, - 'port_security_enabled': True, - 'port_id': uuidutils.generate_uuid(), - 'network_type': 'flat', - 'security_groups': [] - } - - attrs = kwargs.get('attrs', None) - - if attrs: - port_detail.update(attrs) - return port_detail diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/test_fwaas_v2.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/test_fwaas_v2.py deleted file mode 100644 index 9c68353ef..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l2/test_fwaas_v2.py +++ /dev/null @@ -1,770 +0,0 @@ -# Copyright 2017 Cisco Systems -# -# 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 copy - -import mock -from neutron_lib import constants as nl_consts -from neutron_lib import context -from neutron_lib.exceptions import firewall_v2 as f_exc -from oslo_config import cfg - -from neutron_fwaas.common import fwaas_constants as consts -from neutron_fwaas.services.firewall.service_drivers.agents.l2 import fwaas_v2 -from neutron_fwaas.tests import base -from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents.l2\ - import fake_data - - -class TestFWaasV2AgentExtensionBase(base.BaseTestCase): - - def setUp(self): - super(TestFWaasV2AgentExtensionBase, self).setUp() - - self.fake = fake_data.FakeFWaaSL2Agent() - self.port = self.fake.create('port') - self.port_minimal = self.fake.create('port', minimal=True) - self.fwg = self.fake.create('fwg') - self.fwg_with_rule = self.fake.create('fwg_with_rule') - self.port_id = self.port['port_id'] - self.fwg_id = self.fwg['id'] - self.host = fake_data.HOST - self.ctx = context.get_admin_context() - - self.l2 = fwaas_v2.FWaaSV2AgentExtension() - self.l2.consume_api(mock.Mock()) - self.driver = mock.patch( - 'neutron.manager.NeutronManager.load_class_for_provider').start() - self.l2.initialize(None, 'ovs') - self.l2.vlan_manager = mock.Mock() - self.conf = cfg.ConfigOpts() - self.l2.fwg_map = mock.Mock() - self.l2.conf.host = self.host - self.rpc = self.l2.plugin_rpc - - -class TestFWaasV2AgentExtension(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestFWaasV2AgentExtension, self).setUp() - cfg.CONF.set_override('firewall_l2_driver', 'ovs', group='fwaas') - - def test_initialize(self): - with mock.patch('neutron_lib.rpc.Connection') as conn: - self.l2.initialize(None, 'ovs') - self.driver.assert_called_with('neutron.agent.l2.firewall_drivers', - 'ovs') - conn.assert_called_with() - self.l2.conn.create_consumer.assert_called_with( - consts.FW_AGENT, [self.l2], fanout=False) - self.l2.conn.consume_in_threads.assert_called_with() - - -class TestHandlePort(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestHandlePort, self).setUp() - self.rpc.get_firewall_group_for_port = mock.Mock( - return_value=self.fwg) - self.l2._compute_status = mock.Mock(return_value=nl_consts.ACTIVE) - self.l2._apply_fwg_rules = mock.Mock(return_value=True) - self.l2._send_fwg_status = mock.Mock() - self.ctx = context.get_admin_context() - self.l2._add_rule_for_trusted_port = mock.Mock() - - def test_normal(self): - self.l2.fwg_map.get_port_fwg.return_value = None - self.l2.handle_port(self.ctx, self.port) - self.rpc.get_firewall_group_for_port.assert_called_once_with( - self.ctx, self.port['port_id']) - self.l2._apply_fwg_rules.assert_called_once_with(self.fwg, [self.port]) - self.l2._compute_status.assert_called_once_with( - self.fwg, True, event=consts.HANDLE_PORT) - self.l2.fwg_map.set_port_fwg.assert_called_once_with(self.port, - self.fwg) - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, fwg_id=self.fwg['id'], - status=nl_consts.ACTIVE, host=self.l2.conf.host) - - def test_non_layer2_port(self): - self.port['device_owner'] = 'network:router_gateway' - self.l2.handle_port(self.ctx, self.port) - - self.rpc.get_firewall_group_for_port.assert_not_called() - self.l2._apply_fwg_rules.assert_not_called() - self.l2._compute_status.assert_not_called() - self.l2.fwg_map.set_port_fwg.assert_not_called() - self.l2._send_fwg_status.assert_not_called() - - def test_no_fwg_is_asossicate_to_port(self): - self.l2.fwg_map.get_port_fwg.return_value = None - self.rpc.get_firewall_group_for_port.return_value = None - self.l2.handle_port(self.ctx, self.port) - - self.rpc.get_firewall_group_for_port.assert_called_once_with( - self.ctx, self.port['port_id']) - self.l2._apply_fwg_rules.assert_not_called() - self.l2._compute_status.assert_not_called() - self.l2.fwg_map.set_port_fwg.assert_not_called() - self.l2._send_fwg_status.assert_not_called() - - def test_port_already_apply_fwg(self): - self.l2.fwg_map.get_port_fwg.return_value = self.fwg - self.l2.handle_port(self.ctx, self.port) - - self.rpc.get_firewall_group_for_port.assert_not_called() - self.l2._apply_fwg_rules.assert_not_called() - self.l2._compute_status.assert_not_called() - self.l2.fwg_map.set_port_fwg.assert_not_called() - self.l2._send_fwg_status.assert_not_called() - - def test_trusted_port(self): - self.l2.fwg_map.get_port.return_value = None - self.port['device_owner'] = 'network:foo' - self.l2.handle_port(self.ctx, self.port) - - self.l2._add_rule_for_trusted_port.assert_called_once_with(self.port) - self.l2.fwg_map.set_port.assert_called_once_with(self.port) - self.rpc.get_firewall_group_for_port.assert_not_called() - - def test_trusted_port_registered_map(self): - self.port['device_owner'] = 'network:dhcp' - self.l2.fwg_map.get_port.return_value = self.port - self.l2.handle_port(self.ctx, self.port) - - self.l2._add_rule_for_trusted_port.assert_not_called() - self.l2.fwg_map.set_port.assert_not_called() - self.rpc.get_firewall_group_for_port.assert_not_called() - - -class TestDeletePort(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestDeletePort, self).setUp() - self.l2._compute_status = mock.Mock(return_value=nl_consts.ACTIVE) - self.l2._apply_fwg_rules = mock.Mock(return_value=True) - self.l2._send_fwg_status = mock.Mock() - self.l2._delete_rule_for_trusted_port = mock.Mock() - - self.l2.fwg_map.get_port_fwg = mock.Mock(return_value=self.fwg) - self.l2.fwg_map.set_fwg = mock.Mock() - self.l2.fwg_map.get_port = mock.Mock(return_value=self.port) - self.l2.fwg_map.remove_port = mock.Mock() - - def test_include_vif_port_attribute(self): - self.port_minimal.update({'vif_port': None}) - self.l2.fwg_map.get_port_fwg.return_value = None - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2.fwg_map.get_port_fwg.assert_not_called() - self.l2._apply_fwg_rules.assert_not_called() - - def test_port_belongs_to_fwg(self): - expected_ports = self.fwg['ports'] - self.fwg['ports'].append(self.port['port_id']) - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2.fwg_map.get_port_fwg.assert_called_once_with(self.port) - self.l2._apply_fwg_rules.assert_called_once_with( - self.fwg, [self.port], event=consts.DELETE_FWG) - # 'port_id' has been removed from 'ports' - self.assertEqual(expected_ports, self.fwg['ports']) - self.l2.fwg_map.set_fwg.assert_called_once_with(self.fwg) - - def test_port_belongs_to_no_fwg(self): - expected_ports = self.fwg['ports'] - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2.fwg_map.get_port_fwg.assert_called_once_with(self.port) - self.l2._apply_fwg_rules.assert_called_once_with( - self.fwg, [self.port], event=consts.DELETE_FWG) - # 'ports' not changed during delete_port() - self.assertEqual(expected_ports, self.fwg['ports']) - self.l2.fwg_map.set_fwg.assert_called_once_with(self.fwg) - - def test_non_layer2_port(self): - self.port['device_owner'] = 'network:router_gateway' - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2.fwg_map.get_port_fwg.assert_not_called() - - def test_cannot_get_fwg_from_port(self): - self.l2.fwg_map.get_port_fwg.return_value = None - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2.fwg_map.get_port_fwg.assert_called_once_with(self.port) - self.l2._apply_fwg_rules.assert_not_called() - - def test_trusted_port_with_map(self): - self.port['device_owner'] = 'network:dhcp' - self.l2.fwg_map.get_port.return_value = self.port - self.l2.delete_port(self.ctx, self.port_minimal) - - self.l2._delete_rule_for_trusted_port.assert_called_once_with( - self.port) - self.l2.fwg_map.remove_port.assert_called_once_with(self.port) - - -class TestCreateFirewallGroup(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestCreateFirewallGroup, self).setUp() - self.l2._apply_fwg_rules = mock.Mock(return_value=True) - self.l2._compute_status = mock.Mock(return_value='ACTIVE') - self.l2._send_fwg_status = mock.Mock() - - def test_create_event_is_create(self): - fwg = self.fwg_with_rule - fwg['ports'] = [fake_data.PORT1] - ports = [fwg['port_details'][fake_data.PORT1]] - self.l2._create_firewall_group( - self.ctx, fwg, self.host, event=consts.CREATE_FWG) - self.l2._apply_fwg_rules.assert_called_once_with( - fwg, ports, consts.CREATE_FWG) - self.l2._compute_status.assert_called_once_with( - fwg, True, consts.CREATE_FWG) - - def test_create_event_is_not_create(self): - fwg = self.fwg_with_rule - fwg['ports'] = [fake_data.PORT1] - ports = [fwg['port_details'][fake_data.PORT1]] - self.l2._create_firewall_group( - self.ctx, fwg, self.host, event=consts.UPDATE_FWG) - self.l2._apply_fwg_rules.assert_called_once_with( - fwg, ports, consts.UPDATE_FWG) - - def test_create_with_port(self): - fwg = self.fwg_with_rule - ports = [fwg['port_details'][fake_data.PORT1]] - self.l2.create_firewall_group(self.ctx, fwg, self.host) - self.l2._apply_fwg_rules.assert_called_once_with( - fwg, ports, consts.CREATE_FWG) - - for idx, args in enumerate(self.l2._compute_status.call_args_list): - self.assertEqual(fwg, args[0][0]) - self.assertEqual(True, args[0][1]) - self.assertEqual(consts.CREATE_FWG, args[0][2]) - - for idx, args in enumerate(self.l2._send_fwg_status.call_args_list): - self.assertEqual(self.ctx, args[0][0]) - self.assertEqual(fwg['id'], args[0][1]) - self.assertEqual('ACTIVE', args[0][2]) - self.assertEqual(self.host, args[0][3]) - - def test_create_with_no_ports(self): - self.fwg_with_rule['add-port-ids'] = [] - self.assertIsNone(self.l2.create_firewall_group( - self.ctx, self.fwg_with_rule, self.host)) - self.l2._apply_fwg_rules.assert_not_called() - self.l2.fwg_map.set_port_fwg.assert_not_called() - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, self.fwg_with_rule['id'], 'INACTIVE', self.host) - - def test_create_with_invalid_host(self): - self.fwg_with_rule['port_details'][fake_data.PORT1]['host'] = 'invalid' - self.l2.create_firewall_group(self.ctx, self.fwg_with_rule, self.host) - self.l2._apply_fwg_rules.assert_not_called() - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, self.fwg_with_rule['id'], 'INACTIVE', self.host) - - def test_illegal_create_with_no_l2_ports(self): - fwg = { - 'name': 'non-default', - 'id': self.fwg_id, - 'ports': [], - 'add-port-ids': [self.port_id], - 'admin_state_up': True, - 'port_details': { - self.port_id: { - 'device_owner': 'network:router_interface' - } - } - } - self.l2.create_firewall_group(self.ctx, fwg, self.host) - self.l2._apply_fwg_rules.assert_not_called() - self.l2.fwg_map.set_port_fwg.assert_not_called() - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, fwg['id'], 'INACTIVE', self.host) - - -class TestDeleteFirewallGroup(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestDeleteFirewallGroup, self).setUp() - self.l2._apply_fwg_rules = mock.Mock(return_value=True) - self.l2._compute_status = mock.Mock(return_value='ACTIVE') - self.l2._send_fwg_status = mock.Mock() - self.rpc.firewall_group_deleted = mock.Mock() - - def test_delete_with_port(self): - fwg = self.fwg_with_rule - ports = [fwg['port_details'][fake_data.PORT2]] - - self.assertIsNone(self.l2.delete_firewall_group( - self.ctx, self.fwg_with_rule, self.host)) - self.l2._apply_fwg_rules.assert_called_once_with( - fwg, ports, event=consts.DELETE_FWG) - self.l2.fwg_map.remove_fwg.assert_called_once_with(fwg) - for idx, args in enumerate(self.l2._compute_status.call_args_list): - self.assertEqual(fwg, args[0][0]) - self.assertEqual(True, args[0][2]) - self.assertEqual({'event': consts.CREATE_FWG}, args[1]) - - for idx, args in enumerate(self.l2._send_fwg_status.call_args_list): - self.assertEqual(self.ctx, args[0][0]) - self.assertEqual(fwg['id'], args[0][1]) - self.assertEqual('ACTIVE', args[0][2]) - self.assertEqual(self.host, args[0][3]) - - def test_delete_with_no_ports(self): - self.fwg_with_rule['del-port-ids'] = [] - self.l2.delete_firewall_group(self.ctx, self.fwg_with_rule, self.host) - self.l2._apply_fwg_rules.assert_not_called() - - def test_delete_with_no_l2_ports(self): - self.fwg_with_rule['port_details'][fake_data.PORT2][ - 'device_owner'] = 'network:router_interface' - self.l2.delete_firewall_group(self.ctx, self.fwg_with_rule, self.host) - self.l2._apply_fwg_rules.assert_not_called() - - def test_delete_with_exception(self): - self.l2._delete_firewall_group = mock.Mock(side_effect=Exception) - self.assertIsNone(self.l2.delete_firewall_group( - self.ctx, self.fwg_with_rule, self.host)) - - def test_delete_event_is_update(self): - self.l2._delete_firewall_group( - self.ctx, self.fwg_with_rule, self.host, event=consts.UPDATE_FWG) - self.l2.fwg_map.remove_fwg.assert_not_called() - self.rpc.firewall_group_deleted.assert_not_called() - self.l2._compute_status.assert_called_once_with( - self.fwg_with_rule, True, consts.UPDATE_FWG) - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, self.fwg_with_rule['id'], 'ACTIVE', self.host) - - -class TestUpdateFirewallGroup(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestUpdateFirewallGroup, self).setUp() - self.l2._delete_firewall_group = mock.Mock() - self.l2._create_firewall_group = mock.Mock() - self.l2._send_fwg_status = mock.Mock() - - def test_update(self): - self.assertIsNone(self.l2.update_firewall_group( - self.ctx, mock.ANY, self.host)) - - self.l2._delete_firewall_group.assert_called_once_with( - self.ctx, mock.ANY, self.host, event=consts.UPDATE_FWG) - self.l2._create_firewall_group.assert_called_once_with( - self.ctx, mock.ANY, self.host, event=consts.UPDATE_FWG) - - def test_update_raised_in_delete_firewall_group(self): - self.l2._delete_firewall_group.side_effect = Exception - fwg = self.fwg_with_rule - self.assertIsNone(self.l2.update_firewall_group( - self.ctx, fwg, self.host)) - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, fwg['id'], status='ERROR', host=self.host) - - def test_update_raised_in_create_firewall_group(self): - self.l2._create_firewall_group.side_effect = Exception - fwg = self.fwg_with_rule - self.assertIsNone(self.l2.update_firewall_group( - self.ctx, fwg, self.host)) - self.l2._send_fwg_status.assert_called_once_with( - self.ctx, fwg['id'], status='ERROR', host=self.host) - - -class TestIsPortLayer2(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestIsPortLayer2, self).setUp() - - def test_vm_port(self): - self.assertTrue(self.l2._is_port_layer2(self.port)) - - def test_not_vm_port(self): - for device_owner in [nl_consts.DEVICE_OWNER_ROUTER_INTF, - nl_consts.DEVICE_OWNER_ROUTER_GW, - nl_consts.DEVICE_OWNER_DHCP, - nl_consts.DEVICE_OWNER_DVR_INTERFACE, - nl_consts.DEVICE_OWNER_AGENT_GW, - nl_consts.DEVICE_OWNER_ROUTER_SNAT, - nl_consts.DEVICE_OWNER_LOADBALANCER, - nl_consts.DEVICE_OWNER_LOADBALANCERV2, - 'unknown device_owner', - '']: - self.port['device_owner'] = device_owner - self.assertFalse(self.l2._is_port_layer2(self.port)) - - def test_illegal_no_device_owner(self): - del self.port['device_owner'] - self.assertFalse(self.l2._is_port_layer2(self.port)) - - -class TestComputeStatus(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestComputeStatus, self).setUp() - self.ports = list(self.fwg_with_rule['port_details'].values()) - - def test_normal(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status(fwg, result)) - - def test_event_is_delete(self): - result = True - fwg = self.fwg_with_rule - self.assertIsNone(self.l2._compute_status( - fwg, result, consts.DELETE_FWG)) - - def test_event_is_update(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.UPDATE_FWG)) - - def test_event_is_update_and_has_last_port(self): - result = True - fwg = self.fake.create('fwg_with_rule', attrs={'last-port': False}) - - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.UPDATE_FWG)) - - fwg = self.fake.create('fwg_with_rule', attrs={'last-port': True}) - self.assertEqual('INACTIVE', self.l2._compute_status( - fwg, result, consts.UPDATE_FWG)) - - def test_event_is_update_and_has_no_last_port_but_has_ports(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.UPDATE_FWG)) - - def test_event_is_update_and_has_no_last_port_and_ports(self): - result = True - fwg = self.fwg_with_rule - fwg['ports'] = [] - self.assertEqual('INACTIVE', self.l2._compute_status( - fwg, result, consts.UPDATE_FWG)) - - def test_event_is_create(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.CREATE_FWG)) - - def test_event_is_create_and_no_fwg_ports(self): - result = True - fwg = self.fwg_with_rule - fwg['ports'] = [] - self.assertEqual('INACTIVE', self.l2._compute_status( - fwg, result, consts.CREATE_FWG)) - - def test_event_is_handle_port(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.HANDLE_PORT)) - - def test_event_is_delete_port(self): - result = True - fwg = self.fwg_with_rule - self.assertEqual('ACTIVE', self.l2._compute_status( - fwg, result, consts.DELETE_PORT)) - - def test_event_is_delete_port_and_no_fwg_ports(self): - result = True - fwg = self.fwg_with_rule - fwg['ports'] = [] - self.assertEqual('INACTIVE', self.l2._compute_status( - fwg, result, consts.DELETE_PORT)) - - def test_driver_result_is_false(self): - result = False - fwg = self.fwg_with_rule - self.assertEqual('ERROR', self.l2._compute_status( - fwg, result)) - - def test_admin_state_up_is_false(self): - result = True - self.fwg_with_rule['admin_state_up'] = False - - self.assertEqual('DOWN', self.l2._compute_status( - self.fwg_with_rule, self.ports, result)) - - def test_active_inactive_patterns(self): - result = True - fwg = self.fwg_with_rule - # Case1: ingress/egress_firewall_policy_id - # Case2: ports --> already tested at above cases - expect_and_attrs = [ - ('INACTIVE', ('ingress_firewall_policy_id', - 'egress_firewall_policy_id')), - ('ACTIVE', ('ingress_firewall_policy_id',)), - ('ACTIVE', ('egress_firewall_policy_id',)), - ] - for attr in expect_and_attrs: - fwg = self.fake.create('fwg_with_rule') - expect = attr[0] - for p in attr[1]: - fwg[p] = None - self.assertEqual(expect, self.l2._compute_status(fwg, result)) - - -class TestApplyFwgRules(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestApplyFwgRules, self).setUp() - - class DummyVlan(object): - - def __init__(self, vlan=None): - self.vlan = vlan - - self.l2.vlan_manager.get.return_value = DummyVlan(vlan='999') - - def test_event_is_create(self): - fwg_ports = [self.fwg_with_rule['port_details'][fake_data.PORT1]] - driver_ports = copy.deepcopy(fwg_ports) - driver_ports[0].update({'lvlan': 999}) - - self.assertTrue(self.l2._apply_fwg_rules( - self.fwg_with_rule, fwg_ports, event=consts.CREATE_FWG)) - - self.l2.driver.create_firewall_group.assert_called_once_with( - driver_ports, self.fwg_with_rule) - self.l2.driver.delete_firewall_group.assert_not_called() - self.l2.driver.update_firewall_group.assert_not_called() - - def test_event_is_update(self): - fwg_ports = [self.fwg_with_rule['port_details'][fake_data.PORT1]] - driver_ports = copy.deepcopy(fwg_ports) - driver_ports[0].update({'lvlan': 999}) - - self.assertTrue(self.l2._apply_fwg_rules( - self.fwg_with_rule, fwg_ports, event=consts.UPDATE_FWG)) - - self.l2.driver.update_firewall_group.assert_called_once_with( - driver_ports, self.fwg_with_rule) - - def test_event_is_delete(self): - fwg_ports = [self.fwg_with_rule['port_details'][fake_data.PORT1]] - driver_ports = copy.deepcopy(fwg_ports) - driver_ports[0].update({'lvlan': 999}) - - self.assertTrue(self.l2._apply_fwg_rules( - self.fwg_with_rule, fwg_ports, event=consts.DELETE_FWG)) - - self.l2.driver.delete_firewall_group.assert_called_once_with( - fwg_ports, self.fwg_with_rule) - - def test_raised_in_driver(self): - self.l2.driver.delete_firewall_group.side_effect = \ - f_exc.FirewallInternalDriverError(driver='ovs firewall') - fwg_ports = [self.fwg_with_rule['port_details'][fake_data.PORT1]] - driver_ports = copy.deepcopy(fwg_ports) - driver_ports[0].update({'lvlan': 999}) - - self.assertFalse(self.l2._apply_fwg_rules( - self.fwg_with_rule, fwg_ports, event=consts.DELETE_FWG)) - - self.l2.driver.delete_firewall_group.assert_called_once_with( - fwg_ports, self.fwg_with_rule) - - -class TestSendFwgStatus(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestSendFwgStatus, self).setUp() - self.rpc.set_firewall_group_status = mock.Mock() - - def test_success(self): - self.assertIsNone(self.l2._send_fwg_status( - self.ctx, self.fwg_id, 'ACTIVE', self.host)) - - def test_failure(self): - self.rpc.set_firewall_group_status.side_effect = Exception - self.assertIsNone(self.l2._send_fwg_status( - self.ctx, self.fwg_id, 'ACTIVE', self.host)) - - -class TestAddLocalVlanToPorts(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestAddLocalVlanToPorts, self).setUp() - - class DummyVlan(object): - - def __init__(self, vlan=None): - self.vlan = vlan - - self.l2.vlan_manager.get.return_value = DummyVlan(vlan='999') - self.port_with_detail = { - 'port_id': fake_data.PORT1, - 'id': fake_data.PORT1, - 'network_id': fake_data.NETWORK_ID, - 'port_details': { - fake_data.PORT1: { - 'device': 'c12e5c1e-d68e-45bd-a2d3-1f2f32604e41', - 'device_owner': 'compute:nova', - 'host': self.host, - 'network_id': fake_data.NETWORK_ID, - 'fixed_ips': [ - {'subnet_id': fake_data.SUBNET_ID, - 'ip_address': '172.24.4.5'}], - 'allowed_address_pairs': [], - 'port_security_enabled': True, - 'id': fake_data.PORT1 - } - } - } - - def test_port_has_detail_and_port_id(self): - del self.port_with_detail['id'] - expect = [copy.deepcopy(self.port_with_detail)] - expect[0].update({'lvlan': 999}) - actual = self.l2._add_local_vlan_to_ports([self.port_with_detail]) - - self.l2.vlan_manager.get.assert_called_once_with( - self.port_with_detail['network_id']) - self.assertEqual(expect, actual) - - def test_port_has_detail_and_id(self): - del self.port_with_detail['port_id'] - expect = [copy.deepcopy(self.port_with_detail)] - expect[0].update({'lvlan': 999}) - actual = self.l2._add_local_vlan_to_ports([self.port_with_detail]) - - self.l2.vlan_manager.get.assert_called_once_with( - self.port_with_detail['network_id']) - self.assertEqual(expect, actual) - - def test_port_has_no_detail(self): - del self.port_with_detail['port_details'] - expect = [copy.deepcopy(self.port_with_detail)] - expect[0].update({'lvlan': 999}) - actual = self.l2._add_local_vlan_to_ports([self.port_with_detail]) - - self.l2.vlan_manager.get.assert_called_once_with( - self.port_with_detail['network_id']) - self.assertEqual(expect, actual) - - -class TestFWaaSL2PluginApi(TestFWaasV2AgentExtensionBase): - - def setUp(self): - super(TestFWaaSL2PluginApi, self).setUp() - - self.plugin = fwaas_v2.FWaaSL2PluginApi( - consts.FIREWALL_PLUGIN, self.host) - self.plugin.client = mock.Mock() - self.cctxt = self.plugin.client.prepare() - - def test_get_firewall_group_for_port(self): - self.plugin.get_firewall_group_for_port(self.ctx, mock.ANY) - self.cctxt.call.assert_called_once_with( - self.ctx, - 'get_firewall_group_for_port', - port_id=mock.ANY - ) - - def test_set_firewall_group_status(self): - self.plugin.set_firewall_group_status( - self.ctx, self.fwg_id, 'ACTIVE', self.host) - self.cctxt.call.assert_called_once_with( - self.ctx, - 'set_firewall_group_status', - fwg_id=self.fwg_id, - status='ACTIVE', - host=self.host, - ) - - def test_firewall_group_deleted(self): - self.plugin.firewall_group_deleted(self.ctx, self.fwg_id, self.host) - self.cctxt.call.assert_called_once_with( - self.ctx, - 'firewall_group_deleted', - fwg_id=self.fwg_id, - host=self.host, - ) - - -class TestPortFirewallGroupMap(base.BaseTestCase): - - def setUp(self): - super(TestPortFirewallGroupMap, self).setUp() - self.fake = fake_data.FakeFWaaSL2Agent() - self.map = fwaas_v2.PortFirewallGroupMap() - self.fwg = self.fake.create('fwg') - self.fwg_id = self.fwg['id'] - self.port = self.fake.create('port') - self.fwg['ports'] = [] - - def test_set_and_get(self): - self.map.set_fwg(self.fwg) - self.assertEqual(self.fwg, self.map.get_fwg(self.fwg_id)) - - def test_set_and_get_port_fwg(self): - port1 = self.port - port2 = self.fake.create('port') - self.map.set_port_fwg(port1, self.fwg) - self.map.set_port_fwg(port2, self.fwg) - self.assertEqual(self.fwg, self.map.get_port_fwg(port1)) - self.assertEqual(self.fwg, self.map.get_port_fwg(port2)) - self.assertIsNone(self.map.get_port_fwg('unknown')) - - def test_remove_port(self): - port1 = self.port - port2 = self.fake.create('port') - self.map.set_port_fwg(port1, self.fwg) - self.map.remove_port(port2) - - self.map.set_port_fwg(port2, self.fwg) - self.map.remove_port(port1) - self.assertIsNone(self.map.get_port(port1)) - self.assertEqual([port2['port_id']], - self.map.get_fwg(self.fwg_id)['ports']) - self.map.remove_port(port2) - self.assertIsNone(self.map.get_port(port2)) - self.assertEqual([], self.map.get_fwg(self.fwg_id)['ports']) - - def test_remove_non_exist_port(self): - port1 = self.port - port2 = self.fake.create('port') - self.map.set_port_fwg(port1, self.fwg) - - self.map.remove_port(port2) - self.assertIsNone(self.map.get_port(port2)) - - def test_illegal_remove_port_no_relation_with_fwg(self): - port1 = self.port - port1_id = port1['port_id'] - self.map.set_port_fwg(port1, self.fwg) - self.map.port_fwg[port1_id] = None - self.map.remove_port(port1) - self.assertIsNone(self.map.get_port(port1)) - - def test_remove_fwg(self): - self.map.set_fwg(self.fwg) - self.assertEqual(self.fwg, self.map.get_fwg(self.fwg_id)) - self.map.remove_fwg(self.fwg) - self.assertIsNone(self.map.get_fwg(self.fwg_id)) - - def test_remove_fwg_non_exist(self): - self.map.remove_fwg(self.fwg) - self.assertIsNone(self.map.get_fwg(self.fwg_id)) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l3reference/__init__.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l3reference/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l3reference/test_firewall_l3_agent_v2.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l3reference/test_firewall_l3_agent_v2.py deleted file mode 100644 index ade916a1a..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/l3reference/test_firewall_l3_agent_v2.py +++ /dev/null @@ -1,613 +0,0 @@ -# Copyright (c) 2016 -# 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 mock -from neutron.agent.l3 import l3_agent_extension_api as l3_agent_api -from neutron.agent.l3 import router_info -from neutron.agent.linux import ip_lib -from neutron.conf.agent.l3 import config as l3_config -from neutron_lib import context -from oslo_config import cfg -from oslo_utils import uuidutils - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \ - import iptables_fwaas_v2 -from neutron_fwaas.services.firewall.service_drivers.agents \ - import firewall_agent_api -from neutron_fwaas.services.firewall.service_drivers.agents.l3reference \ - import firewall_l3_agent_v2 -from neutron_fwaas.tests import base -from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents \ - import test_firewall_agent_api - - -class FWaasHelper(object): - def __init__(self): - pass - - -class FWaasAgent(firewall_l3_agent_v2.L3WithFWaaS, FWaasHelper): - neutron_service_plugins = [] - - def add_router(self, context, data): - pass - - def delete_router(self, context, data): - pass - - def update_router(self, context, data): - pass - - -def _setup_test_agent_class(service_plugins): - class FWaasTestAgent(firewall_l3_agent_v2.L3WithFWaaS, - FWaasHelper): - neutron_service_plugins = service_plugins - - def __init__(self, conf): - self.event_observers = mock.Mock() - self.conf = conf - firewall_agent_api._check_required_agent_extension = mock.Mock() - super(FWaasTestAgent, self).__init__(conf) - - def delete_router(self, context, data): - pass - - return FWaasTestAgent - - -class TestFWaaSL3AgentExtension(base.BaseTestCase): - def setUp(self): - super(TestFWaaSL3AgentExtension, self).setUp() - - self.conf = cfg.ConfigOpts() - self.conf.register_opts(l3_config.OPTS) - self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas') - self.conf.host = 'myhost' - self.api = FWaasAgent(self.conf) - self.api.agent_api = mock.Mock() - self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriverV2() - self.adminContext = context.get_admin_context() - self.context = mock.sentinel.context - self.router_id = uuidutils.generate_uuid() - self.agent_conf = mock.Mock() - self.ri_kwargs = {'router': {'id': self.router_id, - 'project_id': uuidutils.generate_uuid()}, - 'agent_conf': self.agent_conf, - 'interface_driver': mock.ANY, - 'use_ipv6': mock.ANY - } - - def test_fw_config_match(self): - test_agent_class = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', True, 'fwaas') - with mock.patch('oslo_utils.importutils.import_object'): - test_agent_class(cfg.CONF) - - def test_fw_config_mismatch_plugin_enabled_agent_disabled(self): - self.skipTest('this is broken') - test_agent_class = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', False, 'fwaas') - self.assertRaises(SystemExit, test_agent_class, cfg.CONF) - - def test_fw_plugin_list_unavailable(self): - test_agent_class = _setup_test_agent_class(None) - cfg.CONF.set_override('enabled', False, 'fwaas') - with mock.patch('oslo_utils.importutils.import_object'): - test_agent_class(cfg.CONF) - - def test_create_firewall_group(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'add-port-ids': [1, 2]} - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'create_firewall_group' - ) as mock_driver_create_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_create_firewall_group.return_value = True - - self.api.create_firewall_group(self.context, firewall_group, - host='host') - - mock_get_firewall_group_ports.assert_called_once_with(self.context, - firewall_group) - mock_get_in_ns_ports.assert_called - assert mock_get_in_ns_ports - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'ACTIVE') - - def test_update_firewall_group_with_ports_added_and_deleted(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [1, 2, 3, 4], - 'add-port-ids': [1, 2], - 'del-port-ids': [3, 4], - 'router_ids': [], - 'last-port': False} - - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwaas_driver, - 'delete_firewall_group' - ) as mock_driver_delete_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_delete_firewall_group.return_value = True - mock_driver_update_firewall_group.return_value = True - - calls = [mock.call(self.context, firewall_group, to_delete=True, - require_new_plugin=True), - mock.call(self.context, firewall_group)] - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - - self.assertEqual(mock_get_firewall_group_ports.call_args_list, - calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'ACTIVE') - - def test_update_firewall_group_with_ports_added_and_admin_state_down(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': False, - 'ports': [1, 2], - 'add-port-ids': [1, 2], - 'del-port-ids': [], - 'router_ids': [], - 'last-port': False} - - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_update_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - - mock_get_firewall_group_ports.assert_called - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'DOWN') - - def test_update_firewall_group_with_all_ports_deleted(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [3, 4], - 'add-port-ids': [], - 'del-port-ids': [3, 4], - 'last-port': True} - - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'delete_firewall_group' - ) as mock_driver_delete_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_delete_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - calls = [ - mock.call._get_firewall_group_ports( - self.context, firewall_group, require_new_plugin=True, - to_delete=True), - mock.call._get_firewall_group_ports( - self.context, firewall_group) - ] - mock_get_firewall_group_ports.assert_has_calls(calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'INACTIVE') - - def test_update_firewall_group_with_no_ports_added_or_deleted(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [], - 'add-port-ids': [], - 'del-port-ids': [], - 'last-port': True} - - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_update_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - calls = [ - mock.call._get_firewall_group_ports( - self.context, firewall_group, require_new_plugin=True, - to_delete=True), - mock.call._get_firewall_group_ports( - self.context, firewall_group) - ] - mock_get_firewall_group_ports.assert_has_calls(calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'INACTIVE') - - def test_update_firewall_group_with_only_ports_added(self): - # This test is for bug/1634114 - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [1, 2], - 'add-port-ids': ['1', '2'], - 'del-port-ids': [], - 'last-port': False - } - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_update_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - calls = [ - mock.call._get_firewall_group_ports( - self.context, firewall_group, require_new_plugin=True, - to_delete=True), - mock.call._get_firewall_group_ports( - self.context, firewall_group) - ] - mock_get_firewall_group_ports.assert_has_calls(calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'ACTIVE') - - def test_update_firewall_group_with_only_ports_removed(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [1, 2], - 'add-port-ids': [], - 'del-port-ids': ['1'], - 'last-port': False - } - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_update_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - calls = [ - mock.call._get_firewall_group_ports( - self.context, firewall_group, require_new_plugin=True, - to_delete=True), - mock.call._get_firewall_group_ports( - self.context, firewall_group) - ] - mock_get_firewall_group_ports.assert_has_calls(calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'ACTIVE') - - def test_update_firewall_group_with_only_policies_added_or_deleted(self): - firewall_group = {'id': 0, 'project_id': 1, - 'tenant_id': 1, - 'admin_state_up': True, - 'ports': [1, 2], - 'add-port-ids': [], - 'del-port-ids': [], - 'last-port': False - } - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'update_firewall_group' - ) as mock_driver_update_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'set_firewall_group_status' - ) as mock_set_firewall_group_status: - - mock_driver_update_firewall_group.return_value = True - - self.api.update_firewall_group(self.context, firewall_group, - host='host') - calls = [ - mock.call._get_firewall_group_ports( - self.context, firewall_group, require_new_plugin=True, - to_delete=True), - mock.call._get_firewall_group_ports( - self.context, firewall_group) - ] - mock_get_firewall_group_ports.assert_has_calls(calls) - mock_get_in_ns_ports.assert_called - mock_set_firewall_group_status.assert_called_once_with( - self.context, firewall_group['id'], 'ACTIVE') - - def test_delete_firewall_group(self): - firewall_group = {'id': 0, 'project_id': 1, - 'admin_state_up': True, - 'ports': [3, 4], - 'add-port-ids': [], - 'del-port-ids': [3, 4], - 'last-port': False} - - self.api.plugin_rpc = mock.Mock() - with mock.patch.object(self.api, '_get_firewall_group_ports' - ) as mock_get_firewall_group_ports, \ - mock.patch.object(self.api, '_get_in_ns_ports' - ) as mock_get_in_ns_ports, \ - mock.patch.object(self.api.fwaas_driver, - 'delete_firewall_group' - ) as mock_driver_delete_firewall_group, \ - mock.patch.object(self.api.fwplugin_rpc, - 'firewall_group_deleted' - ) as mock_firewall_group_deleted: - - mock_driver_delete_firewall_group.return_value = True - - self.api.delete_firewall_group(self.context, firewall_group, - host='host') - - mock_get_firewall_group_ports.assert_called_once_with( - self.context, firewall_group, to_delete=True) - mock_get_in_ns_ports.assert_called - mock_firewall_group_deleted.assert_called_once_with(self.context, - firewall_group['id']) - - def _prepare_router_data(self): - return router_info.RouterInfo(self.api, - self.router_id, - **self.ri_kwargs) - - def test_get_in_ns_ports_for_non_ns_fw(self): - port_ids = [1, 2] - ports = [{'id': pid} for pid in port_ids] - ri = self._prepare_router_data() - ri.internal_ports = ports - router_info = {ri.router_id: ri} - api_object = l3_agent_api.L3AgentExtensionAPI(router_info, None) - self.api.consume_api(api_object) - fw_port_ids = port_ids - - with mock.patch.object(ip_lib, - 'list_network_namespaces') as mock_list_netns: - mock_list_netns.return_value = [] - ports_for_fw_list = self.api._get_in_ns_ports(fw_port_ids) - - mock_list_netns.assert_called_with() - self.assertFalse(ports_for_fw_list) - - def test_get_in_ns_ports_for_fw(self): - port_ids = [1, 2] - ports = [{'id': pid} for pid in port_ids] - ri = self._prepare_router_data() - ri.internal_ports = ports - router_info = {} - router_info[ri.router_id] = ri - api_object = l3_agent_api.L3AgentExtensionAPI(router_info, None) - self.api.consume_api(api_object) - fw_port_ids = port_ids - ports_for_fw_expected = [(ri, port_ids)] - - with mock.patch.object(ip_lib, - 'list_network_namespaces') as mock_list_netns: - mock_list_netns.return_value = [ri.ns_name] - ports_for_fw_actual = self.api._get_in_ns_ports(fw_port_ids) - self.assertEqual(ports_for_fw_expected, ports_for_fw_actual) - - def test_add_router_for_check_input(self): - fw_agent = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', True, 'fwaas') - updated_router = { - '_interfaces': [{ - 'device_owner': 'network: router_interface', - 'id': '1', - 'tenant_id': 'demo_tenant_id', - }], - 'tenant_id': 'demo_tenant_id', - 'id': '0b109a4e-d228-479d-ad43-08bf3245adbb', - 'name': 'demo_router' - } - fwg = { - 'status': 'ACTIVE', - 'admin_state_up': True, - 'tenant_id': 'demo_tenant_id', - 'ports': [1], - 'del-port-ids': [], - 'add-port-ids': ['1'], - 'id': '2932b3d9-3a7b-48a1-a16c-bf9f7b2751a5' - } - with mock.patch('oslo_utils.importutils.import_object'): - agent = fw_agent(cfg.CONF) - agent.agent_api = mock.Mock() - agent.fwplugin_rpc = mock.Mock() - agent.conf.agent_mode = mock.Mock() - agent.fwaas_driver = iptables_fwaas_v2.IptablesFwaasDriver() - with mock.patch.object(agent.fwplugin_rpc, - 'get_firewall_groups_for_project' - ) as mock_get_firewall_groups_for_project, \ - mock.patch.object(agent.agent_api, - 'get_router_hosting_port' - ) as mock_get_router_hosting_port, \ - mock.patch.object(agent.fwaas_driver, - '_get_ipt_mgrs_with_if_prefix' - ) as mock_get_ipt_mgrs_with_if_prefix: - mock_get_firewall_groups_for_project.return_value = [fwg] - mock_get_router_hosting_port.return_value = mock.Mock() - agent.add_router(self.context, updated_router) - mock_get_ipt_mgrs_with_if_prefix.assert_any_call( - agent.conf.agent_mode, mock.ANY) - - @mock.patch('oslo_utils.importutils.import_object') - def test_add_router_with_several_ports(self, mock_import_object): - fw_agent = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', True, 'fwaas') - updated_router = { - '_interfaces': [ - {'device_owner': 'network: router_interface', - 'id': '1', - 'tenant_id': 'demo_tenant_id'}, - {'device_owner': 'network: router_interface', - 'id': '2', - 'tenant_id': 'demo_tenant_id'}, - {'device_owner': 'network: router_interface', - 'id': '3', - 'tenant_id': 'demo_tenant_id'}], - 'tenant_id': 'demo_tenant_id', - 'id': '0b109a4e-d228-479d-ad43-08bf3245adbb', - 'name': 'demo_router' - } - fwg1 = { - 'status': 'ACTIVE', - 'admin_state_up': True, - 'tenant_id': 'demo_tenant_id', - 'del-port-ids': [], - 'add-port-ids': ['1', '3'], - 'id': '2932b3d9-3a7b-48a1-a16c-bf9f7b2751a5' - } - fwg2 = { - 'status': 'ACTIVE', - 'admin_state_up': True, - 'tenant_id': 'demo_tenant_id', - 'del-port-ids': [], - 'add-port-ids': ['2', '3'], - 'id': '2932b3d9-3a7b-48a1-a16c-bf9f7b2751a5' - } - agent = fw_agent(cfg.CONF) - agent.agent_api = mock.Mock() - agent.fwplugin_rpc = mock.Mock() - agent.conf.agent_mode = mock.Mock() - agent.fwaas_driver = iptables_fwaas_v2.IptablesFwaasDriver() - - patch_project = mock.patch.object( - agent.fwplugin_rpc, 'get_firewall_groups_for_project') - patch_invoke = mock.patch.object( - agent, '_invoke_driver_for_sync_from_plugin') - - with patch_project as mock_get_firewall_groups, \ - patch_invoke as mock_invoke_driver: - mock_get_firewall_groups.return_value = [fwg1, fwg2] - agent.add_router(self.context, updated_router) - - # Check that mock_invoke_driver was called exactly twice with - # correct arguments. - self.assertEqual([ - mock.call(mock.ANY, {'1', '3'}, fwg1), - mock.call(mock.ANY, {'2'}, fwg2), - ], mock_invoke_driver.call_args_list) - - def test_add_router(self): - fw_agent = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', True, 'fwaas') - new_router = { - '_interfaces': [{ - 'device_owner': 'network: router_interface', - 'id': '1', - 'tenant_id': 'demo_tenant_id', - }], - 'tenant_id': 'demo_tenant_id', - 'id': '0b109a4e-d228-479d-ad43-08bf3245adbb', - 'name': 'demo_router' - } - with mock.patch('oslo_utils.importutils.import_object'): - agent = fw_agent(cfg.CONF) - agent.agent_api = mock.Mock() - agent.fwplugin_rpc = mock.Mock() - agent.conf.agent_mode = mock.Mock() - agent.fwaas_driver = iptables_fwaas_v2.IptablesFwaasDriver() - with mock.patch.object(agent, - '_process_router_update', - ) as mock_process_router_update: - agent.add_router(self.context, new_router) - mock_process_router_update.assert_called_with(new_router) - - def test_update_router(self): - fw_agent = _setup_test_agent_class([fwaas_constants.FIREWALL]) - cfg.CONF.set_override('enabled', True, 'fwaas') - updated_router = { - '_interfaces': [{ - 'device_owner': 'network: router_interface', - 'id': '1', - 'tenant_id': 'demo_tenant_id', - }], - 'tenant_id': 'demo_tenant_id', - 'id': '0b109a4e-d228-479d-ad43-08bf3245adbb', - 'name': 'demo_router' - } - with mock.patch('oslo_utils.importutils.import_object'): - agent = fw_agent(cfg.CONF) - agent.agent_api = mock.Mock() - agent.fwplugin_rpc = mock.Mock() - agent.conf.agent_mode = mock.Mock() - agent.fwaas_driver = iptables_fwaas_v2.IptablesFwaasDriver() - with mock.patch.object(agent, - '_process_router_update', - ) as mock_process_router_update: - agent.update_router(self.context, updated_router) - mock_process_router_update.assert_called_with(updated_router) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_agents.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_agents.py deleted file mode 100644 index b1c9a5ab4..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_agents.py +++ /dev/null @@ -1,654 +0,0 @@ -# Copyright 2016 -# 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 mock -import six - -from neutron import extensions as neutron_extensions -from neutron.tests.unit.extensions import test_l3 -from neutron_lib import constants as nl_constants -from neutron_lib import context -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib.plugins import directory -from oslo_config import cfg - -from neutron_fwaas._i18n import _ -from neutron_fwaas.db.firewall.v2.firewall_db_v2 import FirewallGroup -from neutron_fwaas.services.firewall.service_drivers.agents import agents -from neutron_fwaas.tests import base -from neutron_fwaas.tests.unit.services.firewall import test_fwaas_plugin_v2 - - -FIREWALL_AGENT_PLUGIN = ('neutron_fwaas.services.firewall.service_drivers.' - 'agents.agents') -FIREWALL_AGENT_PLUGIN_KLASS = FIREWALL_AGENT_PLUGIN + '.FirewallAgentDriver' -DELETEFW_PATH = (FIREWALL_AGENT_PLUGIN + '.FirewallAgentApi.' - 'delete_firewall_group') - - -class FakeAgentApi(agents.FirewallAgentCallbacks): - """ - This class used to mock the AgentAPI delete method inherits from - FirewallCallbacks because it needs access to the firewall_deleted method. - The delete_firewall method belongs to the FirewallAgentApi, which has - no access to the firewall_deleted method normally because it's not - responsible for deleting the firewall from the DB. However, it needs - to in the unit tests since there is no agent to call back. - """ - def __init__(self): - return - - def delete_firewall_group(self, context, firewall_group, **kwargs): - self.plugin = directory.get_plugin('FIREWALL_V2') - self.firewall_db = self.plugin.driver.firewall_db - self.firewall_group_deleted(context, firewall_group['id'], **kwargs) - - -class TestFirewallAgentApi(base.BaseTestCase): - def setUp(self): - super(TestFirewallAgentApi, self).setUp() - - self.api = agents.FirewallAgentApi('topic', 'host') - - def test_init(self): - self.assertEqual('topic', self.api.client.target.topic) - self.assertEqual('host', self.api.host) - - def _call_test_helper(self, method_name): - with mock.patch.object(self.api.client, 'cast') as rpc_mock, \ - mock.patch.object(self.api.client, 'prepare') as prepare_mock: - prepare_mock.return_value = self.api.client - getattr(self.api, method_name)(mock.sentinel.context, 'test') - - prepare_args = {'fanout': True} - prepare_mock.assert_called_once_with(**prepare_args) - - rpc_mock.assert_called_once_with(mock.sentinel.context, method_name, - firewall_group='test', host='host') - - def test_create_firewall_group(self): - self._call_test_helper('create_firewall_group') - - def test_update_firewall_group(self): - self._call_test_helper('update_firewall_group') - - def test_delete_firewall_group(self): - self._call_test_helper('delete_firewall_group') - - -class TestAgentDriver(test_fwaas_plugin_v2.FirewallPluginV2TestCase, - test_l3.L3NatTestCaseMixin): - - def setUp(self): - self.agentapi_del_fw_p = mock.patch( - DELETEFW_PATH, create=True, - new=FakeAgentApi().delete_firewall_group, - ).start() - mock.patch.object(agents.n_rpc, 'get_client').start() - mock.patch.object(agents.n_rpc, 'Connection').start() - - l3_plugin_str = ('neutron.tests.unit.extensions.test_l3.' - 'TestL3NatServicePlugin') - l3_plugin = {'l3_plugin_name': l3_plugin_str} - super(TestAgentDriver, self).setUp( - service_provider=FIREWALL_AGENT_PLUGIN_KLASS, - extra_service_plugins=l3_plugin, - extra_extension_paths=neutron_extensions.__path__) - - self.db = self.plugin.driver.firewall_db - self.callbacks = agents.FirewallAgentCallbacks(self.db) - - router_distributed_opts = [ - cfg.BoolOpt( - 'router_distributed', - default=False, - help=_("System-wide flag to determine the type of router " - "that tenants can create. Only admin can override.")), - ] - cfg.CONF.register_opts(router_distributed_opts) - - @property - def _self_context(self): - return context.Context('', self._tenant_id) - - def _get_test_firewall_group_attrs(self, name, - status=nl_constants.INACTIVE): - return super(TestAgentDriver, self)._get_test_firewall_group_attrs( - name, status=status) - - def test_set_firewall_group_status(self): - ctx = context.get_admin_context() - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - ingress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP - ) as fwg: - fwg_id = fwg['firewall_group']['id'] - res = self.callbacks.set_firewall_group_status(ctx, fwg_id, - nl_constants.ACTIVE) - fwg_db = self.plugin.get_firewall_group(ctx, fwg_id) - self.assertEqual(nl_constants.ACTIVE, fwg_db['status']) - self.assertTrue(res) - res = self.callbacks.set_firewall_group_status(ctx, fwg_id, - nl_constants.ERROR) - fwg_db = self.plugin.get_firewall_group(ctx, fwg_id) - self.assertEqual(nl_constants.ERROR, fwg_db['status']) - self.assertFalse(res) - - def test_firewall_group_deleted(self): - ctx = context.get_admin_context() - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - ingress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP, - do_delete=False - ) as fwg: - fwg_id = fwg['firewall_group']['id'] - with ctx.session.begin(subtransactions=True): - fwg_db = self.db._get_firewall_group(ctx, fwg_id) - fwg_db['status'] = nl_constants.PENDING_DELETE - - observed = self.callbacks.firewall_group_deleted(ctx, fwg_id) - self.assertTrue(observed) - - self.assertRaises(f_exc.FirewallGroupNotFound, - self.plugin.get_firewall_group, - ctx, fwg_id) - - def test_firewall_group_deleted_concurrently(self): - ctx = context.get_admin_context() - alt_ctx = context.get_admin_context() - - _get_firewall_group = self.db._get_firewall_group - - def getdelete(context, fwg_id): - fwg_db = _get_firewall_group(context, fwg_id) - # NOTE(cby): Use a different session to simulate a concurrent del - with alt_ctx.session.begin(subtransactions=True): - alt_ctx.session.query(FirewallGroup).filter_by( - id=fwg_id).delete() - return fwg_db - - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP, - do_delete=False - ) as fwg: - fwg_id = fwg['firewall_group']['id'] - with ctx.session.begin(subtransactions=True): - fwg_db = self.db._get_firewall_group(ctx, fwg_id) - fwg_db['status'] = nl_constants.PENDING_DELETE - ctx.session.flush() - - with mock.patch.object( - self.db, '_get_firewall_group', side_effect=getdelete - ): - observed = self.callbacks.firewall_group_deleted( - ctx, fwg_id) - self.assertTrue(observed) - - self.assertRaises(f_exc.FirewallGroupNotFound, - self.plugin.get_firewall_group, - ctx, fwg_id) - - def test_firewall_group_deleted_not_found(self): - ctx = context.get_admin_context() - observed = self.callbacks.firewall_group_deleted( - ctx, 'notfound') - self.assertTrue(observed) - - def test_firewall_group_deleted_error(self): - ctx = context.get_admin_context() - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP, - ) as fwg: - fwg_id = fwg['firewall_group']['id'] - observed = self.callbacks.firewall_group_deleted( - ctx, fwg_id) - self.assertFalse(observed) - fwg_db = self.db._get_firewall_group(ctx, fwg_id) - self.assertEqual(nl_constants.ERROR, fwg_db['status']) - - def test_create_firewall_group_ports_not_specified(self): - """neutron firewall-create test-policy """ - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.INACTIVE, - fwg1['firewall_group']['status']) - - def test_create_firewall_group_with_ports(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - fwg_ports = [port_id1, port_id2] - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - - def test_create_firewall_group_with_ports_on_diff_routers(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2: - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r2, \ - self.subnet() as s3: - - body = self._router_interface_action( - 'add', - r2['router']['id'], - s3['subnet']['id'], - None) - port_id3 = body['port_id'] - - fwg_ports = [port_id1, port_id2, port_id3] - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - - def test_create_firewall_group_with_ports_no_policy(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - fwg_ports = [port_id1, port_id2] - with self.firewall_group( - name='test', - default_policy=False, - ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.INACTIVE, - fwg1['firewall_group']['status']) - - def test_update_firewall_group_with_new_ports_no_policy(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2, \ - self.subnet(cidr='30.0.0.0/24') as s3: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s3['subnet']['id'], - None) - port_id3 = body['port_id'] - - fwg_ports = [port_id1, port_id2] - with self.firewall_group( - name='test', - default_policy=False, - ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.INACTIVE, - fwg1['firewall_group']['status']) - data = {'firewall_group': {'ports': [port_id2, port_id3]}} - req = self.new_update_request('firewall_groups', data, - fwg1['firewall_group']['id'], - context=self._self_context) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - - self.assertEqual(sorted([port_id2, port_id3]), - sorted(res['firewall_group']['ports'])) - - self.assertEqual(nl_constants.INACTIVE, - res['firewall_group']['status']) - - def test_update_firewall_group_with_new_ports_status_pending(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2, \ - self.subnet(cidr='30.0.0.0/24') as s3: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - fwg_ports = [port_id1, port_id2] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s3['subnet']['id'], - None) - port_id3 = body['port_id'] - - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - data = {'firewall_group': {'ports': [port_id2, port_id3]}} - req = self.new_update_request('firewall_groups', data, - fwg1['firewall_group']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_update_firewall_group_with_new_ports_status_active(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1, \ - self.subnet(cidr='20.0.0.0/24') as s2, \ - self.subnet(cidr='30.0.0.0/24') as s3: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - fwg_ports = [port_id1, port_id2] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s3['subnet']['id'], - None) - port_id3 = body['port_id'] - - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - - ctx = context.get_admin_context() - self.callbacks.set_firewall_group_status(ctx, - fwg1['firewall_group']['id'], nl_constants.ACTIVE) - data = {'firewall_group': {'ports': [port_id2, port_id3]}} - req = self.new_update_request('firewall_groups', data, - fwg1['firewall_group']['id'], - context=self._self_context) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - self.assertEqual(sorted([port_id2, port_id3]), - sorted(res['firewall_group']['ports'])) - - def test_update_firewall_rule_on_active_fwg(self): - name = "new_firewall_rule1" - attrs = self._get_test_firewall_rule_attrs(name) - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - with self.firewall_rule() as fwr: - with self.firewall_policy( - firewall_rules=[fwr['firewall_rule']['id']]) as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, ports=[port_id1], - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - - ctx = context.get_admin_context() - self.callbacks.set_firewall_group_status(ctx, - fwg1['firewall_group']['id'], nl_constants.ACTIVE) - 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)) - for k, v in six.iteritems(attrs): - self.assertEqual(v, res['firewall_rule'][k]) - - def test_update_firewall_rule_on_pending_create_fwg(self): - """update should fail""" - name = "new_firewall_rule1" - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet() as s1: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - with self.firewall_rule() as fwr: - with self.firewall_policy( - firewall_rules=[fwr['firewall_rule']['id']]) as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - name='test', - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, ports=[port_id1], - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.PENDING_CREATE, - fwg1['firewall_group']['status']) - - data = {'firewall_rule': {'name': name}} - req = self.new_update_request('firewall_rules', data, - fwr['firewall_rule']['id']) - res = req.get_response(self.ext_api) - self.assertEqual(409, res.status_int) - - def test_update_firewall_group_with_non_exist_ports(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r, \ - self.subnet(cidr='30.0.0.0/24') as s: - body = self._router_interface_action( - 'add', - r['router']['id'], - s['subnet']['id'], - None) - port_id1 = body['port_id'] - foo_port_id = 'caef152d-b118-4b9b-bc77-800661bf082d' - fwg_ports = [port_id1] - with self.firewall_group( - name='test', - default_policy=False, - ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.INACTIVE, - fwg1['firewall_group']['status']) - data = {'firewall_group': {'ports': [foo_port_id]}} - req = self.new_update_request('firewall_groups', data, - fwg1['firewall_group']['id']) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - self.assertEqual('PortNotFound', - res['NeutronError']['type']) - - def test_update_firewall_group_with_ports_and_policy(self): - """neutron firewall_group create test-policy """ - with self.router(name='router1', admin_state_up=True, - tenant_id=self._tenant_id) as r,\ - self.subnet() as s1,\ - self.subnet(cidr='20.0.0.0/24') as s2: - - body = self._router_interface_action( - 'add', - r['router']['id'], - s1['subnet']['id'], - None) - port_id1 = body['port_id'] - - body = self._router_interface_action( - 'add', - r['router']['id'], - s2['subnet']['id'], - None) - port_id2 = body['port_id'] - - fwg_ports = [port_id1, port_id2] - with self.firewall_rule() as fwr: - with self.firewall_policy( - firewall_rules=[fwr['firewall_rule']['id']]) as fwp: - with self.firewall_group( - name='test', - default_policy=False, - ports=fwg_ports, - admin_state_up=True) as fwg1: - self.assertEqual(nl_constants.INACTIVE, - fwg1['firewall_group']['status']) - fwp_id = fwp["firewall_policy"]["id"] - - data = {'firewall_group': {'ports': fwg_ports}} - req = (self. - new_update_request('firewall_groups', data, - fwg1['firewall_group']['id'], - context=self._self_context)) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - self.assertEqual(nl_constants.INACTIVE, - res['firewall_group']['status']) - - data = {'firewall_group': { - 'ingress_firewall_policy_id': fwp_id}} - req = (self. - new_update_request('firewall_groups', data, - fwg1['firewall_group']['id'], - context=self._self_context)) - res = self.deserialize(self.fmt, - req.get_response(self.ext_api)) - self.assertEqual(nl_constants.PENDING_UPDATE, - res['firewall_group']['status']) - - def test_create_firewall_group_with_dvr(self): - cfg.CONF.set_override('router_distributed', True) - attrs = self._get_test_firewall_group_attrs("firewall1") - self._test_create_firewall_group(attrs) - - def test_create_firewall_group(self): - attrs = self._get_test_firewall_group_attrs("firewall1") - self._test_create_firewall_group(attrs) - - def test_create_firewall_group_with_empty_ports(self): - attrs = self._get_test_firewall_group_attrs("fwg1") - attrs['ports'] = [] - self._test_create_firewall_group(attrs) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_agent_api.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_agent_api.py deleted file mode 100644 index 3115b09ab..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_agent_api.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ - import fwaas_base -from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ - import fwaas_base_v2 -from neutron_fwaas.services.firewall.service_drivers.agents \ - import firewall_agent_api as api -from neutron_fwaas.tests import base - - -class NoopFwaasDriver(fwaas_base.FwaasDriverBase): - """Noop Fwaas Driver. - - v1 firewall driver which does nothing. - This driver is for disabling Fwaas functionality. - """ - - def create_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def delete_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def update_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def apply_default_policy(self, agent_mode, apply_list, firewall): - pass - - -class NoopFwaasDriverV2(fwaas_base_v2.FwaasDriverBase): - """Noop Fwaas Driver. - - v2 firewall driver which does nothing. - This driver is for disabling Fwaas functionality. - """ - - def create_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def delete_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def update_firewall_group(self, agent_mode, apply_list, firewall): - pass - - def apply_default_policy(self, agent_mode, apply_list, firewall): - pass - - -class TestFWaaSAgentApi(base.BaseTestCase): - def setUp(self): - super(TestFWaaSAgentApi, self).setUp() - - self.api = api.FWaaSPluginApiMixin( - 'topic', - 'host') - - def test_init(self): - self.assertEqual('host', self.api.host) - - def _test_firewall_method(self, method_name, **kwargs): - with mock.patch.object(self.api.client, 'call') as rpc_mock, \ - mock.patch.object(self.api.client, 'prepare') as prepare_mock: - - prepare_mock.return_value = self.api.client - getattr(self.api, method_name)(mock.sentinel.context, 'test', - **kwargs) - - prepare_args = {} - prepare_mock.assert_called_once_with(**prepare_args) - - rpc_mock.assert_called_once_with(mock.sentinel.context, method_name, - firewall_id='test', host='host', - **kwargs) - - def test_set_firewall_status(self): - self._test_firewall_method('set_firewall_status', status='fake_status') - - def test_firewall_deleted(self): - self._test_firewall_method('firewall_deleted') diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_service.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_service.py deleted file mode 100644 index 950cd4ed1..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/test_firewall_service.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2014 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. - -from neutron.tests import base -from oslo_config import cfg - -from neutron_fwaas.services.firewall.service_drivers.agents import\ - firewall_service - -FWAAS_NOP_DEVICE = ('neutron_fwaas.tests.unit.services.firewall.' - 'service_drivers.agents.test_firewall_agent_api.' - 'NoopFwaasDriver') - - -class TestFirewallDeviceDriverLoading(base.BaseTestCase): - - def setUp(self): - super(TestFirewallDeviceDriverLoading, self).setUp() - self.service = firewall_service.FirewallService() - - def test_loading_firewall_device_driver(self): - """Get the sole device driver for FWaaS.""" - cfg.CONF.set_override('driver', - FWAAS_NOP_DEVICE, - 'fwaas') - driver = self.service.load_device_drivers() - self.assertIsNotNone(driver) - self.assertIn(driver.__class__.__name__, FWAAS_NOP_DEVICE) - - def test_fail_no_such_firewall_device_driver(self): - """Failure test of import error for FWaaS device driver.""" - cfg.CONF.set_override('driver', - 'no.such.class', - 'fwaas') - self.assertRaises(ImportError, - self.service.load_device_drivers) - - def test_fail_firewall_no_device_driver_specified(self): - """Failure test when no FWaaS device driver is specified. - - This is a configuration error, as the user must specify a device - driver, when enabling the firewall service (and there is no default - configuration set. We'll simulate that by using an empty string. - """ - cfg.CONF.set_override('driver', - '', - 'fwaas') - self.assertRaises(ValueError, - self.service.load_device_drivers) diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/test_driver_api.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/test_driver_api.py deleted file mode 100644 index 3749e3395..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/test_driver_api.py +++ /dev/null @@ -1,291 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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 copy - -import mock -from neutron_lib.callbacks import events -from neutron_lib import context - -from neutron_fwaas.common import fwaas_constants as const -from neutron_fwaas.tests.unit.services.firewall import test_fwaas_plugin_v2 - - -class FireWallDriverDBMixinTestCase(test_fwaas_plugin_v2. - FirewallPluginV2TestCase): - - def setUp(self): - provider = ('neutron_fwaas.services.firewall.service_drivers.' - 'driver_api.FirewallDriverDB') - super(FireWallDriverDBMixinTestCase, self).setUp( - service_provider=provider) - self.mock_registry_publish = mock.patch( - 'neutron_lib.callbacks.registry.publish').start() - self.driver_api = self.plugin.driver - self.ctx = context.get_admin_context() - self.firewall_db = self.plugin.driver.firewall_db - self.m_payload = mock.Mock() - m_db_event_payload = mock.patch( - 'neutron_lib.callbacks.events.DBEventPayload').start() - m_db_event_payload.return_value = self.m_payload - self.fake_fwg = { - 'id': 'fake_fwg_id', - 'ingress_firewall_policy_id': 'fake_ifwp_id', - 'egress_firewall_policy_id': 'fake_efwp_id', - 'ports': [], - 'tenant_id': 'fake_tenant_id', - 'status': 'CREATED' - } - - self.fake_fwp = { - 'id': 'fake_fwp_id', - 'firewall_rules': [], - 'info': 'fake_rule_info', - 'project_id': 'fake_project_id' - } - - self.fake_fwr = { - 'id': 'fake_fwr_id', - 'firewall_policy_id': [], - 'project_id': 'fake_project_id' - } - - # Test Firewall Group - def test_create_firewall_group(self): - - with mock.patch.object(self.firewall_db, 'create_firewall_group', - return_value=self.fake_fwg): - self.driver_api.create_firewall_group_postcommit = mock.Mock() - self.driver_api.create_firewall_group(self.ctx, self.fake_fwg) - self.driver_api.create_firewall_group_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwg) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_GROUP, - events.AFTER_CREATE, - self.driver_api, - payload=self.m_payload) - - def test_delete_firewall_group(self): - - with mock.patch.object(self.firewall_db, 'get_firewall_group', - return_value=self.fake_fwg): - self.driver_api.delete_firewall_group_postcommit = mock.Mock() - self.driver_api.delete_firewall_group(self.ctx, 'fake_fwg_id') - self.driver_api.delete_firewall_group_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwg) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_GROUP, - events.AFTER_DELETE, - self.driver_api, - payload=self.m_payload) - - def test_update_firewall_group(self): - fake_fwg_delta = { - 'ingress_firewall_policy_id': 'fake_ifwp_delta_id', - 'egress_firewall_policy_id': 'fake_efwp_delta_id', - 'ports': [], - } - - old_fake_fwg = { - 'id': 'fake_fwg_id', - 'ingress_firewall_policy_id': 'old_fake_ifwp_id', - 'egress_firewall_policy_id': 'old_fake_efwp_id', - 'ports': [], - 'tenant_id': 'fake_tenant_id', - 'status': 'CREATED' - } - - with mock.patch.object(self.firewall_db, 'get_firewall_group', - return_value=old_fake_fwg): - new_fake_fwg = copy.deepcopy(old_fake_fwg) - new_fake_fwg.update(fake_fwg_delta) - - with mock.patch.object(self.firewall_db, 'update_firewall_group', - return_value=new_fake_fwg): - self.driver_api.\ - update_firewall_group_postcommit = mock.Mock() - self.driver_api.\ - update_firewall_group(self.ctx, 'fake_fwg_id', - fake_fwg_delta) - self.driver_api.update_firewall_group_postcommit.\ - assert_called_once_with(self.ctx, old_fake_fwg, - new_fake_fwg) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_GROUP, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) - - # Test Firewall Policy - def test_create_firewall_policy(self): - - with mock.patch.object(self.firewall_db, 'create_firewall_policy', - return_value=self.fake_fwp): - self.driver_api.create_firewall_policy_postcommit = mock.Mock() - self.driver_api.create_firewall_policy(self.ctx, self.fake_fwp) - self.driver_api.create_firewall_policy_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwp) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_POLICY, - events.AFTER_CREATE, - self.driver_api, - payload=self.m_payload) - - def test_delete_firewall_policy(self): - - with mock.patch.object(self.firewall_db, 'delete_firewall_policy'): - with mock.patch.object(self.firewall_db, 'get_firewall_policy', - return_value=self.fake_fwp): - self.driver_api.\ - delete_firewall_policy_postcommit = mock.Mock() - self.driver_api.\ - delete_firewall_policy(self.ctx, 'fake_fwp_id') - self.driver_api.delete_firewall_policy_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwp) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_POLICY, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) - - def test_update_firewall_policy(self): - fake_fwp_delta = { - 'firewall_rules': [], - } - - old_fake_fwp = { - 'id': 'fake_fwp_id', - 'firewall_rules': [], - 'project_id': 'fake_project_id' - } - - with mock.patch.object(self.firewall_db, 'get_firewall_policy', - return_value=old_fake_fwp): - new_fake_fwp = copy.deepcopy(old_fake_fwp) - new_fake_fwp.update(fake_fwp_delta) - - with mock.patch.object(self.firewall_db, 'update_firewall_policy', - return_value=new_fake_fwp): - self.driver_api.\ - update_firewall_policy_postcommit = mock.Mock() - self.driver_api.\ - update_firewall_policy(self.ctx, 'fake_fwp_id', - fake_fwp_delta) - self.driver_api.update_firewall_policy_postcommit.\ - assert_called_once_with(self.ctx, old_fake_fwp, - new_fake_fwp) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_POLICY, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) - - # Test Firewall Rule - def test_create_firewall_rule(self): - - with mock.patch.object(self.firewall_db, 'create_firewall_rule', - return_value=self.fake_fwr): - self.driver_api.create_firewall_rule_postcommit = mock.Mock() - self.driver_api.create_firewall_rule(self.ctx, self.fake_fwr) - self.driver_api.create_firewall_rule_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwr) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_RULE, - events.AFTER_CREATE, - self.driver_api, - payload=self.m_payload) - - def test_delete_firewall_rule(self): - - self.firewall_db.delete_firewall_rule = mock.Mock() - - with mock.patch.object(self.firewall_db, 'get_firewall_rule', - return_value=self.fake_fwr): - self.driver_api.\ - delete_firewall_rule_postcommit = mock.Mock() - self.driver_api.\ - delete_firewall_rule(self.ctx, 'fake_fwr_id') - self.driver_api.delete_firewall_rule_postcommit.\ - assert_called_once_with(self.ctx, self.fake_fwr) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_RULE, - events.AFTER_DELETE, - self.driver_api, - payload=self.m_payload) - - def test_update_firewall_rule(self): - - fake_fwr_delta = { - 'firewall_policy_id': [], - } - - old_fake_fwr = { - 'id': 'fake_fwr_id', - 'firewall_policy_id': [], - 'project_id': 'fake_project_id' - } - - with mock.patch.object(self.firewall_db, 'get_firewall_rule', - return_value=old_fake_fwr): - new_fake_fwr = copy.deepcopy(old_fake_fwr) - new_fake_fwr.update(fake_fwr_delta) - - with mock.patch.object(self.firewall_db, 'update_firewall_rule', - return_value=new_fake_fwr): - self.driver_api.\ - update_firewall_rule_postcommit = mock.Mock() - self.driver_api. \ - update_firewall_rule(self.ctx, 'fake_fwr_id', - fake_fwr_delta) - self.driver_api.update_firewall_rule_postcommit.\ - assert_called_once_with(self.ctx, old_fake_fwr, - new_fake_fwr) - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_RULE, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) - - def test_insert_rule(self): - - with mock.patch.object(self.firewall_db, 'insert_rule', - return_value=self.fake_fwp): - self.driver_api.insert_rule_postcommit = mock.Mock() - self.driver_api.insert_rule(self.ctx, 'fake_fwp_id', - 'fake_rule_info') - self.driver_api.insert_rule_postcommit.\ - assert_called_once_with(self.ctx, 'fake_fwp_id', - 'fake_rule_info') - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_POLICY, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) - - def test_remove_rule(self): - - with mock.patch.object(self.firewall_db, 'remove_rule', - return_value=self.fake_fwp): - self.driver_api.remove_rule_postcommit = mock.Mock() - self.driver_api.remove_rule(self.ctx, 'fake_fwp_id', - 'fake_rule_info') - self.driver_api.remove_rule_postcommit.\ - assert_called_once_with(self.ctx, 'fake_fwp_id', - 'fake_rule_info') - self.mock_registry_publish.\ - assert_called_with(const.FIREWALL_POLICY, - events.AFTER_UPDATE, - self.driver_api, - payload=self.m_payload) diff --git a/neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin_v2.py b/neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin_v2.py deleted file mode 100644 index 2793f7795..000000000 --- a/neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin_v2.py +++ /dev/null @@ -1,737 +0,0 @@ -# Copyright 2016 -# 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 mock -import six -import webob.exc - -from neutron.api import extensions as api_ext -from neutron.db import servicetype_db as sdb -from neutron.tests.unit.db import test_db_base_plugin_v2 as test_db_plugin -from neutron_lib.api.definitions import firewall_v2 -from neutron_lib import constants as nl_constants -from neutron_lib import context -from neutron_lib.exceptions import firewall_v2 as f_exc -from neutron_lib.plugins import directory -from oslo_utils import importutils - -from neutron_fwaas.common import fwaas_constants -from neutron_fwaas import extensions -from neutron_fwaas.services.firewall import fwaas_plugin_v2 -from neutron_fwaas.services.firewall.service_drivers.driver_api import \ - FirewallDriverDB - - -def http_client_error(req, res): - explanation = "Request '%s %s %s' failed: %s" % (req.method, req.url, - req.body, res.body) - return webob.exc.HTTPClientError(code=res.status_int, - explanation=explanation) - - -class DummyDriverDB(FirewallDriverDB): - def is_supported_l2_port(self, port): - return True - - def is_supported_l3_port(self, port): - return True - - -class FirewallPluginV2TestCase(test_db_plugin.NeutronDbPluginV2TestCase): - DESCRIPTION = 'default description' - PROTOCOL = 'tcp' - IP_VERSION = 4 - SOURCE_IP_ADDRESS_RAW = '1.1.1.1' - DESTINATION_IP_ADDRESS_RAW = '2.2.2.2' - SOURCE_PORT = '55000:56000' - DESTINATION_PORT = '56000:57000' - ACTION = 'allow' - AUDITED = True - ENABLED = True - ADMIN_STATE_UP = True - SHARED = True - - resource_prefix_map = dict( - (k, firewall_v2.API_PREFIX) - for k in firewall_v2.RESOURCE_ATTRIBUTE_MAP.keys() - ) - - def setUp(self, service_provider=None, core_plugin=None, - extra_service_plugins=None, extra_extension_paths=None): - provider = fwaas_constants.FIREWALL_V2 - if not service_provider: - provider += (':dummy:neutron_fwaas.tests.unit.services.firewall.' - 'test_fwaas_plugin_v2.DummyDriverDB:default') - else: - provider += ':test:' + service_provider + ':default' - - bits = provider.split(':') - provider = { - 'service_type': bits[0], - 'name': bits[1], - 'driver': bits[2], - 'default': True, - } - # override the default service provider - self.service_providers = ( - mock.patch.object(sdb.ServiceTypeManager, - 'get_service_providers').start()) - self.service_providers.return_value = [provider] - - plugin_str = ('neutron_fwaas.services.firewall.fwaas_plugin_v2.' - 'FirewallPluginV2') - service_plugins = {'fw_plugin_name': plugin_str} - service_plugins.update(extra_service_plugins or {}) - - # we need to provide a plugin instance, although the extension manager - # will create a new instance of the plugin - plugins = { - fwaas_constants.FIREWALL_V2: fwaas_plugin_v2.FirewallPluginV2(), - } - for plugin_name, plugin_str in (extra_service_plugins or {}).items(): - plugins[plugin_name] = importutils.import_object(plugin_str) - ext_mgr = api_ext.PluginAwareExtensionManager( - ':'.join(extensions.__path__ + (extra_extension_paths or [])), - plugins, - ) - - super(FirewallPluginV2TestCase, self).setUp( - plugin=core_plugin, - service_plugins=service_plugins, - ext_mgr=ext_mgr, - ) - - # find the Firewall plugin that was instantiated by the extension - # manager - self.plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) - - def _get_admin_context(self): - # FIXME NOTE(ivasilevskaya) seems that test framework treats context - # with user_id=None/tenant_id=None (return value of - # context._get_admin_context() method) in a somewhat special way. - # So as a workaround to have the framework behave properly right now - # let's implement our own _get_admin_context method and look into the - # matter some other time. - return context.Context(user_id='admin', - tenant_id='admin-tenant', - is_admin=True) - - def _get_nonadmin_context(self, user_id='non-admin', tenant_id='tenant1'): - return context.Context(user_id=user_id, tenant_id=tenant_id) - - def _test_list_resources(self, resource, items, - neutron_context=None, - query_params=None): - if resource.endswith('y'): - resource_plural = resource.replace('y', 'ies') - else: - resource_plural = resource + 's' - - res = self._list(resource_plural, - neutron_context=neutron_context, - query_params=query_params) - resource = resource.replace('-', '_') - self.assertEqual( - sorted([i[resource]['id'] for i in items]), - sorted([i['id'] for i in res[resource_plural]])) - - def _list_req(self, resource_plural, ctx=None): - if not ctx: - ctx = self._get_admin_context() - req = self.new_list_request(resource_plural) - req.environ['neutron.context'] = ctx - return self.deserialize( - self.fmt, req.get_response(self.ext_api))[resource_plural] - - def _show_req(self, resource_plural, obj_id, ctx=None): - req = self.new_show_request(resource_plural, obj_id, fmt=self.fmt) - if not ctx: - ctx = self._get_admin_context() - req.environ['neutron.context'] = ctx - res = self.deserialize( - self.fmt, req.get_response(self.ext_api)) - return res - - def _build_default_fwg(self, ctx=None, is_one=True): - res = self._list_req('firewall_groups', ctx=ctx) - if is_one: - self.assertEqual(1, len(res)) - return res[0] - return res - - def _get_test_firewall_rule_attrs(self, name='firewall_rule1'): - attrs = {'name': name, - 'tenant_id': self._tenant_id, - 'project_id': self._tenant_id, - 'protocol': self.PROTOCOL, - 'ip_version': self.IP_VERSION, - 'source_ip_address': self.SOURCE_IP_ADDRESS_RAW, - 'destination_ip_address': self.DESTINATION_IP_ADDRESS_RAW, - 'source_port': self.SOURCE_PORT, - 'destination_port': self.DESTINATION_PORT, - 'action': self.ACTION, - 'enabled': self.ENABLED, - 'shared': self.SHARED} - return attrs - - def _get_test_firewall_policy_attrs(self, name='firewall_policy1', - audited=AUDITED): - attrs = {'name': name, - 'description': self.DESCRIPTION, - 'tenant_id': self._tenant_id, - 'project_id': self._tenant_id, - 'firewall_rules': [], - 'audited': audited, - 'shared': self.SHARED} - return attrs - - def _get_test_firewall_group_attrs(self, name='firewall_1', - status=nl_constants.CREATED): - attrs = {'name': name, - 'tenant_id': self._tenant_id, - 'project_id': self._tenant_id, - 'admin_state_up': self.ADMIN_STATE_UP, - 'status': status} - - return attrs - - def _create_firewall_policy(self, fmt, name, description, shared, - firewall_rules, audited, - expected_res_status=None, **kwargs): - data = {'firewall_policy': {'name': name, - 'description': description, - 'firewall_rules': firewall_rules, - 'audited': audited, - 'shared': shared}} - ctx = kwargs.get('context', None) - if ctx is None or ctx.is_admin: - tenant_id = kwargs.get('tenant_id', self._tenant_id) - data['firewall_policy'].update({'tenant_id': tenant_id}) - data['firewall_policy'].update({'project_id': tenant_id}) - - req = self.new_create_request('firewall_policies', data, fmt, - context=ctx) - res = req.get_response(self.ext_api) - if expected_res_status: - self.assertEqual(expected_res_status, res.status_int) - elif res.status_int >= 400: - raise http_client_error(req, res) - - return res - - def _replace_firewall_status(self, attrs, old_status, new_status): - if attrs['status'] is old_status: - attrs['status'] = new_status - return attrs - - @contextlib.contextmanager - def firewall_policy(self, fmt=None, name='firewall_policy1', - description=DESCRIPTION, shared=SHARED, - firewall_rules=None, audited=True, - do_delete=True, **kwargs): - if firewall_rules is None: - firewall_rules = [] - if not fmt: - fmt = self.fmt - res = self._create_firewall_policy(fmt, name, description, shared, - firewall_rules, audited, **kwargs) - if res.status_int >= 400: - raise webob.exc.HTTPClientError(code=res.status_int) - firewall_policy = self.deserialize(fmt or self.fmt, res) - yield firewall_policy - if do_delete: - self._delete('firewall_policies', - firewall_policy['firewall_policy']['id']) - - def _create_firewall_rule(self, fmt, name, shared, protocol, - ip_version, source_ip_address, - destination_ip_address, source_port, - destination_port, action, enabled, - expected_res_status=None, **kwargs): - tenant_id = kwargs.get('tenant_id', self._tenant_id) - data = {'firewall_rule': {'name': name, - 'protocol': protocol, - 'ip_version': ip_version, - 'source_ip_address': source_ip_address, - 'destination_ip_address': - destination_ip_address, - 'source_port': source_port, - 'destination_port': destination_port, - 'action': action, - 'enabled': enabled, - 'shared': shared}} - ctx = kwargs.get('context', None) - if ctx is None or ctx.is_admin: - tenant_id = kwargs.get('tenant_id', self._tenant_id) - data['firewall_rule'].update({'tenant_id': tenant_id}) - data['firewall_rule'].update({'project_id': tenant_id}) - - req = self.new_create_request('firewall_rules', data, fmt, context=ctx) - res = req.get_response(self.ext_api) - if expected_res_status: - self.assertEqual(expected_res_status, res.status_int) - elif res.status_int >= 400: - raise http_client_error(req, res) - - return res - - @contextlib.contextmanager - def firewall_rule(self, fmt=None, name='firewall_rule1', - shared=SHARED, protocol=PROTOCOL, ip_version=IP_VERSION, - source_ip_address=SOURCE_IP_ADDRESS_RAW, - destination_ip_address=DESTINATION_IP_ADDRESS_RAW, - source_port=SOURCE_PORT, - destination_port=DESTINATION_PORT, - action=ACTION, enabled=ENABLED, - do_delete=True, **kwargs): - if not fmt: - fmt = self.fmt - res = self._create_firewall_rule(fmt, name, shared, protocol, - ip_version, source_ip_address, - destination_ip_address, - source_port, destination_port, - action, enabled, **kwargs) - if res.status_int >= 400: - raise webob.exc.HTTPClientError(code=res.status_int) - firewall_rule = self.deserialize(fmt or self.fmt, res) - yield firewall_rule - if do_delete: - self._delete('firewall_rules', - firewall_rule['firewall_rule']['id']) - - def _create_firewall_group(self, fmt, name, description, - ingress_firewall_policy_id=None, - egress_firewall_policy_id=None, - ports=None, admin_state_up=True, - expected_res_status=None, **kwargs): - if ingress_firewall_policy_id is None: - default_policy = kwargs.get('default_policy', True) - if default_policy: - res = self._create_firewall_policy( - fmt, - 'fwp', - description=self.DESCRIPTION, - shared=self.SHARED, - firewall_rules=[], - audited=self.AUDITED, - ) - firewall_policy = self.deserialize(fmt or self.fmt, res) - fwp_id = firewall_policy["firewall_policy"]["id"] - ingress_firewall_policy_id = fwp_id - data = {'firewall_group': {'name': name, - 'description': description, - 'ingress_firewall_policy_id': ingress_firewall_policy_id, - 'egress_firewall_policy_id': egress_firewall_policy_id, - 'admin_state_up': admin_state_up}} - ctx = kwargs.get('context', None) - if ctx is None or ctx.is_admin: - tenant_id = kwargs.get('tenant_id', self._tenant_id) - data['firewall_group'].update({'tenant_id': tenant_id}) - data['firewall_group'].update({'project_id': tenant_id}) - if ports is not None: - data['firewall_group'].update({'ports': ports}) - - req = self.new_create_request('firewall_groups', data, fmt, - context=ctx) - res = req.get_response(self.ext_api) - if expected_res_status: - self.assertEqual(expected_res_status, res.status_int) - elif res.status_int >= 400: - raise http_client_error(req, res) - return res - - @contextlib.contextmanager - def firewall_group(self, fmt=None, name='firewall_1', - description=DESCRIPTION, - ingress_firewall_policy_id=None, - egress_firewall_policy_id=None, - ports=None, admin_state_up=True, - do_delete=True, **kwargs): - if not fmt: - fmt = self.fmt - res = self._create_firewall_group(fmt, name, description, - ingress_firewall_policy_id, - egress_firewall_policy_id, - ports=ports, - admin_state_up=admin_state_up, - **kwargs) - if res.status_int >= 400: - raise webob.exc.HTTPClientError(code=res.status_int) - firewall_group = self.deserialize(fmt or self.fmt, res) - yield firewall_group - if do_delete: - self._delete('firewall_groups', - firewall_group['firewall_group']['id']) - - def _rule_action(self, action, id, firewall_rule_id, insert_before=None, - insert_after=None, expected_code=webob.exc.HTTPOk.code, - expected_body=None, body_data=None): - # We intentionally do this check for None since we want to distinguish - # from empty dictionary - if body_data is None: - if action == 'insert': - body_data = {'firewall_rule_id': firewall_rule_id, - 'insert_before': insert_before, - 'insert_after': insert_after} - else: - body_data = {'firewall_rule_id': firewall_rule_id} - - req = self.new_action_request('firewall_policies', - body_data, id, - "%s_rule" % action) - res = req.get_response(self.ext_api) - self.assertEqual(expected_code, res.status_int) - response = self.deserialize(self.fmt, res) - if expected_body: - self.assertEqual(expected_body, response) - return response - - def _compare_firewall_rule_lists(self, firewall_policy_id, - observed_list, expected_list): - position = 0 - for r1, r2 in zip(observed_list, expected_list): - rule = r1['firewall_rule'] - rule['firewall_policy_id'] = firewall_policy_id - position += 1 - rule['position'] = position - for k in rule: - self.assertEqual(r2[k], rule[k]) - - def _test_create_firewall_group(self, attrs): - with self.firewall_policy() as fwp: - fwp_id = fwp['firewall_policy']['id'] - attrs['ingress_firewall_policy_id'] = fwp_id - attrs['egress_firewall_policy_id'] = fwp_id - with self.firewall_group( - name=attrs['name'], - ingress_firewall_policy_id=fwp_id, - egress_firewall_policy_id=fwp_id, - admin_state_up=self.ADMIN_STATE_UP, - ports=attrs['ports'] if 'ports' in attrs else None, - ) as firewall_group: - for k, v in six.iteritems(attrs): - self.assertEqual(v, firewall_group['firewall_group'][k]) - - -class TestFirewallPluginBasev2(FirewallPluginV2TestCase): - - def _test_fwg_with_port(self, device_owner): - with self.port(device_owner=device_owner) as port: - with self.firewall_rule() as fwr: - fwr_id = fwr['firewall_rule']['id'] - with self.firewall_policy(firewall_rules=[fwr_id]) as fwp: - fwp_id = fwp['firewall_policy']['id'] - self.firewall_group( - self.fmt, - "firewall_group", - self.DESCRIPTION, - ports=[port['port']['id']], - ingress_firewall_policy_id=fwp_id, - ) - - def test_create_fwg_with_l3_ports(self): - for device_owner_for_l3 in nl_constants.ROUTER_INTERFACE_OWNERS: - self._test_fwg_with_port(device_owner_for_l3) - - def test_create_fwg_with_l2_port(self): - device_owner_for_l2 = nl_constants.DEVICE_OWNER_COMPUTE_PREFIX + 'nova' - self._test_fwg_with_port(device_owner_for_l2) - - def test_create_firewall_group_with_port_on_different_project(self): - with self.port(tenant_id='fake_project_id_1') as port: - admin_ctx = context.get_admin_context() - self._create_firewall_group( - self.fmt, - "firewall_group1", - self.DESCRIPTION, - context=admin_ctx, - ports=[port['port']['id']], - expected_res_status=webob.exc.HTTPConflict.code, - ) - - def test_update_firewall_group_with_port_on_different_project(self): - ctx = context.Context('not_admin', 'fake_project_id_1') - with self.firewall_group(ctx=ctx) as firewall_group: - with self.port(tenant_id='fake_project_id_2') as port: - data = { - 'firewall_group': { - 'ports': [port['port']['id']], - }, - } - req = self.new_update_request( - 'firewall_groups', - data, - firewall_group['firewall_group']['id'], - ) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_create_firewall_group_with_with_wrong_type_port(self): - with self.port(device_owner="wrong port type") as port: - self._create_firewall_group( - self.fmt, - "firewall_group1", - self.DESCRIPTION, - ports=[port['port']['id']], - expected_res_status=webob.exc.HTTPConflict.code, - ) - - def test_update_firewall_group_with_with_wrong_type_port(self): - with self.firewall_group() as firewall_group: - with self.port(device_owner="wrong port type") as port: - data = { - 'firewall_group': { - 'ports': [port['port']['id']], - }, - } - req = self.new_update_request( - 'firewall_groups', - data, - firewall_group['firewall_group']['id'], - ) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - - def test_create_firewall_group_with_router_port_already_in_use(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF) as port: - with self.firewall_group(ports=[port['port']['id']]): - self._create_firewall_group( - self.fmt, - "firewall_group2", - self.DESCRIPTION, - ports=[port['port']['id']], - expected_res_status=webob.exc.HTTPConflict.code, - ) - - def test_create_firewall_group_with_dvr_port_already_in_use(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_DVR_INTERFACE) as port: - with self.firewall_group(ports=[port['port']['id']]): - self._create_firewall_group( - self.fmt, - "firewall_group2", - self.DESCRIPTION, - ports=[port['port']['id']], - expected_res_status=webob.exc.HTTPConflict.code, - ) - - def test_update_firewall_group_with_port_already_in_use(self): - with self.port( - device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF) as port: - with self.firewall_group(ports=[port['port']['id']]): - with self.firewall_group() as firewall_group: - data = { - 'firewall_group': { - 'ports': [port['port']['id']], - }, - } - req = self.new_update_request( - 'firewall_groups', - data, - firewall_group['firewall_group']['id'], - ) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, - res.status_int) - - def test_firewall_group_policy_rule_can_be_updated(self): - pending_status = [nl_constants.PENDING_CREATE, - nl_constants.PENDING_UPDATE, - nl_constants.PENDING_DELETE] - - for status in pending_status: - with self.firewall_rule() as fwr: - fwr_id = fwr['firewall_rule']['id'] - with self.firewall_policy(firewall_rules=[fwr_id]) as fwp: - fwp_id = fwp['firewall_policy']['id'] - with self.firewall_group( - ingress_firewall_policy_id=fwp_id) as fwg: - self.plugin.driver.firewall_db.\ - update_firewall_group_status( - context.get_admin_context(), - fwg['firewall_group']['id'], - status - ) - data = { - 'firewall_rule': { - 'name': 'new_name', - }, - } - req = self.new_update_request( - 'firewall_rules', - data, - fwr_id, - ) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPConflict.code, - res.status_int) - - def test_create_firewall_policy_with_other_project_not_shared_rule(self): - project1_context = self._get_nonadmin_context(tenant_id='project1') - project2_context = self._get_nonadmin_context(tenant_id='project2') - with self.firewall_rule(context=project1_context, shared=False) as fwr: - fwr_id = fwr['firewall_rule']['id'] - self.firewall_policy( - context=project2_context, - firewall_rules=[fwr_id], - expected_res_status=webob.exc.HTTPNotFound.code, - ) - - def test_update_firewall_policy_with_other_project_not_shared_rule(self): - project1_context = self._get_nonadmin_context(tenant_id='project1') - project2_context = self._get_nonadmin_context(tenant_id='project2') - with self.firewall_rule(context=project1_context, shared=False) as fwr: - with self.firewall_policy(context=project2_context, - shared=False) as fwp: - fwr_id = fwr['firewall_rule']['id'] - fwp_id = fwp['firewall_policy']['id'] - data = { - 'firewall_policy': { - 'firewall_rules': [fwr_id], - }, - } - req = self.new_update_request('firewall_policy', data, fwp_id) - res = req.get_response(self.ext_api) - self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int) - - def test_create_firewall_policy_with_other_project_shared_rule(self): - admin_context = self._get_admin_context() - project1_context = self._get_nonadmin_context(tenant_id='project1') - with self.firewall_rule(context=admin_context, shared=True) as fwr: - fwr_id = fwr['firewall_rule']['id'] - self.firewall_policy( - context=project1_context, - firewall_rules=[fwr_id], - expected_res_status=webob.exc.HTTPOk.code, - ) - - -class TestAutomaticAssociation(TestFirewallPluginBasev2): - def setUp(self): - # TODO(yushiro): Replace constant value for this test class - # Set auto association fwg - super(TestAutomaticAssociation, self).setUp() - - def test_vm_port(self): - port = { - "id": "fake_port", - "device_owner": "compute:nova", - "binding:vif_type": "ovs", - "binding:vif_details": {"ovs_hybrid_plug": False}, - "project_id": "fake_project", - "port_security_enabled": True, - } - self.plugin._core_plugin.get_port = mock.Mock(return_value=port) - fake_default_fwg = { - 'id': 'fake_id', - 'name': 'default', - 'ports': ['fake_port_id1'], - } - self.plugin.get_firewall_groups = \ - mock.Mock(return_value=[fake_default_fwg]) - self.plugin.update_firewall_group = mock.Mock() - kwargs = { - "context": mock.ANY, - "port": port, - "original_port": {"binding:vif_type": "unbound"} - } - self.plugin.handle_update_port( - "PORT", "after_update", "test_plugin", **kwargs) - self.plugin.get_firewall_groups.assert_called_once_with( - mock.ANY, - filters={ - 'tenant_id': [kwargs['port']['project_id']], - 'name': [fake_default_fwg['name']], - }, - fields=['id', 'ports'], - ) - port_ids = fake_default_fwg['ports'] + [kwargs['port']['id']] - self.plugin.update_firewall_group.assert_called_once_with( - mock.ANY, - fake_default_fwg['id'], - {'firewall_group': {'ports': port_ids}}, - ) - - def test_vm_port_not_newly_created(self): - self.plugin.get_firewall_group = mock.Mock() - self.plugin.update_firewall_group = mock.Mock() - # Just updated for VM port(name or description...etc.) - kwargs = { - "context": mock.ANY, - "port": { - "id": "fake_port", - "device_owner": "compute:nova", - "binding:vif_type": "ovs", - "project_id": "fake_project" - }, - "original_port": { - "device_owner": "compute:nova", - "binding:vif_type": "ovs", - "project_id": "fake_project" - } - } - self.plugin.handle_update_port( - "PORT", "after_update", "test_plugin", **kwargs) - self.plugin.get_firewall_group.assert_not_called() - self.plugin.update_firewall_group.assert_not_called() - - def test_not_vm_port(self): - self.plugin.get_firewall_group = mock.Mock() - self.plugin.update_firewall_group = mock.Mock() - for device_owner in ["network:router_interface", - "network:router_gateway", - "network:dhcp"]: - kwargs = { - "context": mock.ANY, - "port": {"id": "fake_port", - "device_owner": device_owner, - "project_id": "fake_project"}, - "original_port": {"device_owner": device_owner, - "binding:vif_type": "unbound", - "project_id": "fake_project"} - } - self.plugin.handle_update_port( - "PORT", "after_update", "test_plugin", **kwargs) - self.plugin.get_firewall_group.assert_not_called() - self.plugin.update_firewall_group.assert_not_called() - - def test_set_port_for_default_firewall_group_raised_port_in_use(self): - port_id = 'fake_port_id_already_associated_to_default_fw' - port = { - "id": port_id, - "device_owner": "compute:nova", - "binding:vif_type": "ovs", - "binding:vif_details": {"ovs_hybrid_plug": False}, - "project_id": "fake_project", - "port_security_enabled": True, - } - self.plugin._core_plugin.get_port = mock.Mock(return_value=port) - self.plugin.get_firewall_groups = mock.Mock(return_value=[]) - self.plugin.update_firewall_group = mock.Mock( - side_effect=f_exc.FirewallGroupPortInUse(port_ids=[port_id])) - kwargs = { - "context": mock.ANY, - "port": port, - "original_port": {"binding:vif_type": "unbound"} - } - try: - self.plugin.handle_update_port("PORT", "after_update", - "test_plugin", **kwargs) - except f_exc.FirewallGroupPortInUse: - self.fail("Associating port to default firewall group raises " - "'FirewallGroupPortInUse' while it should ignore it") diff --git a/neutron_fwaas/tests/unit/services/logapi/__init__.py b/neutron_fwaas/tests/unit/services/logapi/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/__init__.py b/neutron_fwaas/tests/unit/services/logapi/agents/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/__init__.py b/neutron_fwaas/tests/unit/services/logapi/agents/drivers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/__init__.py b/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_driver.py b/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_driver.py deleted file mode 100644 index ccb07564a..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_driver.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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. - -from neutron.services.logapi.drivers import base as log_base_driver -from neutron_fwaas.tests import base - -SUPPORTED_LOGGING_TYPES = ['firewall_group'] - - -class FakeDriver(log_base_driver.DriverBase): - - @staticmethod - def create(): - return FakeDriver( - name='fake_driver', - vif_types=[], - vnic_types=[], - supported_logging_types=SUPPORTED_LOGGING_TYPES, - requires_rpc=True - ) - - -class TestDriverBase(base.BaseTestCase): - - def setUp(self): - super(TestDriverBase, self).setUp() - self.driver = FakeDriver.create() - - def test_is_vif_type_compatible(self): - self.assertFalse( - self.driver.is_vif_type_compatible([])) - - def test_is_vnic_compatible(self): - self.assertFalse( - self.driver.is_vnic_compatible([])) - - def test_is_logging_type_supported(self): - self.assertTrue( - self.driver.is_logging_type_supported('firewall_group')) - self.assertFalse( - self.driver.is_logging_type_supported('security_group')) diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_log.py b/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_log.py deleted file mode 100644 index db1627c10..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/agents/drivers/iptables/test_log.py +++ /dev/null @@ -1,341 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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. - -from collections import defaultdict - -import mock -from neutron.tests.unit.api.v2 import test_base -from neutron_lib.services.logapi import constants as log_const - -from neutron_fwaas.privileged.netfilter_log import libnetfilter_log as libnflog -from neutron_fwaas.services.logapi.agents.drivers.iptables import log -from neutron_fwaas.tests import base - -FAKE_PROJECT_ID = 'fake_project_id' -FAKE_PORT_ID = 'fake_port_id' -FAKE_FWG_ID = 'fake_fwg_id' -FAKE_LOG_ID = 'fake_log_id' -FAKE_RESOURCE_TYPE = 'firewall_group' - -FAKE_RATE = 100 -FAKE_BURST = 25 - - -class TestLogPrefix(base.BaseTestCase): - - def setUp(self): - super(TestLogPrefix, self).setUp() - self.log_prefix = log.LogPrefix(FAKE_PORT_ID, - 'fake_event', - FAKE_PROJECT_ID) - self.log_prefix.log_object_refs = set([FAKE_LOG_ID]) - - def test_add_log_obj_ref(self): - added_log_id = test_base._uuid - expected_log_obj_ref = set([FAKE_LOG_ID, added_log_id]) - self.log_prefix.add_log_obj_ref(added_log_id) - self.assertEqual(expected_log_obj_ref, self.log_prefix.log_object_refs) - - def test_remove_log_obj_ref(self): - expected_log_obj_ref = set() - self.log_prefix.remove_log_obj_ref(FAKE_LOG_ID) - self.assertEqual(expected_log_obj_ref, self.log_prefix.log_object_refs) - - def test_is_empty(self): - self.log_prefix.remove_log_obj_ref(FAKE_LOG_ID) - result = self.log_prefix.is_empty - self.assertEqual(True, result) - - -class BaseIptablesLogTestCase(base.BaseTestCase): - - def setUp(self): - super(BaseIptablesLogTestCase, self).setUp() - self.iptables_manager_patch = mock.patch( - 'neutron.agent.linux.iptables_manager.IptablesManager') - self.iptables_manager_mock = self.iptables_manager_patch.start() - resource_rpc_mock = mock.Mock() - - self.iptables_mock = mock.Mock() - self.v4filter_mock = mock.Mock() - self.v6filter_mock = mock.Mock() - self.iptables_mock.ipv4 = {'filter': self.v4filter_mock} - self.iptables_mock.ipv6 = {'filter': self.v6filter_mock} - - self.log_driver = log.IptablesLoggingDriver(mock.Mock()) - self.log_driver.iptables_manager = self.iptables_mock - self.log_driver.resource_rpc = resource_rpc_mock - self.context = mock.Mock() - self.log_driver.agent_api = mock.Mock() - - def test_start_logging(self): - fake_router_info = mock.Mock() - fake_router_info.router_id = 'fake_router_id' - fake_router_info.ns_name = 'fake_namespace' - libnflog.run_nflog = mock.Mock() - self.log_driver._create_firewall_group_log = mock.Mock() - - # Test with router_info that has internal ports - fake_router_info.internal_ports = [ - {'id': 'fake_port1'}, - {'id': 'fake_port2'}, - ] - fake_kwargs = { - 'router_info': fake_router_info - } - self.log_driver.ports_belong_router = defaultdict(set) - self.log_driver.start_logging(self.context, **fake_kwargs) - self.log_driver._create_firewall_group_log.\ - assert_called_once_with(self.context, - FAKE_RESOURCE_TYPE, - ports=fake_router_info.internal_ports, - router_id=fake_router_info.router_id) - - # Test with log_resources - fake_kwargs = { - 'log_resources': 'fake' - } - self.log_driver._create_firewall_group_log.reset_mock() - self.log_driver.start_logging(self.context, **fake_kwargs) - self.log_driver._create_firewall_group_log. \ - assert_called_once_with(self.context, - FAKE_RESOURCE_TYPE, - **fake_kwargs) - - def test_stop_logging(self): - fake_kwargs = { - 'log_resources': 'fake' - } - self.log_driver._delete_firewall_group_log = mock.Mock() - self.log_driver.stop_logging(self.context, **fake_kwargs) - self.log_driver._delete_firewall_group_log.\ - assert_called_once_with(self.context, **fake_kwargs) - fake_kwargs = { - 'fake': 'fake' - } - self.log_driver._delete_firewall_group_log.reset_mock() - self.log_driver.stop_logging(self.context, **fake_kwargs) - self.log_driver._delete_firewall_group_log.assert_not_called() - - def test_clean_up_unused_ipt_mgrs(self): - f_router_ids = ['r1', 'r2', 'r3'] - self.log_driver.ipt_mgr_list = self._fake_ipt_mgr_list(f_router_ids) - - # Test with a port is delete from router - self.log_driver.unused_port_ids = set(['r1_port1']) - self.log_driver._cleanup_unused_ipt_mgrs() - self.assertEqual(set(), self.log_driver.unused_port_ids) - self.assertIsNone(self.log_driver.ipt_mgr_list['r1'].get('r1_port1')) - - # Test with all ports are deleted from router - self.log_driver.unused_port_ids = set(['r2_port1', 'r2_port2']) - self.log_driver._cleanup_unused_ipt_mgrs() - self.assertEqual(set(), self.log_driver.unused_port_ids) - self.assertIsNone(self.log_driver.ipt_mgr_list.get('r2')) - - def test_get_intf_name(self): - fake_router = mock.Mock() - fake_port_id = 'fake_router_port_id' - - # Test with legacy router - self.log_driver.conf.agent_mode = 'legacy' - fake_router.router = { - 'fake': 'fake_mode' - } - with mock.patch.object(self.log_driver.agent_api, - 'get_router_hosting_port', - return_value=fake_router): - intf_name = self.log_driver._get_intf_name(fake_port_id) - expected_name = 'qr-fake_router' - self.assertEqual(expected_name, intf_name) - - # Test with dvr router - self.log_driver.conf.agent_mode = 'dvr_snat' - fake_router.router = { - 'distributed': 'fake_mode' - } - with mock.patch.object(self.log_driver.agent_api, - 'get_router_hosting_port', - return_value=fake_router): - intf_name = self.log_driver._get_intf_name(fake_port_id) - expected_name = 'sg-fake_router' - self.assertEqual(expected_name, intf_name) - - # Test with fip dev - self.log_driver.conf.agent_mode = 'dvr_snat' - fake_router.router = { - 'distributed': 'fake_mode' - } - fake_router.rtr_fip_connect = 'fake' - self.log_driver.conf.agent_mode = 'fake' - with mock.patch.object(self.log_driver.agent_api, - 'get_router_hosting_port', - return_value=fake_router): - intf_name = self.log_driver._get_intf_name(fake_port_id) - expected_name = 'rfp-fake_route' - self.assertEqual(expected_name, intf_name) - - def test_setup_chains(self): - self.log_driver._add_nflog_rules_accepted = mock.Mock() - self.log_driver._add_log_rules_dropped = mock.Mock() - m_ipt_mgr = mock.Mock() - m_fwg_port_log = mock.Mock() - - # Test with ALL event - m_fwg_port_log.event = log_const.ALL_EVENT - self.log_driver._setup_chains(m_ipt_mgr, m_fwg_port_log) - - self.log_driver._add_nflog_rules_accepted.\ - assert_called_once_with(m_ipt_mgr, m_fwg_port_log) - self.log_driver._add_log_rules_dropped.\ - assert_called_once_with(m_ipt_mgr, m_fwg_port_log) - - # Test with ACCEPT event - self.log_driver._add_nflog_rules_accepted.reset_mock() - self.log_driver._add_log_rules_dropped.reset_mock() - - m_fwg_port_log.event = log_const.ACCEPT_EVENT - self.log_driver._setup_chains(m_ipt_mgr, m_fwg_port_log) - - self.log_driver._add_nflog_rules_accepted.\ - assert_called_once_with(m_ipt_mgr, m_fwg_port_log) - self.log_driver._add_log_rules_dropped.assert_not_called() - - # Test with DROP event - self.log_driver._add_nflog_rules_accepted.reset_mock() - self.log_driver._add_log_rules_dropped.reset_mock() - - m_fwg_port_log.event = log_const.DROP_EVENT - self.log_driver._setup_chains(m_ipt_mgr, m_fwg_port_log) - - self.log_driver._add_nflog_rules_accepted.assert_not_called() - self.log_driver._add_log_rules_dropped.\ - assert_called_once_with(m_ipt_mgr, m_fwg_port_log) - - def test_add_nflog_rules_accepted(self): - ipt_mgr = mock.Mock() - f_accept_prefix = log.LogPrefix(FAKE_PORT_ID, log_const. - ACCEPT_EVENT, - FAKE_PROJECT_ID) - - f_port_log = self._fake_port_log('fake_log_id', - log_const.ACCEPT_EVENT, - FAKE_PORT_ID) - - self.log_driver._add_rules_to_chain_v4v6 = mock.Mock() - self.log_driver._get_ipt_mgr_by_port = mock.Mock(return_value=ipt_mgr) - self.log_driver._get_intf_name = mock.Mock(return_value='fake_device') - - with mock.patch.object(self.log_driver, '_get_prefix', - side_effect=[f_accept_prefix, None]): - - # Test with prefix already added into prefixes_table - self.log_driver._add_nflog_rules_accepted(ipt_mgr, f_port_log) - self.log_driver._add_rules_to_chain_v4v6.assert_not_called() - self.assertEqual(set(['fake_log_id']), - f_accept_prefix.log_object_refs) - - # Test with prefixes_tables does not include the prefix - prefix = log.LogPrefix(FAKE_PORT_ID, log_const. - ACCEPT_EVENT, FAKE_PROJECT_ID) - with mock.patch.object(log, 'LogPrefix', return_value=prefix): - self.log_driver._add_nflog_rules_accepted(ipt_mgr, f_port_log) - v4_rules, v6_rules = self._fake_nflog_rule_v4v6('fake_device', - prefix.id) - - self.log_driver._add_rules_to_chain_v4v6.\ - assert_called_once_with(ipt_mgr, 'accepted', - v4_rules, v6_rules, - wrap=True, top=True, tag=prefix.id) - self.assertEqual(set(['fake_log_id']), - prefix.log_object_refs) - - def test_add_nflog_rules_dropped(self): - ipt_mgr = mock.Mock() - f_drop_prefix = log.LogPrefix(FAKE_PORT_ID, log_const. - DROP_EVENT, - FAKE_PROJECT_ID) - - f_port_log = self._fake_port_log('fake_log_id', - log_const.DROP_EVENT, - FAKE_PORT_ID) - - self.log_driver._add_rules_to_chain_v4v6 = mock.Mock() - self.log_driver._get_ipt_mgr_by_port = mock.Mock(return_value=ipt_mgr) - self.log_driver._get_intf_name = mock.Mock(return_value='fake_device') - - with mock.patch.object(self.log_driver, '_get_prefix', - side_effect=[f_drop_prefix, None]): - - # Test with prefix already added into prefixes_table - self.log_driver._add_log_rules_dropped(ipt_mgr, f_port_log) - self.log_driver._add_rules_to_chain_v4v6.assert_not_called() - self.assertEqual(set(['fake_log_id']), - f_drop_prefix.log_object_refs) - - # Test with prefixes_tables does not include the prefix - prefix = log.LogPrefix(FAKE_PORT_ID, log_const. - ACCEPT_EVENT, FAKE_PROJECT_ID) - with mock.patch.object(log, 'LogPrefix', return_value=prefix): - self.log_driver._add_log_rules_dropped(ipt_mgr, f_port_log) - v4_rules, v6_rules = self._fake_nflog_rule_v4v6('fake_device', - prefix.id) - - calls = [ - mock.call(ipt_mgr, 'dropped', v4_rules, v6_rules, - wrap=True, top=True, tag=prefix.id), - mock.call(ipt_mgr, 'rejected', v4_rules, v6_rules, - wrap=True, top=True, tag=prefix.id), - ] - self.log_driver._add_rules_to_chain_v4v6.\ - assert_has_calls(calls) - self.assertEqual(set(['fake_log_id']), - prefix.log_object_refs) - - def _fake_port_log(self, log_id, event, port_id): - f_log_info = { - 'event': event, - 'project_id': FAKE_PROJECT_ID, - 'id': log_id - } - return log.FWGPortLog(port_id, f_log_info) - - def _fake_nflog_rule_v4v6(self, device, tag): - v4_nflog_rule = ['-i %s -m limit --limit %s/s --limit-burst %s ' - '-j NFLOG --nflog-prefix %s' - % (device, FAKE_RATE, FAKE_BURST, tag)] - v4_nflog_rule += ['-o %s -m limit --limit %s/s --limit-burst %s ' - '-j NFLOG --nflog-prefix %s' - % (device, FAKE_RATE, FAKE_BURST, tag)] - v6_nflog_rule = ['-i %s -m limit --limit %s/s --limit-burst %s ' - '-j NFLOG --nflog-prefix %s' - % (device, FAKE_RATE, FAKE_BURST, tag)] - v6_nflog_rule += ['-o %s -m limit --limit %s/s --limit-burst %s ' - '-j NFLOG --nflog-prefix %s' - % (device, FAKE_RATE, FAKE_BURST, tag)] - return v4_nflog_rule, v6_nflog_rule - - def _fake_ipt_mgr_list(self, router_ids): - f_ipt_mgrs = defaultdict(dict) - - for router_id in router_ids: - f_port_id1 = router_id + '_port1' - f_port_id2 = router_id + '_port2' - ipt_mgr = mock.Mock() - ipt_mgr.ns_name = 'ns_' + router_id - f_ipt_mgrs[router_id][f_port_id1] = ipt_mgr - f_ipt_mgrs[router_id][f_port_id2] = ipt_mgr - - return f_ipt_mgrs diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/l3/__init__.py b/neutron_fwaas/tests/unit/services/logapi/agents/l3/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/agents/l3/test_fwg_log.py b/neutron_fwaas/tests/unit/services/logapi/agents/l3/test_fwg_log.py deleted file mode 100644 index 6a110d939..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/agents/l3/test_fwg_log.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited. -# 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 mock - -from neutron.api.rpc.callbacks.consumer import registry -from neutron.api.rpc.callbacks import resources -from neutron.api.rpc.handlers import resources_rpc -from neutron.tests.unit.services.logapi.agent.l3 import test_base as base -from neutron_lib import constants as lib_const - -from neutron_fwaas.services.logapi.agents.l3 import fwg_log - - -class FWaaSL3LoggingExtensionInitializeTestCase(base.L3LoggingExtBaseTestCase): - - def setUp(self): - super(FWaaSL3LoggingExtensionInitializeTestCase, self).setUp() - self.fw_l3_log_ext = fwg_log.FWaaSL3LoggingExtension() - self.fw_l3_log_ext.consume_api(self.agent_api) - - @mock.patch.object(registry, 'register') - @mock.patch.object(resources_rpc, 'ResourcesPushRpcCallback') - def test_initialize_subscribed_to_rpc(self, rpc_mock, subscribe_mock): - call_to_patch = 'neutron_lib.rpc.Connection' - with mock.patch(call_to_patch, - return_value=self.connection) as create_connection: - self.fw_l3_log_ext.initialize( - self.connection, lib_const.L3_AGENT_MODE) - create_connection.assert_has_calls([mock.call()]) - self.connection.create_consumer.assert_has_calls( - [mock.call( - resources_rpc.resource_type_versioned_topic( - resources.LOGGING_RESOURCE), - [rpc_mock()], - fanout=True)] - ) - subscribe_mock.assert_called_with( - mock.ANY, resources.LOGGING_RESOURCE) diff --git a/neutron_fwaas/tests/unit/services/logapi/base.py b/neutron_fwaas/tests/unit/services/logapi/base.py deleted file mode 100644 index 585387b49..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/base.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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 mock - -from neutron.api.rpc.callbacks.consumer import registry as cons_registry -from neutron.api.rpc.callbacks.producer import registry as prod_registry -from neutron.api.rpc.callbacks import resource_manager -from neutron.tests.unit import testlib_api - - -class BaseLogTestCase(testlib_api.SqlTestCase): - def setUp(self): - super(BaseLogTestCase, self).setUp() - - with mock.patch.object( - resource_manager.ResourceCallbacksManager, '_singleton', - new_callable=mock.PropertyMock(return_value=False)): - - self.cons_mgr = resource_manager.ConsumerResourceCallbacksManager() - self.prod_mgr = resource_manager.ProducerResourceCallbacksManager() - for mgr in (self.cons_mgr, self.prod_mgr): - mgr.clear() - - mock.patch.object( - cons_registry, '_get_manager', return_value=self.cons_mgr).start() - - mock.patch.object( - prod_registry, '_get_manager', return_value=self.prod_mgr).start() diff --git a/neutron_fwaas/tests/unit/services/logapi/common/__init__.py b/neutron_fwaas/tests/unit/services/logapi/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/common/test_fwg_callback.py b/neutron_fwaas/tests/unit/services/logapi/common/test_fwg_callback.py deleted file mode 100644 index e34a56cde..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/common/test_fwg_callback.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 mock -from neutron.objects import ports as port_objects -from neutron.services.logapi.drivers import base as log_driver_base -from neutron.services.logapi.drivers import manager as driver_mgr -from neutron.tests import base -from neutron_lib.callbacks import events -from neutron_lib.callbacks import registry -from neutron_lib import constants as nl_const - -from neutron_fwaas.common import fwaas_constants as fw_const -from neutron_fwaas.services.logapi.common import fwg_callback -from neutron_fwaas.services.logapi.common import log_db_api - -FAKE_DRIVER = None - - -class FakeDriver(log_driver_base.DriverBase): - - @staticmethod - def create(): - return FakeDriver( - name='fake_driver', - vif_types=[], - vnic_types=[], - supported_logging_types=['firewall_group'], - requires_rpc=True - ) - - -def fake_register(): - global FAKE_DRIVER - if not FAKE_DRIVER: - FAKE_DRIVER = FakeDriver.create() - driver_mgr.register(fw_const.FIREWALL_GROUP, - fwg_callback.FirewallGroupCallBack) - - -class TestFirewallGroupRuleCallback(base.BaseTestCase): - - def setUp(self): - super(TestFirewallGroupRuleCallback, self).setUp() - self.driver_manager = driver_mgr.LoggingServiceDriverManager() - self.fwg_callback = fwg_callback.FirewallGroupCallBack(mock.Mock(), - mock.Mock()) - self.m_context = mock.Mock() - - @mock.patch.object(fwg_callback.FirewallGroupCallBack, 'handle_event') - def test_handle_event(self, mock_fwg_cb): - fake_register() - self.driver_manager.register_driver(FAKE_DRIVER) - - registry.notify( - fw_const.FIREWALL_GROUP, events.AFTER_CREATE, mock.ANY) - mock_fwg_cb.assert_called_once_with( - fw_const.FIREWALL_GROUP, events.AFTER_CREATE, mock.ANY) - - mock_fwg_cb.reset_mock() - registry.notify( - fw_const.FIREWALL_GROUP, events.AFTER_UPDATE, mock.ANY) - mock_fwg_cb.assert_called_once_with( - fw_const.FIREWALL_GROUP, events.AFTER_UPDATE, mock.ANY) - - mock_fwg_cb.reset_mock() - registry.notify( - 'non_registered_resource', events.AFTER_CREATE, mock.ANY) - mock_fwg_cb.assert_not_called() - - mock_fwg_cb.reset_mock() - registry.notify( - 'non_registered_resource', events.AFTER_UPDATE, mock.ANY) - mock_fwg_cb.assert_not_called() - - def test_need_to_notify(self): - port_objects.Port.get_object = \ - mock.Mock(side_effect=self._get_object_side_effect) - - # Test with router devices - for device in nl_const.ROUTER_INTERFACE_OWNERS: - result = self.fwg_callback.need_to_notify(self.m_context, [device]) - self.assertEqual(True, result) - # Test with non-router device - result = self.fwg_callback.need_to_notify(self.m_context, - ['fake_port']) - self.assertEqual(False, result) - - # Test with ports_delta is empty - result = self.fwg_callback.need_to_notify(self.m_context, []) - self.assertEqual(False, result) - - def test_trigger_logging(self): - m_payload = mock.Mock() - self.fwg_callback.resource_push_api = mock.Mock() - m_payload.resource_id = 'fake_resource_id' - ports_delta = ['fake_port_id'] - - # Test with log resource could be found from DB - with mock.patch.object(log_db_api, 'get_logs_for_fwg', - return_value={'fake': 'fake'}): - self.fwg_callback.trigger_logging(self.m_context, - m_payload.resource_id, - ports_delta) - self.fwg_callback.resource_push_api.assert_called() - - # Test with log resource could not be found from DB - self.fwg_callback.resource_push_api.reset_mock() - with mock.patch.object(log_db_api, 'get_logs_for_fwg', - return_value={}): - self.fwg_callback.trigger_logging(self.m_context, - m_payload.resource_id, - ports_delta) - self.fwg_callback.resource_push_api.assert_not_called() - - def _get_object_side_effect(self, context, id): - fake_port = { - 'id': 'fake_id', - 'device_owner': id, - } - return fake_port - - def test_handle_event_with_router_port(self): - with mock.patch.object(self.fwg_callback, 'need_to_notify', - return_value=True): - with mock.patch.object(self.fwg_callback, 'trigger_logging'): - # Test for firewall group creation with router port - m_payload = self._mock_payload(events.AFTER_CREATE, - 'fake_port_id') - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_CREATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_called() - - # Test for firewall group update with router port - self.fwg_callback.trigger_logging.reset_mock() - m_payload = self._mock_payload(events.AFTER_UPDATE, - 'fake_port_id') - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_called() - - def test_handle_event_with_non_router_port(self): - with mock.patch.object(self.fwg_callback, 'need_to_notify', - return_value=False): - with mock.patch.object(self.fwg_callback, 'trigger_logging'): - - # Test for firewall group creation with non router ports - m_payload = self._mock_payload(events.AFTER_CREATE, - 'fake_port_id') - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_CREATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_not_called() - - # Test for firewall group creation without ports - self.fwg_callback.trigger_logging.reset_mock() - m_payload = self._mock_payload(events.AFTER_CREATE) - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_CREATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_not_called() - - # Test for firewall group update with non router ports - self.fwg_callback.trigger_logging.reset_mock() - m_payload = self._mock_payload(events.AFTER_UPDATE, - 'fake_port_id') - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_not_called() - - # Test for firewall group update without ports - self.fwg_callback.trigger_logging.reset_mock() - m_payload = self._mock_payload(events.AFTER_UPDATE) - self.fwg_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **{'payload': m_payload}) - self.fwg_callback.trigger_logging.assert_not_called() - - def _mock_payload(self, event, ports_delta=None): - m_payload = mock.Mock() - m_payload.context = self.m_context - if event == events.AFTER_CREATE: - if ports_delta: - m_payload.latest_state = { - 'ports': [ports_delta] - } - else: - m_payload.latest_state = { - 'ports': [] - } - if event == events.AFTER_UPDATE: - if ports_delta: - m_payload.states = [ - {'ports': [ports_delta]}, - {'ports': []} - ] - else: - m_payload.states = [ - {'ports': []}, - {'ports': []} - ] - return m_payload diff --git a/neutron_fwaas/tests/unit/services/logapi/common/test_log_db_api.py b/neutron_fwaas/tests/unit/services/logapi/common/test_log_db_api.py deleted file mode 100644 index 33b193f9b..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/common/test_log_db_api.py +++ /dev/null @@ -1,329 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 mock -from neutron.objects.logapi import logging_resource as log_object -from neutron.objects import ports as port_objects -from neutron.services.logapi.rpc import server as server_rpc -from neutron.tests import base -from neutron_lib import constants as nl_const -from oslo_utils import uuidutils - -from neutron_fwaas.services.logapi.common import log_db_api -from neutron_fwaas.services.logapi.rpc import log_server as fwg_rpc - -FWG = 'firewall_group' - - -def _create_log_object(tenant_id, resource_id=None, - target_id=None, event='ALL'): - - log_data = { - 'id': uuidutils.generate_uuid(), - 'name': 'fake_log_name', - 'resource_type': FWG, - 'project_id': tenant_id, - 'event': event, - 'enabled': True} - if resource_id: - log_data['resource_id'] = resource_id - if target_id: - log_data['target_id'] = target_id - return log_object.Log(**log_data) - - -def _fake_log_info(id, project_id, ports_id, event='ALL'): - expected = { - 'id': id, - 'project_id': project_id, - 'ports_log': ports_id, - 'event': event - } - return expected - - -def _fake_port_object(port_id, device_owner, status, - project_id=uuidutils.generate_uuid()): - port_data = { - 'id': port_id, - 'device_owner': device_owner, - 'project_id': project_id - } - if status: - port_data['status'] = status - return port_data - - -class LoggingRpcCallbackTestCase(base.BaseTestCase): - - def setUp(self): - super(LoggingRpcCallbackTestCase, self).setUp() - self.context = mock.Mock() - self.rpc_callback = server_rpc.LoggingApiSkeleton() - - log_db_api.fw_plugin_db = mock.Mock() - - self.vm_port = uuidutils.generate_uuid() - self.router_port = uuidutils.generate_uuid() - self.fake_vm_port = \ - _fake_port_object(self.vm_port, - nl_const.DEVICE_OWNER_COMPUTE_PREFIX, - nl_const.PORT_STATUS_ACTIVE) - - self.fake_router_port = \ - _fake_port_object(self.router_port, - nl_const.DEVICE_OWNER_ROUTER_INTF, - nl_const.PORT_STATUS_ACTIVE) - self.fake_router_ports = \ - [_fake_port_object(self.router_port, device, - nl_const.PORT_STATUS_ACTIVE) - for device in nl_const.ROUTER_INTERFACE_OWNERS] - - def test_get_fwg_log_info_for_log_resources(self): - fwg_id = uuidutils.generate_uuid() - tenant_id = uuidutils.generate_uuid() - log_obj = _create_log_object(tenant_id, resource_id=fwg_id) - - rpc_call = fwg_rpc.get_fwg_log_info_for_log_resources - with mock.patch.object(server_rpc, 'get_rpc_method', - return_value=rpc_call): - fake_ports = ['fake_port_1', 'fake_port_2'] - with mock.patch.object(log_db_api, '_get_ports_being_logged', - return_value=fake_ports): - expected_log_info = [ - _fake_log_info(log_obj['id'], tenant_id, fake_ports) - ] - - logs_info = self.rpc_callback.\ - get_sg_log_info_for_log_resources(self.context, - resource_type=FWG, - log_resources=[log_obj]) - self.assertEqual(expected_log_info, logs_info) - - def test_get_fwg_log_info_for_port(self): - fwg_id = uuidutils.generate_uuid() - port_id = uuidutils.generate_uuid() - tenant_id = uuidutils.generate_uuid() - - log_obj = _create_log_object(tenant_id, resource_id=fwg_id, - target_id=port_id) - - rpc_call = fwg_rpc.get_fwg_log_info_for_port - with mock.patch.object(server_rpc, 'get_rpc_method', - return_value=rpc_call): - with mock.patch.object(log_db_api, 'get_logs_for_port', - return_value=[log_obj]): - fake_ports = [port_id, 'fake_port2'] - with mock.patch.object(log_db_api, '_get_ports_being_logged', - return_value=fake_ports): - expected_log_info = [_fake_log_info(log_obj['id'], - tenant_id, - fake_ports)] - logs_info = self.rpc_callback.\ - get_sg_log_info_for_port(self.context, - resource_type=FWG, - port_id=port_id) - self.assertEqual(expected_log_info, logs_info) - - def test_get_ports_being_logged_with_target_id(self): - tenant_id = uuidutils.generate_uuid() - fwg_id = uuidutils.generate_uuid() - - # Test with VM port - log_obj = _create_log_object(tenant_id, resource_id=fwg_id, - target_id=self.vm_port) - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_vm_port): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([], logged_port_ids) - - # Test with router ports - log_obj = _create_log_object(tenant_id, resource_id=fwg_id, - target_id=self.router_port) - - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - with mock.patch.object(port_objects.Port, 'get_object', - side_effect=self.fake_router_ports): - - for port in self.fake_router_ports: - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([self.router_port], logged_port_ids) - - # Test with inactive router port - self.fake_router_port['status'] = nl_const.PORT_STATUS_DOWN - log_obj = _create_log_object(tenant_id, resource_id=fwg_id, - target_id=self.router_port) - - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_router_port): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([], logged_port_ids) - - def test_get_ports_being_logged_with_resource_id(self): - tenant_id = uuidutils.generate_uuid() - fwg_id = uuidutils.generate_uuid() - log_obj = _create_log_object(tenant_id, resource_id=fwg_id) - - log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ - mock.Mock(return_value=[self.vm_port]) - # Test with VM port - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_vm_port): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([], logged_port_ids) - - # Test with router ports - router_ports = [self.router_port, self.router_port, self.router_port] - log_db_api.fw_plugin_db. \ - get_ports_in_firewall_group = mock.Mock(return_value=router_ports) - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - - with mock.patch.object(port_objects.Port, 'get_object', - side_effect=self.fake_router_ports): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual(router_ports, logged_port_ids) - - # Test with both vm port and router ports - log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ - mock.Mock(return_value=[self.vm_port, self.router_port]) - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - - with mock.patch.object(port_objects.Port, 'get_object', - side_effect=[self.fake_vm_port, - self.fake_router_port]): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([self.router_port], logged_port_ids) - - # Test with inactive router port - log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ - mock.Mock(return_value=[self.router_port]) - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_router_port): - logged_port_ids = \ - log_db_api._get_ports_being_logged(self.context, log_obj) - self.assertEqual([self.router_port], logged_port_ids) - - def test_get_ports_being_logged_with_ports_in_tenant(self): - tenant_id = uuidutils.generate_uuid() - log_obj = _create_log_object(tenant_id) - - log_db_api.fw_plugin_db.get_fwg_ports_in_tenant = \ - mock.Mock(return_value=[self.router_port]) - log_db_api.fw_plugin_db. \ - get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') - - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_router_port): - log_db_api._get_ports_being_logged(self.context, log_obj) - log_db_api.fw_plugin_db.get_fwg_ports_in_tenant.\ - assert_called_with(self.context, tenant_id) - - def test_logs_for_port_with_vm_port(self): - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_vm_port): - logs = log_db_api.get_logs_for_port(self.context, self.vm_port) - self.assertEqual([], logs) - - def test_logs_for_port_with_router_port(self): - tenant_id = uuidutils.generate_uuid() - resource_id = uuidutils.generate_uuid() - target_id = uuidutils.generate_uuid() - log_db_api.fw_plugin_db.get_fwg_attached_to_port = \ - mock.Mock(side_effect=[[], resource_id, resource_id]) - with mock.patch.object(port_objects.Port, 'get_object', - return_value=self.fake_router_port): - - # Test with router port that did not attach to fwg - logs = log_db_api.get_logs_for_port(self.context, self.router_port) - self.assertEqual([], logs) - - # Test with router port that attached to fwg - # Fake log objects that bounds a given port - log = _create_log_object(tenant_id) - resource_log = _create_log_object(tenant_id, resource_id) - target_log = _create_log_object(tenant_id, resource_id, target_id) - log_objs = [log, target_log, resource_log] - - with mock.patch.object(log_object.Log, 'get_objects', - return_value=log_objs): - self.fake_router_port = mock.Mock(return_value=target_id) - logs = log_db_api.get_logs_for_port(self.context, - self.router_port) - self.assertEqual(log_objs, logs) - - # Fake log objects that does not bound a given port - unbound_resource = uuidutils.generate_uuid() - resource_log = _create_log_object(tenant_id, unbound_resource) - target_log = _create_log_object(tenant_id, unbound_resource, - target_id) - log_objs = [log, target_log, resource_log] - - with mock.patch.object(log_object.Log, 'get_objects', - return_value=log_objs): - self.fake_router_port = mock.Mock(return_value=target_id) - logs = log_db_api.get_logs_for_port(self.context, - self.router_port) - self.assertEqual([log], logs) - - def test_logs_for_fwg(self): - tenant_id = uuidutils.generate_uuid() - resource_id = uuidutils.generate_uuid() - target_id = uuidutils.generate_uuid() - - # Fake log objects that bounds a given fwg - log = _create_log_object(tenant_id) - resource_log = _create_log_object(tenant_id, resource_id) - target_log = _create_log_object(tenant_id, target_id=target_id) - ports_delta = [target_id] - - # Test with port that in ports_delta - log_db_api.fw_plugin_db.get_fwg_attached_to_port = \ - mock.Mock(return_value=None) - with mock.patch.object(log_object.Log, 'get_objects', - return_value=[target_log]): - logs = log_db_api.get_logs_for_fwg(self.context, - resource_id, - ports_delta) - self.assertEqual([target_log], logs) - - # Test with log that bound to a give fwg - with mock.patch.object(log_object.Log, 'get_objects', - return_value=[resource_log]): - logs = log_db_api.get_logs_for_fwg(self.context, - resource_id, - ports_delta) - self.assertEqual([resource_log], logs) - - # Test with log that does not bound to any fwg or port - with mock.patch.object(log_object.Log, 'get_objects', - return_value=[log]): - logs = log_db_api.get_logs_for_fwg(self.context, - resource_id, - ports_delta) - self.assertEqual([log], logs) diff --git a/neutron_fwaas/tests/unit/services/logapi/common/test_port_callback.py b/neutron_fwaas/tests/unit/services/logapi/common/test_port_callback.py deleted file mode 100644 index a7eba97f6..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/common/test_port_callback.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 mock -from neutron.objects import ports as port_objects -from neutron.services.logapi.drivers import base as log_driver_base -from neutron.services.logapi.drivers import manager as driver_mgr -from neutron.tests import base -from neutron_lib.callbacks import events -from neutron_lib.callbacks import registry -from neutron_lib.callbacks import resources -from neutron_lib import constants as nl_const -from oslo_utils import uuidutils - -from neutron_fwaas.services.logapi.common import log_db_api -from neutron_fwaas.services.logapi.common import port_callback - -FAKE_DRIVER = None - - -class FakeDriver(log_driver_base.DriverBase): - - @staticmethod - def create(): - return FakeDriver( - name='fake_driver', - vif_types=[], - vnic_types=[], - supported_logging_types=['firewall_group'], - requires_rpc=True - ) - - -def fake_register(): - global FAKE_DRIVER - if not FAKE_DRIVER: - FAKE_DRIVER = FakeDriver.create() - driver_mgr.register(resources.PORT, port_callback.NeutronPortCallBack) - - -class TestFirewallGroupRuleCallback(base.BaseTestCase): - - def setUp(self): - super(TestFirewallGroupRuleCallback, self).setUp() - self.driver_manager = driver_mgr.LoggingServiceDriverManager() - self.port_callback = port_callback.NeutronPortCallBack(mock.Mock(), - mock.Mock()) - self.m_context = mock.Mock() - - def _create_port_object(self, name=None, device_owner=None, - status=nl_const.PORT_STATUS_ACTIVE): - port_data = { - 'id': uuidutils.generate_uuid(), - 'project_id': 'fake_tenant_id', - 'status': status - } - if name: - port_data['name'] = name - if device_owner: - port_data['device_owner'] = device_owner - return port_objects.Port(**port_data) - - @mock.patch.object(port_callback.NeutronPortCallBack, 'handle_event') - def test_handle_event(self, m_port_cb_handler): - fake_register() - self.driver_manager.register_driver(FAKE_DRIVER) - - registry.notify(resources.PORT, events.AFTER_CREATE, mock.ANY) - m_port_cb_handler.assert_called_once_with( - resources.PORT, events.AFTER_CREATE, mock.ANY) - - m_port_cb_handler.reset_mock() - registry.notify( - resources.PORT, events.AFTER_UPDATE, mock.ANY) - m_port_cb_handler.assert_called_once_with( - resources.PORT, events.AFTER_UPDATE, mock.ANY) - - m_port_cb_handler.reset_mock() - registry.notify( - 'non_registered_resource', events.AFTER_CREATE, mock.ANY) - m_port_cb_handler.assert_not_called() - - m_port_cb_handler.reset_mock() - registry.notify( - 'non_registered_resource', events.AFTER_UPDATE, mock.ANY) - m_port_cb_handler.assert_not_called() - - def test_trigger_logging(self): - fake_log_obj = mock.Mock() - self.port_callback.resource_push_api = mock.Mock() - port = self._create_port_object(device_owner='fake_device_owner') - - # Test with log resource could be found from DB - with mock.patch.object(log_db_api, 'get_logs_for_port', - return_value=[fake_log_obj]): - self.port_callback.trigger_logging(self.m_context, port) - self.port_callback.resource_push_api.assert_called() - - # Test with log resource could not be found from DB - self.port_callback.resource_push_api.reset_mock() - with mock.patch.object(log_db_api, 'get_logs_for_port', - return_value=[]): - self.port_callback.trigger_logging(self.m_context, port) - self.port_callback.resource_push_api.assert_not_called() - - def test_handle_event_with_router_port(self): - with mock.patch.object(self.port_callback, 'trigger_logging'): - # Test for router port enabling - f_port_config = self._fake_port_config( - nl_const.DEVICE_OWNER_ROUTER_INTF, action='enable') - self.port_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **f_port_config) - self.port_callback.trigger_logging.assert_called() - - # Test for router port disabling - self.port_callback.trigger_logging.reset_mock() - f_port_config = self._fake_port_config( - nl_const.DEVICE_OWNER_ROUTER_INTF, action='disable') - self.port_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **f_port_config) - self.port_callback.trigger_logging.assert_called() - - # Test for router port status does not change - self.port_callback.trigger_logging.reset_mock() - f_port_config = \ - self._fake_port_config(nl_const.DEVICE_OWNER_ROUTER_INTF) - self.port_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **f_port_config) - self.port_callback.trigger_logging.assert_not_called() - - def test_handle_event_with_non_router_port(self): - with mock.patch.object(self.port_callback, 'trigger_logging'): - # Test for port enabling - f_port_config = self._fake_port_config('fake_port_type', - action='enable') - self.port_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **f_port_config) - self.port_callback.trigger_logging.assert_not_called() - - # Test for port disabling - self.port_callback.trigger_logging.reset_mock() - f_port_config = self._fake_port_config('fake_port_type', - action='disable') - self.port_callback.handle_event(mock.ANY, - events.AFTER_UPDATE, - mock.ANY, - **f_port_config) - self.port_callback.trigger_logging.assert_not_called() - - def _fake_port_config(self, device_owner, action=None): - f_kwargs = {} - f_kwargs['context'] = self.m_context - if action == 'enable': - # Create original port with DOWN status - original_port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_DOWN) - - # Create port with ACTIVE status - port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_ACTIVE) - f_kwargs['original_port'] = original_port - f_kwargs['port'] = port - elif action == 'disable': - # Create original port with ACTIVE status - original_port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_ACTIVE) - - # Create port with DOWN status - port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_DOWN) - f_kwargs['original_port'] = original_port - f_kwargs['port'] = port - else: - # Create original port with ACTIVE status - original_port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_ACTIVE) - - # Create port with ACTIVE status - port = self._create_port_object( - device_owner=device_owner, status=nl_const.PORT_STATUS_ACTIVE) - f_kwargs['original_port'] = original_port - f_kwargs['port'] = port - return f_kwargs diff --git a/neutron_fwaas/tests/unit/services/logapi/rpc/__init__.py b/neutron_fwaas/tests/unit/services/logapi/rpc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/neutron_fwaas/tests/unit/services/logapi/rpc/test_log_server.py b/neutron_fwaas/tests/unit/services/logapi/rpc/test_log_server.py deleted file mode 100644 index 092a148c6..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/rpc/test_log_server.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 mock - -from neutron.services.logapi.rpc import server as server_rpc -from neutron.tests import base - -from neutron_fwaas.services.logapi.rpc import log_server as fw_server_rpc - - -class FWGLoggingApiSkeletonTestCase(base.BaseTestCase): - @mock.patch("neutron_fwaas.services.logapi.common.log_db_api." - "get_fwg_log_info_for_port") - def test_get_fwg_log_info_for_port(self, mock_callback): - with mock.patch.object( - server_rpc, - 'get_rpc_method', - return_value=fw_server_rpc.get_fwg_log_info_for_port - ): - test_obj = server_rpc.LoggingApiSkeleton() - m_context = mock.Mock() - port_id = '123' - test_obj.get_sg_log_info_for_port(m_context, - resource_type='firewall_v2', - port_id=port_id) - mock_callback.assert_called_with(m_context, port_id) - - @mock.patch("neutron_fwaas.services.logapi.common.log_db_api." - "get_fwg_log_info_for_log_resources") - def test_get_fwg_log_info_for_log_resources(self, mock_callback): - with mock.patch.object( - server_rpc, - 'get_rpc_method', - return_value=fw_server_rpc.get_fwg_log_info_for_log_resources - ): - test_obj = server_rpc.LoggingApiSkeleton() - m_context = mock.Mock() - log_resources = [mock.Mock()] - test_obj.get_sg_log_info_for_log_resources( - m_context, - resource_type='firewall_v2', - log_resources=log_resources) - mock_callback.assert_called_with(m_context, log_resources) diff --git a/neutron_fwaas/tests/unit/services/logapi/test_fwg_validate.py b/neutron_fwaas/tests/unit/services/logapi/test_fwg_validate.py deleted file mode 100644 index 2ee9876fa..000000000 --- a/neutron_fwaas/tests/unit/services/logapi/test_fwg_validate.py +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright (c) 2018 Fujitsu Limited -# 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 mock -from neutron.objects import ports -from neutron.services.logapi.common import exceptions as log_exc -from neutron.services.logapi.common import validators -from neutron.tests import base -from neutron_lib import constants as nl_const -from sqlalchemy.orm import exc as orm_exc - -from neutron_fwaas.services.logapi import exceptions as fwg_log_exc -from neutron_fwaas.services.logapi import fwg_validate - - -class TestFWGLogRequestValidations(base.BaseTestCase): - """Test validator for a log creation request""" - - def setUp(self): - super(TestFWGLogRequestValidations, self).setUp() - fwg_validate.fwg_plugin = mock.Mock() - fwg_validate.fwg_plugin.driver = mock.Mock() - fwg_validate.fwg_plugin.driver.firewall_db = mock.Mock() - - def test_validate_fwg_request(self): - m_context = mock.Mock() - fake_data = { - 'resource_type': 'firewall_group', - 'resource_id': 'fake_fwg_id' - } - with mock.patch.object(fwg_validate, '_check_fwg'): - fwg_validate.validate_firewall_group_request(m_context, fake_data) - fwg_validate._check_fwg.\ - assert_called_with(m_context, fake_data['resource_id']) - fake_data = { - 'resource_type': 'firewall_group', - 'resource_id': 'fake_fwg_id', - 'target_id': 'fake_port_id' - } - with mock.patch.object(fwg_validate, - '_check_target_resource_bound_fwg'): - with mock.patch.object(fwg_validate, '_check_fwg'): - with mock.patch.object(fwg_validate, '_check_fwg_port'): - fwg_validate.validate_firewall_group_request(m_context, - fake_data) - fwg_validate._check_target_resource_bound_fwg.\ - assert_called_with(m_context, - fake_data['resource_id'], - fake_data['target_id']) - fwg_validate._check_fwg. \ - assert_called_with(m_context, - fake_data['resource_id']) - fwg_validate._check_fwg_port. \ - assert_called_with(m_context, - fake_data['target_id']) - - def test_validate_request_fwg_id_not_exists(self): - - with mock.patch.object(fwg_validate.fwg_plugin, 'get_firewall_group', - side_effect=orm_exc.NoResultFound): - self.assertRaises( - log_exc.ResourceNotFound, - fwg_validate._check_fwg, - mock.ANY, - 'fake_fwg_id') - - def test_validate_request_fwg_not_active(self): - fake_fwg = {'id': '1234', 'status': 'PENDING'} - with mock.patch.object(fwg_validate.fwg_plugin, 'get_firewall_group', - return_value=fake_fwg): - self.assertRaises( - fwg_log_exc.FWGIsNotReadyForLogging, - fwg_validate._check_fwg, - mock.ANY, - 'fake_fwg_id') - - def test_validate_request_router_or_port_id_not_exists(self): - with mock.patch.object(ports.Port, 'get_object', return_value=None): - self.assertRaises( - log_exc.TargetResourceNotFound, - fwg_validate._check_fwg_port, - mock.ANY, - 'fake_port_id') - - def test_validate_request_unsupported_fwg_log_on_vm_port(self): - - fake_port = {'device_owner': "compute:"} - with mock.patch.object(ports.Port, 'get_object', - return_value=fake_port): - with mock.patch.object(validators, 'validate_log_type_for_port', - return_value=False): - self.assertRaises( - log_exc.LoggingTypeNotSupported, - fwg_validate._check_fwg_port, - mock.ANY, - 'fake_port_id') - - def test_validate_request_router_port_is_not_active(self): - - non_active_status = [nl_const.PORT_STATUS_DOWN, - nl_const.PORT_STATUS_ERROR, - nl_const.PORT_STATUS_NOTAPPLICABLE, - nl_const.PORT_STATUS_BUILD] - fake_port = [{'device_owner': nl_const.DEVICE_OWNER_ROUTER_INTF, - 'status': status} - for status in non_active_status] - with mock.patch.object(ports.Port, 'get_object', - side_effect=fake_port): - for status in non_active_status: - self.assertRaises( - fwg_log_exc.PortIsNotReadyForLogging, - fwg_validate._check_fwg_port, - mock.ANY, - 'fake_port_id') - - def test_validate_request_router_port_was_not_associated_fwg(self): - - fake_port = {'device_owner': nl_const.DEVICE_OWNER_ROUTER_INTF, - 'status': nl_const.PORT_STATUS_ACTIVE} - - with mock.patch.object(ports.Port, 'get_object', - return_value=fake_port): - with mock.patch.object(fwg_validate.fwg_plugin.driver.firewall_db, - 'get_fwg_attached_to_port', - return_value=None): - self.assertRaises( - fwg_log_exc.TargetResourceNotAssociated, - fwg_validate._check_fwg_port, - mock.ANY, - 'fake_port_id') - - def test_validate_request_target_resource_not_bound_fwg(self): - - fake_ports_in_fwg = ['fake_port_id1, fake_port_id2'] - with mock.patch.object( - fwg_validate.fwg_plugin.driver.firewall_db, - 'get_ports_in_firewall_group', - return_value=fake_ports_in_fwg): - - self.assertRaises( - log_exc.InvalidResourceConstraint, - fwg_validate._check_target_resource_bound_fwg, - mock.ANY, - mock.ANY, - 'fake_target_id') diff --git a/neutron_fwaas/version.py b/neutron_fwaas/version.py deleted file mode 100644 index 6d5e0bf79..000000000 --- a/neutron_fwaas/version.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2011 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. - -import pbr.version - -version_info = pbr.version.VersionInfo('neutron-fwaas') diff --git a/releasenotes/notes/.placeholder b/releasenotes/notes/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/releasenotes/notes/adding-new-tables-for-future-consumption-ffd537c1f82e2e01.yaml b/releasenotes/notes/adding-new-tables-for-future-consumption-ffd537c1f82e2e01.yaml deleted file mode 100644 index 455f623b7..000000000 --- a/releasenotes/notes/adding-new-tables-for-future-consumption-ffd537c1f82e2e01.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -prelude: > - Adding new tables for future consumption. -features: - - | - New tables ``ACCEPTED_EGRESS_TRAFFIC_TABLE=91`` - and ``ACCEPTED_INGRESS_TRAFFIC_TABLE=92`` & ``DROPPED_TRAFFIC_TABLE=93`` - are added to OVS based FWaaS L2 driver for future comsumption like logging - service. -fixes: - - | - The limitation related to logging for security group in case of - co-existence between SG and FWG is also fixed. \ No newline at end of file diff --git a/releasenotes/notes/auto-association-default-firewall-group-7e9faf1afca1df85.yaml b/releasenotes/notes/auto-association-default-firewall-group-7e9faf1afca1df85.yaml deleted file mode 100644 index 046ffcc4c..000000000 --- a/releasenotes/notes/auto-association-default-firewall-group-7e9faf1afca1df85.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -prelude: > - Associating default firewall group for new VM ports within a project - automatically. -features: - - | - The default firewall group won't be applied to all new VM ports as default. - However, if option ``auto_associate_default_firewall_group`` is enabled in - neutron_fwaas.conf like: - - [fwaas] - auto_associate_default_firewall_group = True - - Then, the default firewall group will be applied to all new VM ports. diff --git a/releasenotes/notes/bug-1702242-c917c832ac2fa4e1.yaml b/releasenotes/notes/bug-1702242-c917c832ac2fa4e1.yaml deleted file mode 100644 index 099a0cad6..000000000 --- a/releasenotes/notes/bug-1702242-c917c832ac2fa4e1.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -fixes: - - | - [`bug 1702242 `__] - Port range specification of a firewall rule now works expectedly - with the reference L3 agent based implementation. - Previously, when creating a firewall rule with port range like - ``8778:9000``, the rule was not deleted correctly and only entries - associated with the first port number were clean up. - Note that this bug is only applied to the reference L3 agent - based implementation. diff --git a/releasenotes/notes/bug-1746404-493a66faac333403.yaml b/releasenotes/notes/bug-1746404-493a66faac333403.yaml deleted file mode 100644 index 959d0eb88..000000000 --- a/releasenotes/notes/bug-1746404-493a66faac333403.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -prelude: > - Taking security for VM instance into consideration, we've removed an option - to disable automatic association with default firewall group feature. - Therefore, `auto_associate_default_firewall_group` has been removed. -fixes: - - | - There is no validation to check if an updated port is for VM or not so far. - After this fix, default firewall group association is called only for - VM ports which are newly created. diff --git a/releasenotes/notes/bug-1799358-360c6ab27a32e0ac.yaml b/releasenotes/notes/bug-1799358-360c6ab27a32e0ac.yaml deleted file mode 100644 index 05a8774c8..000000000 --- a/releasenotes/notes/bug-1799358-360c6ab27a32e0ac.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -fixes: - - | - There was no way to define default firewall group rules. - Default firewall group rules can be now defined in neutron_fwaas.conf - in section ``default_fwg_rules``. - Default firewall group rules are same as hardcoded values before. diff --git a/releasenotes/notes/cisco-fwaas-driver-move-8f46325d13c93543.yaml b/releasenotes/notes/cisco-fwaas-driver-move-8f46325d13c93543.yaml deleted file mode 100644 index ea175b27a..000000000 --- a/releasenotes/notes/cisco-fwaas-driver-move-8f46325d13c93543.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -prelude: > - The Cisco Firewall Driver is being moved from the - FWaaS repo to the Cisco specific repo: - https://github.com/openstack/networking-cisco -upgrade: - - The Cisco FWaaS driver will not be available from - the neutron-fwaas repo in Newton. For the Cisco - FWaaS driver, refer to the openstack/networking-cisco - repo. - diff --git a/releasenotes/notes/coexistence-between-sg-and-fwg-1f77a755539a9463.yaml b/releasenotes/notes/coexistence-between-sg-and-fwg-1f77a755539a9463.yaml deleted file mode 100644 index aa695dcda..000000000 --- a/releasenotes/notes/coexistence-between-sg-and-fwg-1f77a755539a9463.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -prelude: > - Coexistence between security group and firewall group. -features: - - L2 firewall group driver based OVS can work in coexistence mode. - That means, if a port is associated with both firewall group and - security group, then a packet must be allowed by both features. -other: - - If a port is associated with both firewall group & security group and - there is a security group logging, which is enabled to collect ``DROP`` - events for this port, then most of invalid packets will be dropped at - firewall group for performance reason except first dropped packet, which - is allowed by firewall group but not accepted by security group. So not - every dropped packet will be logged (like in case of security group - works in standalone mode). - diff --git a/releasenotes/notes/config-file-generation-265c5256668a26bf.yaml b/releasenotes/notes/config-file-generation-265c5256668a26bf.yaml deleted file mode 100644 index bb8749ce5..000000000 --- a/releasenotes/notes/config-file-generation-265c5256668a26bf.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -prelude: > - Generation of sample Neutron FWaaS configuration files. -features: - - Neutron FWaaS no longer includes static example configuration files. - Instead, use tools/generate_config_file_samples.sh to generate them. - The files are generated with a .sample extension. diff --git a/releasenotes/notes/deprecate-neutron-fwaas-as-stadium-project-934d6acb3e824249.yaml b/releasenotes/notes/deprecate-neutron-fwaas-as-stadium-project-934d6acb3e824249.yaml deleted file mode 100644 index f2c7125a1..000000000 --- a/releasenotes/notes/deprecate-neutron-fwaas-as-stadium-project-934d6acb3e824249.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -prelude: > - Neutron-fwaas project is now deprecated in the Neutron stadium. -deprecations: - - | - Due to lack of maintainers neutron-fwaas project is now deprecated in the - Neutron stadium. There is no planned releases of this project in the - ``Victoria`` cycle. - In ``W`` cycle project will be moved out from the stadium to the unofficial - OpenStack projects. - If You want to step in and be maintainer of this project to keep it in the - Neutron stadium, please contact the ``neutron team`` via - openstack-discuss@lists.openstack.org or IRC channel #openstack-neutron - @freenode. diff --git a/releasenotes/notes/drop-python-2-7-73d3113c69d724c1.yaml b/releasenotes/notes/drop-python-2-7-73d3113c69d724c1.yaml deleted file mode 100644 index cbffe4f47..000000000 --- a/releasenotes/notes/drop-python-2-7-73d3113c69d724c1.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -upgrade: - - | - Python 2.7 support has been dropped. The minimum version of Python now - supported by neutron-fwaas is Python 3.6. diff --git a/releasenotes/notes/enable-quotas-a3d0a21743bb1985.yaml b/releasenotes/notes/enable-quotas-a3d0a21743bb1985.yaml deleted file mode 100644 index 216f1ef0f..000000000 --- a/releasenotes/notes/enable-quotas-a3d0a21743bb1985.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -prelude: > - Enable quotas for FWaaS. -features: - - The FWaaS extension will register quotas. - The default values for quota_firewall and - quota_firewall_policy are set to 10. - The default value for quota_firewall_rule - is set to 100. - Quotas can be adjusted in the conf files, including - -1 values to allow unlimited. -issues: - - Tenants may receive a 409 Conflict error with a - message body containing a quota exceeded message - during resource creation if their quota is exceeded. -other: - - Operators that increase the default limit for quota_routers - from 10 may want to bump FWaaS quotas as well, since with - router insertion a tenant can potentially have a unique - policy and firewall for each router. diff --git a/releasenotes/notes/fwaas-config-9c780ccfb0e7887f.yaml b/releasenotes/notes/fwaas-config-9c780ccfb0e7887f.yaml deleted file mode 100644 index 9bba1bed3..000000000 --- a/releasenotes/notes/fwaas-config-9c780ccfb0e7887f.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -features: - - Neutron Firewall as a Service can be configured by the users - with the newly introduced fwaas configuration file. diff --git a/releasenotes/notes/fwaas-v2-logging-79cbaa43ff17f47f.yaml b/releasenotes/notes/fwaas-v2-logging-79cbaa43ff17f47f.yaml deleted file mode 100644 index 00903d5db..000000000 --- a/releasenotes/notes/fwaas-v2-logging-79cbaa43ff17f47f.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -prelude: > - Resource type **firewall group** has been supported for neutron packet - logging framework. You can specify firewall group as ``--resource-type`` - for logging API. -features: - - | - Enable to collect network packet log for ACCEPT/DROP action from firewall - groups. Currently, packet logging supports only L3(router) ports. -issues: - - | - [`bug 1720727 `__] - Currently, we cannot specify the following combination on CLI due to - missing validation of --resource-type: - - - --resource-type firewall_group --resource - - --resource-type firewall_group --resource --target - - Therefore, you can only run with following combinations: - - - --resource-type firewall_group --target - - --resource-type firewall_group diff --git a/releasenotes/notes/fwaas_v2-374471c215af0ca0.yaml b/releasenotes/notes/fwaas_v2-374471c215af0ca0.yaml deleted file mode 100644 index 577d1a2d7..000000000 --- a/releasenotes/notes/fwaas_v2-374471c215af0ca0.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -prelude: > - The FWaaS team is pleased to release FWaaS v2.0. This release of FWaaS - supports either the original FWaaS v1 or the new FWaaS v2. -features: - - In FWaaS v2 firewall policies are applied to router ports, as opposed to - applying to routers in FWaaS v1. - - Earlier the FWaaS agent integrated with the L3 agent by having the L3 Agent - class inherit from the FWaaS Agent class. This meant that other service - agents could not also integrate with the L3 agent. Now, using the L3 agent - extensions mechanism, FWaaS (v1 and v2) plugs in to the L3 agent. This - means that it can interoperate peacefully with other L3 advanced services - that also implement the L3 agent extension mechanism, all without any code - changes to Neutron. -upgrade: - - There is not currently a defined upgrade path from FWaaS v1 to FWaaS v2. - - FWaaS v1 can not be enabled at the same time as FWaaS v2; one or the other - must be chosen. diff --git a/releasenotes/notes/mcafee-fwaas-driver-removal-8915271e5d4288cf.yaml b/releasenotes/notes/mcafee-fwaas-driver-removal-8915271e5d4288cf.yaml deleted file mode 100644 index d8239fc4f..000000000 --- a/releasenotes/notes/mcafee-fwaas-driver-removal-8915271e5d4288cf.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -prelude: > - - The McAfee Firewall Driver is being removed from the FwaaS repo, - due to lack of active maintainers. -upgrade: - - The McAfee Firewall Driver will not be available for use in the - Newton release. diff --git a/releasenotes/notes/ovs-firewall-driver-c347ea0a560b7e38.yaml b/releasenotes/notes/ovs-firewall-driver-c347ea0a560b7e38.yaml deleted file mode 100644 index ba6c5162f..000000000 --- a/releasenotes/notes/ovs-firewall-driver-c347ea0a560b7e38.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -issues: - - | - Currently, the FWaaSv2 L2 driver can be configured as: - - ``firewall_driver = ovs`` - - And the Security Group driver is specified as: - - ``firewall_driver = openvswitch`` - - If both are configured, the packet will still only hit the FWaaS table in - OVS and will not traverse the rules in the SG table. There are some fixes - needed to support this model which are being tested and will be merged - shortly. Currently there are no checks to allow only one of FWaaS L2 or SG - to be configured. diff --git a/releasenotes/notes/remove_fwaas_v1-15c6e19484f46d1b.yaml b/releasenotes/notes/remove_fwaas_v1-15c6e19484f46d1b.yaml deleted file mode 100644 index 3412ede54..000000000 --- a/releasenotes/notes/remove_fwaas_v1-15c6e19484f46d1b.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -prelude: > - - FWaaS V1 is being removed from the neutron-fwaas repo. Because FWaaS V2 - has been available since the Newton release. -upgrade: - - The FWaaS V1 source code will not be available in neutron-fwaas repo from - Stein. - neutron-fwaas-migrate-v1-to-v2 can be used for migrating V1 object to V2 model. diff --git a/releasenotes/notes/validation_if_port_is_supported-639d0df705eb67f9.yaml b/releasenotes/notes/validation_if_port_is_supported-639d0df705eb67f9.yaml deleted file mode 100644 index 4a24db60a..000000000 --- a/releasenotes/notes/validation_if_port_is_supported-639d0df705eb67f9.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -prelude: > - Validating if a port is supported by FWaaS V2 -fixes: - - | - [`bug 1746855 `__] - Now, FWaaS V2 will validate if a port is supported before adding it - to a FWG. This helps to make sure FWaaS V2 API works as expected. \ No newline at end of file diff --git a/releasenotes/notes/varmour-fwaas-driver-removal-f7aa304a4544134a.yaml b/releasenotes/notes/varmour-fwaas-driver-removal-f7aa304a4544134a.yaml deleted file mode 100644 index 0c90e0339..000000000 --- a/releasenotes/notes/varmour-fwaas-driver-removal-f7aa304a4544134a.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -prelude: > - - The vArmour Firewall Driver is being removed from the FwaaS repo, - as per decision to remove vendor drivers from the community repo. -upgrade: - - The vArmour Firewall Driver will not be available for use in the - Newton release. diff --git a/releasenotes/notes/vyatta-fwaas-driver-removal-e38e6ecde5105084.yaml b/releasenotes/notes/vyatta-fwaas-driver-removal-e38e6ecde5105084.yaml deleted file mode 100644 index ef2fb710d..000000000 --- a/releasenotes/notes/vyatta-fwaas-driver-removal-e38e6ecde5105084.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -prelude: > - - The vyatta Firewall Driver is being removed from the FwaaS repo, - as per decision to remove vendor drivers from the community repo. -upgrade: - - The vyatta Firewall Driver will not be available for use in the - Newton release from the community repo. diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/releasenotes/source/_templates/.placeholder b/releasenotes/source/_templates/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py deleted file mode 100644 index 58b1e388c..000000000 --- a/releasenotes/source/conf.py +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -# Neutron FWaaS Release Notes documentation build configuration file, created -# by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'openstackdocstheme', - 'reno.sphinxext', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Neutron FWaaS Release Notes' -copyright = u'2015, Neutron FWaaS Developers' - -# Release notes are version independent. -# The full version, including alpha/beta/rc tags. -release = '' -# The short X.Y version. -version = '' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'openstackdocs' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'NeutronFWaaSReleaseNotesdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'NeutronFWaaSReleaseNotes.tex', - u'Neutron FWaaS Release Notes Documentation', - u'Neutron FWaaS Developers', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'neutronfwaasreleasenotes', u'Neutron FWaaS Release Notes ' - 'Documentation', [u'Neutron FWaaS Developers'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'NeutronFWaaSReleaseNotes', u'Neutron FWaaS Release Notes ' - 'Documentation', - u'Neutron FWaaS Developers', 'NeutronFWaaSReleaseNotes', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - -# -- Options for Internationalization output ------------------------------ -locale_dirs = ['locale/'] - -# -- Options for openstackdocstheme ------------------------------------------- -repository_name = 'openstack/neutron-fwaas' -bug_project = 'neutron' -bug_tag = 'doc' diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst deleted file mode 100644 index 890a78928..000000000 --- a/releasenotes/source/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -============================= - Neutron FWaaS Release Notes -============================= - -.. toctree:: - :maxdepth: 1 - - unreleased - stein - rocky - queens - pike - ocata - newton - mitaka - liberty diff --git a/releasenotes/source/liberty.rst b/releasenotes/source/liberty.rst deleted file mode 100644 index 36217be84..000000000 --- a/releasenotes/source/liberty.rst +++ /dev/null @@ -1,6 +0,0 @@ -============================== - Liberty Series Release Notes -============================== - -.. release-notes:: - :branch: origin/stable/liberty diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po deleted file mode 100644 index 5b219d9f0..000000000 --- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po +++ /dev/null @@ -1,473 +0,0 @@ -# Andi Chandler , 2017. #zanata -# Andi Chandler , 2018. #zanata -# Andi Chandler , 2020. #zanata -msgid "" -msgstr "" -"Project-Id-Version: neutron-fwaas\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-01-24 00:17+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2020-04-16 12:40+0000\n" -"Last-Translator: Andi Chandler \n" -"Language-Team: English (United Kingdom)\n" -"Language: en_GB\n" -"X-Generator: Zanata 4.3.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -msgid "--resource-type firewall_group" -msgstr "--resource-type firewall_group" - -msgid "--resource-type firewall_group --resource " -msgstr "--resource-type firewall_group --resource " - -msgid "" -"--resource-type firewall_group --resource --target " -"" -msgstr "" -"--resource-type firewall_group --resource --target " -"" - -msgid "--resource-type firewall_group --target " -msgstr "--resource-type firewall_group --target " - -msgid "11.0.0" -msgstr "11.0.0" - -msgid "12.0.0" -msgstr "12.0.0" - -msgid "13.0.0" -msgstr "13.0.0" - -msgid "14.0.0" -msgstr "14.0.0" - -msgid "15.0.0-9" -msgstr "15.0.0-9" - -msgid "7.0.2" -msgstr "7.0.2" - -msgid "7.1.1" -msgstr "7.1.1" - -msgid "8.0.0" -msgstr "8.0.0" - -msgid "9.0.0" -msgstr "9.0.0" - -msgid "9.0.0.0b2" -msgstr "9.0.0.0b2" - -msgid "9.0.0.0b3" -msgstr "9.0.0.0b3" - -msgid "9.0.0.0rc1" -msgstr "9.0.0.0rc1" - -msgid "Adding new tables for future consumption." -msgstr "Adding new tables for future consumption." - -msgid "And the Security Group driver is specified as:" -msgstr "And the Security Group driver is specified as:" - -msgid "" -"Associating default firewall group for new VM ports within a project " -"automatically." -msgstr "" -"Associating default firewall group for new VM ports within a project " -"automatically." - -msgid "Bug Fixes" -msgstr "Bug Fixes" - -msgid "Coexistence between security group and firewall group." -msgstr "Coexistence between security group and firewall group." - -msgid "Current Series Release Notes" -msgstr "Current Series Release Notes" - -msgid "Currently, the FWaaSv2 L2 driver can be configured as:" -msgstr "Currently, the FWaaSv2 L2 driver can be configured as:" - -msgid "" -"Earlier the FWaaS agent integrated with the L3 agent by having the L3 Agent " -"class inherit from the FWaaS Agent class. This meant that other service " -"agents could not also integrate with the L3 agent. Now, using the L3 agent " -"extensions mechanism, FWaaS (v1 and v2) plugs in to the L3 agent. This " -"means that it can interoperate peacefully with other L3 advanced services " -"that also implement the L3 agent extension mechanism, all without any code " -"changes to Neutron." -msgstr "" -"Earlier the FWaaS agent integrated with the L3 agent by having the L3 Agent " -"class inherit from the FWaaS Agent class. This meant that other service " -"agents could not also integrate with the L3 agent. Now, using the L3 agent " -"extensions mechanism, FWaaS (v1 and v2) plugs in to the L3 agent. This " -"means that it can interoperate peacefully with other L3 advanced services " -"that also implement the L3 agent extension mechanism, all without any code " -"changes to Neutron." - -msgid "Enable quotas for FWaaS." -msgstr "Enable quotas for FWaaS." - -msgid "" -"Enable to collect network packet log for ACCEPT/DROP action from firewall " -"groups. Currently, packet logging supports only L3(router) ports." -msgstr "" -"Enable to collect network packet log for ACCEPT/DROP action from firewall " -"groups. Currently, packet logging supports only L3(router) ports." - -msgid "" -"FWaaS V1 is being removed from the neutron-fwaas repo. Because FWaaS V2 has " -"been available since the Newton release." -msgstr "" -"FWaaS V1 is being removed from the neutron-fwaas repo. Because FWaaS V2 has " -"been available since the Newton release." - -msgid "" -"FWaaS v1 can not be enabled at the same time as FWaaS v2; one or the other " -"must be chosen." -msgstr "" -"FWaaS v1 can not be enabled at the same time as FWaaS v2; one or the other " -"must be chosen." - -msgid "Generation of sample Neutron FWaaS configuration files." -msgstr "Generation of sample Neutron FWaaS configuration files." - -msgid "" -"If a port is associated with both firewall group & security group and there " -"is a security group logging, which is enabled to collect ``DROP`` events for " -"this port, then most of invalid packets will be dropped at firewall group " -"for performance reason except first dropped packet, which is allowed by " -"firewall group but not accepted by security group. So not every dropped " -"packet will be logged (like in case of security group works in standalone " -"mode)." -msgstr "" -"If a port is associated with both firewall group & security group and there " -"is a security group logging, which is enabled to collect ``DROP`` events for " -"this port, then most of invalid packets will be dropped at firewall group " -"for performance reason except first dropped packet, which is allowed by " -"firewall group but not accepted by security group. So not every dropped " -"packet will be logged (like in case of security group works in standalone " -"mode)." - -msgid "" -"If both are configured, the packet will still only hit the FWaaS table in " -"OVS and will not traverse the rules in the SG table. There are some fixes " -"needed to support this model which are being tested and will be merged " -"shortly. Currently there are no checks to allow only one of FWaaS L2 or SG " -"to be configured." -msgstr "" -"If both are configured, the packet will still only hit the FWaaS table in " -"OVS and will not traverse the rules in the SG table. There are some fixes " -"needed to support this model which are being tested and will be merged " -"shortly. Currently there are no checks to allow only one of FWaaS L2 or SG " -"to be configured." - -msgid "" -"In FWaaS v2 firewall policies are applied to router ports, as opposed to " -"applying to routers in FWaaS v1." -msgstr "" -"In FWaaS v2 firewall policies are applied to router ports, as opposed to " -"applying to routers in FWaaS v1." - -msgid "Known Issues" -msgstr "Known Issues" - -msgid "" -"L2 firewall group driver based OVS can work in coexistence mode. That means, " -"if a port is associated with both firewall group and security group, then a " -"packet must be allowed by both features." -msgstr "" -"L2 firewall group driver based OVS can work in coexistence mode. That means, " -"if a port is associated with both firewall group and security group, then a " -"packet must be allowed by both features." - -msgid "Liberty Series Release Notes" -msgstr "Liberty Series Release Notes" - -msgid "Mitaka Series Release Notes" -msgstr "Mitaka Series Release Notes" - -msgid "Neutron FWaaS Release Notes" -msgstr "Neutron FWaaS Release Notes" - -msgid "" -"Neutron FWaaS no longer includes static example configuration files. " -"Instead, use tools/generate_config_file_samples.sh to generate them. The " -"files are generated with a .sample extension." -msgstr "" -"Neutron FWaaS no longer includes static example configuration files. " -"Instead, use tools/generate_config_file_samples.sh to generate them. The " -"files are generated with a .sample extension." - -msgid "" -"Neutron Firewall as a Service can be configured by the users with the newly " -"introduced fwaas configuration file." -msgstr "" -"Neutron Firewall as a Service can be configured by the users with the newly " -"introduced FWaaS configuration file." - -msgid "New Features" -msgstr "New Features" - -msgid "" -"New tables ``ACCEPTED_EGRESS_TRAFFIC_TABLE=91`` and " -"``ACCEPTED_INGRESS_TRAFFIC_TABLE=92`` & ``DROPPED_TRAFFIC_TABLE=93`` are " -"added to OVS based FWaaS L2 driver for future comsumption like logging " -"service." -msgstr "" -"New tables ``ACCEPTED_EGRESS_TRAFFIC_TABLE=91`` and " -"``ACCEPTED_INGRESS_TRAFFIC_TABLE=92`` & ``DROPPED_TRAFFIC_TABLE=93`` are " -"added to OVS based FWaaS L2 driver for future consumption like logging " -"service." - -msgid "Newton Series Release Notes" -msgstr "Newton Series Release Notes" - -msgid "Ocata Series Release Notes" -msgstr "Ocata Series Release Notes" - -msgid "" -"Operators that increase the default limit for quota_routers from 10 may want " -"to bump FWaaS quotas as well, since with router insertion a tenant can " -"potentially have a unique policy and firewall for each router." -msgstr "" -"Operators that increase the default limit for quota_routers from 10 may want " -"to bump FWaaS quotas as well, since with router insertion a tenant can " -"potentially have a unique policy and firewall for each router." - -msgid "Other Notes" -msgstr "Other Notes" - -msgid "Pike Series Release Notes" -msgstr "Pike Series Release Notes" - -msgid "Prelude" -msgstr "Prelude" - -msgid "" -"Python 2.7 support has been dropped. The minimum version of Python now " -"supported by neutron-fwaas is Python 3.6." -msgstr "" -"Python 2.7 support has been dropped. The minimum version of Python now " -"supported by neutron-fwaas is Python 3.6." - -msgid "Queens Series Release Notes" -msgstr "Queens Series Release Notes" - -msgid "" -"Resource type **firewall group** has been supported for neutron packet " -"logging framework. You can specify firewall group as ``--resource-type`` " -"for logging API." -msgstr "" -"Resource type **firewall group** has been supported for neutron packet " -"logging framework. You can specify firewall group as ``--resource-type`` " -"for logging API." - -msgid "Rocky Series Release Notes" -msgstr "Rocky Series Release Notes" - -msgid "Start using reno to manage release notes." -msgstr "Start using Reno to manage release notes." - -msgid "Stein Series Release Notes" -msgstr "Stein Series Release Notes" - -msgid "" -"Taking security for VM instance into consideration, we've removed an option " -"to disable automatic association with default firewall group feature. " -"Therefore, `auto_associate_default_firewall_group` has been removed." -msgstr "" -"Taking security for VM instance into consideration, we've removed an option " -"to disable automatic association with default firewall group feature. " -"Therefore, `auto_associate_default_firewall_group` has been removed." - -msgid "" -"Tenants may receive a 409 Conflict error with a message body containing a " -"quota exceeded message during resource creation if their quota is exceeded." -msgstr "" -"Tenants may receive a 409 Conflict error with a message body containing a " -"quota exceeded message during resource creation if their quota is exceeded." - -msgid "" -"The Cisco FWaaS driver will not be available from the neutron-fwaas repo in " -"Newton. For the Cisco FWaaS driver, refer to the openstack/networking-cisco " -"repo." -msgstr "" -"The Cisco FWaaS driver will not be available from the neutron-fwaas repo in " -"Newton. For the Cisco FWaaS driver, refer to the openstack/networking-cisco " -"repo." - -msgid "" -"The Cisco Firewall Driver is being moved from the FWaaS repo to the Cisco " -"specific repo: https://github.com/openstack/networking-cisco" -msgstr "" -"The Cisco Firewall Driver is being moved from the FWaaS repo to the Cisco " -"specific repo: https://github.com/openstack/networking-cisco" - -msgid "" -"The FWaaS V1 source code will not be available in neutron-fwaas repo from " -"Stein. neutron-fwaas-migrate-v1-to-v2 can be used for migrating V1 object to " -"V2 model." -msgstr "" -"The FWaaS V1 source code will not be available in neutron-fwaas repo from " -"Stein. neutron-fwaas-migrate-v1-to-v2 can be used for migrating V1 object to " -"V2 model." - -msgid "" -"The FWaaS extension can register quotas. The default values for " -"quota_firewall, quota_firewall_policy, and quota_firewall_rule are set to -1 " -"(unlimited)." -msgstr "" -"The FWaaS extension can register quotas. The default values for " -"quota_firewall, quota_firewall_policy, and quota_firewall_rule are set to -1 " -"(unlimited)." - -msgid "" -"The FWaaS extension will register quotas. The default values for " -"quota_firewall and quota_firewall_policy are set to 10. The default value " -"for quota_firewall_rule is set to 100. Quotas can be adjusted in the conf " -"files, including -1 values to allow unlimited." -msgstr "" -"The FWaaS extension will register quotas. The default values for " -"quota_firewall and quota_firewall_policy are set to 10. The default value " -"for quota_firewall_rule is set to 100. Quotas can be adjusted in the conf " -"files, including -1 values to allow unlimited." - -msgid "" -"The FWaaS team is pleased to release FWaaS v2.0. This release of FWaaS " -"supports either the original FWaaS v1 or the new FWaaS v2." -msgstr "" -"The FWaaS team is pleased to release FWaaS v2.0. This release of FWaaS " -"supports either the original FWaaS v1 or the new FWaaS v2." - -msgid "" -"The McAfee Firewall Driver is being removed from the FwaaS repo, due to lack " -"of active maintainers." -msgstr "" -"The McAfee Firewall Driver is being removed from the FWaaS repo, due to lack " -"of active maintainers." - -msgid "" -"The McAfee Firewall Driver will not be available for use in the Newton " -"release." -msgstr "" -"The McAfee Firewall Driver will not be available for use in the Newton " -"release." - -msgid "" -"The default firewall group won't be applied to all new VM ports as default. " -"However, if option ``auto_associate_default_firewall_group`` is enabled in " -"neutron_fwaas.conf like:" -msgstr "" -"The default firewall group won't be applied to all new VM ports as default. " -"However, if option ``auto_associate_default_firewall_group`` is enabled in " -"neutron_fwaas.conf like:" - -msgid "" -"The limitation related to logging for security group in case of co-existence " -"between SG and FWG is also fixed." -msgstr "" -"The limitation related to logging for security group in case of co-existence " -"between SG and FWG is also fixed." - -msgid "" -"The vArmour Firewall Driver is being removed from the FwaaS repo, as per " -"decision to remove vendor drivers from the community repo." -msgstr "" -"The vArmour Firewall Driver is being removed from the FWaaS repo, as per " -"decision to remove vendor drivers from the community repo." - -msgid "" -"The vArmour Firewall Driver will not be available for use in the Newton " -"release." -msgstr "" -"The vArmour Firewall Driver will not be available for use in the Newton " -"release." - -msgid "The vyatta Firewall Driver is being removed from the FwaaS repo," -msgstr "The Vyatta Firewall Driver is being removed from the FWaaS repo," - -msgid "" -"The vyatta Firewall Driver will not be available for use in the Newton " -"release from the community repo." -msgstr "" -"The Vyatta Firewall Driver will not be available for use in the Newton " -"release from the community repo." - -msgid "Then, the default firewall group will be applied to all new VM ports." -msgstr "Then, the default firewall group will be applied to all new VM ports." - -msgid "" -"There is no validation to check if an updated port is for VM or not so far. " -"After this fix, default firewall group association is called only for VM " -"ports which are newly created." -msgstr "" -"There is no validation to check if an updated port is for VM or not so far. " -"After this fix, default firewall group association is called only for VM " -"ports which are newly created." - -msgid "" -"There is not currently a defined upgrade path from FWaaS v1 to FWaaS v2." -msgstr "" -"There is not currently a defined upgrade path from FWaaS v1 to FWaaS v2." - -msgid "Therefore, you can only run with following combinations:" -msgstr "Therefore, you can only run with following combinations:" - -msgid "Upgrade Notes" -msgstr "Upgrade Notes" - -msgid "Validating if a port is supported by FWaaS V2" -msgstr "Validating if a port is supported by FWaaS V2" - -msgid "" -"[`bug 1702242 `__] Port " -"range specification of a firewall rule now works expectedly with the " -"reference L3 agent based implementation. Previously, when creating a " -"firewall rule with port range like ``8778:9000``, the rule was not deleted " -"correctly and only entries associated with the first port number were clean " -"up. Note that this bug is only applied to the reference L3 agent based " -"implementation." -msgstr "" -"[`bug 1702242 `__] Port " -"range specification of a firewall rule now works expectedly with the " -"reference L3 agent based implementation. Previously, when creating a " -"firewall rule with port range like ``8778:9000``, the rule was not deleted " -"correctly and only entries associated with the first port number were clean " -"up. Note that this bug is only applied to the reference L3 agent based " -"implementation." - -msgid "" -"[`bug 1720727 `__] " -"Currently, we cannot specify the following combination on CLI due to missing " -"validation of --resource-type:" -msgstr "" -"[`bug 1720727 `__] " -"Currently, we cannot specify the following combination on CLI due to missing " -"validation of --resource-type:" - -msgid "" -"[`bug 1746855 `__] Now, " -"FWaaS V2 will validate if a port is supported before adding it to a FWG. " -"This helps to make sure FWaaS V2 API works as expected." -msgstr "" -"[`bug 1746855 `__] Now, " -"FWaaS V2 will validate if a port is supported before adding it to a FWG. " -"This helps to make sure FWaaS V2 API works as expected." - -msgid "[fwaas] auto_associate_default_firewall_group = True" -msgstr "[fwaas] auto_associate_default_firewall_group = True" - -msgid "``firewall_driver = openvswitch``" -msgstr "``firewall_driver = openvswitch``" - -msgid "``firewall_driver = ovs``" -msgstr "``firewall_driver = ovs``" - -msgid "as per decision to remove vendor drivers from the community repo." -msgstr "as per decision to remove vendor drivers from the community repo." diff --git a/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po deleted file mode 100644 index 250b7f911..000000000 --- a/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po +++ /dev/null @@ -1,66 +0,0 @@ -# Gérald LONLAS , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: Neutron FWaaS Release Notes 11.0.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-08-16 20:31+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-10-22 05:48+0000\n" -"Last-Translator: Gérald LONLAS \n" -"Language-Team: French\n" -"Language: fr\n" -"X-Generator: Zanata 3.9.6\n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" - -msgid "7.0.2" -msgstr "7.0.2" - -msgid "7.1.1" -msgstr "7.1.1" - -msgid "8.0.0" -msgstr "8.0.0" - -msgid "9.0.0" -msgstr "9.0.0" - -msgid "9.0.0.0b2" -msgstr "9.0.0.0b2" - -msgid "9.0.0.0b3" -msgstr "9.0.0.0b3" - -msgid "9.0.0.0rc1" -msgstr "9.0.0.0rc1" - -msgid "Current Series Release Notes" -msgstr "Note de la release actuelle" - -msgid "Known Issues" -msgstr "Problèmes connus" - -msgid "Liberty Series Release Notes" -msgstr "Note de release pour Liberty" - -msgid "Mitaka Series Release Notes" -msgstr "Note de release pour Mitaka" - -msgid "Neutron FWaaS Release Notes" -msgstr "Note de release de Neutron FWaaS" - -msgid "New Features" -msgstr "Nouvelles fonctionnalités" - -msgid "Newton Series Release Notes" -msgstr "Note de release pour Newton" - -msgid "Other Notes" -msgstr "Autres notes" - -msgid "Start using reno to manage release notes." -msgstr "Commence à utiliser reno pour la gestion des notes de release" - -msgid "Upgrade Notes" -msgstr "Notes de mises à jours" diff --git a/releasenotes/source/mitaka.rst b/releasenotes/source/mitaka.rst deleted file mode 100644 index e54560965..000000000 --- a/releasenotes/source/mitaka.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Mitaka Series Release Notes -=================================== - -.. release-notes:: - :branch: origin/stable/mitaka diff --git a/releasenotes/source/newton.rst b/releasenotes/source/newton.rst deleted file mode 100644 index 97036ed25..000000000 --- a/releasenotes/source/newton.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Newton Series Release Notes -=================================== - -.. release-notes:: - :branch: origin/stable/newton diff --git a/releasenotes/source/ocata.rst b/releasenotes/source/ocata.rst deleted file mode 100644 index ebe62f42e..000000000 --- a/releasenotes/source/ocata.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Ocata Series Release Notes -=================================== - -.. release-notes:: - :branch: origin/stable/ocata diff --git a/releasenotes/source/pike.rst b/releasenotes/source/pike.rst deleted file mode 100644 index e43bfc0ce..000000000 --- a/releasenotes/source/pike.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Pike Series Release Notes -=================================== - -.. release-notes:: - :branch: stable/pike diff --git a/releasenotes/source/queens.rst b/releasenotes/source/queens.rst deleted file mode 100644 index 36ac6160c..000000000 --- a/releasenotes/source/queens.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Queens Series Release Notes -=================================== - -.. release-notes:: - :branch: stable/queens diff --git a/releasenotes/source/rocky.rst b/releasenotes/source/rocky.rst deleted file mode 100644 index 40dd517b7..000000000 --- a/releasenotes/source/rocky.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Rocky Series Release Notes -=================================== - -.. release-notes:: - :branch: stable/rocky diff --git a/releasenotes/source/stein.rst b/releasenotes/source/stein.rst deleted file mode 100644 index efaceb667..000000000 --- a/releasenotes/source/stein.rst +++ /dev/null @@ -1,6 +0,0 @@ -=================================== - Stein Series Release Notes -=================================== - -.. release-notes:: - :branch: stable/stein diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst deleted file mode 100644 index cd22aabcc..000000000 --- a/releasenotes/source/unreleased.rst +++ /dev/null @@ -1,5 +0,0 @@ -============================== - Current Series Release Notes -============================== - -.. release-notes:: diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 69969bf09..000000000 --- a/requirements.txt +++ /dev/null @@ -1,28 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -pbr>=4.0.0 # Apache-2.0 - -eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT -netaddr>=0.7.18 # BSD -SQLAlchemy>=1.2.0 # MIT -alembic>=0.8.10 # MIT -six>=1.10.0 # MIT -neutron-lib>=1.26.0 # Apache-2.0 -os-ken >= 0.3.0 # Apache-2.0 -oslo.config>=5.2.0 # Apache-2.0 -oslo.db>=4.37.0 # Apache-2.0 -oslo.log>=3.36.0 # Apache-2.0 -oslo.messaging>=5.29.0 # Apache-2.0 -oslo.service!=1.28.1,>=1.24.0 # Apache-2.0 -oslo.utils>=3.33.0 # Apache-2.0 -oslo.privsep>=1.32.0 # Apache-2.0 -pyroute2>=0.5.3;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2) -neutron>=13.0.0.0b1 # Apache-2.0 -pyzmq>=14.3.1 # LGPL+BSD - -# The comment below indicates this project repo is current with neutron-lib -# and should receive neutron-lib consumption patches as they are released -# in neutron-lib. It also implies the project will stay current with TC -# and infra initiatives ensuring consumption patches can land. -# neutron-lib-current diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1aae59f85..000000000 --- a/setup.cfg +++ /dev/null @@ -1,75 +0,0 @@ -[metadata] -name = neutron-fwaas -summary = OpenStack Networking FWaaS -description-file = - README.rst -author = OpenStack -author-email = openstack-discuss@lists.openstack.org -home-page = https://docs.openstack.org/neutron-fwaas/latest/ -python-requires = >=3.6 -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3 :: Only - -[files] -packages = - neutron_fwaas - -data_files = - etc/neutron/rootwrap.d = - etc/neutron/rootwrap.d/fwaas-privsep.filters - -[entry_points] -firewall_drivers = - iptables_v2 = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas_v2:IptablesFwaasDriver -neutron.service_plugins = - firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2 - -neutron.db.alembic_migrations = - neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations -oslo.config.opts = - neutron.fwaas = neutron_fwaas.opts:list_opts - firewall.agent = neutron_fwaas.opts:list_agent_opts -oslo.policy.policies = - neutron-fwaas = neutron_fwaas.policies:list_rules -neutron.policies = - neutron-fwaas = neutron_fwaas.policies:list_rules -neutron.agent.l2.extensions = - fwaas_v2 = neutron_fwaas.services.firewall.service_drivers.agents.l2.fwaas_v2:FWaaSV2AgentExtension -neutron.agent.l2.firewall_drivers = - noop = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.noop.noop_driver:NoopFirewallL2Driver - ovs = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.openvswitch_firewall.firewall:OVSFirewallDriver -neutron.agent.l3.extensions = - fwaas_v2 = neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent_v2:L3WithFWaaS - fwaas_v2_log = neutron_fwaas.services.logapi.agents.l3.fwg_log:FWaaSL3LoggingExtension -neutron.agent.l3.firewall_drivers = - conntrack = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.legacy_conntrack:ConntrackLegacy - netlink_conntrack = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.netlink_conntrack:ConntrackNetlink -neutron.services.logapi.drivers = - fwaas_v2_log = neutron_fwaas.services.logapi.agents.drivers.iptables.log:IptablesLoggingDriver -console_scripts = - neutron-fwaas-migrate-v1-to-v2 = neutron_fwaas.cmd.v1_to_v2_db_migration:main -neutron.status.upgrade.checks = - neutron_fwaas = neutron_fwaas.cmd.upgrade_checks.checks:Checks - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = neutron_fwaas/locale/neutron_fwaas.pot - -[compile_catalog] -directory = neutron_fwaas/locale -domain = neutron_fwaas - -[update_catalog] -domain = neutron_fwaas -output_dir = neutron_fwaas/locale -input_file = neutron_fwaas/locale/neutron_fwaas.pot diff --git a/setup.py b/setup.py deleted file mode 100644 index 566d84432..000000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 524587a8d..000000000 --- a/test-requirements.txt +++ /dev/null @@ -1,22 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking>=1.1.0,<1.2.0 # Apache-2.0 - -coverage!=4.4,>=4.0 # Apache-2.0 -flake8-import-order==0.12 # LGPLv3 -mock>=2.0.0 # BSD -python-subunit>=1.0.0 # Apache-2.0/BSD -requests-mock>=1.2.0 # Apache-2.0 -oslo.concurrency>=3.26.0 # Apache-2.0 -stestr>=1.0.0 # Apache-2.0 -testresources>=2.0.0 # Apache-2.0/BSD -testtools>=2.2.0 # MIT -testscenarios>=0.4 # Apache-2.0/BSD -WebOb>=1.8.2 # MIT -WebTest>=2.0.27 # MIT -oslotest>=3.2.0 # Apache-2.0 -PyMySQL>=0.7.6 # MIT License -psycopg2>=2.7.3 # LGPL/ZPL -doc8>=0.6.0 # Apache-2.0 -Pygments>=2.2.0 # BSD diff --git a/tools/check_unit_test_structure.sh b/tools/check_unit_test_structure.sh deleted file mode 100755 index 4e6d58d9f..000000000 --- a/tools/check_unit_test_structure.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -# This script identifies the unit test modules that do not correspond -# directly with a module in the code tree. See TESTING.rst for the -# intended structure. - -neutron_path=$(cd "$(dirname "$0")/.." && pwd) -base_test_path=neutron_fwaas/tests/unit -test_path=$neutron_path/$base_test_path - -test_files=$(find ${test_path} -iname 'test_*.py') - -ignore_regexes=( - "^plugins.*$", - "^misc.*$" -) - -error_count=0 -ignore_count=0 -total_count=0 -for test_file in ${test_files[@]}; do - relative_path=${test_file#$test_path/} - expected_path=$(dirname $neutron_path/neutron_fwaas/$relative_path) - test_filename=$(basename "$test_file") - expected_filename=${test_filename#test_} - # Module filename (e.g. foo/bar.py -> foo/test_bar.py) - filename=$expected_path/$expected_filename - # Package dir (e.g. foo/ -> test_foo.py) - package_dir=${filename%.py} - if [ ! -f "$filename" ] && [ ! -d "$package_dir" ]; then - for ignore_regex in ${ignore_regexes[@]}; do - if [[ "$relative_path" =~ $ignore_regex ]]; then - ((ignore_count++)) - continue 2 - fi - done - echo "Unexpected test file: $base_test_path/$relative_path" - ((error_count++)) - fi - ((total_count++)) -done - -if [ "$ignore_count" -ne 0 ]; then - echo "$ignore_count unmatched test modules were ignored" -fi - -if [ "$error_count" -eq 0 ]; then - echo 'Success! All test modules match targets in the code tree.' - exit 0 -else - echo "Failure! $error_count of $total_count test modules do not match targets in the code tree." - exit 1 -fi diff --git a/tools/clean.sh b/tools/clean.sh deleted file mode 100755 index b79f03526..000000000 --- a/tools/clean.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -rm -rf ./*.deb ./*.tar.gz ./*.dsc ./*.changes -rm -rf */*.deb -rm -rf ./plugins/**/build/ ./plugins/**/dist -rm -rf ./plugins/**/lib/neutron_*_plugin.egg-info ./plugins/neutron-* diff --git a/tools/configure_for_func_testing.sh b/tools/configure_for_func_testing.sh deleted file mode 100755 index 84869292f..000000000 --- a/tools/configure_for_func_testing.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env bash - -# 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. - - -set -e - - -# Control variable used to determine whether to execute this script -# directly or allow the gate_hook to import. -IS_GATE=${IS_GATE:-False} -USE_CONSTRAINT_ENV=${USE_CONSTRAINT_ENV:-True} - - -if [[ "$IS_GATE" != "True" ]] && [[ "$#" -lt 1 ]]; then - >&2 echo "Usage: $0 /path/to/devstack [-i] -Configure a host to run Neutron's functional test suite. - --i Install Neutron's package dependencies. By default, it is assumed - that devstack has already been used to deploy neutron-fwaas to the - target host and that package dependencies need not be installed. - -Warning: This script relies on devstack to perform extensive -modification to the underlying host. It is recommended that it be -invoked only on a throw-away VM." - exit 1 -fi - - -# Skip the first argument -OPTIND=2 -while getopts ":i" opt; do - case $opt in - i) - INSTALL_BASE_DEPENDENCIES=True - ;; - esac - -done - -# Default to environment variables to permit the gate_hook to override -# when sourcing. -VENV=${VENV:-dsvm-functional} -DEVSTACK_PATH=${DEVSTACK_PATH:-$1} -PROJECT_NAME=${PROJECT_NAME:-neutron-fwaas} -REPO_BASE=${GATE_DEST:-$(cd $(dirname "$0")/../.. && pwd)} -INSTALL_MYSQL_ONLY=${INSTALL_MYSQL_ONLY:-False} -# The gate should automatically install dependencies. -INSTALL_BASE_DEPENDENCIES=${INSTALL_BASE_DEPENDENCIES:-$IS_GATE} - - -if [ ! -f "$DEVSTACK_PATH/stack.sh" ]; then - >&2 echo "Unable to find devstack at '$DEVSTACK_PATH'. Please verify that the specified path points to a valid devstack repo." - exit 1 -fi - - -set -x - - -function _init { - # Subsequently-called devstack functions depend on the following variables. - HOST_IP=127.0.0.1 - FILES=$DEVSTACK_PATH/files - TOP_DIR=$DEVSTACK_PATH - - source $DEVSTACK_PATH/stackrc - - # Allow the gate to override values set by stackrc. - DEST=${GATE_DEST:-$DEST} - STACK_USER=${GATE_STACK_USER:-$STACK_USER} -} - - -function _install_base_deps { - echo_summary "Installing base dependencies" - - INSTALL_TESTONLY_PACKAGES=True - PACKAGES=$(get_packages general,neutron,q-agt,q-l3) - # Do not install 'python-' prefixed packages other than - # python-dev*. Neutron's functional testing relies on deployment - # to a tox env so there is no point in installing python - # dependencies system-wide. - PACKAGES=$(echo $PACKAGES | perl -pe 's|python-(?!dev)[^ ]*||g') - install_package $PACKAGES -} - - -function _install_rpc_backend { - echo_summary "Installing rabbitmq" - - RABBIT_USERID=${RABBIT_USERID:-stackrabbit} - RABBIT_HOST=${RABBIT_HOST:-$SERVICE_HOST} - RABBIT_PASSWORD=${RABBIT_HOST:-secretrabbit} - - source $DEVSTACK_PATH/lib/rpc_backend - - enable_service rabbit - install_rpc_backend - restart_rpc_backend -} - - -# _install_databases [install_pg] -function _install_databases { - local install_pg=${1:-True} - - echo_summary "Installing databases" - - # Avoid attempting to configure the db if it appears to already - # have run. The setup as currently defined is not idempotent. - if mysql openstack_citest > /dev/null 2>&1 < /dev/null; then - echo_summary "DB config appears to be complete, skipping." - return 0 - fi - - MYSQL_PASSWORD=${MYSQL_PASSWORD:-secretmysql} - DATABASE_PASSWORD=${DATABASE_PASSWORD:-secretdatabase} - - source $DEVSTACK_PATH/lib/database - - enable_service mysql - initialize_database_backends - install_database - configure_database_mysql - - if [[ "$install_pg" == "True" ]]; then - enable_service postgresql - initialize_database_backends - install_database - configure_database_postgresql - fi - - # Set up the 'openstack_citest' user and database in each backend - tmp_dir=$(mktemp -d) - trap "rm -rf $tmp_dir" EXIT - - cat << EOF > $tmp_dir/mysql.sql -CREATE DATABASE openstack_citest; -CREATE USER 'openstack_citest'@'localhost' IDENTIFIED BY 'openstack_citest'; -CREATE USER 'openstack_citest' IDENTIFIED BY 'openstack_citest'; -GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'@'localhost'; -GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'; -FLUSH PRIVILEGES; -EOF - /usr/bin/mysql -u root < $tmp_dir/mysql.sql - - if [[ "$install_pg" == "True" ]]; then - cat << EOF > $tmp_dir/postgresql.sql -CREATE USER openstack_citest WITH CREATEDB LOGIN PASSWORD 'openstack_citest'; -CREATE DATABASE openstack_citest WITH OWNER openstack_citest; -EOF - - # User/group postgres needs to be given access to tmp_dir - setfacl -m g:postgres:rwx $tmp_dir - sudo -u postgres /usr/bin/psql --file=$tmp_dir/postgresql.sql - fi -} - - -function _install_agent_deps { - echo_summary "Installing agent dependencies" - - ENABLED_SERVICES=q-agt,q-dhcp,q-l3 - install_neutron_agent_packages -} - - -# Set up the rootwrap sudoers for neutron to target the rootwrap -# configuration deployed in the venv. -function _install_rootwrap_sudoers { - echo_summary "Installing rootwrap sudoers file" - - PROJECT_VENV=$REPO_BASE/$PROJECT_NAME/.tox/$VENV - ROOTWRAP_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap $PROJECT_VENV/etc/neutron/rootwrap.conf *" - ROOTWRAP_DAEMON_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap-daemon $PROJECT_VENV/etc/neutron/rootwrap.conf" - TEMPFILE=$(mktemp) - cat << EOF > $TEMPFILE -# A bug in oslo.rootwrap [1] prevents commands executed with 'ip netns -# exec' from being automatically qualified with a prefix from -# rootwrap's configured exec_dirs. To work around this problem, add -# the venv bin path to a user-specific secure_path. -# -# While it might seem preferable to set a command-specific -# secure_path, this would only ensure the correct path for 'ip netns -# exec' and the command targeted for execution in the namespace would -# not inherit the path. -# -# 1: https://bugs.launchpad.net/oslo.rootwrap/+bug/1417331 -# -Defaults:$STACK_USER secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PROJECT_VENV/bin" -$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD -$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_DAEMON_SUDOER_CMD -EOF - chmod 0440 $TEMPFILE - sudo chown root:root $TEMPFILE - # Name the functional testing rootwrap to ensure that it will be - # loaded after the devstack rootwrap (50_stack_sh if present) so - # that the functional testing secure_path (a superset of what - # devstack expects) will not be overwritten. - sudo mv $TEMPFILE /etc/sudoers.d/60-neutron-func-test-rootwrap -} - - -function _install_post_devstack { - echo_summary "Performing post-devstack installation" - - _install_databases - _install_rootwrap_sudoers - - if is_ubuntu; then - install_package isc-dhcp-client - install_package netcat-openbsd - elif is_fedora; then - install_package dhclient - else - exit_distro_not_supported "installing dhclient package" - fi - - # Installing python-openvswitch from packages is a stop-gap while - # python-openvswitch remains unavailable from pypi. This also - # requires that sitepackages=True be set in tox.ini to allow the - # venv to use the installed package. Once python-openvswitch - # becomes available on pypi, this will no longer be required. - # - # NOTE: the package name 'python-openvswitch' is common across - # supported distros. - install_package python-openvswitch - - enable_kernel_bridge_firewall -} - - -function _configure_iptables_rules { - # For linuxbridge agent fullstack tests we need to add special rules to - # iptables for connection of agents to rabbitmq: - CHAIN_NAME="openstack-INPUT" - sudo iptables -n --list $CHAIN_NAME 1> /dev/null 2>&1 || CHAIN_NAME="INPUT" - sudo iptables -I $CHAIN_NAME -s 240.0.0.0/8 -p tcp -m tcp -d 240.0.0.0/8 --dport 5672 -j ACCEPT -} - - -function configure_host_for_func_testing { - echo_summary "Configuring host for functional testing" - - if [[ "$INSTALL_BASE_DEPENDENCIES" == "True" ]]; then - # Installing of the following can be achieved via devstack by - # installing neutron, so their installation is conditional to - # minimize the work to do on a devstack-configured host. - _install_base_deps - _install_agent_deps - _install_rpc_backend - fi - _install_post_devstack -} - - -_init - - -if [[ "$IS_GATE" != "True" ]]; then - if [[ "$INSTALL_MYSQL_ONLY" == "True" ]]; then - _install_databases nopg - else - configure_host_for_func_testing - fi -fi - -if [[ "$VENV" =~ "dsvm-fullstack" ]]; then - _configure_iptables_rules -fi diff --git a/tools/configure_for_fwaas_func_testing.sh b/tools/configure_for_fwaas_func_testing.sh deleted file mode 100755 index a2f9be3fa..000000000 --- a/tools/configure_for_fwaas_func_testing.sh +++ /dev/null @@ -1,9 +0,0 @@ -set -e - - -IS_GATE=${IS_GATE:-False} -USE_CONSTRAINT_ENV=${USE_CONSTRAINT_ENV:-False} -PROJECT_NAME=${PROJECT_NAME:-neutron-fwaas} -REPO_BASE=${GATE_DEST:-$(cd $(dirname "$BASH_SOURCE")/../.. && pwd)} - -source $REPO_BASE/neutron/tools/configure_for_func_testing.sh diff --git a/tools/deploy_rootwrap.sh b/tools/deploy_rootwrap.sh deleted file mode 100755 index b261aee2c..000000000 --- a/tools/deploy_rootwrap.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -set -eu - -if [ "$#" -ne 3 ]; then - >&2 echo "Usage: $0 /path/to/neutron_fwaas /path/to/target/etc /path/to/target/bin -Deploy Neutron FWaaS's rootwrap configuration. - -Warning: Any existing rootwrap files at the specified etc path will be -removed by this script. - -Optional: set OS_SUDO_TESTING=1 to deploy the filters required by -Neutron's functional testing suite." - exit 1 -fi - -OS_SUDO_TESTING=${OS_SUDO_TESTING:-0} - -neutron_path=${OS_NEUTRON_PATH} -fwaas_path=$1 -target_etc_path=$2 -target_bin_path=$3 - -src_conf_path=${neutron_path}/etc -src_conf=${src_conf_path}/rootwrap.conf -src_rootwrap_path=${src_conf_path}/neutron/rootwrap.d - -fwaas_src_conf_path=${fwaas_path}/etc -fwaas_src_rootwrap_path=${fwaas_src_conf_path}/neutron/rootwrap.d - -dst_conf_path=${target_etc_path}/neutron -dst_conf=${dst_conf_path}/rootwrap.conf -dst_rootwrap_path=${dst_conf_path}/rootwrap.d - -if [[ -d "$dst_rootwrap_path" ]]; then - rm -rf ${dst_rootwrap_path} -fi -mkdir -p -m 755 ${dst_rootwrap_path} - -cp -p ${src_rootwrap_path}/* ${fwaas_src_rootwrap_path}/* ${dst_rootwrap_path}/ -cp -p ${src_conf} ${dst_conf} -sed -i "s:^filters_path=.*$:filters_path=${dst_rootwrap_path}:" ${dst_conf} -sed -i "s:^\(exec_dirs=.*\)$:\1,${target_bin_path}:" ${dst_conf} - -if [[ "$OS_SUDO_TESTING" = "1" ]]; then - sed -i 's/use_syslog=False/use_syslog=True/g' ${dst_conf} - sed -i 's/syslog_log_level=ERROR/syslog_log_level=DEBUG/g' ${dst_conf} - cp -p ${neutron_path}/neutron/tests/contrib/testing.filters \ - ${dst_rootwrap_path}/ - cp -p ${fwaas_path}/neutron_fwaas/tests/contrib/functional-testing.filters \ - ${dst_rootwrap_path}/ -fi diff --git a/tools/generate_config_file_samples.sh b/tools/generate_config_file_samples.sh deleted file mode 100755 index 6b0f4ec2e..000000000 --- a/tools/generate_config_file_samples.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# 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. - -set -e - -GEN_CMD=oslo-config-generator - -if ! type "$GEN_CMD" > /dev/null; then - echo "ERROR: $GEN_CMD not installed on the system." - exit 1 -fi - -for file in `ls etc/oslo-config-generator/*`; do - $GEN_CMD --config-file=$file -done - -set -x diff --git a/tox.ini b/tox.ini deleted file mode 100644 index afcb46888..000000000 --- a/tox.ini +++ /dev/null @@ -1,212 +0,0 @@ -[tox] -envlist = py37,pep8,pylint -minversion = 3.1.1 -skipsdist = True - -[testenv] -basepython = python3 -setenv = VIRTUAL_ENV={envdir} - PYTHONWARNINGS=default::DeprecationWarning - OS_LOG_CAPTURE={env:OS_LOG_CAPTURE:true} - OS_STDOUT_CAPTURE={env:OS_STDOUT_CAPTURE:true} - OS_STDERR_CAPTURE={env:OS_STDERR_CAPTURE:true} -usedevelop = True -deps = -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} - -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -whitelist_externals = - sh - find -commands = - find . -type f -name "*.py[c|o]" -delete - find . -path "*/__pycache__*" -delete - stestr run {posargs} - -[testenv:common] -# Fake job to define environment variables shared between dsvm/non-dsvm jobs -setenv = OS_TEST_TIMEOUT=180 -commands = false - -[testenv:dsvm] -# Fake job to define environment variables shared between dsvm jobs -setenv = OS_SUDO_TESTING=1 - OS_ROOTWRAP_CMD=sudo {envdir}/bin/neutron-rootwrap {envdir}/etc/neutron/rootwrap.conf - OS_ROOTWRAP_DAEMON_CMD=sudo {envdir}/bin/neutron-rootwrap-daemon {envdir}/etc/neutron/rootwrap.conf - OS_FAIL_ON_MISSING_DEPS=1 - OS_LOG_PATH={env:OS_LOG_PATH:/opt/stack/logs} -commands = false - -[testenv:functional] -setenv = {[testenv]setenv} - {[testenv:common]setenv} - OS_TEST_PATH=./neutron_fwaas/tests/functional - OS_LOG_PATH={env:OS_LOG_PATH:/opt/stack/logs} -commands = - stestr run {posargs} - -[testenv:dsvm-fullstack] -setenv = {[testenv]setenv} - {[testenv:common]setenv} - {[testenv:dsvm]setenv} - OS_NEUTRON_PATH={env:OS_NEUTRON_PATH:/home/zuul/src/opendev.org/openstack/neutron} - # workaround for DB teardown lock contention (bug/1541742) - OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:600} - OS_TEST_PATH=./neutron_fwaas/tests/fullstack -commands = - {toxinidir}/tools/deploy_rootwrap.sh {toxinidir} {envdir}/etc {envdir}/bin - stestr run --concurrency 4 {posargs} - - -[testenv:api] -sitepackages=True -setenv = - OS_TEST_PATH=./neutron_fwaas/tests/tempest_plugin/tests/api/ - OS_TESTR_CONCURRENCY=1 - TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} -commands = - stestr run {posargs} - -[testenv:scenario] -sitepackages=True -setenv = - OS_TEST_PATH=./neutron_fwaas/tests/tempest_plugin/tests/scenario/ - OS_TESTR_CONCURRENCY=1 - TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} -commands = - stestr run {posargs} - -[testenv:dsvm-functional] -setenv = - OS_TEST_PATH=./neutron_fwaas/tests/functional - OS_SUDO_TESTING=1 - OS_ROOTWRAP_CMD=sudo {envdir}/bin/neutron-rootwrap {envdir}/etc/neutron/rootwrap.conf - OS_ROOTWRAP_DAEMON_CMD=sudo {envdir}/bin/neutron-rootwrap-daemon {envdir}/etc/neutron/rootwrap.conf - OS_FAIL_ON_MISSING_DEPS=1 - OS_NEUTRON_PATH={env:OS_NEUTRON_PATH:/home/zuul/src/opendev.org/openstack/neutron} -whitelist_externals = - sh - cp - sudo -commands = - {toxinidir}/tools/deploy_rootwrap.sh {toxinidir} {envdir}/etc {envdir}/bin - stestr run {posargs} - -[testenv:releasenotes] -deps = -r{toxinidir}/doc/requirements.txt -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html - -[testenv:pep8] -commands = - flake8 - doc8 {posargs} - {toxinidir}/tools/check_unit_test_structure.sh - neutron-db-manage --subproject neutron-fwaas --database-connection sqlite:// check_migration - {[testenv:genconfig]commands} - {[testenv:genpolicy]commands} -whitelist_externals = sh - -[testenv:cover] -setenv = VIRTUAL_ENV={envdir} - LANGUAGE=en_US - PYTHON=coverage run --source neutron_fwaas --omit='*tests*' --parallel-mode -commands = - coverage erase - stestr run {posargs} - coverage combine - coverage report --skip-covered --omit='*test*' - coverage html -d cover - coverage xml -o cover/coverage.xml - -[testenv:venv] -commands = {posargs} -deps = -r{toxinidir}/doc/requirements.txt - -[testenv:docs] -deps = -r{toxinidir}/doc/requirements.txt -whitelist_externals = - rm -commands = - rm -rf doc/source/contributor/api - sphinx-build -W -b html doc/source doc/build/html - -[testenv:pdf-docs] -envdir = {toxworkdir}/docs -deps = {[testenv:docs]deps} -whitelist_externals = - rm - make -commands = - rm -rf doc/source/contributor/api - sphinx-build -W -b latex doc/source doc/build/pdf - make -C doc/build/pdf - -[doc8] -ignore = D000 -ignore-path = .venv,.git,.tox,.tmp,*neutron_fwaas/locale*,*lib/python*,neutron_fwaas.egg*,doc/build,releasenotes/*,doc/source/contributor/api,requirements.txt,test-requirements.txt - -[flake8] -# E125 continuation line does not distinguish itself from next logical line -# E126 continuation line over-indented for hanging indent -# E128 continuation line under-indented for visual indent -# E129 visually indented line with same indent as next logical line -# E265 block comment should start with '# ' -# H404 multi line docstring should start with a summary -# H405 multi line docstring summary not separated with an empty line -# TODO(dougwig) -- uncomment this to test for remaining linkages -# N530 direct neutron imports not allowed -# TODO(ihrachys) -- reenable N537 when new neutron-lib release is available -# H106: Do not put vim configuration in source files -# H203: Use assertIs(Not)None to check for None -# H204: Use assert(Not)Equal to check for equality -# H205: Use assert(Greater|Less)(Equal) for comparison -# H904: Delay string interpolations at logging calls -# N521: jsonutils.loads must be used instead of json.loads -# W504 line break after binary operator -# (W503 and W504 are incompatible and we need to choose one of them. -# Existing codes follows W503, so we disable W504.) -ignore = E125,E126,E128,E129,E265,H404,H405,N530,N521,W504 -enable-extensions=H106,H203,H204,H205,H904 -show-source = true -exclude = .venv,.git,.tox,dist,doc,*lib/python*,.tmp,*egg,build,tools,.ropeproject,rally-scenarios -import-order-style = pep8 - -[testenv:pylint] -deps = - {[testenv]deps} - pylint -commands = - pylint --rcfile=.pylintrc --output-format=colorized {posargs:neutron_fwaas} - -[hacking] -import_exceptions = neutron_fwaas._i18n -local-check-factory = neutron_lib.hacking.checks.factory - -[testenv:genconfig] -commands = {toxinidir}/tools/generate_config_file_samples.sh - -[testenv:genpolicy] -commands = oslopolicy-sample-generator --config-file=etc/oslo-policy-generator/policy.conf - -[testenv:lower-constraints] -deps = - -c{toxinidir}/lower-constraints.txt - -r{toxinidir}/test-requirements.txt - -r{toxinidir}/requirements.txt - -[testenv:dev] -# run locally (not in the gate) using editable mode -# https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs -commands = - pip install -q -e "git+https://git.openstack.org/openstack/neutron#egg=neutron" - -[testenv:py3-dev] -commands = - {[testenv:dev]commands} - {[testenv]commands} - -[testenv:pep8-dev] -deps = - {[testenv]deps} -commands = - {[testenv:dev]commands} - {[testenv:pep8]commands}