revive neutron-fwaas project
This reverts commit caae7b6a6f
.
Reason for revert:
Many users still need L3 firewalls and Inspur team wants to maintain
this project.
Neutron drivers team discussed the topic of the maintenance of
neutron-fwaas, and agreed to include neutron-fwaas again to Neutron
stadium[1].
Some updates have been made:
Remove use "autonested_transaction" method, see more [2]
Replace "neutron_lib.callbacks.registry.notify" with "registry.publish"
Replace rootwrap execution with privsep context execution.
Ensure db Models and migration scripts are sync, set table
firewall_group_port_associations_v2's two columns nullable=False
[1] https://meetings.opendev.org/meetings/neutron_drivers/2022/neutron_drivers.2022-01-28-14.00.log.html#l-14
[2] https://review.opendev.org/c/openstack/neutron-lib/+/761728
Change-Id: I14f551c199d9badcf25b9e65c954c012326d27cd
This commit is contained in:
parent
11f0534e8b
commit
a9f26b81e2
7
.coveragerc
Normal file
7
.coveragerc
Normal file
@ -0,0 +1,7 @@
|
||||
[run]
|
||||
branch = True
|
||||
source = neutron_fwaas
|
||||
omit = neutron_fwaas/tests/*
|
||||
|
||||
[report]
|
||||
ignore_errors = True
|
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
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
|
11
.mailmap
Normal file
11
.mailmap
Normal file
@ -0,0 +1,11 @@
|
||||
# Format is:
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
||||
lawrancejing <lawrancejing@gmail.com> <liuqing@windawn.com>
|
||||
Jiajun Liu <jiajun@unitedstack.com> <iamljj@gmail.com>
|
||||
Zhongyue Luo <zhongyue.nah@intel.com> <lzyeval@gmail.com>
|
||||
Kun Huang <gareth@unitedstack.com> <academicgareth@gmail.com>
|
||||
Zhenguo Niu <zhenguo@unitedstack.com> <Niu.ZGlinux@gmail.com>
|
||||
Isaku Yamahata <isaku.yamahata@intel.com> <isaku.yamahata@gmail.com>
|
||||
Isaku Yamahata <isaku.yamahata@intel.com> <yamahata@private.email.ne.jp>
|
||||
Morgan Fainberg <morgan.fainberg@gmail.com> <m@metacloud.com>
|
130
.pylintrc
Normal file
130
.pylintrc
Normal file
@ -0,0 +1,130 @@
|
||||
# The format of this file isn't really documented; just use --generate-rcfile
|
||||
[MASTER]
|
||||
# Add <file or directory> 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
|
3
.stestr.conf
Normal file
3
.stestr.conf
Normal file
@ -0,0 +1,3 @@
|
||||
[DEFAULT]
|
||||
test_path=${OS_TEST_PATH:-./neutron_fwaas/tests/unit}
|
||||
top_dir=./
|
77
.zuul.yaml
Normal file
77
.zuul.yaml
Normal file
@ -0,0 +1,77 @@
|
||||
- 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-fwaas-v2-dsvm-tempest-multinode:
|
||||
voting: false
|
||||
gate:
|
||||
jobs:
|
||||
- neutron-fwaas-functional
|
||||
experimental:
|
||||
jobs:
|
||||
- neutron-fwaas-fullstack
|
||||
|
||||
- job:
|
||||
name: neutron-fwaas-functional
|
||||
parent: neutron-functional
|
||||
timeout: 2400
|
||||
pre-run: playbooks/configure_functional_job.yaml
|
||||
vars:
|
||||
project_name: neutron-fwaas
|
||||
devstack_services:
|
||||
INSTALL_OVN: false
|
||||
|
||||
- job:
|
||||
name: neutron-fwaas-fullstack
|
||||
parent: neutron-fullstack
|
||||
vars:
|
||||
project_name: neutron-fwaas
|
||||
|
||||
- job:
|
||||
name: neutron-fwaas-v2-dsvm-tempest-multinode
|
||||
parent: neutron-ovs-tempest-multinode-full
|
||||
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"
|
||||
Q_AGENT: openvswitch
|
||||
Q_ML2_TENANT_NETWORK_TYPE: vxlan
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
|
||||
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
|
4
CONTRIBUTING.rst
Normal file
4
CONTRIBUTING.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Please see the Neutron CONTRIBUTING.rst file for how to contribute to
|
||||
neutron-fwaas:
|
||||
|
||||
`Neutron CONTRIBUTING.rst <https://opendev.org/openstack/neutron/src/branch/master/CONTRIBUTING.rst>`_
|
7
HACKING.rst
Normal file
7
HACKING.rst
Normal file
@ -0,0 +1,7 @@
|
||||
Neutron FWaaS Style Commandments
|
||||
================================
|
||||
|
||||
Please see the Neutron HACKING.rst file for style commandments for
|
||||
neutron-fwaas:
|
||||
|
||||
`Neutron HACKING.rst <https://opendev.org/openstack/neutron/src/branch/master/HACKING.rst>`_
|
176
LICENSE
Normal file
176
LICENSE
Normal file
@ -0,0 +1,176 @@
|
||||
|
||||
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.
|
||||
|
45
README.rst
45
README.rst
@ -1,10 +1,39 @@
|
||||
This project is no longer maintained.
|
||||
========================
|
||||
Team and repository tags
|
||||
========================
|
||||
|
||||
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".
|
||||
.. image:: https://governance.openstack.org/tc/badges/neutron-fwaas.svg
|
||||
:target: https://governance.openstack.org/tc/reference/tags/index.html
|
||||
|
||||
.. 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:
|
||||
<https://opendev.org/openstack/neutron-fwaas>.
|
||||
|
||||
Please refer to Neutron documentation for more information:
|
||||
`Neutron README.rst <https://opendev.org/openstack/neutron/src/branch/master/README.rst>`_
|
||||
|
||||
Get release notes:
|
||||
`Neutron FWaaS Release Notes <https://docs.openstack.org/releasenotes/neutron-fwaas/>`_
|
||||
|
||||
For any further questions, please email
|
||||
openstack-discuss@lists.openstack.org or join #openstack-dev on
|
||||
OFTC.
|
||||
|
12
TESTING.rst
Normal file
12
TESTING.rst
Normal file
@ -0,0 +1,12 @@
|
||||
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 <https://opendev.org/openstack/neutron/src/branch/master/TESTING.rst>`_
|
||||
|
||||
For instructions on how to use FWaaS with devstack, look at:
|
||||
|
||||
`Neutron-FWaaS DevStack <https://opendev.org/openstack/neutron-fwaas/src/branch/master/devstack/README.rst>`_
|
10
bindep.txt
Normal file
10
bindep.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# 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]
|
30
devstack/README.rst
Normal file
30
devstack/README.rst
Normal file
@ -0,0 +1,30 @@
|
||||
=========================
|
||||
neutron-fwaas in DevStack
|
||||
=========================
|
||||
|
||||
This is setup as a DevStack plugin. For more information on DevStack plugins,
|
||||
see the `DevStack Plugins documentation
|
||||
<https://docs.openstack.org/devstack/latest/plugins.html>`_.
|
||||
|
||||
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
|
16
devstack/lib/l2_agent
Normal file
16
devstack/lib/l2_agent
Normal file
@ -0,0 +1,16 @@
|
||||
# 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"
|
||||
}
|
16
devstack/lib/l3_agent
Normal file
16
devstack/lib/l3_agent
Normal file
@ -0,0 +1,16 @@
|
||||
# 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"
|
||||
}
|
145
devstack/plugin.sh
Executable file
145
devstack/plugin.sh
Executable file
@ -0,0 +1,145 @@
|
||||
#!/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
|
12
devstack/settings
Normal file
12
devstack/settings
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
7
doc/requirements.txt
Normal file
7
doc/requirements.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# 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
|
||||
openstackdocstheme>=1.18.1 # Apache-2.0
|
||||
reno>=2.5.0 # Apache-2.0
|
0
doc/source/_static/.placeholder
Normal file
0
doc/source/_static/.placeholder
Normal file
311
doc/source/conf.py
Normal file
311
doc/source/conf.py
Normal file
@ -0,0 +1,311 @@
|
||||
# -*- 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
|
||||
# "<project> v<release> 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 <link> 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'
|
6
doc/source/configuration/fwaas_driver.rst
Normal file
6
doc/source/configuration/fwaas_driver.rst
Normal file
@ -0,0 +1,6 @@
|
||||
================
|
||||
fwaas_driver.ini
|
||||
================
|
||||
|
||||
.. show-options::
|
||||
:config-file: etc/oslo-config-generator/fwaas_driver.ini
|
41
doc/source/configuration/index.rst
Normal file
41
doc/source/configuration/index.rst
Normal file
@ -0,0 +1,41 @@
|
||||
.. _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 <policy>
|
||||
Sample Policy File <policy-sample>
|
6
doc/source/configuration/neutron_fwaas.rst
Normal file
6
doc/source/configuration/neutron_fwaas.rst
Normal file
@ -0,0 +1,6 @@
|
||||
==================
|
||||
neutron_fwaas.conf
|
||||
==================
|
||||
|
||||
.. show-options::
|
||||
:config-file: etc/oslo-config-generator/neutron_fwaas.conf
|
16
doc/source/configuration/policy-sample.rst
Normal file
16
doc/source/configuration/policy-sample.rst
Normal file
@ -0,0 +1,16 @@
|
||||
================================
|
||||
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
|
||||
</_static/neutron-fwaas.policy.yaml.sample>`.
|
||||
|
||||
.. 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
|
9
doc/source/configuration/policy.rst
Normal file
9
doc/source/configuration/policy.rst
Normal file
@ -0,0 +1,9 @@
|
||||
======================
|
||||
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
|
8
doc/source/configuration/samples/fwaas_driver.rst
Normal file
8
doc/source/configuration/samples/fwaas_driver.rst
Normal file
@ -0,0 +1,8 @@
|
||||
=======================
|
||||
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
|
8
doc/source/configuration/samples/neutron_fwaas.rst
Normal file
8
doc/source/configuration/samples/neutron_fwaas.rst
Normal file
@ -0,0 +1,8 @@
|
||||
=========================
|
||||
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
|
28
doc/source/contributor/contributing.rst
Normal file
28
doc/source/contributor/contributing.rst
Normal file
@ -0,0 +1,28 @@
|
||||
=============================
|
||||
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
|
||||
<http://eavesdrop.openstack.org/#Firewall_as_a_Service_(FWaaS)_Team_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.
|
1
doc/source/contributor/devstack.rst
Normal file
1
doc/source/contributor/devstack.rst
Normal file
@ -0,0 +1 @@
|
||||
.. include:: ../../../devstack/README.rst
|
7
doc/source/contributor/fwaas_v2.rst
Normal file
7
doc/source/contributor/fwaas_v2.rst
Normal file
@ -0,0 +1,7 @@
|
||||
FireWall as a Service V2
|
||||
========================
|
||||
|
||||
The `FireWall as a Service API V2
|
||||
<https://specs.openstack.org/openstack/neutron-specs/specs/newton/fwaas-api-2.0.html>`_
|
||||
specification lists the changes that together compose FWaaS V2. These changes
|
||||
are not fully implemented.
|
17
doc/source/contributor/index.rst
Normal file
17
doc/source/contributor/index.rst
Normal file
@ -0,0 +1,17 @@
|
||||
=================
|
||||
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
|
19
doc/source/contributor/modules.rst
Normal file
19
doc/source/contributor/modules.rst
Normal file
@ -0,0 +1,19 @@
|
||||
================
|
||||
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.
|
27
doc/source/index.rst
Normal file
27
doc/source/index.rst
Normal file
@ -0,0 +1,27 @@
|
||||
===========================
|
||||
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`
|
39
doc/source/install/index.rst
Normal file
39
doc/source/install/index.rst
Normal file
@ -0,0 +1,39 @@
|
||||
..
|
||||
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 <https://docs.openstack.org/neutron/latest/admin/fwaas-v2-scenario.html>`_ or
|
||||
the `Firewall-as-a-Service (FWaaS) v1 scenario <https://docs.openstack.org/neutron/latest/admin/fwaas-v1-scenario.html>`_.
|
9
etc/README.txt
Normal file
9
etc/README.txt
Normal file
@ -0,0 +1,9 @@
|
||||
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
|
7
etc/neutron/rootwrap.d/fwaas-privsep.filters
Normal file
7
etc/neutron/rootwrap.d/fwaas-privsep.filters
Normal file
@ -0,0 +1,7 @@
|
||||
# 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
|
5
etc/oslo-config-generator/fwaas_driver.ini
Normal file
5
etc/oslo-config-generator/fwaas_driver.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
output_file = etc/fwaas_driver.ini.sample
|
||||
wrap_width = 79
|
||||
|
||||
namespace = firewall.agent
|
6
etc/oslo-config-generator/neutron_fwaas.conf
Normal file
6
etc/oslo-config-generator/neutron_fwaas.conf
Normal file
@ -0,0 +1,6 @@
|
||||
[DEFAULT]
|
||||
output_file = etc/neutron_fwaas.conf.sample
|
||||
wrap_width = 79
|
||||
|
||||
namespace = neutron.fwaas
|
||||
|
3
etc/oslo-policy-generator/policy.conf
Normal file
3
etc/oslo-policy-generator/policy.conf
Normal file
@ -0,0 +1,3 @@
|
||||
[DEFAULT]
|
||||
output_file = etc/policy.yaml.sample
|
||||
namespace = neutron-fwaas
|
147
lower-constraints.txt
Normal file
147
lower-constraints.txt
Normal file
@ -0,0 +1,147 @@
|
||||
alabaster==0.7.10
|
||||
alembic==1.6.5
|
||||
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==4.1.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==3.6.0
|
||||
future==0.16.0
|
||||
futurist==1.2.0
|
||||
greenlet==0.4.10
|
||||
hacking==3.0.1
|
||||
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==1.0.7
|
||||
MarkupSafe==1.1.1
|
||||
mccabe==0.6.0
|
||||
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==2.0.0
|
||||
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.4.23
|
||||
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
|
24
neutron_fwaas/__init__.py
Normal file
24
neutron_fwaas/__init__.py
Normal file
@ -0,0 +1,24 @@
|
||||
# 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')
|
32
neutron_fwaas/_i18n.py
Normal file
32
neutron_fwaas/_i18n.py
Normal file
@ -0,0 +1,32 @@
|
||||
# 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)
|
0
neutron_fwaas/cmd/__init__.py
Normal file
0
neutron_fwaas/cmd/__init__.py
Normal file
0
neutron_fwaas/cmd/upgrade_checks/__init__.py
Normal file
0
neutron_fwaas/cmd/upgrade_checks/__init__.py
Normal file
40
neutron_fwaas/cmd/upgrade_checks/checks.py
Normal file
40
neutron_fwaas/cmd/upgrade_checks/checks.py
Normal file
@ -0,0 +1,40 @@
|
||||
# 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)
|
138
neutron_fwaas/cmd/v1_to_v2_db_migration.py
Normal file
138
neutron_fwaas/cmd/v1_to_v2_db_migration.py
Normal file
@ -0,0 +1,138 @@
|
||||
# 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._i18n import _
|
||||
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.")
|
0
neutron_fwaas/common/__init__.py
Normal file
0
neutron_fwaas/common/__init__.py
Normal file
24
neutron_fwaas/common/exceptions.py
Normal file
24
neutron_fwaas/common/exceptions.py
Normal file
@ -0,0 +1,24 @@
|
||||
# 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'.")
|
42
neutron_fwaas/common/fwaas_constants.py
Normal file
42
neutron_fwaas/common/fwaas_constants.py
Normal file
@ -0,0 +1,42 @@
|
||||
# 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'
|
17
neutron_fwaas/common/resources.py
Normal file
17
neutron_fwaas/common/resources.py
Normal file
@ -0,0 +1,17 @@
|
||||
# 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
|
0
neutron_fwaas/db/__init__.py
Normal file
0
neutron_fwaas/db/__init__.py
Normal file
0
neutron_fwaas/db/firewall/__init__.py
Normal file
0
neutron_fwaas/db/firewall/__init__.py
Normal file
89
neutron_fwaas/db/firewall/firewall_db.py
Normal file
89
neutron_fwaas/db/firewall/firewall_db.py
Normal file
@ -0,0 +1,89 @@
|
||||
# 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)
|
0
neutron_fwaas/db/firewall/v2/__init__.py
Normal file
0
neutron_fwaas/db/firewall/v2/__init__.py
Normal file
1101
neutron_fwaas/db/firewall/v2/firewall_db_v2.py
Normal file
1101
neutron_fwaas/db/firewall/v2/firewall_db_v2.py
Normal file
File diff suppressed because it is too large
Load Diff
0
neutron_fwaas/db/migration/__init__.py
Normal file
0
neutron_fwaas/db/migration/__init__.py
Normal file
1
neutron_fwaas/db/migration/alembic_migrations/README
Normal file
1
neutron_fwaas/db/migration/alembic_migrations/README
Normal file
@ -0,0 +1 @@
|
||||
Generic single-database configuration.
|
86
neutron_fwaas/db/migration/alembic_migrations/env.py
Normal file
86
neutron_fwaas/db/migration/alembic_migrations/env.py
Normal file
@ -0,0 +1,86 @@
|
||||
# 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()
|
36
neutron_fwaas/db/migration/alembic_migrations/script.py.mako
Normal file
36
neutron_fwaas/db/migration/alembic_migrations/script.py.mako
Normal file
@ -0,0 +1,36 @@
|
||||
# Copyright ${create_date.year} <PUT YOUR NAME/COMPANY HERE>
|
||||
#
|
||||
# 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"}
|
@ -0,0 +1,35 @@
|
||||
# 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)
|
@ -0,0 +1,62 @@
|
||||
# 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')
|
@ -0,0 +1,45 @@
|
||||
# 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')
|
||||
)
|
@ -0,0 +1 @@
|
||||
fd38cd995cc0
|
@ -0,0 +1 @@
|
||||
f24e0d5e5bff
|
@ -0,0 +1,29 @@
|
||||
# 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
|
@ -0,0 +1,38 @@
|
||||
# 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
|
@ -0,0 +1,47 @@
|
||||
# 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)
|
@ -0,0 +1,34 @@
|
||||
# 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
|
@ -0,0 +1,49 @@
|
||||
#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 <name> 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)
|
@ -0,0 +1,143 @@
|
||||
# Copyright 2016 <PUT YOUR NAME/COMPANY HERE>
|
||||
#
|
||||
# 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()
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
# 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'),
|
||||
nullable=False),
|
||||
sa.Column('port_id', sa.String(length=36),
|
||||
sa.ForeignKey('ports.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
)
|
||||
|
||||
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))
|
@ -0,0 +1,37 @@
|
||||
# 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)
|
@ -0,0 +1,67 @@
|
||||
# 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()
|
@ -0,0 +1,71 @@
|
||||
# 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]
|
@ -0,0 +1,30 @@
|
||||
# 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
|
0
neutron_fwaas/db/models/__init__.py
Normal file
0
neutron_fwaas/db/models/__init__.py
Normal file
17
neutron_fwaas/db/models/head.py
Normal file
17
neutron_fwaas/db/models/head.py
Normal file
@ -0,0 +1,17 @@
|
||||
# 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
|
0
neutron_fwaas/extensions/__init__.py
Normal file
0
neutron_fwaas/extensions/__init__.py
Normal file
302
neutron_fwaas/extensions/firewall_v2.py
Normal file
302
neutron_fwaas/extensions/firewall_v2.py
Normal file
@ -0,0 +1,302 @@
|
||||
# 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
|
36
neutron_fwaas/opts.py
Normal file
36
neutron_fwaas/opts.py
Normal file
@ -0,0 +1,36 @@
|
||||
# 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),
|
||||
]
|
25
neutron_fwaas/policies/__init__.py
Normal file
25
neutron_fwaas/policies/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# 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(),
|
||||
)
|
17
neutron_fwaas/policies/base.py
Normal file
17
neutron_fwaas/policies/base.py
Normal file
@ -0,0 +1,17 @@
|
||||
# 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'
|
113
neutron_fwaas/policies/firewall_group.py
Normal file
113
neutron_fwaas/policies/firewall_group.py
Normal file
@ -0,0 +1,113 @@
|
||||
# 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
|
113
neutron_fwaas/policies/firewall_policy.py
Normal file
113
neutron_fwaas/policies/firewall_policy.py
Normal file
@ -0,0 +1,113 @@
|
||||
# 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
|
136
neutron_fwaas/policies/firewall_rule.py
Normal file
136
neutron_fwaas/policies/firewall_rule.py
Normal file
@ -0,0 +1,136 @@
|
||||
# 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
|
29
neutron_fwaas/privileged/__init__.py
Normal file
29
neutron_fwaas/privileged/__init__.py
Normal file
@ -0,0 +1,29 @@
|
||||
# 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],
|
||||
)
|
0
neutron_fwaas/privileged/netfilter_log/__init__.py
Normal file
0
neutron_fwaas/privileged/netfilter_log/__init__.py
Normal file
331
neutron_fwaas/privileged/netfilter_log/libnetfilter_log.py
Normal file
331
neutron_fwaas/privileged/netfilter_log/libnetfilter_log.py
Normal file
@ -0,0 +1,331 @@
|
||||
# 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)
|
86
neutron_fwaas/privileged/netlink_constants.py
Normal file
86
neutron_fwaas/privileged/netlink_constants.py
Normal file
@ -0,0 +1,86 @@
|
||||
# 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 <andrew@ei-grad.ru>
|
||||
#
|
||||
# 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}
|
314
neutron_fwaas/privileged/netlink_lib.py
Normal file
314
neutron_fwaas/privileged/netlink_lib.py
Normal file
@ -0,0 +1,314 @@
|
||||
# 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 <andrew@ei-grad.ru>
|
||||
#
|
||||
# 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)
|
0
neutron_fwaas/privileged/tests/__init__.py
Normal file
0
neutron_fwaas/privileged/tests/__init__.py
Normal file
29
neutron_fwaas/privileged/tests/functional/dummy.py
Normal file
29
neutron_fwaas/privileged/tests/functional/dummy.py
Normal file
@ -0,0 +1,29 @@
|
||||
# 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)
|
39
neutron_fwaas/privileged/tests/functional/utils.py
Normal file
39
neutron_fwaas/privileged/tests/functional/utils.py
Normal file
@ -0,0 +1,39 @@
|
||||
# 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
|
58
neutron_fwaas/privileged/utils.py
Normal file
58
neutron_fwaas/privileged/utils.py
Normal file
@ -0,0 +1,58 @@
|
||||
# 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)
|
0
neutron_fwaas/services/__init__.py
Normal file
0
neutron_fwaas/services/__init__.py
Normal file
0
neutron_fwaas/services/firewall/__init__.py
Normal file
0
neutron_fwaas/services/firewall/__init__.py
Normal file
429
neutron_fwaas/services/firewall/fwaas_plugin_v2.py
Normal file
429
neutron_fwaas/services/firewall/fwaas_plugin_v2.py
Normal file
@ -0,0 +1,429 @@
|
||||
# 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, payload):
|
||||
context = payload.context
|
||||
original_port = payload.states[0]
|
||||
updated_port = payload.states[1]
|
||||
if not updated_port['device_owner'].startswith(
|
||||
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
||||
return
|
||||
|
||||
if (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
|
||||
|
||||
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)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user