Revert "Retire neutron-fwaas-dashboard project"

This reverts commit 4a0f1a3ae54a69f37ab38a0209e3a9996f727693.

Reason for revert:
Neutron drivers team agreed to include neutron-fwaas again to Neutron
stadium[1], and goverance change is proposed at [2].

[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/governance/+/828078

Change-Id: I5018dfdf9ea866e113a17f9bd5a3b153e4f1c08f
This commit is contained in:
ZhouHeng 2022-02-09 03:21:05 +00:00 committed by zhouhenglc
parent dffb01f9b9
commit e8463a1ad4
127 changed files with 12844 additions and 8 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
*.pyc
*.swp
*.egg*/
.coverage
.tox/
build/
cover/
dist/
AUTHORS
ChangeLog
# Translation catalogs
*.mo
*.pot

35
.zuul.yaml Normal file
View File

@ -0,0 +1,35 @@
- job:
name: neutron-fwaas-dashboard-integration-tests
parent: horizon-integration-tests
required-projects:
- name: openstack/horizon
- name: openstack/neutron-fwaas
- name: openstack/neutron-fwaas-dashboard
roles:
- zuul: openstack-infra/devstack
- zuul: openstack/horizon
irrelevant-files:
- ^.*\.rst$
- ^doc/.*$
- ^releasenotes/.*$
vars:
devstack_plugins:
neutron-fwaas: https://git.openstack.org/openstack/neutron-fwaas
neutron-fwaas-dashboard: https://git.openstack.org/openstack/neutron-fwaas-dashboard
devstack_services:
horizon: true
tox_envlist: integration
- project:
templates:
- check-requirements
- horizon-non-primary-django-jobs
- openstack-cover-jobs-horizon
- openstack-lower-constraints-jobs-horizon
- openstack-python3-victoria-jobs-horizon
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
jobs:
- neutron-fwaas-dashboard-integration-tests:
voting: false

17
CONTRIBUTING.rst Normal file
View File

@ -0,0 +1,17 @@
If you would like to contribute to the development of OpenStack, you must
follow the steps in this page:
https://docs.openstack.org/infra/manual/developers.html
If you already have a good understanding of how the system works and your
OpenStack accounts are set up, you can skip to the development workflow
section of this documentation to learn how changes to OpenStack should be
submitted for review via the Gerrit tool:
https://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/neutron-fwaas-dashboard

13
HACKING.rst Normal file
View File

@ -0,0 +1,13 @@
==========================================
Neutron FWaaS Dashboard Style Commandments
==========================================
Read the OpenStack Style Commandments
https://docs.openstack.org/hacking/latest/user/hacking.html
Project Specific Commandments
-----------------------------
- Read the Horizon contributing documentation at
https://docs.openstack.org/horizon/latest/contributor/contributing.html
- [M322] Method's default argument shouldn't be mutable.

176
LICENSE Normal file
View 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.

View File

@ -1,10 +1,18 @@
This project is no longer maintained.
=======================
Neutron FWaaS Dashboard
=======================
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".
.. 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.
For any further questions, please email
openstack-discuss@lists.openstack.org or join #openstack-dev on
OFTC.
OpenStack Dashboard panels for Neutron FWaaS
* Documentation: https://docs.openstack.org/neutron-fwaas-dashboard/latest/
* Source: https://opendev.org/openstack/neutron-fwaas-dashboard
* Bugs: https://bugs.launchpad.net/neutron-fwaas-dashboard
* Release Notes: https://docs.openstack.org/releasenotes/neutron-fwaas-dashboard/

2
babel-django.cfg Normal file
View File

@ -0,0 +1,2 @@
[python: **.py]
[django: **/templates/**.html]

2
babel-djangojs.cfg Normal file
View File

@ -0,0 +1,2 @@
[javascript: **.js]
[angular: **/static/**.html]

5
bindep.txt Normal file
View File

@ -0,0 +1,5 @@
# selenium tests
firefox [selenium]
xvfb [selenium platform:dpkg]
# already part of xorg-x11-server on openSUSE
xorg-x11-server-Xvfb [selenium platform:redhat]

25
devstack/README.rst Normal file
View File

@ -0,0 +1,25 @@
===========================================
DevStack plugin for neutron-fwaas-dashboard
===========================================
This is setup as a DevStack plugin.
For more information on DevStack plugins,
see the `DevStack Plugins documentation
<https://docs.openstack.org/developer/devstack/plugins.html>`__.
If neutron-fwaas-dashboard DevStack plugin is enabled,
Neutron FWaaS dashboard is automatically enabled and
the appropriate version of FWaaS panel is displayed based on
the FWaaS version enabled in your neutron server.
You do not need to specify FWaaS API version in the DevStack plugin
configuration.
To enable FWaaS dashboard, add the following to the localrc section
of your local.conf.
.. code-block:: none
[[local|localrc]]
enable_plugin neutron-fwaas https://opendev.org/openstack/neutron-fwaas master
enable_service q-fwaas-v2
enable_plugin neutron-fwaas-dashboard https://opendev.org/openstack/neutron-fwaas-dashboard master

64
devstack/plugin.sh Normal file
View File

@ -0,0 +1,64 @@
# plugin.sh - DevStack plugin.sh dispatch script neutron-fwaas-dashboard
FWAAS_DASHBOARD_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
FWAAS_ENABLED_DIR=$FWAAS_DASHBOARD_DIR/neutron_fwaas_dashboard/enabled
OPENSTACK_DASHBOARD_DIR=$DEST/horizon/openstack_dashboard
HORIZON_ENABLED_DIR=$OPENSTACK_DASHBOARD_DIR/local/enabled
function install_neutron_fwaas_dashboard {
setup_develop $FWAAS_DASHBOARD_DIR
}
function configure_neutron_fwaas_dashboard {
cp -a $FWAAS_ENABLED_DIR/_[0-9]*.py $HORIZON_ENABLED_DIR
# NOTE: If locale directory does not exist, compilemessages will fail,
# so check for an existence of locale directory is required.
if [ -d $FWAAS_DASHBOARD_DIR/neutron_fwaas_dashboard/locale ]; then
(cd $FWAAS_DASHBOARD_DIR/neutron_fwaas_dashboard; \
DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $PYTHON ../manage.py compilemessages)
fi
# Add policy file for FWaaS
cp $FWAAS_DASHBOARD_DIR/etc/neutron-fwaas-policy.json $OPENSTACK_DASHBOARD_DIR/conf/
cp $FWAAS_DASHBOARD_DIR/neutron_fwaas_dashboard/local_settings.d/_7000_neutron_fwaas.py \
$OPENSTACK_DASHBOARD_DIR/local/local_settings.d/
}
# check for service enabled
if is_service_enabled neutron-fwaas-dashboard; then
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
# Set up system services
# no-op
:
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
# Perform installation of service source
echo_summary "Installing Neutron FWaaS Dashboard"
install_neutron_fwaas_dashboard
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
# Configure after the other layer 1 and 2 services have been configured
echo_summary "Configurng Neutron FWaaS Dashboard"
configure_neutron_fwaas_dashboard
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
# no-op
:
fi
if [[ "$1" == "unstack" ]]; then
# Remove enabled file(s)
for _enabled_file in $FWAAS_ENABLED_DIR/_[0-9]*.py; do
_enabled_basename=$(basename $_enabled_file .py)
rm -f $HORIZON_ENABLED_DIR/${_enabled_basename}.py*
rm -f $HORIZON_ENABLED_DIR/__pycache__/${_enabled_basename}.*pyc
done
fi
if [[ "$1" == "clean" ]]; then
# Remove state and transient data
# Remember clean.sh first calls unstack.sh
rm -f $OPENSTACK_DASHBOARD_DIR/local/local_settings.d/_7000_neutron_fwaas.py*
rm -f $OPENSTACK_DASHBOARD_DIR/conf/neutron-fwaas-policy.json
fi
fi

2
devstack/settings Normal file
View File

@ -0,0 +1,2 @@
# settings file for neutron-fwaas-dashboard plugin
enable_service neutron-fwaas-dashboard

215
doc/source/conf.py Normal file
View File

@ -0,0 +1,215 @@
# 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.
#
# Horizon documentation build configuration file, created by
# sphinx-quickstart on Thu Oct 27 11:38:59 2011.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import sys
import django
PROJECT = 'neutron-fwaas-dashboard'
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.abspath(os.path.join(BASE_DIR, "..", ".."))
sys.path.insert(0, ROOT)
# This is required for ReadTheDocs.org, but isn't a bad idea anyway.
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
'neutron_fwaas_dashboard.test.settings')
django.setup()
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings.
# They can be extensions coming with Sphinx (named 'sphinx.ext.*')
# or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'reno.sphinxext',
'openstackdocstheme',
]
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/neutron-fwaas-dashboard'
openstackdocs_pdf_link = True
openstackdocs_auto_name = False
openstackdocs_bug_project = 'neutron-fwaas-dashboard'
openstackdocs_bug_tag = 'doc'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Neutron FWaaS Dashboard'
copyright = u'2017, OpenStack Foundation'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['**/#*', '**~', '**/#*#']
# The reST default role (used for this markup: `text`)
# to use for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['neutron_fwaas_dashboard.']
primary_domain = 'py'
nitpicky = False
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# html_theme_path = ['.']
html_theme = 'openstackdocs'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
"nosidebar": "false"
}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<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 = []
# 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'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <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 = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'neutronfwaasdashboarddoc'
# -- Options for LaTeX output ------------------------------------------------
latex_documents = [
('index', 'doc-neutron-fwaas-dashboard.tex',
u'Neutron FWaaS Dashboard Documentation',
u'Neutron Contributors', 'howto'),
]

View File

@ -0,0 +1,28 @@
..
Copyright 2017 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.
=============
Configuration
=============
Neutron FWaaS dashboard has no configuration option.
It checks if Neutron FWaaS service is enabled in your neutron server
and the FWaaS panel is displayed if enabled.
For more configurations, see
`Settings Reference
<https://docs.openstack.org/horizon/latest/configuration/settings.html>`__
in the Horizon documentation.

View File

@ -0,0 +1 @@
.. include:: ../../../devstack/README.rst

View File

@ -0,0 +1,32 @@
..
Copyright 2017 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.
=================
Contributor Guide
=================
There is no topic specific to neutron-fwaas-dashboard now.
See `Horizon Contributor Documentation
<https://docs.openstack.org/horizon/latest/contributor/>`__
for general topic on developing a dashboard on horizon.
----
.. toctree::
:maxdepth: 1
DevStack plugin <devstack-plugin>

37
doc/source/index.rst Normal file
View File

@ -0,0 +1,37 @@
..
Copyright 2017 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.
================================
Neutron FWaaS Dashboard Project
================================
.. 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.
Neutron FWaaS Dashboard is a horizon plugin for Neutron FWaaS.
.. toctree::
:maxdepth: 1
install/index
configuration/index
contributor/index
Release Notes <https://docs.openstack.org/releasenotes/neutron-fwaas-dashboard/>

View File

@ -0,0 +1,99 @@
..
Copyright 2017 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.
============
Installation
============
Manual Installation
-------------------
Before installing neutron-fwaas-dashboard,
you first need to install horizon in your environment.
Fetch the source code from git and run pip install.
Make sure to install neutron-fwaas-dashboard into the same python environment
where horizon is installed.
.. code-block:: console
$ git clone https://opendev.org/openstack/neutron-fwaas-dashboard
$ cd neutron-fwaas-dashboard
$ sudo pip install .
Enable the horizon plugin.
.. code-block:: console
$ cp neutron_fwaas_dashboard/enabled/_70*_*.py \
/opt/stack/horizon/openstack_dashboard/local/enabled/
.. note::
The directory ``local/enabled`` may be different depending on your
environment or distribution used. For example, for Ubuntu, this is
``/usr/share/openstack-dashboard/openstack_dashboard/local/enabled``.
.. note::
The number of the plugin enabled file determines the order of panels.
If you would like to configure the place of the Neutron FWaaS dashboard,
change the number of the file.
.. note::
For more detail of the horizon plugin settings,
see `Pluggable Settings
<https://docs.openstack.org/horizon/latest/configuration/pluggable_panels.html>`__
in the horizon documentation.
Configure the policy file for Neutron FWaaS dashboard
in OpenStack Dashboard ``local_settings.py``.
``<fwaas-dashboard-config-dir>`` is a directory which contains
configurations for Neutron FWaaS dashboard and the location varies
across distributions or deployments.
.. code-block:: python
POLICY_FILES['neutron-fwaas'] = '<fwaas-dashboard-config-dir>/etc/neutron-fwaas-policy.json'
.. note::
If you do not configure ``POLICY_FILES`` in your ``local_settings.py``,
you also need to define the default ``POLICY_FILES`` in
``local_settings.py``. If you use the example ``local_settings.py`` file
from horizon, what you need is to uncomment ``POLICY_FILES`` (which contains
the default values).
Compile the message catalogs of Neutron FWaaS dashboard.
.. code-block:: console
$ cd neutron-fwaas-dashboard
$ ./manage.py compilemessages
Run the Django update commands (if you use).
.. code-block:: console
$ DJANGO_SETTINGS_MODULE=openstack_dashboard.settings python manage.py collectstatic --noinput
$ DJANGO_SETTINGS_MODULE=openstack_dashboard.settings python manage.py compress --force
Restart Apache:
.. code-block:: console
$ sudo service apache2 restart

View File

@ -0,0 +1,36 @@
{
"context_is_admin": "role:admin",
"owner": "tenant_id:%(tenant_id)s",
"admin_or_owner": "rule:context_is_admin or rule:owner",
"admin_only": "rule:context_is_admin",
"shared_firewalls": "field:firewalls:shared=True",
"shared_firewall_policies": "field:firewall_policies:shared=True",
"default": "rule:admin_or_owner",
"create_firewall": "",
"get_firewall": "rule:admin_or_owner",
"create_firewall:shared": "rule:admin_only",
"get_firewall:shared": "rule:admin_only",
"update_firewall": "rule:admin_or_owner",
"update_firewall:shared": "rule:admin_only",
"delete_firewall": "rule:admin_or_owner",
"create_firewall_policy": "",
"get_firewall_policy": "rule:admin_or_owner or rule:shared_firewall_policies",
"update_firewall_policy": "rule:admin_or_owner",
"delete_firewall_policy": "rule:admin_or_owner",
"create_firewall_policy:shared": "rule:admin_only",
"update_firewall_policy:shared": "rule:admin_only",
"delete_firewall_policy:shared": "rule:admin_only",
"insert_rule": "rule:admin_or_owner",
"remove_rule": "rule:admin_or_owner",
"create_firewall_rule": "",
"get_firewall_rule": "rule:admin_or_owner or rule:shared_firewalls",
"update_firewall_rule": "rule:admin_or_owner",
"delete_firewall_rule": "rule:admin_or_owner",
"create_firewall_rule:shared": "rule:admin_only",
"update_firewall_rule:shared": "rule:admin_only",
"delete_firewall_rule:shared": "rule:admin_only"
}

151
lower-constraints.txt Normal file
View File

@ -0,0 +1,151 @@
alabaster==0.7.10
amqp==2.1.1
appdirs==1.3.0
asn1crypto==0.23.0
Babel==2.3.4
cachetools==2.0.0
cffi==1.7.0
cliff==2.8.0
cmd2==0.8.0
contextlib2==0.4.0
coverage==4.0
cryptography==2.1
debtcollector==1.2.0
decorator==4.1.0
deprecation==1.0
Django==2.2
django-appconf==1.0.2
django-babel==0.6.2
django-compressor==2.0
django-pyscss==2.0.2
docutils==0.12
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==3.6.0
flake8-import-order==0.13
futurist==1.2.0
greenlet==0.4.10
hacking==3.0.1
horizon==17.1.0
idna==2.6
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
kombu==4.0.0
linecache2==1.0.0
MarkupSafe==1.1.1
mccabe==0.6.0
monotonic==0.6
msgpack-python==0.4.0
munch==2.1.0
netaddr==0.7.18
netifaces==0.10.4
openstackdocstheme==2.2.1
openstacksdk==0.11.2
os-client-config==1.28.0
os-service-types==1.2.0
osc-lib==1.8.0
oslo.concurrency==3.26.0
oslo.config==5.2.0
oslo.context==2.19.2
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.serialization==2.18.0
oslo.service==1.24.0
oslo.utils==3.33.0
osprofiler==2.3.0
Paste==2.0.2
PasteDeploy==1.5.0
pbr==2.0.0
pep8==1.5.7
pika==0.10.0
pika-pool==0.1.3
Pint==0.5
positional==1.2.1
prettytable==0.7.2
pycodestyle==2.4.0
pycparser==2.18
pyflakes==2.0.0
Pygments==2.2.0
pyinotify==0.9.6
pymongo==3.0.2
pyOpenSSL==17.1.0
pyparsing==2.1.0
pyperclip==1.5.27
pyScss==1.3.7
python-cinderclient==5.0.0
python-dateutil==2.5.3
python-glanceclient==2.8.0
python-keystoneclient==3.22.0
python-mimeparse==1.6.0
python-neutronclient==6.7.0
python-novaclient==9.1.0
python-swiftclient==3.2.0
pytz==2013.6
PyYAML==3.12
rcssmin==1.0.6
reno==3.1.0
repoze.lru==0.7
requests==2.14.2
requestsexceptions==1.2.0
rfc3986==0.3.1
rjsmin==1.0.12
Routes==2.3.1
selenium==2.50.1
semantic-version==2.3.1
simplejson==3.5.1
six==1.10.0
snowballstemmer==1.2.1
Sphinx==2.0.0
sphinxcontrib-websupport==1.0.1
statsd==3.2.1
stevedore==1.20.0
tenacity==3.2.1
testtools==2.2.0
traceback2==1.4.0
unittest2==1.1.0
vine==1.1.4
warlock==1.2.0
WebOb==1.7.1
wrapt==1.7.0
XStatic==1.0.0
XStatic-Angular==1.5.8.0
XStatic-Angular-Bootstrap==2.2.0.0
XStatic-Angular-FileUpload==12.0.4.0
XStatic-Angular-Gettext==2.3.8.0
XStatic-Angular-lrdragndrop==1.0.2.2
XStatic-Angular-Schema-Form==0.8.13.0
XStatic-Bootstrap-Datepicker==1.3.1.0
XStatic-Bootstrap-SCSS==3.3.7.1
XStatic-bootswatch==3.3.7.0
XStatic-D3==3.5.17.0
XStatic-Font-Awesome==4.7.0.0
XStatic-Hogan==2.0.0.2
XStatic-Jasmine==2.4.1.1
XStatic-jQuery==1.8.2.1
XStatic-JQuery-Migrate==1.2.1.1
XStatic-jquery-ui==1.10.4.1
XStatic-JQuery.quicksearch==2.0.3.1
XStatic-JQuery.TableSorter==2.14.5.1
XStatic-JSEncrypt==2.3.1.1
XStatic-mdi==1.4.57.0
XStatic-objectpath==1.2.1.0
XStatic-Rickshaw==1.5.0.0
XStatic-roboto-fontface==0.5.0.0
XStatic-smart-table==1.4.13.2
XStatic-Spin==1.2.5.2
XStatic-term.js==0.0.7.0
XStatic-tv4==1.2.7.0
xvfbwrapper==0.1.3

23
manage.py Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import sys
from django.core.management import execute_from_command_line # noqa
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
"neutron_fwaas_dashboard.test.settings")
execute_from_command_line(sys.argv)

View File

View File

View File

@ -0,0 +1,348 @@
# 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 collections
from openstack_dashboard.api import neutron
import openstack_dashboard.api.nova as nova
from openstack_dashboard.contrib.developer.profiler import api as profiler
neutronclient = neutron.neutronclient
class Port(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron port."""
class Rule(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron firewall rule."""
class Policy(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron firewall policy."""
class FirewallGroup(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron firewall group."""
def rule_create(request, **kwargs):
"""Create a firewall rule
:param request: request context
:param name: name for rule
:param description: description for rule
:param protocol: protocol for rule
:param action: action for rule
:param source_ip_address: source IP address or subnet
:param source_port: integer in [1, 65535] or range in a:b
:param destination_ip_address: destination IP address or subnet
:param destination_port: integer in [1, 65535] or range in a:b
:param shared: boolean (default false)
:param enabled: boolean (default true)
:return: Rule object
"""
body = {'firewall_rule': kwargs}
rule = neutronclient(request).create_fwaas_firewall_rule(
body).get('firewall_rule')
return Rule(rule)
@profiler.trace
def get_network_names(request):
networks = neutronclient(request).list_networks(fields=["name", "id"])\
.get('networks', [])
mapped = {n['id']: neutron.Network(n) for n in networks}
return mapped
@profiler.trace
def get_router_names(request):
routers = neutronclient(request).list_routers(fields=["name", "id"])\
.get('routers', [])
mapped = {r['id']: neutron.Router(r) for r in routers}
return mapped
@profiler.trace
def get_servers(request):
servers = nova.server_list(request)[0]
mapped = {s.id: s for s in servers}
return mapped
@profiler.trace
def rule_list(request, **kwargs):
return _rule_list(request, **kwargs)
@profiler.trace
def port_list(request, tenant_id, **kwargs):
kwargs['tenant_id'] = tenant_id
ports = neutronclient(request).list_ports(**kwargs).get('ports')
return {
p['id']: Port(p) for p in ports if _is_target(p)
}
# Gets ids of all ports assigned to firewall groups
@profiler.trace
def fwg_port_list(request, **kwargs):
fwgs = neutronclient(request).list_fwaas_firewall_groups(
**kwargs).get('firewall_groups')
ports = set()
for fwg in fwgs:
if fwg['ports']:
ports.update(fwg['ports'])
return ports
@profiler.trace
def fwg_port_list_for_tenant(request, tenant_id, **kwargs):
kwargs['tenant_id'] = tenant_id
ports = neutronclient(request).list_ports(**kwargs).get('ports')
# TODO(SarathMekala): Remove ports which are already associated with a FWG
fwgs = neutronclient(request).list_fwaas_firewall_groups(
**kwargs).get('firewall_groups')
fwg_ports = []
for fwg in fwgs:
if not fwg['ports']:
continue
fwg_ports += fwg['ports']
return [Port(p) for p in ports
if _is_target(p) and p['id'] not in fwg_ports]
def _is_target(port):
return (port['device_owner'].startswith('compute:') or
port['device_owner'].startswith('network:router_interface'))
@profiler.trace
def rule_list_for_tenant(request, tenant_id, **kwargs):
"""Return a rule list available for the tenant.
The list contains rules owned by the tenant and shared rules.
This is required because Neutron returns all resources including
all tenants if a user has admin role.
"""
rules = rule_list(request, tenant_id=tenant_id, shared=False, **kwargs)
shared_rules = rule_list(request, shared=True, **kwargs)
return rules + shared_rules
def _rule_list(request, **kwargs):
rules = neutronclient(request).list_fwaas_firewall_rules(
**kwargs).get('firewall_rules')
return [Rule(r) for r in rules]
@profiler.trace
def rule_get(request, rule_id):
return _rule_get(request, rule_id)
def _rule_get(request, rule_id):
rule = neutronclient(request).show_fwaas_firewall_rule(
rule_id).get('firewall_rule')
return Rule(rule)
@profiler.trace
def rule_delete(request, rule_id):
neutronclient(request).delete_fwaas_firewall_rule(rule_id)
@profiler.trace
def rule_update(request, rule_id, **kwargs):
body = {'firewall_rule': kwargs}
rule = neutronclient(request).update_fwaas_firewall_rule(
rule_id, body).get('firewall_rule')
return Rule(rule)
@profiler.trace
def policy_create(request, **kwargs):
"""Create a firewall policy
:param request: request context
:param name: name for policy
:param description: description for policy
:param firewall_rules: ordered list of rules in policy
:param shared: boolean (default false)
:param audited: boolean (default false)
:return: Policy object
"""
body = {'firewall_policy': kwargs}
policy = neutronclient(request).create_fwaas_firewall_policy(
body).get('firewall_policy')
return Policy(policy)
@profiler.trace
def policy_list(request, **kwargs):
return _policy_list(request, expand_rule=True, **kwargs)
@profiler.trace
def policy_list_for_tenant(request, tenant_id, **kwargs):
"""Return a policy list available for the tenant.
The list contains policies owned by the tenant and shared policies.
This is required because Neutron returns all resources including
all tenants if a user has admin role.
"""
policies = policy_list(request, tenant_id=tenant_id,
shared=False, **kwargs)
shared_policies = policy_list(request, shared=True, **kwargs)
return policies + shared_policies
def _policy_list(request, expand_rule, **kwargs):
policies = neutronclient(request).list_fwaas_firewall_policies(
**kwargs).get('firewall_policies')
if expand_rule and policies:
rules = _rule_list(request)
rule_dict = collections.OrderedDict((rule.id, rule) for rule in rules)
for p in policies:
p['rules'] = [rule_dict.get(rule) for rule in p['firewall_rules']]
return [Policy(p) for p in policies]
@profiler.trace
def policy_get(request, policy_id):
return _policy_get(request, policy_id, expand_rule=True)
def _policy_get(request, policy_id, expand_rule):
policy = neutronclient(request).show_fwaas_firewall_policy(
policy_id).get('firewall_policy')
if expand_rule:
policy_rules = policy['firewall_rules']
if policy_rules:
rules = _rule_list(request, firewall_policy_id=policy_id)
rule_dict = collections.OrderedDict((rule.id, rule)
for rule in rules)
policy['rules'] = [rule_dict.get(rule) for rule in policy_rules]
else:
policy['rules'] = []
return Policy(policy)
@profiler.trace
def policy_delete(request, policy_id):
neutronclient(request).delete_fwaas_firewall_policy(policy_id)
@profiler.trace
def policy_update(request, policy_id, **kwargs):
body = {'firewall_policy': kwargs}
policy = neutronclient(request).update_fwaas_firewall_policy(
policy_id, body).get('firewall_policy')
return Policy(policy)
@profiler.trace
def policy_insert_rule(request, policy_id, **kwargs):
policy = neutronclient(request).insert_rule_fwaas_firewall_policy(
policy_id, kwargs)
return Policy(policy)
@profiler.trace
def policy_remove_rule(request, policy_id, **kwargs):
policy = neutronclient(request).remove_rule_fwaas_firewall_policy(
policy_id, kwargs)
return Policy(policy)
@profiler.trace
def firewall_group_create(request, **kwargs):
"""Create a firewall group for specified policy
:param request: request context
:param name: name for firewall group
:param description: description for firewall group
:param firewall_policy_id: policy id used by firewall group
:param shared: boolean (default false)
:param admin_state_up: boolean (default true)
:return: Firewall group object
"""
body = {'firewall_group': kwargs}
firewall_group = neutronclient(request).create_fwaas_firewall_group(body)
return FirewallGroup(firewall_group['firewall_group'])
@profiler.trace
def firewall_group_list(request, **kwargs):
return _firewall_group_list(request, **kwargs)
@profiler.trace
def firewall_group_list_for_tenant(request, tenant_id, **kwargs):
"""Return a firewall group list available for the tenant.
The list contains firewall groups owned by the tenant and shared firewall
groups. This is required because Neutron returns all resources including
all tenants if a user has admin role.
"""
fwg = firewall_group_list(request, tenant_id=tenant_id,
shared=False, **kwargs)
shared_fwg = firewall_group_list(request, shared=True, **kwargs)
return fwg + shared_fwg
# TODO(SarathMekala): Support expand_policy for _firewall_group_list
def _firewall_group_list(request, **kwargs):
firewall_groups = neutronclient(request).list_fwaas_firewall_groups(
**kwargs).get('firewall_groups')
return [FirewallGroup(f) for f in firewall_groups]
@profiler.trace
def firewall_group_get(request, firewallgroup_id):
return _firewall_group_get(request, firewallgroup_id, expand_policy=True)
def _firewall_group_get(request, firewallgroup_id, expand_policy):
firewall_group = neutronclient(request).show_fwaas_firewall_group(
firewallgroup_id).get('firewall_group')
if expand_policy:
ingress_policy_id = firewall_group['ingress_firewall_policy_id']
if ingress_policy_id:
firewall_group['ingress_policy'] = _policy_get(
request, ingress_policy_id, expand_rule=False)
else:
firewall_group['ingress_policy'] = None
egress_policy_id = firewall_group['egress_firewall_policy_id']
if egress_policy_id:
firewall_group['egress_policy'] = _policy_get(
request, egress_policy_id, expand_rule=False)
else:
firewall_group['egress_policy'] = None
return FirewallGroup(firewall_group)
@profiler.trace
def firewall_group_delete(request, firewallgroup_id):
neutronclient(request).delete_fwaas_firewall_group(firewallgroup_id)
@profiler.trace
def firewall_group_update(request, firewallgroup_id, **kwargs):
body = {'firewall_group': kwargs}
firewall_group = neutronclient(request).update_fwaas_firewall_group(
firewallgroup_id, body).get('firewall_group')
return FirewallGroup(firewall_group)

View File

@ -0,0 +1,449 @@
# Copyright 2017, Juniper Networks, 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 logging
from operator import attrgetter
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from horizon.utils import validators
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 import widgets
port_validator = validators.validate_port_or_colon_separated_port_range
LOG = logging.getLogger(__name__)
class UpdateRule(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(
required=False,
max_length=80, label=_("Description"))
protocol = forms.ThemableChoiceField(
label=_("Protocol"),
choices=[('tcp', _('TCP')), ('udp', _('UDP')), ('icmp', _('ICMP')),
('any', _('ANY'))],
help_text=_('Protocol for the firewall rule'))
action = forms.ThemableChoiceField(
label=_("Action"),
choices=[('allow', _('ALLOW')), ('deny', _('DENY')),
('reject', _('REJECT'))],
help_text=_('Action for the firewall rule'))
source_ip_address = forms.IPField(
label=_("Source IP Address/Subnet"),
version=forms.IPv4 | forms.IPv6,
required=False, mask=True,
help_text=_('Source IP address or subnet'))
destination_ip_address = forms.IPField(
label=_('Destination IP Address/Subnet'),
version=forms.IPv4 | forms.IPv6,
required=False, mask=True,
help_text=_('Destination IP address or subnet'))
source_port = forms.CharField(
max_length=80,
label=_("Source Port/Port Range"),
required=False,
validators=[port_validator],
help_text=_('Source port (integer in [1, 65535] or range in a:b)'))
destination_port = forms.CharField(
max_length=80,
label=_("Destination Port/Port Range"),
required=False,
validators=[port_validator],
help_text=_('Destination port (integer in [1, 65535] or range'
' in a:b)'))
ip_version = forms.ThemableChoiceField(
label=_("IP Version"),
choices=[('4', '4'), ('6', '6')],
help_text=_('IP Version for Firewall Rule'))
shared = forms.BooleanField(label=_("Shared"), required=False)
enabled = forms.BooleanField(label=_("Enabled"), required=False)
failure_url = 'horizon:project:firewalls_v2:index'
def _convert_req_body(self, body):
for key in ['source_port', 'source_ip_address',
'destination_port', 'destination_ip_address']:
if key in body and not body[key]:
body[key] = None
if body.get('protocol') == 'any':
body['protocol'] = None
return body
def handle(self, request, context):
rule_id = self.initial['id']
name_or_id = context.get('name') or rule_id
body = self._convert_req_body(_get_request_body(context, self.initial))
try:
rule = api_fwaas_v2.rule_update(request, rule_id, **body)
msg = _('Rule %s was successfully updated.') % name_or_id
messages.success(request, msg)
return rule
except Exception as e:
msg = (_('Failed to update rule %(name)s: %(reason)s') %
{'name': name_or_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdatePolicy(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(required=False,
max_length=80, label=_("Description"))
shared = forms.BooleanField(label=_("Shared"), required=False)
audited = forms.BooleanField(label=_("Audited"), required=False)
failure_url = 'horizon:project:firewalls_v2:index'
def handle(self, request, context):
policy_id = self.initial['id']
name_or_id = context.get('name') or policy_id
body = _get_request_body(context, self.initial)
try:
policy = api_fwaas_v2.policy_update(request, policy_id, **body)
msg = _('Policy %s was successfully updated.') % name_or_id
messages.success(request, msg)
return policy
except Exception as e:
msg = (_('Failed to update policy %(name)s: %(reason)s') %
{'name': name_or_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateFirewall(forms.SelfHandlingForm):
name = forms.CharField(max_length=80,
label=_("Name"),
required=False)
description = forms.CharField(max_length=80,
label=_("Description"),
required=False)
ingress_firewall_policy_id = forms.ThemableChoiceField(
label=_("Ingress Policy"), required=False)
egress_firewall_policy_id = forms.ThemableChoiceField(
label=_("Egress Policy"), required=False)
admin_state_up = forms.BooleanField(label=_("Admin State"),
required=False)
shared = forms.BooleanField(label=_("Shared"), required=False)
failure_url = 'horizon:project:firewalls_v2:index'
def __init__(self, request, *args, **kwargs):
super(UpdateFirewall, self).__init__(request, *args, **kwargs)
try:
tenant_id = self.request.user.tenant_id
policies = api_fwaas_v2.policy_list_for_tenant(request, tenant_id)
policies = sorted(policies, key=attrgetter('name'))
except Exception:
exceptions.handle(request, _('Unable to retrieve policy list.'))
policies = []
egress_policy_id_choices = []
ingress_policy_id_choices = []
ingress_policy_id = kwargs['initial']['ingress_firewall_policy_id']
if ingress_policy_id:
ingress_policy_name = [
p.name for p in policies if p.id == ingress_policy_id][0]
ingress_policy_id_choices.append(
(ingress_policy_id, ingress_policy_name))
egress_policy_id = kwargs['initial']['egress_firewall_policy_id']
if egress_policy_id:
egress_policy_name = [
p.name for p in policies if p.id == egress_policy_id][0]
egress_policy_id_choices.append((egress_policy_id,
egress_policy_name))
ingress_policy_id_choices.append(('', _('None')))
egress_policy_id_choices.append(('', _('None')))
for p in policies:
if p.id != ingress_policy_id:
ingress_policy_id_choices.append((p.id, p.name_or_id))
if p.id != egress_policy_id:
egress_policy_id_choices.append((p.id, p.name_or_id))
self.fields['ingress_firewall_policy_id'].choices = \
ingress_policy_id_choices
self.fields['egress_firewall_policy_id'].choices = \
egress_policy_id_choices
def _convert_req_body(self, body):
for key in ['ingress_firewall_policy_id', 'egress_firewall_policy_id']:
if key in body and not body[key]:
body[key] = None
return body
def handle(self, request, context):
firewallgroup_id = self.initial['id']
name_or_id = context.get('name') or firewallgroup_id
body = self._convert_req_body(_get_request_body(context, self.initial))
try:
fwg = api_fwaas_v2.firewall_group_update(request,
firewallgroup_id,
**body)
msg = _('Firewall group %s was successfully updated.') % name_or_id
messages.success(request, msg)
return fwg
except Exception as e:
msg = (_('Failed to update firewall group %(name)s: %(reason)s') %
{'name': name_or_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class PortSelectionForm(forms.SelfHandlingForm):
port_id = forms.ThemableDynamicChoiceField(
label=_("Ports"),
required=False,
widget=widgets.TableSelectWidget(
columns=['Port', 'Network', 'Owner', 'Device'],
alternate_xs=True
)
)
networks = {}
routers = {}
servers = {}
ports = {}
def __init__(self, request, *args, **kwargs):
super(PortSelectionForm, self).__init__(request, *args, **kwargs)
tenant_id = self.request.user.tenant_id
self.ports = api_fwaas_v2.port_list(request, tenant_id, **kwargs)
self.networks = api_fwaas_v2.get_network_names(request)
self.routers = api_fwaas_v2.get_router_names(request)
self.servers = api_fwaas_v2.get_servers(request)
self.fields['port_id'].widget.build_columns = self._build_col
self.fields['port_id'].choices = self.get_ports(request)
def get_ports(self, request):
return []
def _build_col(self, option):
port = self.ports[option[0]]
columns = self._build_option(port)
return columns
def _build_option(self, port):
network = self.networks.get(port.network_id)
network_label = network.name_or_id if network else port.network_id
owner_label = ''
device_label = ''
if port.device_owner.startswith('network'):
owner_label = 'network'
router = self.routers.get(port.device_id, None)
device_label = router.name_or_id if router else port.device_id
elif port.device_owner.startswith('compute'):
owner_label = 'compute'
server = self.servers.get(port.device_id, None)
device_label = server.name_or_id if server else port.device_id
columns = (port.name_or_id, network_label, owner_label, device_label)
# The return value works off of the original themeable select widget
# This needs to be maintained for the original javascript to work
return columns
class AddPort(PortSelectionForm):
failure_url = 'horizon:project:firewalls_v2:index'
def get_ports(self, request):
used_ports = api_fwaas_v2.fwg_port_list(request)
ports = self.ports.values()
return [(p.id, p.id) for p in ports if p.id not in used_ports]
def handle(self, request, context):
firewallgroup_id = self.initial['id']
name_or_id = context.get('name') or firewallgroup_id
body = _get_request_body(context, self.initial)
add_port = context['port_id']
if add_port:
ports = self.initial['ports']
ports.append(add_port)
body['ports'] = ports
try:
firewallgroup = api_fwaas_v2.firewall_group_update(
request, firewallgroup_id, **body)
msg = (_('Added the port(s) to the firewall group %s '
'successfully.') % name_or_id)
messages.success(request, msg)
return firewallgroup
except Exception as e:
msg = (_('Failed to add the port(s) to the firewall group '
'%(name)s: %(reason)s') %
{'name': name_or_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class RemovePort(PortSelectionForm):
failure_url = 'horizon:project:firewalls_v2:index'
def get_ports(self, request):
ports = self.initial['ports']
return [(p, p) for p in ports]
def handle(self, request, context):
firewallgroup_id = self.initial['id']
name_or_id = context.get('name') or firewallgroup_id
body = _get_request_body(context, self.initial)
remove_port = context['port_id']
if remove_port:
ports = self.initial['ports']
ports.remove(remove_port)
body['ports'] = ports
try:
firewallgroup = api_fwaas_v2.firewall_group_update(
request, firewallgroup_id, **body)
msg = _('Removed the port(s) from the firewall group %s '
'successfully.') % name_or_id
messages.success(request, msg)
return firewallgroup
except Exception as e:
msg = (_('Failed to remove the port(s) from the firewall group '
'%(name)s: %(reason)s') %
{'name': name_or_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class InsertRuleToPolicy(forms.SelfHandlingForm):
firewall_rule_id = forms.ThemableChoiceField(label=_("Insert Rule"))
insert_before = forms.ThemableChoiceField(label=_("Before"),
required=False)
insert_after = forms.ThemableChoiceField(label=_("After"),
required=False)
failure_url = 'horizon:project:firewalls_v2:index'
def __init__(self, request, *args, **kwargs):
super(InsertRuleToPolicy, self).__init__(request, *args, **kwargs)
try:
tenant_id = self.request.user.tenant_id
all_rules = api_fwaas_v2.rule_list_for_tenant(request, tenant_id)
all_rules = sorted(all_rules, key=attrgetter('name_or_id'))
available_rules = [r for r in all_rules]
current_rules = []
for x in kwargs['initial']['firewall_rules']:
r_obj = [rule for rule in all_rules if x == rule.id][0]
current_rules.append(r_obj)
available_choices = [(r.id, r.name_or_id) for r in available_rules]
current_choices = [(r.id, r.name_or_id) for r in current_rules]
except Exception as e:
msg = _('Failed to retrieve available rules: %s') % e
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
self.fields['firewall_rule_id'].choices = available_choices
self.fields['insert_before'].choices = [('', _('-'))] + current_choices
self.fields['insert_after'].choices = [('', _('-'))] + current_choices
def handle(self, request, context):
policy_id = self.initial['id']
policy_name_or_id = self.initial['name'] or policy_id
try:
insert_rule_id = context['firewall_rule_id']
insert_rule = api_fwaas_v2.rule_get(request, insert_rule_id)
body = {'firewall_rule_id': insert_rule_id,
'insert_before': context['insert_before'],
'insert_after': context['insert_after']}
policy = api_fwaas_v2.policy_insert_rule(request, policy_id,
**body)
msg = (_('Rule %(rule)s was successfully inserted to policy '
'%(policy)s.') %
{'rule': insert_rule.name or insert_rule.id,
'policy': policy_name_or_id})
messages.success(request, msg)
return policy
except Exception as e:
msg = (_('Failed to insert rule to policy %(name)s: %(reason)s') %
{'name': policy_id, 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class RemoveRuleFromPolicy(forms.SelfHandlingForm):
firewall_rule_id = forms.ThemableChoiceField(label=_("Remove Rule"))
failure_url = 'horizon:project:firewalls_v2:index'
def __init__(self, request, *args, **kwargs):
super(RemoveRuleFromPolicy, self).__init__(request, *args, **kwargs)
try:
tenant_id = request.user.tenant_id
all_rules = api_fwaas_v2.rule_list_for_tenant(request, tenant_id)
current_rules = []
for r in kwargs['initial']['firewall_rules']:
r_obj = [rule for rule in all_rules if r == rule.id][0]
current_rules.append(r_obj)
current_choices = [(r.id, r.name_or_id) for r in current_rules]
except Exception as e:
msg = (_('Failed to retrieve current rules in policy %(name)s: '
'%(reason)s') %
{'name': self.initial['name'], 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
self.fields['firewall_rule_id'].choices = current_choices
def handle(self, request, context):
policy_id = self.initial['id']
policy_name_or_id = self.initial['name'] or policy_id
try:
remove_rule_id = context['firewall_rule_id']
remove_rule = api_fwaas_v2.rule_get(request, remove_rule_id)
body = {'firewall_rule_id': remove_rule_id}
policy = api_fwaas_v2.policy_remove_rule(request, policy_id,
**body)
msg = (_('Rule %(rule)s was successfully removed from policy '
'%(policy)s.') %
{'rule': remove_rule.name or remove_rule.id,
'policy': policy_name_or_id})
messages.success(request, msg)
return policy
except Exception as e:
msg = (_('Failed to remove rule from policy %(name)s: %(reason)s')
% {'name': self.initial['name'], 'reason': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
def _get_request_body(context, initial_values):
body = {}
for key, value in context.items():
# TODO(yushiro): Refactor after Q-2.
if key == 'port_id':
continue
if value != initial_values[key]:
body[key] = value
return body

View File

@ -0,0 +1,43 @@
# Copyright 2017, Juniper Networks, 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 logging
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import neutron
LOG = logging.getLogger(__name__)
class Firewall_V2(horizon.Panel):
name = _("Firewall Groups")
slug = "firewalls_v2"
permissions = ('openstack.services.network',)
def allowed(self, context):
request = context['request']
if not request.user.has_perms(self.permissions):
return False
try:
if not neutron.is_extension_supported(request, 'fwaas_v2'):
return False
except Exception:
LOG.error("Call to list enabled services failed. This is likely "
"due to a problem communicating with the Neutron "
"endpoint. Firewall Groups panel will not be displayed.")
return False
if not super(Firewall_V2, self).allowed(context):
return False
return True

View File

@ -0,0 +1,425 @@
# Copyright 2017, Juniper Networks, 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 logging
from django.template import defaultfilters as filters
from django.urls import reverse
from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from openstack_dashboard.dashboards.project.networks.ports \
import tables as port_tables
from openstack_dashboard import policy
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
LOG = logging.getLogger(__name__)
class AddRuleLink(tables.LinkAction):
name = "addrule"
verbose_name = _("Add Rule")
url = "horizon:project:firewalls_v2:addrule"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("neutron-fwaas", "create_fwaas_firewall_rule"),)
class AddPolicyLink(tables.LinkAction):
name = "addpolicy"
verbose_name = _("Add Policy")
url = "horizon:project:firewalls_v2:addpolicy"
classes = ("ajax-modal", "btn-addpolicy",)
icon = "plus"
policy_rules = (("neutron-fwaas", "create_fwaas_firewall_policy"),)
class AddFirewallGroupLink(tables.LinkAction):
name = "addfirewallgroup"
verbose_name = _("Create Firewall Group")
url = "horizon:project:firewalls_v2:addfirewallgroup"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("neutron-fwaas", "create_fwaas_firewall_group"),)
class DeleteRuleLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deleterule"
policy_rules = (("neutron-fwaas", "delete_fwaas_firewall_rule"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Rule",
u"Delete Rules",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Rule",
u"Scheduled deletion of Rules",
count
)
def allowed(self, request, datum=None):
# TODO(Sarath Mekala): If the rule is associated with a policy then
# return false.
return True
def delete(self, request, obj_id):
try:
api_fwaas_v2.rule_delete(request, obj_id)
except Exception as e:
exceptions.handle(request, _('Unable to delete rule. %s') % e)
class DeletePolicyLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletepolicy"
policy_rules = (("neutron-fwaas", "delete_fwaas_firewall_policy"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Policy",
u"Delete Policies",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Policy",
u"Scheduled deletion of Policies",
count
)
def delete(self, request, obj_id):
try:
api_fwaas_v2.policy_delete(request, obj_id)
except Exception as e:
exceptions.handle(request, _('Unable to delete policy. %s') % e)
class DeleteFirewallGroupLink(policy.PolicyTargetMixin,
tables.DeleteAction):
name = "deletefirewallgroup"
policy_rules = (("neutron-fwaas", "delete_fwaas_firewall_group"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Firewall Group",
u"Delete Firewall Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Firewall Group",
u"Scheduled deletion of Firewall Groups",
count
)
def delete(self, request, obj_id):
try:
api_fwaas_v2.firewall_group_delete(request, obj_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete firewall group. %s') % e)
class UpdateRuleLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updaterule"
verbose_name = _("Edit Rule")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "update_fwaas_firewall_rule"),)
def get_link_url(self, rule):
return reverse("horizon:project:firewalls_v2:updaterule",
kwargs={'rule_id': rule.id})
class UpdatePolicyLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatepolicy"
verbose_name = _("Edit Policy")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "update_fwaas_firewall_policy"),)
def get_link_url(self, policy):
return reverse("horizon:project:firewalls_v2:updatepolicy",
kwargs={'policy_id': policy.id})
class UpdateFirewallGroupLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatefirewall"
verbose_name = _("Edit Firewall Group")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "update_firewall"),)
def get_link_url(self, firewallgroup):
return reverse("horizon:project:firewalls_v2:updatefirewall",
kwargs={'firewall_id': firewallgroup.id})
def allowed(self, request, firewallgroup):
return firewallgroup.status not in (
"PENDING_CREATE",
"PENDING_UPDATE",
"PENDING_DELETE")
class InsertRuleToPolicyLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "insertrule"
verbose_name = _("Insert Rule")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "show_fwaas_firewall_policy"),
("neutron-fwaas", "insert_rule_fwaas_firewall_policy"),)
def get_link_url(self, policy):
return reverse("horizon:project:firewalls_v2:insertrule",
kwargs={'policy_id': policy.id})
class RemoveRuleFromPolicyLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "removerule"
verbose_name = _("Remove Rule")
classes = ("ajax-modal",)
policy_rules = (("neutron-fwaas", "show_fwaas_firewall_policy"),
("neutron-fwaas", "firewall_policy_remove_rule"),)
action_type = "danger"
def get_link_url(self, policy):
return reverse("horizon:project:firewalls_v2:removerule",
kwargs={'policy_id': policy.id})
def allowed(self, request, policy):
return bool(policy.rules)
class AddPortToFirewallGroupLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "addport"
verbose_name = _("Add Port")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "update_fwaas_firewall_group"),)
def get_link_url(self, firewallgroup):
return reverse("horizon:project:firewalls_v2:addport",
kwargs={'firewallgroup_id': firewallgroup.id})
def allowed(self, request, firewallgroup):
return firewallgroup.status not in (
"PENDING_CREATE",
"PENDING_UPDATE",
"PENDING_DELETE")
class RemovePortFromFirewallGroupLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "removeport"
verbose_name = _("Remove Port")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("neutron-fwaas", "update_fwaas_firewall_group"),)
def get_link_url(self, firewallgroup):
return reverse("horizon:project:firewalls_v2:removeport",
kwargs={'firewallgroup_id': firewallgroup.id})
def allowed(self, request, firewallgroup):
return firewallgroup.status not in (
"PENDING_CREATE",
"PENDING_UPDATE",
"PENDING_DELETE")
def get_rules_name(datum):
return ', '.join([rule.name_or_id for rule in datum.rules])
def get_ports_name(datum):
return len(datum.ports)
def get_ports_link(datum):
url = reverse("horizon:project:firewalls_v2:firewallgroupdetails",
args=(datum.id,))
return '%s?tab=%s__%s' % (url, 'firewallgrouptabs', 'ports_tab')
def get_ingress_policy_link(datum):
if datum.ingress_firewall_policy_id:
return reverse('horizon:project:firewalls_v2:policydetails',
kwargs={'policy_id': datum.ingress_firewall_policy_id})
def get_egress_policy_link(datum):
if datum.egress_firewall_policy_id:
return reverse('horizon:project:firewalls_v2:policydetails',
kwargs={'policy_id': datum.egress_firewall_policy_id})
def get_ingress_policy_name(datum):
if datum.ingress_firewall_policy_id:
return datum.ingress_policy.name
def get_egress_policy_name(datum):
if datum.egress_firewall_policy_id:
return datum.egress_policy.name
class RulesTable(tables.DataTable):
ACTION_DISPLAY_CHOICES = (
("Allow", pgettext_lazy("Action Name of a Firewall Rule", u"ALLOW")),
("Deny", pgettext_lazy("Action Name of a Firewall Rule", u"DENY")),
("Reject", pgettext_lazy("Action Name of a Firewall Rule", u"REJECT")),
)
name = tables.Column("name_or_id",
verbose_name=_("Name"),
link="horizon:project:firewalls_v2:ruledetails")
description = tables.Column('description', verbose_name=_('Description'))
ip_version = tables.Column('ip_version', verbose_name=('IP Version'))
protocol = tables.Column("protocol",
filters=(lambda v: filters.default(v, _("ANY")),
filters.upper,),
verbose_name=_("Protocol"))
source_ip_address = tables.Column("source_ip_address",
verbose_name=_("Source IP"))
source_port = tables.Column("source_port",
verbose_name=_("Source Port"))
destination_ip_address = tables.Column("destination_ip_address",
verbose_name=_("Destination IP"))
destination_port = tables.Column("destination_port",
verbose_name=_("Destination Port"))
action = tables.Column("action",
display_choices=ACTION_DISPLAY_CHOICES,
verbose_name=_("Action"))
shared = tables.Column("shared",
verbose_name=_("Shared"),
filters=(filters.yesno, filters.capfirst))
enabled = tables.Column("enabled",
verbose_name=_("Enabled"),
filters=(filters.yesno, filters.capfirst))
class Meta(object):
name = "rulestable"
verbose_name = _("Rules")
table_actions = (AddRuleLink,
DeleteRuleLink,
tables.NameFilterAction)
row_actions = (UpdateRuleLink, DeleteRuleLink)
class PoliciesTable(tables.DataTable):
name = tables.Column("name_or_id",
verbose_name=_("Name"),
link="horizon:project:firewalls_v2:policydetails")
description = tables.Column('description', verbose_name=_('Description'))
firewall_rules = tables.Column(get_rules_name,
verbose_name=_("Rules"))
shared = tables.Column("shared",
verbose_name=_("Shared"),
filters=(filters.yesno, filters.capfirst))
audited = tables.Column("audited",
verbose_name=_("Audited"),
filters=(filters.yesno, filters.capfirst))
class Meta(object):
name = "policiestable"
verbose_name = _("Policies")
table_actions = (AddPolicyLink,
DeletePolicyLink,
tables.NameFilterAction)
row_actions = (UpdatePolicyLink, InsertRuleToPolicyLink,
RemoveRuleFromPolicyLink, DeletePolicyLink)
class FirewallGroupsTable(tables.DataTable):
STATUS_DISPLAY_CHOICES = (
("Active", pgettext_lazy("Current status of a Firewall Group",
u"Active")),
("Down", pgettext_lazy("Current status of a Firewall Group",
u"Down")),
("Error", pgettext_lazy("Current status of a Firewall Group",
u"Error")),
("Created", pgettext_lazy("Current status of a Firewall Group",
u"Created")),
("Pending_Create", pgettext_lazy("Current status of a Firewall Group",
u"Pending Create")),
("Pending_Update", pgettext_lazy("Current status of a Firewall Group",
u"Pending Update")),
("Pending_Delete", pgettext_lazy("Current status of a Firewall Group",
u"Pending Delete")),
("Inactive", pgettext_lazy("Current status of a Firewall Group",
u"Inactive")),
)
ADMIN_STATE_DISPLAY_CHOICES = (
("UP", pgettext_lazy("Admin state of a Firewall Group", u"UP")),
("DOWN", pgettext_lazy("Admin state of a Firewall Group", u"DOWN")),
)
name = tables.Column(
"name_or_id",
verbose_name=_("Name"),
link="horizon:project:firewalls_v2:firewallgroupdetails")
description = tables.Column('description', verbose_name=_('Description'))
ingress_firewall_policy_id = tables.Column(
get_ingress_policy_name,
link=get_ingress_policy_link,
verbose_name=_("Ingress Policy"))
egress_firewall_policy_id = tables.Column(get_egress_policy_name,
link=get_egress_policy_link,
verbose_name=_("Egress Policy"))
ports = tables.Column(get_ports_name,
link=get_ports_link,
verbose_name=_("Ports"))
status = tables.Column("status",
verbose_name=_("Status"),
display_choices=STATUS_DISPLAY_CHOICES)
admin_state_up = tables.Column("admin_state_up",
verbose_name=_("Admin State"))
shared = tables.Column("shared",
verbose_name=_("Shared"),
filters=(filters.yesno, filters.capfirst))
class Meta(object):
name = "FirewallGroupsTable"
verbose_name = _("Firewall Groups")
table_actions = (AddFirewallGroupLink,
DeleteFirewallGroupLink,
tables.NameFilterAction)
row_actions = (
UpdateFirewallGroupLink,
DeleteFirewallGroupLink,
AddPortToFirewallGroupLink,
RemovePortFromFirewallGroupLink)
class FirewallGroupPortsTable(port_tables.PortsTable):
class Meta(object):
name = 'ports'
verbose_name = _('Ports')
table_actions = []
row_actions = []

View File

@ -0,0 +1,165 @@
# Copyright 2017, Juniper Networks, 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 django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import neutron as api_neutron
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 import tables
FirewallGroupsTable = tables.FirewallGroupsTable
PoliciesTable = tables.PoliciesTable
RulesTable = tables.RulesTable
class RulesTab(tabs.TableTab):
table_classes = (RulesTable,)
name = _("Firewall Rules")
slug = "rules"
template_name = "horizon/common/_detail_table.html"
def get_rulestable_data(self):
try:
tenant_id = self.request.user.tenant_id
request = self.tab_group.request
rules = api_fwaas_v2.rule_list_for_tenant(request, tenant_id)
except Exception:
rules = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve rules list.'))
return rules
class PoliciesTab(tabs.TableTab):
table_classes = (PoliciesTable,)
name = _("Firewall Policies")
slug = "policies"
template_name = "horizon/common/_detail_table.html"
def get_policiestable_data(self):
try:
tenant_id = self.request.user.tenant_id
request = self.tab_group.request
policies = api_fwaas_v2.policy_list_for_tenant(request, tenant_id)
except Exception:
policies = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve policies list.'))
return policies
class FirewallGroupsTab(tabs.TableTab):
table_classes = (FirewallGroupsTable,)
name = _("Firewall Groups")
slug = "firewallgroups"
template_name = "horizon/common/_detail_table.html"
def get_policy_dict(self, policies):
return dict((policy.id, policy) for policy in policies)
def get_FirewallGroupsTable_data(self):
try:
tenant_id = self.request.user.tenant_id
request = self.tab_group.request
fw_groups = api_fwaas_v2.firewall_group_list_for_tenant(request,
tenant_id)
tenant_policies = api_fwaas_v2.policy_list_for_tenant(
request, tenant_id)
policy_dict = self.get_policy_dict(policies=tenant_policies)
for fw_group in fw_groups:
if fw_group['ingress_firewall_policy_id'] in policy_dict:
fw_group.ingress_policy = \
policy_dict[fw_group['ingress_firewall_policy_id']]
if fw_group['egress_firewall_policy_id'] in policy_dict:
fw_group.egress_policy = \
policy_dict[fw_group['egress_firewall_policy_id']]
except Exception:
fw_groups = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve firewall group list.'))
return fw_groups
class RuleDetailsTab(tabs.Tab):
name = _("Rule")
slug = "ruledetails"
template_name = "project/firewalls_v2/_rule_details.html"
def get_context_data(self, request):
return {"rule": self.tab_group.kwargs['rule']}
class PolicyDetailsTab(tabs.Tab):
name = _("Policy")
slug = "policydetails"
template_name = "project/firewalls_v2/_policy_details.html"
def get_context_data(self, request):
return {"policy": self.tab_group.kwargs['policy']}
class FirewallGroupDetailsTab(tabs.Tab):
name = _("FirewallGroup")
slug = "firewallgroupdetails"
template_name = "project/firewalls_v2/_firewallgroup_details.html"
def get_context_data(self, request):
return {"firewall_group": self.tab_group.kwargs['firewallgroup']}
class FirewallGroupPortsTab(tabs.TableTab):
name = _("Ports")
slug = "ports_tab"
table_classes = (tables.FirewallGroupPortsTable,)
template_name = ("horizon/common/_detail_table.html")
preload = False
def get_ports_data(self):
port_ids = self.tab_group.kwargs['firewallgroup']['ports']
if not port_ids:
return []
try:
ports = api_neutron.port_list(self.request, id=port_ids)
except Exception:
ports = []
msg = _('Failed to retrieve port list of the firewall group.')
exceptions.handle(self.request, msg)
return ports
class FirewallGroupTabs(tabs.TabGroup):
slug = "fwtabs"
tabs = (FirewallGroupsTab, PoliciesTab, RulesTab)
sticky = True
class RuleDetailsTabs(tabs.DetailTabsGroup):
slug = "ruletabs"
tabs = (RuleDetailsTab,)
class PolicyDetailsTabs(tabs.DetailTabsGroup):
slug = "policytabs"
tabs = (PolicyDetailsTab,)
class FirewallGroupDetailsTabs(tabs.DetailTabsGroup):
slug = "firewallgrouptabs"
tabs = (FirewallGroupDetailsTab, FirewallGroupPortsTab)

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may add ports to firewall group here." %}</p>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ firewall_group.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ firewall_group.description|default:_("-") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ firewall_group.id }} </dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ firewall_group.tenant_id }}</dd>
<dt>{% trans "Ingress Policy ID" %}</dt>
<dd>
{% if firewall_group.ingress_firewall_policy_id %}
{% url 'horizon:project:firewalls_v2:policydetails' firewall_group.ingress_firewall_policy_id as policy_url %}
<a href="{{ policy_url }}">{{firewall_group.ingress_policy.name|default:firewall_group.ingress_firewall_policy_id }}</a>
{% else %}
{% trans "-" %}
{% endif %}
</dd>
<dt>{% trans "Egress Policy ID" %}</dt>
<dd>
{% if firewall_group.egress_firewall_policy_id %}
{% url 'horizon:project:firewalls_v2:policydetails' firewall_group.egress_firewall_policy_id as policy_url %}
<a href="{{ policy_url }}">{{firewall_group.egress_policy.name|default:firewall_group.egress_firewall_policy_id }}</a>
{% else %}
{% trans "-" %}
{% endif %}
</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ firewall_group.status }}</dd>
<dt>{% trans "Admin State Up" %}</dt>
<dd>{{ firewall_group.admin_state_up}}</dd>
<dt>{% trans "Shared" %}</dt>
<dd>{{ firewall_group.shared|yesno|capfirst }}</dd>
</dl>
</div>

View File

@ -0,0 +1,12 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% blocktrans trimmed %}
Choose the rule you want to insert.
Specify either the rule you want to insert immediately before,
or the rule to insert immediately after.
If both are specified, the prior takes precedence.
{% endblocktrans %}</p>
{% endblock %}

View File

@ -0,0 +1,37 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ policy.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ policy.description|default:_("-") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ policy.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ policy.tenant_id }}</dd>
<dt>{% trans "Rules" %}</dt>
<dd>
{% if policy.rules %}
<ol>
{% for rule in policy.rules %}
{% url 'horizon:project:firewalls_v2:ruledetails' rule.id as rule_url %}
<li><a href="{{ rule_url }}">{{ rule.name|default:rule.id }}</a></li>
{% endfor %}
</ol>
{% else %}
{% trans "-" %}
{% endif %}
</dd>
<dt>{% trans "Shared" %}</dt>
<dd>{{ policy.shared|yesno|capfirst }}</dd>
<dt>{% trans "Audited" %}</dt>
<dd>{{ policy.audited|yesno|capfirst }}</dd>
</dl>
</div>

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Choose the rule you want to remove." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may remove ports from firewall group here." %}</p>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ rule.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ rule.description|default:_("-") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ rule.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ rule.tenant_id }}</dd>
<dt>{% trans "Action" %}</dt>
<dd>{{ rule.action|upper }}</dd>
<dt>{% trans "IP Version" %}</dt>
<dd>{{ rule.ip_version }}</dd>
<dt>{% trans "Protocol" %}</dt>
<dd>{{ rule.protocol|default:_("ANY")|upper }}</dd>
<dt>{% trans "Source IP Address" %}</dt>
<dd>{{ rule.source_ip_address|default:_("ANY") }}</dd>
<dt>{% trans "Source Port" %}</dt>
<dd>{{ rule.source_port|default:_("ANY") }}</dd>
<dt>{% trans "Destination IP Address" %}</dt>
<dd>{{ rule.destination_ip_address|default:_("ANY") }}</dd>
<dt>{% trans "Destination Port"%}</dt>
<dd>{{ rule.destination_port|default:_("ANY") }}</dd>
<dt>{% trans "Shared" %}</dt>
<dd>{{ rule.shared|yesno|capfirst }}</dd>
<dt>{% trans "Enabled" %}</dt>
<dd>{{ rule.enabled|yesno|capfirst }}</dd>
</dl>
</div>

View File

@ -0,0 +1,3 @@
{% load i18n %}
<p>{% blocktrans %}Choose port(s) from Available Ports. {% endblocktrans %}</p>

View File

@ -0,0 +1,35 @@
{% load i18n %}
<noscript><h3>{{ step }}</h3></noscript>
<div id="portListSortContainer" class="sort-container">
<div class="col-sm-6">
<h4 id="selected_port_label">{% trans "Selected Ports" %}</h4>
<ul id="selected_port" class="portlist box-list"></ul>
<h4>{% trans "Available Ports" %}</h4>
<ul id="available_port" class="portlist box-list"></ul>
</div>
<div class="col-sm-6">
{% include "project/firewalls_v2/_update_port_help.html" %}
</div>
</div>
<div id="portListIdContainer">
<div class="actions">
<div id="portListId">
{% include "horizon/common/_form_fields.html" %}
</div>
</div>
<div class="help_text">
{{ step.get_help_text }}
</div>
</div>
<script>
if (typeof $ !== 'undefined') {
horizon.firewalls_v2.workflow_init($(".workflow"));
} else {
addHorizonLoadEvent(function() {
horizon.firewalls_v2.workflow_init($(".workflow"));
});
}
</script>

View File

@ -0,0 +1,6 @@
{% load i18n horizon %}
<p>{% blocktrans trimmed %}
Choose rule(s) from Available Rules to Selected Rule by push button or
drag and drop, you may change their order by drag and drop as well.
{% endblocktrans %}</p>

View File

@ -0,0 +1,35 @@
{% load i18n %}
<noscript><h3>{{ step }}</h3></noscript>
<div id="ruleListSortContainer" class="sort-container">
<div class="col-sm-6">
<h4 id="selected_rule_label">{% trans "Selected Rules" %}</h4>
<ul id="selected_rule" class="rulelist box-list"></ul>
<h4>{% trans "Available Rules" %}</h4>
<ul id="available_rule" class="rulelist box-list"></ul>
</div>
<div class="col-sm-6">
{% include "project/firewalls_v2/_update_rule_help.html" %}
</div>
</div>
<div id="ruleListIdContainer">
<div class="actions">
<div id="ruleListId">
{% include "horizon/common/_form_fields.html" %}
</div>
</div>
<div class="help_text">
{{ step.get_help_text }}
</div>
</div>
<script>
if (typeof $ !== 'undefined') {
horizon.firewalls_v2.workflow_init($(".workflow"));
} else {
addHorizonLoadEvent(function() {
horizon.firewalls_v2.workflow_init($(".workflow"));
});
}
</script>

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update firewall group details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% blocktrans trimmed %}
You may update policy details here.
Use 'Insert Rule' or 'Remove Rule' links instead to insert or remove a rule.
{% endblocktrans %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update rule details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Add New Firewall Group" %}{% endblock %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Add New Policy" %}{% endblock %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Add Port to Firewall Group" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_addport.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Add New Rule" %}{% endblock %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Firewall Groups" %}{% endblock %}
{% block main %}
<div class="row">
<div class="col-sm-12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Insert Rule to Policy" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_insert_rule_to_policy.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Remove Rule from Policy" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_remove_rule_from_policy.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Remove Port from Firewall Group" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_removeport.html' %}
{% endblock %}

View File

@ -0,0 +1,94 @@
{% load horizon %}
{% minifyspace %}
<div class="themable-select dropdown {% if not stand_alone %} form-control{% endif %}"
xmlns="http://www.w3.org/1999/html">
<button type="button" class="btn btn-default dropdown-toggle"
data-toggle="dropdown"
{% if value %} title="{{ value }}" {% endif %}
aria-expanded="false"
{% if options|length < 1 %}
disabled="true"
{% endif %}
>
<span class="dropdown-title">
{% if options|length < 1 %}
{{ empty_text }}
{% elif initial_value %}
{{ initial_value.1 }}
{% endif %}
</span>
<span class="fa fa-caret-down"></span>
</button>
<ul class="dropdown-menu container-fluid dropdown-table">
<li class="row dropdown-thead">
<div class="col-xs-12">
<div class="row dropdown-tr ">
{% if alternate_xs %}
<div class="visible-xs-block col-xs-12 dropdown-th">{{ summarized_headers }}</div>
{% for column in columns %}
<div class="hidden-xs col-sm-{{ column_size }} dropdown-th">{{ column }}</div>
{% endfor %}
{% else %}
{% for column in columns %}
<div class="col-xs-{{ column_size }} dropdown-th">{{ column }}</div>
{% endfor %}
{% endif %}
</div>
</div>
</li>
{% for option in options %}
<li data-original-index="{{ forloop.counter0 }}"
class="row dropdown-tr"
data-toggle="tooltip"
data-placement="top"
>
<a data-select-value="{{ option.0 }}"
class="col-xs-12"
href="#"
>
<div class="row">
{% if alternate_xs %}
<div class="visible-xs-block col-xs-12 dropdown-td">
{{ option.1 }}
</div>
{% for column in option.2 %}
<div class="hidden-xs col-sm-{{ column_size }} dropdown-td">{{ column }}</div>
{% endfor %}
{% else %}
{% for column in option.2 %}
<div class="col-xs-{{ column_size }} dropdown-td">{{ column }}</div>
{% endfor %}
{% endif %}
</div>
</a>
</li>
{% endfor %}
</ul>
<select
{% if id %}
id="{{ id }}"{% endif %}
{% if name %}
name="{{ name }}"
{% endif %}
{% for k,v in select_attrs.items %}
{% if k != 'class' or 'switch' in v %}
{{ k|safe }}="{{ v }}"
{% endif %}
{% endfor %}
>
{% for option in options %}
<option value="{{ option.0 }}"
{% if option.0 == value %}
selected="selected"
{% endif %}
{% if option.3 %}
{{ option.3|safe }}
{% endif %}>
{{ option.1 }}
</option>
{% endfor %}
</select>
</div>
{% endminifyspace %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Firewall Group" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_updatefirewall.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Policy" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_updatepolicy.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Rule" %}{% endblock %}
{% block main %}
{% include 'project/firewalls_v2/_updaterule.html' %}
{% endblock %}

View File

@ -0,0 +1,798 @@
# Copyright 2017, Juniper Networks, 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 unittest import mock
from django.urls import reverse
from openstack_dashboard.test import helpers
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
from neutron_fwaas_dashboard.test import helpers as test
class FirewallTests(test.TestCase):
INDEX_URL = reverse('horizon:project:firewalls_v2:index')
ADDRULE_PATH = 'horizon:project:firewalls_v2:addrule'
ADDPOLICY_PATH = 'horizon:project:firewalls_v2:addpolicy'
ADDFIREWALLGROUP_PATH = 'horizon:project:firewalls_v2:addfirewallgroup'
RULE_DETAIL_PATH = 'horizon:project:firewalls_v2:ruledetails'
POLICY_DETAIL_PATH = 'horizon:project:firewalls_v2:policydetails'
FIREWALLGROUP_DETAIL_PATH = \
'horizon:project:firewalls_v2:firewallgroupdetails'
UPDATERULE_PATH = 'horizon:project:firewalls_v2:updaterule'
UPDATEPOLICY_PATH = 'horizon:project:firewalls_v2:updatepolicy'
UPDATEFIREWALLGROUP_PATH = 'horizon:project:firewalls_v2:updatefirewall'
INSERTRULE_PATH = 'horizon:project:firewalls_v2:insertrule'
REMOVERULE_PATH = 'horizon:project:firewalls_v2:removerule'
ADDPORT_PATH = 'horizon:project:firewalls_v2:addport'
REMOVEPORT_PATH = 'horizon:project:firewalls_v2:removeport'
def setup_mocks(self):
firewallgroups = self.firewall_groups_v2.list()
self.mock_firewall_group_list_for_tenant.return_value = firewallgroups
policies = self.fw_policies_v2.list()
self.mock_policy_list_for_tenant.return_value = policies
self.mock_rule_list_for_tenant.return_value = self.fw_rules_v2.list()
def check_mocks(self):
tenant_id = self.tenant.id
self.mock_firewall_group_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
# TODO(amotoki): get_firewallgroupstable_data() also calls
# policy_list_for_tenant(). This needs to be clean up.
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_policy_list_for_tenant, 2,
mock.call(helpers.IsHttpRequest(), tenant_id))
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
def setup_mocks_with_exception(self):
self.mock_rule_list_for_tenant.side_effect = self.exceptions.neutron
self.mock_policy_list_for_tenant.side_effect = self.exceptions.neutron
self.mock_firewall_group_list_for_tenant.side_effect = \
self.exceptions.neutron
def check_mocks_with_exception(self):
tenant_id = self.tenant.id
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_firewall_group_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant',)})
def test_index_firewallgroups(self):
self.setup_mocks()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL, tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data),
len(self.firewall_groups_v2.list()))
self.check_mocks()
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant',)})
def test_index_policies(self):
self.setup_mocks()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__policies',
tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['policiestable_table'].data),
len(self.fw_policies_v2.list()))
self.check_mocks()
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant',)})
def test_index_rules(self):
self.setup_mocks()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__rules',
tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['rulestable_table'].data),
len(self.fw_rules_v2.list()))
self.check_mocks()
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant')})
def test_index_exception_firewallgroups(self):
self.setup_mocks_with_exception()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL, tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data), 0)
self.check_mocks_with_exception()
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant')})
def test_index_exception_policies(self):
self.setup_mocks_with_exception()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__policies',
tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res,
'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['policiestable_table'].data), 0)
self.check_mocks_with_exception()
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'rule_list_for_tenant')})
def test_index_exception_rules(self):
self.setup_mocks_with_exception()
tenant_id = self.tenant.id
res = self.client.get(self.INDEX_URL + '?tab=fwtabs__rules',
tenant_id=tenant_id)
self.assertTemplateUsed(res, 'project/firewalls_v2/details_tabs.html')
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['rulestable_table'].data), 0)
self.check_mocks_with_exception()
@helpers.create_mocks({api_fwaas_v2: ('rule_create',), })
def test_add_rule_post(self):
rule1 = self.fw_rules_v2.first()
form_data = {'name': rule1.name,
'description': rule1.description,
'protocol': rule1.protocol,
'action': rule1.action,
'source_ip_address': rule1.source_ip_address,
'source_port': rule1.source_port,
'destination_ip_address': rule1.destination_ip_address,
'destination_port': rule1.destination_port,
'shared': rule1.shared,
'enabled': rule1.enabled,
'ip_version': rule1.ip_version
}
self.mock_rule_create.return_value = rule1
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_rule_create.assert_called_once_with(
helpers.IsHttpRequest(), **form_data)
@helpers.create_mocks({api_fwaas_v2: ('rule_create',), })
def test_add_rule_post_src_None(self):
rule1 = self.fw_rules_v2.first()
form_data = {'name': rule1.name,
'description': rule1.description,
'protocol': rule1.protocol,
'action': rule1.action,
'source_ip_address': '',
'destination_ip_address': rule1.destination_ip_address,
'source_port': '',
'destination_port': rule1.destination_port,
'shared': rule1.shared,
'enabled': rule1.enabled,
'ip_version': rule1.ip_version
}
self.mock_rule_create.return_value = rule1
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
data = form_data.copy()
data['source_ip_address'] = None
data['source_port'] = None
self.mock_rule_create.assert_called_once_with(
helpers.IsHttpRequest(), **data)
@helpers.create_mocks({api_fwaas_v2: ('rule_create',), })
def test_add_rule_post_dest_None(self):
rule1 = self.fw_rules_v2.first()
form_data = {'name': rule1.name,
'description': rule1.description,
'protocol': rule1.protocol,
'action': rule1.action,
'source_ip_address': rule1.source_ip_address,
'destination_ip_address': '',
'source_port': rule1.source_port,
'destination_port': '',
'shared': rule1.shared,
'enabled': rule1.enabled,
'ip_version': rule1.ip_version
}
self.mock_rule_create.return_value = rule1
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
data = form_data.copy()
data['destination_ip_address'] = None
data['destination_port'] = None
self.mock_rule_create.assert_called_once_with(
helpers.IsHttpRequest(), **data)
def test_add_rule_post_with_error(self):
rule1 = self.fw_rules_v2.first()
form_data = {'name': rule1.name,
'description': rule1.description,
'protocol': 'abc',
'action': 'pass',
'source_ip_address': rule1.source_ip_address,
'source_port': rule1.source_port,
'destination_ip_address': rule1.destination_ip_address,
'destination_port': rule1.destination_port,
'shared': rule1.shared,
'enabled': rule1.enabled,
'ip_version': 6
}
res = self.client.post(reverse(self.ADDRULE_PATH), form_data)
self.assertFormErrors(res, 3)
@helpers.create_mocks({api_fwaas_v2: ('policy_create',
'rule_list_for_tenant'), })
def test_add_policy_post(self):
policy = self.fw_policies_v2.first()
rules = self.fw_rules_v2.list()
tenant_id = self.tenant.id
form_data = {'name': policy.name,
'description': policy.description,
'firewall_rules': policy.firewall_rules,
'shared': policy.shared,
'audited': policy.audited
}
post_data = {'name': policy.name,
'description': policy.description,
'rule': policy.firewall_rules,
'shared': policy.shared,
'audited': policy.audited
}
# NOTE: SelectRulesAction.populate_rule_choices() lists rule not
# associated with any policy. We need to ensure that rules specified
# in policy.firewall_rules in post_data (above) are not associated
# with any policy. Test data in neutron_data is data in a stable state,
# so we need to modify here.
for rule in rules:
if rule.id in policy.firewall_rules:
rule.firewall_policy_id = rule.policy = None
self.mock_rule_list_for_tenant.return_value = rules
self.mock_policy_create.return_value = policy
res = self.client.post(reverse(self.ADDPOLICY_PATH), post_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_policy_create.assert_called_once_with(
helpers.IsHttpRequest(), **form_data)
@helpers.create_mocks({api_fwaas_v2: ('rule_list_for_tenant',)})
def test_add_policy_post_with_error(self):
policy = self.fw_policies_v2.first()
rules = self.fw_rules_v2.list()
tenant_id = self.tenant.id
form_data = {'description': policy.description,
'firewall_rules': '',
'shared': policy.shared,
'audited': policy.audited
}
self.mock_rule_list_for_tenant.return_value = rules
res = self.client.post(reverse(self.ADDPOLICY_PATH), form_data)
self.assertFormErrors(res, 1)
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_create',
'policy_list_for_tenant',
'fwg_port_list_for_tenant',)})
def test_add_firewall_group_post(self):
fwg = self.firewall_groups_v2.first()
policies = self.fw_policies_v2.list()
tenant_id = self.tenant.id
form_data = {
'name': fwg.name,
'description': fwg.description,
'ingress_firewall_policy_id': fwg.ingress_firewall_policy_id,
'egress_firewall_policy_id': fwg.egress_firewall_policy_id,
'admin_state_up': fwg.admin_state_up,
'shared': False,
'port': [],
}
self.mock_policy_list_for_tenant.return_value = policies
self.mock_fwg_port_list_for_tenant.return_value = []
self.mock_firewall_group_create.return_value = fwg
res = self.client.post(reverse(self.ADDFIREWALLGROUP_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_fwg_port_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
data = form_data.copy()
data['ports'] = data.pop('port')
self.mock_firewall_group_create.assert_called_once_with(
helpers.IsHttpRequest(), **data)
# TODO(SarathMekala) : Fix this test.
# @helpers.create_mocks({api_fwaas_v2: ('firewall_group_create',
# 'policy_list_for_tenant',
# 'fwg_port_list_for_tenant',)})
# def test_add_firewall_post_with_error(self):
# firewall_groups = self.firewall_groups_v2.first()
# policies = self.fw_policies_v2.list()
# tenant_id = self.tenant.id
# form_data = {'name': firewall_groups.name,
# 'description': firewall_groups.description,
# 'admin_state_up': False
# }
# self.mock_policy_list_for_tenant(
# helpers.IsHttpRequest(), tenant_id).AndReturn(policies)
#
# self.mox.ReplayAll()
# res = self.client.post(reverse(self.ADDFIREWALLGROUP_PATH), form_data)
#
# self.assertFormErrors(res, 1)
@helpers.create_mocks({api_fwaas_v2: ('rule_get',)})
def test_update_rule_get(self):
rule = self.fw_rules_v2.first()
self.mock_rule_get.return_value = rule
res = self.client.get(reverse(self.UPDATERULE_PATH, args=(rule.id,)))
self.assertTemplateUsed(res, 'project/firewalls_v2/updaterule.html')
self.mock_rule_get.assert_called_once_with(helpers.IsHttpRequest(),
rule.id)
@helpers.create_mocks({api_fwaas_v2: ('rule_get', 'rule_update')})
def test_update_rule_post(self):
rule = self.fw_rules_v2.first()
self.mock_rule_get.return_value = rule
self.mock_rule_update.return_value = rule
data = {
'name': 'new name',
'description': 'new desc',
'protocol': 'icmp',
'action': 'allow',
'shared': False,
'enabled': True,
'ip_version': rule.ip_version,
'source_ip_address': rule.source_ip_address,
'destination_ip_address': None,
'source_port': None,
'destination_port': rule.destination_port,
}
expected_put_data = {
'name': 'new name',
'description': 'new desc',
'protocol': 'icmp',
'action': 'allow',
'shared': False,
'destination_ip_address': None,
'source_port': None,
}
form_data = data.copy()
form_data['destination_ip_address'] = ''
form_data['source_port'] = ''
res = self.client.post(
reverse(self.UPDATERULE_PATH, args=(rule.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_rule_get.assert_called_once_with(helpers.IsHttpRequest(),
rule.id)
self.mock_rule_update.assert_called_once_with(
helpers.IsHttpRequest(), rule.id, **expected_put_data)
@helpers.create_mocks({api_fwaas_v2: ('rule_get', 'rule_update')})
def test_update_protocol_any_rule_post(self):
# protocol any means protocol == None in neutron context.
rule = self.fw_rules_v2.get(protocol=None)
self.mock_rule_get.return_value = rule
self.mock_rule_update.return_value = rule
data = {
'name': 'new name',
'description': 'new desc',
'protocol': 'icmp',
'action': 'allow',
'shared': False,
'enabled': True,
'ip_version': rule.ip_version,
'source_ip_address': rule.source_ip_address,
'destination_ip_address': None,
'source_port': None,
'destination_port': rule.destination_port,
}
expected_put_data = {
'name': 'new name',
'description': 'new desc',
'protocol': 'icmp',
'action': 'allow',
'shared': False,
'destination_ip_address': None,
'source_port': None,
}
form_data = data.copy()
form_data['destination_ip_address'] = ''
form_data['source_port'] = ''
res = self.client.post(
reverse(self.UPDATERULE_PATH, args=(rule.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_rule_get.assert_called_once_with(helpers.IsHttpRequest(),
rule.id)
self.mock_rule_update.assert_called_once_with(
helpers.IsHttpRequest(), rule.id, **expected_put_data)
@helpers.create_mocks({api_fwaas_v2: ('rule_get', 'rule_update')})
def test_update_rule_protocol_to_ANY_post(self):
rule = self.fw_rules_v2.first()
self.mock_rule_get.return_value = rule
self.mock_rule_update.return_value = rule
form_data = {
'name': 'new name',
'description': 'new desc',
'protocol': 'any',
'action': 'allow',
'shared': False,
'enabled': True,
'ip_version': rule.ip_version,
'source_ip_address': rule.source_ip_address,
'destination_ip_address': '',
'source_port': '',
'destination_port': rule.destination_port,
}
expected_put_data = {
'name': 'new name',
'description': 'new desc',
'protocol': None,
'action': 'allow',
'shared': False,
'destination_ip_address': None,
'source_port': None,
}
res = self.client.post(
reverse(self.UPDATERULE_PATH, args=(rule.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_rule_get.assert_called_once_with(helpers.IsHttpRequest(),
rule.id)
self.mock_rule_update.assert_called_once_with(
helpers.IsHttpRequest(), rule.id, **expected_put_data)
@helpers.create_mocks({api_fwaas_v2: ('policy_get',)})
def test_update_policy_get(self):
policy = self.fw_policies_v2.first()
self.mock_policy_get.return_value = policy
res = self.client.get(
reverse(self.UPDATEPOLICY_PATH, args=(policy.id,)))
self.assertTemplateUsed(res, 'project/firewalls_v2/updatepolicy.html')
self.mock_policy_get.assert_called_once_with(helpers.IsHttpRequest(),
policy.id)
@helpers.create_mocks({api_fwaas_v2: ('policy_get', 'policy_update')})
def test_update_policy_post(self):
policy = self.fw_policies_v2.first()
self.mock_policy_get.return_value = policy
self.mock_policy_update.return_value = policy
data = {
'name': 'new name',
'description': 'new desc',
'shared': True,
'audited': False
}
expected_put_data = {
'name': 'new name',
'description': 'new desc',
'audited': False,
}
res = self.client.post(
reverse(self.UPDATEPOLICY_PATH, args=(policy.id,)), data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_policy_get.assert_called_once_with(helpers.IsHttpRequest(),
policy.id)
self.mock_policy_update.assert_called_once_with(
helpers.IsHttpRequest(), policy.id, **expected_put_data)
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_get',
'policy_list_for_tenant')})
def test_update_firewall_group_get(self):
firewall_group = self.firewall_groups_v2.first()
policies = self.fw_policies_v2.list()
tenant_id = self.tenant.id
self.mock_policy_list_for_tenant.return_value = policies
self.mock_firewall_group_get.return_value = firewall_group
res = self.client.get(
reverse(self.UPDATEFIREWALLGROUP_PATH, args=(firewall_group.id,)))
self.assertTemplateUsed(res,
'project/firewalls_v2/updatefirewall.html')
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_firewall_group_get.assert_called_once_with(
helpers.IsHttpRequest(), firewall_group.id)
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_get',
'policy_list_for_tenant',
'firewall_group_update')})
def test_update_firewall_post(self):
fwg = self.firewall_groups_v2.first()
tenant_id = self.tenant.id
policies = self.fw_policies_v2.list()
data = {
'name': 'new name',
'description': 'new desc',
'ingress_firewall_policy_id': fwg.ingress_firewall_policy_id,
'egress_firewall_policy_id': '',
'admin_state_up': False,
'shared': False,
}
expected_put_data = {
'name': 'new name',
'description': 'new desc',
'egress_firewall_policy_id': None,
'admin_state_up': False,
}
self.mock_firewall_group_get.return_value = fwg
self.mock_policy_list_for_tenant.return_value = policies
self.mock_firewall_group_update.return_value = fwg
res = self.client.post(
reverse(
self.UPDATEFIREWALLGROUP_PATH,
args=(
fwg.id,
)),
data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_firewall_group_get.assert_called_once_with(
helpers.IsHttpRequest(), fwg.id)
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_firewall_group_update.assert_called_once_with(
helpers.IsHttpRequest(), fwg.id, **expected_put_data)
@helpers.create_mocks({api_fwaas_v2: ('policy_get', 'policy_insert_rule',
'rule_list_for_tenant', 'rule_get')})
def test_policy_insert_rule(self):
policy = self.fw_policies_v2.first()
tenant_id = self.tenant.id
rules = self.fw_rules_v2.list()
new_rule_id = rules[2].id
data = {'firewall_rule_id': new_rule_id,
'insert_before': rules[1].id,
'insert_after': rules[0].id}
self.mock_policy_get.return_value = policy
policy.firewall_rules = [rules[0].id,
new_rule_id,
rules[1].id]
self.mock_rule_list_for_tenant.return_value = rules
self.mock_rule_get.return_value = rules[2]
self.mock_policy_insert_rule.return_value = policy
res = self.client.post(
reverse(self.INSERTRULE_PATH, args=(policy.id,)), data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_policy_get.assert_called_once_with(helpers.IsHttpRequest(),
policy.id)
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_rule_get.assert_called_once_with(
helpers.IsHttpRequest(), new_rule_id)
self.mock_policy_insert_rule.assert_called_once_with(
helpers.IsHttpRequest(), policy.id, **data)
@helpers.create_mocks({api_fwaas_v2: ('policy_get', 'policy_remove_rule',
'rule_list_for_tenant', 'rule_get')})
def test_policy_remove_rule(self):
policy = self.fw_policies_v2.first()
tenant_id = self.tenant.id
rules = self.fw_rules_v2.list()
remove_rule_id = policy.firewall_rules[0]
left_rule_id = policy.firewall_rules[1]
data = {'firewall_rule_id': remove_rule_id}
after_remove_policy_dict = {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'tenant_id': '1',
'name': 'policy1',
'description': 'policy description',
'firewall_rules': [left_rule_id],
'audited': True,
'shared': True}
after_remove_policy = api_fwaas_v2.Policy(after_remove_policy_dict)
self.mock_policy_get.return_value = policy
self.mock_rule_list_for_tenant.return_value = rules
self.mock_rule_get.return_value = rules[0]
self.mock_policy_remove_rule.return_value = after_remove_policy
res = self.client.post(
reverse(self.REMOVERULE_PATH, args=(policy.id,)), data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
self.mock_policy_get.assert_called_once_with(helpers.IsHttpRequest(),
policy.id)
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), tenant_id)
self.mock_rule_get.assert_called_once_with(
helpers.IsHttpRequest(), remove_rule_id)
self.mock_policy_remove_rule.assert_called_once_with(
helpers.IsHttpRequest(), policy.id, **data)
@helpers.create_mocks({api_fwaas_v2: ('rule_list_for_tenant',
'rule_delete')})
def test_delete_rule(self):
rule = self.fw_rules_v2.list()[2]
self.mock_rule_list_for_tenant.return_value = self.fw_rules_v2.list()
self.mock_rule_delete.return_value = None
form_data = {"action": "rulestable__deleterule__%s" % rule.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
self.mock_rule_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), self.tenant.id)
self.mock_rule_delete.assert_called_once_with(
helpers.IsHttpRequest(), rule.id)
@helpers.create_mocks({api_fwaas_v2: ('policy_list_for_tenant',
'policy_delete')})
def test_delete_policy(self):
policy = self.fw_policies_v2.first()
self.mock_policy_list_for_tenant.return_value = \
self.fw_policies_v2.list()
self.mock_policy_delete.return_value = None
form_data = {"action": "policiestable__deletepolicy__%s" % policy.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), self.tenant.id)
self.mock_policy_delete.assert_called_once_with(
helpers.IsHttpRequest(), policy.id)
@helpers.create_mocks({api_fwaas_v2: ('firewall_group_list_for_tenant',
'policy_list_for_tenant',
'firewall_group_delete',)})
def test_delete_firewall_group(self):
fwl = self.firewall_groups_v2.first()
self.mock_firewall_group_list_for_tenant.return_value = [fwl]
self.mock_policy_list_for_tenant.return_value = \
self.fw_policies_v2.list()
self.mock_firewall_group_delete.return_value = None
form_data = {
"action": "FirewallGroupsTable__deletefirewallgroup__%s" %
fwl.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
self.mock_firewall_group_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), self.tenant.id)
self.mock_policy_list_for_tenant.assert_called_once_with(
helpers.IsHttpRequest(), self.tenant.id)
self.mock_firewall_group_delete.assert_called_once_with(
helpers.IsHttpRequest(), fwl.id)

View File

@ -0,0 +1,53 @@
# Copyright 2017, Juniper Networks, 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 django.conf.urls import url
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 import views
# TODO(Sarath Mekala) : Fix 'firewall' --> 'firewallgroup' in URLs as
# well as in other places.
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^\?tab=fwtabs__firewalls$',
views.IndexView.as_view(), name='firewalls'),
url(r'^\?tab=fwtabs__rules$', views.IndexView.as_view(), name='rules'),
url(r'^\?tab=fwtabs__policies$',
views.IndexView.as_view(), name='policies'),
url(r'^addrule$', views.AddRuleView.as_view(), name='addrule'),
url(r'^addpolicy$', views.AddPolicyView.as_view(), name='addpolicy'),
url(r'^addfirewallgroup$',
views.AddFirewallGroupView.as_view(),
name='addfirewallgroup'),
url(r'^insertrule/(?P<policy_id>[^/]+)/$',
views.InsertRuleToPolicyView.as_view(), name='insertrule'),
url(r'^removerule/(?P<policy_id>[^/]+)/$',
views.RemoveRuleFromPolicyView.as_view(), name='removerule'),
url(r'^updaterule/(?P<rule_id>[^/]+)/$',
views.UpdateRuleView.as_view(), name='updaterule'),
url(r'^updatepolicy/(?P<policy_id>[^/]+)/$',
views.UpdatePolicyView.as_view(), name='updatepolicy'),
url(r'^updatefirewall/(?P<firewall_id>[^/]+)/$',
views.UpdateFirewallView.as_view(), name='updatefirewall'),
url(r'^addport/(?P<firewallgroup_id>[^/]+)/$',
views.AddPortView.as_view(), name='addport'),
url(r'^removeport/(?P<firewallgroup_id>[^/]+)/$',
views.RemovePortView.as_view(), name='removeport'),
url(r'^rule/(?P<rule_id>[^/]+)/$',
views.RuleDetailsView.as_view(), name='ruledetails'),
url(r'^policy/(?P<policy_id>[^/]+)/$',
views.PolicyDetailsView.as_view(), name='policydetails'),
url(r'^firewallgroup/(?P<firewallgroup_id>[^/]+)/$',
views.FirewallGroupDetailsView.as_view(), name='firewallgroupdetails'),
]

View File

@ -0,0 +1,444 @@
# Copyright 2017, Juniper Networks, 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 django.urls import reverse
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import tabs
from horizon.utils import memoized
from horizon import workflows
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 \
import forms as fw_forms
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 \
import tabs as fw_tabs
from neutron_fwaas_dashboard.dashboards.project.firewalls_v2 \
import workflows as fw_workflows
InsertRuleToPolicy = fw_forms.InsertRuleToPolicy
RemoveRuleFromPolicy = fw_forms.RemoveRuleFromPolicy
UpdateFirewall = fw_forms.UpdateFirewall
UpdatePolicy = fw_forms.UpdatePolicy
UpdateRule = fw_forms.UpdateRule
AddPort = fw_forms.AddPort
RemovePort = fw_forms.RemovePort
FirewallGroupDetailsTabs = fw_tabs.FirewallGroupDetailsTabs
FirewallGroupTabs = fw_tabs.FirewallGroupTabs
PolicyDetailsTabs = fw_tabs.PolicyDetailsTabs
RuleDetailsTabs = fw_tabs.RuleDetailsTabs
AddFirewallGroup = fw_workflows.AddFirewallGroup
AddPolicy = fw_workflows.AddPolicy
AddRule = fw_workflows.AddRule
class IndexView(tabs.TabbedTableView):
tab_group_class = FirewallGroupTabs
template_name = 'project/firewalls_v2/details_tabs.html'
page_title = _("Firewall Groups")
class AddRuleView(workflows.WorkflowView):
workflow_class = AddRule
template_name = "project/firewalls_v2/addrule.html"
page_title = _("Add New Rule")
class AddPolicyView(workflows.WorkflowView):
workflow_class = AddPolicy
template_name = "project/firewalls_v2/addpolicy.html"
page_title = _("Add New Policy")
class AddFirewallGroupView(workflows.WorkflowView):
workflow_class = AddFirewallGroup
template_name = "project/firewalls_v2/addfirewallgroup.html"
page_title = _("Add New Firewall Group")
class RuleDetailsView(tabs.TabView):
tab_group_class = (RuleDetailsTabs)
template_name = 'horizon/common/_detail.html'
page_title = "{{ rule.name|default:rule.id }}"
failure_url = reverse_lazy('horizon:project:firewalls_v2:index')
def get_context_data(self, **kwargs):
context = super(RuleDetailsView, self).get_context_data(**kwargs)
rule = self.get_data()
table = fw_tabs.RulesTable(self.request)
breadcrumb = [
(_("Rules"), reverse_lazy('horizon:project:firewalls_v2:rules'))]
context["custom_breadcrumb"] = breadcrumb
context["rule"] = rule
context["url"] = self.failure_url
context["actions"] = table.render_row_actions(rule)
return context
@memoized.memoized_method
def get_data(self):
try:
rule_id = self.kwargs['rule_id']
rule = api_fwaas_v2.rule_get(self.request, rule_id)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve rule details.'),
redirect=self.failure_url)
return rule
def get_tabs(self, request, *args, **kwargs):
rule = self.get_data()
return self.tab_group_class(request, rule=rule, **kwargs)
class PolicyDetailsView(tabs.TabView):
tab_group_class = (PolicyDetailsTabs)
template_name = 'horizon/common/_detail.html'
page_title = "{{ policy.name|default:policy.id }}"
failure_url = reverse_lazy('horizon:project:firewalls_v2:index')
def get_context_data(self, **kwargs):
context = super(PolicyDetailsView, self).get_context_data(**kwargs)
policy = self.get_data()
table = fw_tabs.PoliciesTable(self.request)
breadcrumb = [
(_("Policies"),
reverse_lazy('horizon:project:firewalls_v2:policies'))]
context["custom_breadcrumb"] = breadcrumb
context["policy"] = policy
context["url"] = self.failure_url
context["actions"] = table.render_row_actions(policy)
return context
@memoized.memoized_method
def get_data(self):
try:
policy_id = self.kwargs['policy_id']
policy = api_fwaas_v2.policy_get(self.request, policy_id)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve policy details.'),
redirect=self.failure_url)
return policy
def get_tabs(self, request, *args, **kwargs):
policy = self.get_data()
return self.tab_group_class(request, policy=policy, **kwargs)
class FirewallGroupDetailsView(tabs.TabView):
tab_group_class = (FirewallGroupDetailsTabs)
template_name = 'horizon/common/_detail.html'
page_title = "{{ firewall_group.name|default:firewall_group.id }}"
failure_url = reverse_lazy('horizon:project:firewalls_v2:index')
def get_context_data(self, **kwargs):
context = super(FirewallGroupDetailsView, self) \
.get_context_data(**kwargs)
firewall_group = self.get_data()
table = fw_tabs.FirewallGroupsTable(self.request)
context["firewall_group"] = firewall_group
context["url"] = self.failure_url
context["actions"] = table.render_row_actions(firewall_group)
return context
@memoized.memoized_method
def get_data(self):
try:
firewallgroup_id = self.kwargs['firewallgroup_id']
firewall_group = api_fwaas_v2.firewall_group_get(self.request,
firewallgroup_id)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve firewall group details.'),
redirect=self.failure_url)
return firewall_group
def get_tabs(self, request, *args, **kwargs):
firewall_group = self.get_data()
return self.tab_group_class(request, firewallgroup=firewall_group,
**kwargs)
class UpdateRuleView(forms.ModalFormView):
form_class = UpdateRule
form_id = "update_rule_form"
template_name = "project/firewalls_v2/updaterule.html"
context_object_name = 'rule'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:updaterule"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Edit Rule {{ name }}")
def get_context_data(self, **kwargs):
context = super(UpdateRuleView, self).get_context_data(**kwargs)
context['rule_id'] = self.kwargs['rule_id']
args = (self.kwargs['rule_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name_or_id
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
rule_id = self.kwargs['rule_id']
try:
rule = api_fwaas_v2.rule_get(self.request, rule_id)
return rule
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve rule details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
rule = self._get_object()
initial = rule.to_dict()
protocol = initial['protocol']
initial['protocol'] = protocol.upper() if protocol else 'ANY'
initial['action'] = initial['action'].upper()
return initial
class UpdatePolicyView(forms.ModalFormView):
form_class = UpdatePolicy
form_id = "update_policy_form"
template_name = "project/firewalls_v2/updatepolicy.html"
context_object_name = 'policy'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:updatepolicy"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Edit Policy {{ name }}")
def get_context_data(self, **kwargs):
context = super(UpdatePolicyView, self).get_context_data(**kwargs)
context["policy_id"] = self.kwargs['policy_id']
args = (self.kwargs['policy_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name_or_id
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
policy_id = self.kwargs['policy_id']
try:
policy = api_fwaas_v2.policy_get(self.request, policy_id)
return policy
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve policy details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
policy = self._get_object()
initial = policy.to_dict()
return initial
class UpdateFirewallView(forms.ModalFormView):
form_class = UpdateFirewall
form_id = "update_firewall_form"
template_name = "project/firewalls_v2/updatefirewall.html"
context_object_name = 'firewall'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:updatefirewall"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Edit FirewallGroup {{ name }}")
def get_context_data(self, **kwargs):
context = super(UpdateFirewallView, self).get_context_data(**kwargs)
context["firewall_id"] = self.kwargs['firewall_id']
args = (self.kwargs['firewall_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
fwg_id = self.kwargs['firewall_id']
try:
fwg = api_fwaas_v2.firewall_group_get(self.request, fwg_id)
return fwg
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve firewall group details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
fwg = self._get_object()
initial = fwg.to_dict()
return initial
class AddPortView(forms.ModalFormView):
form_class = AddPort
form_id = "update_firewall_port_form"
template_name = "project/firewalls_v2/addport.html"
context_object_name = 'firewallgroup'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:addport"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Add port to Firewall Group {{ name }}")
def get_context_data(self, **kwargs):
context = super(AddPortView, self).get_context_data(**kwargs)
context["firewallgroup_id"] = self.kwargs['firewallgroup_id']
args = (self.kwargs['firewallgroup_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
firewallgroup_id = self.kwargs['firewallgroup_id']
try:
firewallgroup = api_fwaas_v2.firewall_group_get(self.request,
firewallgroup_id)
return firewallgroup
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve firewallgroup details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
firewallgroup = self._get_object()
initial = firewallgroup.to_dict()
return initial
class RemovePortView(forms.ModalFormView):
form_class = RemovePort
form_id = "update_firewall_port_form"
template_name = "project/firewalls_v2/removeport.html"
context_object_name = 'firewallgroup'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:removeport"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Remove port from FirewallGroup {{ name }}")
def get_context_data(self, **kwargs):
context = super(RemovePortView, self).get_context_data(**kwargs)
context["firewallgroup_id"] = self.kwargs['firewallgroup_id']
args = (self.kwargs['firewallgroup_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
firewallgroup_id = self.kwargs['firewallgroup_id']
try:
firewallgroup = api_fwaas_v2.firewall_group_get(self.request,
firewallgroup_id)
return firewallgroup
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve firewall group details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
firewallgroup = self._get_object()
initial = firewallgroup.to_dict()
return initial
class InsertRuleToPolicyView(forms.ModalFormView):
form_class = InsertRuleToPolicy
form_id = "update_policy_form"
template_name = "project/firewalls_v2/insert_rule_to_policy.html"
context_object_name = 'policy'
submit_url = "horizon:project:firewalls_v2:insertrule"
submit_label = _("Save Changes")
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Insert Rule to Policy")
def get_context_data(self, **kwargs):
context = super(InsertRuleToPolicyView,
self).get_context_data(**kwargs)
context["policy_id"] = self.kwargs['policy_id']
args = (self.kwargs['policy_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name_or_id
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
policy_id = self.kwargs['policy_id']
try:
policy = api_fwaas_v2.policy_get(self.request, policy_id)
return policy
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve policy details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
policy = self._get_object()
initial = policy.to_dict()
initial['policy_id'] = initial['id']
return initial
class RemoveRuleFromPolicyView(forms.ModalFormView):
form_class = RemoveRuleFromPolicy
form_id = "update_policy_form"
template_name = "project/firewalls_v2/remove_rule_from_policy.html"
context_object_name = 'policy'
submit_label = _("Save Changes")
submit_url = "horizon:project:firewalls_v2:removerule"
success_url = reverse_lazy("horizon:project:firewalls_v2:index")
page_title = _("Remove Rule from Policy")
def get_context_data(self, **kwargs):
context = super(RemoveRuleFromPolicyView,
self).get_context_data(**kwargs)
context["policy_id"] = self.kwargs['policy_id']
args = (self.kwargs['policy_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
obj = self._get_object()
if obj:
context['name'] = obj.name_or_id
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
policy_id = self.kwargs['policy_id']
try:
policy = api_fwaas_v2.policy_get(self.request, policy_id)
return policy
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve policy details.')
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
policy = self._get_object()
initial = policy.to_dict()
initial['policy_id'] = initial['id']
return initial

View File

@ -0,0 +1,260 @@
# 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 django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _
from horizon.forms import fields
"""A custom Horizon Forms Select widget that displays select choices as a table
The widgets is meant as an optional replacement for the existing Horizon
ThemableDynamicSelectWidget which it extends and is compatible with.
Columns
-------
Columns are defined by setting the widgets 'column' attribute, which is
expected to be an iterable of strings, each one corresponding to one column and
used for that columns heading.
Rows
----
Each row corresponds to one choice/select option with a defined value in
each column.
The values displayed in each column are derived using the 'build_columns'
attribute, which is expected to be a function that:
- takes a choice tuple of the form (value, label) as defined
for the Django SelectField instances as it's only parameter
- returns an iterable of Strings which are rendered as column
values for the given choice row in the same order as in the
iterable
The default implementation simply uses the provided value and label as separate
column values.
See the default implementation and example bellow for more details.
Condensed values
----------------
To maintain visual consistency, the currently selected value is displayed in
the 'standard' ThemableDynamicSelectWidget HTML setup. To accommodate this, a
condensed, single string value is created from the individual columns and
displayed in the select box.
This behavior can be modified by setting the 'condense' attribute. This is
expected to be a function that:
- Takes the column iterable returned by 'build_columns' function
- Returns a single string representation of the choice
By default, the condensed value is created by joining all of the provided
columns and joining them using commas as a delimiter.
See the default implementation and example bellow for more details.
Small screen reactivity
-----------------------
Support for small screens (< 768px) is turned on by setting the attribute
'alternate_xs' to True. When on, a condesned version of the popup table
us used for small screens, where a single column is used with the condensed
row values used instead of the full table rows.
The 'condense' function described above is used to construct this table.
Example
-------
port_id = forms.ThemableDynamicChoiceField(
label=_("Ports"),
widget=TableSelectWidget(
columns=[
'ID',
'Name'
],
build_columns=lambda choice: return (choice[1], choice[0]),
choices=[
('port 1', 'id1'),
('port 2', 'id2')
],
alternate_xs=True,
condense=lambda columns: return ",".join(columns)
)
)
Produces:
+------+--------+
| ID | Name |
+------+--------+
| id1 | port 1 |
| id2 | port 2 |
+------+--------+
on normal screens and
+-------------+
| ID, Name |
+-------------+
| id1, port 1 |
| id2, port 2 |
+-------------+
on xs screens.
"""
class TableSelectWidget(fields.ThemableDynamicSelectWidget):
def __init__(self,
attrs=None,
columns=None,
alternate_xs=False,
empty_text=_("No options available"),
other_html=None,
condense=None,
build_columns=None, *args, **kwargs
):
"""Initializer for TableSelectWidget
:param attrs: A { attribute: value } dictionary which is attached to
the hidden select element; see
ThemableDynamicSelectWidget for further information
:param columns: An iterable of column headers/names
:param alternate_xs: A truth-y value which enables/disables an
alternate rendering method for small screens
:param empty_text: The text to be displayed in case no options are
available
:param other_html: A method for adding custom HTML to the hidden option
HTML.
NOTE: This mimics the behavior of
ThemableDynamicSelectWidget and is retained to
maintain compatibility with any related, potential
functionality
:param condense: A function callback that produces a condensed label
for each option
:param build_columns: A function used to populate the individual
columns in the pop up table for each option
"""
super(TableSelectWidget, self).__init__(attrs, *args, **kwargs)
self.columns = columns or [_('Label'), _('Value'), 'Nothing']
self.alternate_xs = alternate_xs
self.empty_text = empty_text
if other_html:
self.other_html = other_html
if condense:
self.condense = condense
if build_columns:
self.build_columns = build_columns
@staticmethod
def build_columns(choice):
"""Default column building method
Overwrite this method when initializing this widget or using
self.fields[name].widget.build_columns in a parent form initialization
to customize the behavior (see above for details)
:param choice:
:return:
"""
return choice
@staticmethod
def condense(choice_columns):
"""The default condense method
Overwrite this method when initializing this widget or using
self.fields[name].widget.condense in a parent form initialization to
customize the behavior (see above for details)
:param choice_columns:
:return:
"""
return " / ".join([str(c) for c in choice_columns])
# Implements the parent 'other_html' construction for compatibility reasons
# Can be set in initializer to change the behavior as needed
def other_html(self, choice):
opt_label = choice[1]
other_html = self.transform_option_html_attrs(opt_label)
data_attr_html = self.get_data_attrs(opt_label)
if data_attr_html:
other_html += ' ' + data_attr_html
return other_html
def render(self, name, value, attrs=None, choices=None, renderer=None):
new_choices = []
initial_value = value
choices = choices or []
for opt in itertools.chain(self.choices, choices):
other_html = self.other_html(opt)
choice_columns = self.build_columns(opt)
condensed_label = self.condense(choice_columns)
built_choice = (
opt[0], condensed_label, choice_columns, other_html
)
new_choices.append(built_choice)
# Initial selection
if opt[0] == value:
initial_value = built_choice
if not initial_value and new_choices:
initial_value = new_choices[0]
element_id = attrs.pop('id', 'id_%s' % name)
# Size of individual columns in terms of the bootstrap grid - used
# for styling purposes
column_size = 12 // len(self.columns)
# Creates a single string label for all columns for use with small
# screens
condensed_headers = self.condense(self.columns)
template = get_template('project/firewalls_v2/table_select.html')
select_attrs = self.build_attrs(attrs)
context = {
'name': name,
'options': new_choices,
'id': element_id,
'value': value,
'initial_value': initial_value,
'select_attrs': select_attrs,
'column_size': column_size,
'columns': self.columns,
'condensed_headers': condensed_headers,
'alternate_xs': self.alternate_xs,
'empty_text': self.empty_text
}
return template.render(context)

View File

@ -0,0 +1,388 @@
# Copyright 2017, Juniper Networks, 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 operator import attrgetter
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon.utils import validators
from horizon import workflows
import netaddr
from neutron_fwaas_dashboard.api import fwaas_v2 as api_fwaas_v2
port_validator = validators.validate_port_or_colon_separated_port_range
class AddRuleAction(workflows.Action):
name = forms.CharField(
max_length=80,
label=_("Name"),
required=False)
description = forms.CharField(
max_length=80,
label=_("Description"),
required=False)
protocol = forms.ThemableChoiceField(
label=_("Protocol"),
choices=[('tcp', _('TCP')),
('udp', _('UDP')),
('icmp', _('ICMP')),
('any', _('ANY'))],)
action = forms.ThemableChoiceField(
label=_("Action"),
choices=[('allow', _('ALLOW')),
('deny', _('DENY')),
('reject', _('REJECT'))],)
source_ip_address = forms.IPField(
label=_("Source IP Address/Subnet"),
version=forms.IPv4 | forms.IPv6,
required=False, mask=True)
destination_ip_address = forms.IPField(
label=_("Destination IP Address/Subnet"),
version=forms.IPv4 | forms.IPv6,
required=False, mask=True)
source_port = forms.CharField(
max_length=80,
label=_("Source Port/Port Range"),
required=False,
validators=[port_validator])
destination_port = forms.CharField(
max_length=80,
label=_("Destination Port/Port Range"),
required=False,
validators=[port_validator])
ip_version = forms.ThemableChoiceField(
label=_("IP Version"), required=False,
choices=[('4', '4'), ('6', '6')])
shared = forms.BooleanField(
label=_("Shared"), initial=False, required=False)
enabled = forms.BooleanField(
label=_("Enabled"), initial=True, required=False)
def _check_ip_addr_and_ip_version(self, cleaned_data):
ip_version = int(str(cleaned_data.get('ip_version')))
src_ip = cleaned_data.get('source_ip_address')
dst_ip = cleaned_data.get('destination_ip_address')
msg = _('Source/Destination Network Address and IP version '
'are inconsistent. Please make them consistent.')
if (src_ip and
netaddr.IPNetwork(src_ip).version != ip_version):
self._errors['ip_version'] = self.error_class([msg])
elif (dst_ip and
netaddr.IPNetwork(dst_ip).version != ip_version):
self._errors['ip_version'] = self.error_class([msg])
def clean(self):
cleaned_data = super(AddRuleAction, self).clean()
self._check_ip_addr_and_ip_version(cleaned_data)
class Meta(object):
name = _("Rule")
permissions = ('openstack.services.network',)
help_text = _("Create a firewall rule.\n\n"
"A Firewall rule is an association of the following "
"attributes:\n\n"
"<li>IP Addresses: The addresses from/to which the "
"traffic filtration needs to be applied.</li>"
"<li>IP Version: The type of IP packets (IP V4/V6) "
"that needs to be filtered.</li>"
"<li>Protocol: Type of packets (UDP, ICMP, TCP, Any) "
"that needs to be checked.</li>"
"<li>Action: Action is the type of filtration "
"required, it can be Reject/Deny/Allow data "
"packets.</li>\n"
"The protocol and action fields are required, all "
"others are optional.")
class AddRuleStep(workflows.Step):
action_class = AddRuleAction
contributes = ("name", "description", "protocol", "action",
"source_ip_address", "source_port",
"destination_ip_address", "destination_port",
"enabled", "shared", "ip_version")
def contribute(self, data, context):
context = super(AddRuleStep, self).contribute(data, context)
if data:
if context['protocol'] == 'any':
del context['protocol']
for field in ['source_port',
'destination_port',
'source_ip_address',
'destination_ip_address']:
if not context[field]:
del context[field]
return context
class AddRule(workflows.Workflow):
slug = "addrule"
name = _("Add Rule")
finalize_button_name = _("Add")
success_message = _('Added Rule "%s".')
failure_message = _('Unable to add Rule "%s".')
success_url = "horizon:project:firewalls_v2:index"
default_steps = (AddRuleStep,)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_fwaas_v2.rule_create(request, **context)
return True
except Exception as e:
msg = self.format_status_message(self.failure_message) + str(e)
exceptions.handle(request, msg)
return False
class SelectRulesAction(workflows.Action):
rule = forms.MultipleChoiceField(
label=_("Rules"),
required=False,
widget=forms.ThemableCheckboxSelectMultiple(),
help_text=_("Create a policy with selected rules."))
class Meta(object):
name = _("Rules")
permissions = ('openstack.services.network',)
help_text = _("Select rules for your policy.")
def populate_rule_choices(self, request, context):
try:
tenant_id = self.request.user.tenant_id
rules = api_fwaas_v2.rule_list_for_tenant(request, tenant_id)
rules = sorted(rules,
key=attrgetter('name_or_id'))
rule_list = [(rule.id, rule.name_or_id) for rule in rules]
except Exception as e:
rule_list = []
exceptions.handle(request, _('Unable to retrieve rules (%s).') % e)
return rule_list
class SelectRulesStep(workflows.Step):
action_class = SelectRulesAction
template_name = "project/firewalls_v2/_update_rules.html"
contributes = ("firewall_rules",)
def contribute(self, data, context):
if data:
rules = self.workflow.request.POST.getlist("rule")
if rules:
rules = [r for r in rules if r]
context['firewall_rules'] = rules
return context
class AddPolicyAction(workflows.Action):
name = forms.CharField(max_length=80,
label=_("Name"))
description = forms.CharField(max_length=80,
label=_("Description"),
required=False)
shared = forms.BooleanField(label=_("Shared"),
initial=False,
required=False)
audited = forms.BooleanField(label=_("Audited"),
initial=False,
required=False)
class Meta(object):
name = _("Policy")
permissions = ('openstack.services.network',)
help_text = _("Create a firewall policy with an ordered list "
"of firewall rules.\n\n"
"A firewall policy is an ordered collection of firewall "
"rules. So if the traffic matches the first rule, the "
"other rules are not executed. If the traffic does not "
"match the current rule, then the next rule is "
"executed. A firewall policy has the following "
"attributes:\n\n"
"<li>Shared: A firewall policy can be shared across "
"tenants. Thus it can also be made part of an audit "
"workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li>"
"<li>Audited: When audited is set to True, it indicates "
"that the firewall policy has been audited. "
"Each time the firewall policy or the associated "
"firewall rules are changed, this attribute will be "
"set to False and will have to be explicitly set to "
"True through an update operation.</li>\n"
"The name field is required, all others are optional.")
class AddPolicyStep(workflows.Step):
action_class = AddPolicyAction
contributes = ("name", "description", "shared", "audited")
def contribute(self, data, context):
context = super(AddPolicyStep, self).contribute(data, context)
if data:
return context
class AddPolicy(workflows.Workflow):
slug = "addpolicy"
name = _("Add Policy")
finalize_button_name = _("Add")
success_message = _('Added Policy "%s".')
failure_message = _('Unable to add Policy "%s".')
success_url = "horizon:project:firewalls_v2:index"
default_steps = (AddPolicyStep, SelectRulesStep)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_fwaas_v2.policy_create(request, **context)
return True
except Exception as e:
msg = self.format_status_message(self.failure_message) + str(e)
exceptions.handle(request, msg)
return False
class AddFWGPortsAction(workflows.Action):
port = forms.MultipleChoiceField(
label=_("Ports"),
required=False,
widget=forms.ThemableCheckboxSelectMultiple(),
help_text=_("Create a Firewall Group with selected ports."))
class Meta(object):
name = _("Ports")
permissions = ('openstack.services.network',)
help_text = _("Select ports for your firewall group.")
def populate_port_choices(self, request, context):
try:
tenant_id = self.request.user.tenant_id
ports = api_fwaas_v2.fwg_port_list_for_tenant(request, tenant_id)
ports = sorted(ports,
key=attrgetter('name_or_id'))
port_list = [(port.id, port.name_or_id) for port in ports]
except Exception as e:
port_list = []
exceptions.handle(request, _('Unable to retrieve ports (%s).') % e)
return port_list
class AddFWGPortsStep(workflows.Step):
action_class = AddFWGPortsAction
template_name = "project/firewalls_v2/_update_ports.html"
contributes = ("ports")
def contribute(self, data, context):
if data:
ports = self.workflow.request.POST.getlist("port")
if ports:
ports = [r for r in ports if r != '']
context['ports'] = ports
else:
context['ports'] = []
return context
class AddFirewallGroupAction(workflows.Action):
name = forms.CharField(max_length=80,
label=_("Name"),
required=False)
description = forms.CharField(max_length=80,
label=_("Description"),
required=False)
ingress_firewall_policy_id = forms.ThemableChoiceField(
label=_("Ingress Policy"),
required=False)
egress_firewall_policy_id = forms.ThemableChoiceField(
label=_("Egress Policy"),
required=False)
admin_state_up = forms.BooleanField(
label=_("Admin State"), initial=True, required=False)
shared = forms.BooleanField(
label=_("Shared"), initial=False, required=False)
def __init__(self, request, *args, **kwargs):
super(AddFirewallGroupAction, self).__init__(request, *args, **kwargs)
firewall_policy_id_choices = [('', _("Select a Policy"))]
try:
tenant_id = self.request.user.tenant_id
policies = api_fwaas_v2.policy_list_for_tenant(request, tenant_id)
policies = sorted(policies, key=attrgetter('name'))
except Exception as e:
exceptions.handle(request,
_('Unable to retrieve policy list (%s).') % e)
policies = []
for p in policies:
firewall_policy_id_choices.append((p.id, p.name_or_id))
self.fields['ingress_firewall_policy_id'].choices = \
firewall_policy_id_choices
self.fields['egress_firewall_policy_id'].choices = \
firewall_policy_id_choices
def clean(self):
cleaned_data = super(AddFirewallGroupAction, self).clean()
for field in ('ingress_firewall_policy_id',
'egress_firewall_policy_id'):
if not cleaned_data[field]:
cleaned_data[field] = None
return cleaned_data
class Meta(object):
name = _("FirewallGroup")
permissions = ('openstack.services.network',)
help_text = _("Create a firewall group based on a policy.\n\n"
"A firewall group represents a logical firewall "
"resource that a tenant can instantiate and manage. "
"A firewall group must be associated with one policy, "
"all other fields are optional.")
class AddFirewallGroupStep(workflows.Step):
action_class = AddFirewallGroupAction
contributes = ("name", "description", "admin_state_up", "shared",
"ingress_firewall_policy_id",
"egress_firewall_policy_id")
def contribute(self, data, context):
context = super(AddFirewallGroupStep, self).contribute(data, context)
return context
class AddFirewallGroup(workflows.Workflow):
slug = "addfirewallgroup"
name = _("Add Firewall Group")
finalize_button_name = _("Add")
success_message = _('Added Firewall Group"%s".')
failure_message = _('Unable to add Firewall Group "%s".')
success_url = "horizon:project:firewalls_v2:index"
default_steps = (AddFirewallGroupStep, AddFWGPortsStep)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_fwaas_v2.firewall_group_create(request, **context)
return True
except Exception as e:
msg = self.format_status_message(self.failure_message) + str(e)
exceptions.handle(request, msg)
return False

View File

@ -0,0 +1,20 @@
# 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.
# FEATURE just declares this enabled file needs to be loaded.
# This is required for ADD_INSTALLED_APPS to be processed.
# The value itself has no meaning in the current horizon.
FEATURE = 'neutron-fwaas-dashboard'
ADD_INSTALLED_APPS = ['neutron_fwaas_dashboard']
AUTO_DISCOVER_STATIC_FILES = True
ADD_SCSS_FILES = ['neutron_fwaas_dashboard/scss/firewalls.scss']

View File

@ -0,0 +1,22 @@
# 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.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'firewalls_v2'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'network'
# Python panel class of the PANEL to be added.
ADD_PANEL = ('neutron_fwaas_dashboard.dashboards.project.'
'firewalls_v2.panel.Firewall_V2')

View File

@ -0,0 +1,16 @@
# 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 django.conf import settings
settings.POLICY_FILES['neutron-fwaas'] = 'neutron-fwaas-policy.json'

View File

@ -0,0 +1,649 @@
# Frank Kloeker <eumel@arcor.de>, 2016. #zanata
# Robert Simai <robert.simai@suse.com>, 2016. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2017. #zanata
# Frank Kloeker <eumel@arcor.de>, 2017. #zanata
# Robert Simai <robert.simai@suse.com>, 2017. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2018. #zanata
# Frank Kloeker <eumel@arcor.de>, 2018. #zanata
# Reik Keutterling <spielkind@gmail.com>, 2018. #zanata
# Robert Simai <robert.simai@suse.com>, 2018. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2019. #zanata
# Robert Simai <robert.simai@suse.com>, 2019. #zanata
msgid ""
msgstr ""
"Project-Id-Version: neutron-fwaas-dashboard VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2019-04-25 13:36+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-05-03 02:14+0000\n"
"Last-Translator: Robert Simai <robert.simai@suse.com>\n"
"Language-Team: German\n"
"Language: de\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid "-"
msgstr "-"
msgid "ALLOW"
msgstr "Erlauben"
msgctxt "Action Name of a Firewall Rule"
msgid "ALLOW"
msgstr "Erlauben"
msgid "ANY"
msgstr "ALLE"
msgid "Action"
msgstr "Aktion"
msgid "Action for the firewall rule"
msgstr "Aktion für die Firewallregel"
msgctxt "Current status of a Firewall Group"
msgid "Active"
msgstr "Aktiv"
msgid "Add"
msgstr "Hinzufügen"
msgid "Add Firewall Group"
msgstr "Firewall-Gruppe hinzufügen"
msgid "Add New Firewall Group"
msgstr "Neue Firewall-Gruppe hinzufügen"
msgid "Add New Policy"
msgstr "Neue Richtlinie hinzufügen"
msgid "Add New Rule"
msgstr "Neue Regel hinzufügen"
msgid "Add Policy"
msgstr "Richtlinie hinzufügen"
msgid "Add Port"
msgstr "Port hinzufügen"
msgid "Add Port to Firewall Group"
msgstr "Port zur Firewallgruppe hinzufügen"
msgid "Add Rule"
msgstr "Regel hinzufügen"
msgid "Add port to Firewall Group {{ name }}"
msgstr "Port zur Firewallgruppe {{ name }} hinzufügen"
#, python-format
msgid "Added Firewall Group\"%s\"."
msgstr "Firewall-Gruppe \"%s\" hinzugefügt."
#, python-format
msgid "Added Policy \"%s\"."
msgstr "Richtlinie \"%s\" hinzugefügt."
#, python-format
msgid "Added Rule \"%s\"."
msgstr "Regel \"%s\" wurde hinzugefügt."
#, python-format
msgid "Added the port(s) to the firewall group %s successfully."
msgstr "Port(s) wurde(n) zur Firewall-Gruppe %s erfolgreich hinzugefügt."
msgid "Admin State"
msgstr "Adminstatus"
msgid "Admin State Up"
msgstr "Adminstatus aktiv"
msgid "After"
msgstr "Nachher"
msgid "Audited"
msgstr "Geprüft"
msgid "Available Ports"
msgstr "Verfügbare Ports"
msgid "Available Rules"
msgstr "Verfügbare Regeln"
msgid "Before"
msgstr "Vorher"
msgid "Choose port(s) from Available Ports. "
msgstr "Wählen Sie aus den verfügbaren Ports aus."
msgid ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgstr ""
"Wählen Sie aus den \"Verfügbaren Regeln\" Regel(n) aus, indem Sie den Knopf "
"drücken oder mit Ziehen und Ablegen. Sie können auch die Reihenfolge mit "
"Ziehen und Ablegen ändern."
msgid ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgstr ""
"Wählen Sie die Regel aus, die Sie einfügen wollen. Spezifizieren Sie "
"entweder die Regel unmittelbar vor der Sie einfügen wollen oder die Regel "
"unmittelbar nach der Sie einfügen wollen. Wenn beide angegeben werden, hat "
"die vorherige Vorrang. "
msgid "Choose the rule you want to remove."
msgstr "Zu entfernende Richtlinie auswählen."
msgid "Create Firewall Group"
msgstr "Firewall-Gruppe erstellen"
msgid "Create a Firewall Group with selected ports."
msgstr "Erstellen einer Firewall-Gruppe mit den ausgewählten Ports."
msgid ""
"Create a firewall group based on a policy.\n"
"\n"
"A firewall group represents a logical firewall resource that a tenant can "
"instantiate and manage. A firewall group must be associated with one policy, "
"all other fields are optional."
msgstr ""
"Erzeugen einer Firewall-Gruppe auf Basis einer Richtlinie\n"
"\n"
"Eine Firewall-Gruppe repräsentiert eine logische Firewall-Ressource, die ein "
"Mandant instanzieren und verwalten kann. Eine Firewall-Gruppe muss mit einer "
"Richtlinie verbunden werden. Alle anderen Felder sind optional."
msgid ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgstr ""
"Erzeugen einer Firewall-Richtlinie mit einer geordneten Liste von Regeln.\n"
"\n"
"Eine Firewall-Richtlinie ist eine geordnete Sammlung von Firewall-Regeln. "
"Sobald eine Regel auf den Datenverkehr zutrifft, werden die weiteren Regeln "
"nicht mehr ausgeführt. Solange die Regeln nicht zutreffen, werden weitere "
"Regeln ausgeführt. Eine Firewall-Richtlinie hat die folgenden Attribute:\n"
"\n"
"<li>Geteilt/Shared: eine Firewall-Richtlinie kann mit mehreren Mandanten "
"geteilt werden. Dadurch kann sie auch als Teil eines Audit-Workflows "
"verwendet werden, um von einer berechtigten Einheit/Organisation/Person "
"geprüft zu werden.</li><li>Auditiert/Audited: wenn dies auf wahr/true "
"gesetzt ist, zeigt es an, dass die Richtlinie geprüft wurde. Jedes Mal, wenn "
"eine Richtlinie oder eine der Regeln darin geändert wird, wird der Indikator "
"wieder auf falsch/false gesetzt und muss durch eine Update-Operation "
"explizit wieder auf wahr/true gesetzt werden.</li>\n"
"Das Namensfeld ist erforderlich, alle anderen sind optional."
msgid ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgstr ""
"Firewall-Regel anlegen\n"
"\n"
"Eine Firewall-Regel bezieht sich auf die folgenden Attribute:\n"
"\n"
"<li>IP-Adresse: die Adresse, auf zu/von der der Datenverkehr gefiltert wird."
"</li><li>IP-Version: der IP Pakettyp (IPV4/6) der gefiltert wird.</"
"li><li>Protokoll: der Pakettyp (UDP, ICMP, TCP, Any) der kontrolliert wird.</"
"li><li>Aktion: die vorhergesehene Filteraktion, möglich ist Abweisen/"
"Verweigern/Erlauben für Datenpakete.</li>\n"
"Die Protokoll- und Aktionsfelder sind erforderlich, andere optional."
msgid "Create a policy with selected rules."
msgstr "Richtlinie mit ausgewählten Regeln erstellen."
msgctxt "Current status of a Firewall Group"
msgid "Created"
msgstr "Erstellt"
msgid "DENY"
msgstr "Verweigern"
msgctxt "Action Name of a Firewall Rule"
msgid "DENY"
msgstr "Verweigern"
msgctxt "Admin state of a Firewall Group"
msgid "DOWN"
msgstr "INAKTIV"
msgid "Delete Firewall Group"
msgid_plural "Delete Firewall Groups"
msgstr[0] "Firewall-Gruppe löschen"
msgstr[1] "Firewall-Gruppen löschen"
msgid "Delete Policy"
msgid_plural "Delete Policies"
msgstr[0] "Richtlinie löschen"
msgstr[1] "Richtlinien löschen"
msgid "Delete Rule"
msgid_plural "Delete Rules"
msgstr[0] "Regel löschen"
msgstr[1] "Regeln löschen"
msgid "Description"
msgstr "Beschreibung"
msgid "Description:"
msgstr "Beschreibung:"
msgid "Destination IP"
msgstr "Ziel-IP"
msgid "Destination IP Address"
msgstr "Ziel-IP-Adresse"
msgid "Destination IP Address/Subnet"
msgstr "Ziel-IP-Adresse oder Subnetz"
msgid "Destination IP address or subnet"
msgstr "Ziel-IP-Adresse oder Subnetz"
msgid "Destination Port"
msgstr "Ziel-Port"
msgid "Destination Port/Port Range"
msgstr "Ziel-Port/-Portbereich"
msgid "Destination port (integer in [1, 65535] or range in a:b)"
msgstr "Ziel-Port (Ganzzahl aus [1, 65535] oder Bereich als a:b)"
msgctxt "Current status of a Firewall Group"
msgid "Down"
msgstr "Inaktiv"
msgid "Edit Firewall Group"
msgstr "Firewall-Gruppe bearbeiten"
msgid "Edit FirewallGroup {{ name }}"
msgstr "Firewall-Gruppe bearbeiten {{ name }}"
msgid "Edit Policy"
msgstr "Richtlinie bearbeiten"
msgid "Edit Policy {{ name }}"
msgstr "Richtlinie bearbeiten {{ name }}"
msgid "Edit Rule"
msgstr "Regel bearbeiten"
msgid "Edit Rule {{ name }}"
msgstr "Regel bearbeiten {{ name }}"
msgid "Egress Policy"
msgstr "Austrittsrichtlinie"
msgid "Egress Policy ID"
msgstr "Ausgang Richtlinien-ID"
msgid "Enabled"
msgstr "Aktiviert"
msgctxt "Current status of a Firewall Group"
msgid "Error"
msgstr "Fehler"
#, python-format
msgid "Failed to add the port(s) to the firewall group %(name)s: %(reason)s"
msgstr ""
"Port konnte zur der Firewallgruppe %(name)s nicht hinzugefügt werden: "
"%(reason)s"
#, python-format
msgid "Failed to insert rule to policy %(name)s: %(reason)s"
msgstr "Regel konnte nicht eingefügt werden in Richtlinie %(name)s: %(reason)s"
#, python-format
msgid "Failed to remove rule from policy %(name)s: %(reason)s"
msgstr "Entfernen der Regel von Richtlinie %(name)s fehlgeschlagen: %(reason)s"
#, python-format
msgid ""
"Failed to remove the port(s) from the firewall group %(name)s: %(reason)s"
msgstr ""
"Port konnte von der Firewallgruppe %(name)s nicht entfernt werden: %(reason)s"
#, python-format
msgid "Failed to retrieve available rules: %s"
msgstr "Verfügbare Regeln konnten nicht abgerufen werden: %s"
#, python-format
msgid "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgstr ""
"Aktuelle Regeln in Richtline %(name)s konnten nicht abgerufen werden: "
"%(reason)s"
msgid "Failed to retrieve port list of the firewall group."
msgstr "Abruf der Portliste der Firewall-Gruppe ist fehlgeschlagen."
#, python-format
msgid "Failed to update firewall group %(name)s: %(reason)s"
msgstr "Firewallgruppe %(name)s konnte nicht aktualisiert werden: %(reason)s"
#, python-format
msgid "Failed to update policy %(name)s: %(reason)s"
msgstr "Fehler beim Aktualisieren der Richtlinie %(name)s: %(reason)s"
#, python-format
msgid "Failed to update rule %(name)s: %(reason)s"
msgstr "Regel %(name)s konnte nicht aktualisiert werden: %(reason)s"
msgid "Firewall Groups"
msgstr "Firewall-Gruppe"
msgid "Firewall Policies"
msgstr "Firewallrichtlinien"
msgid "Firewall Rules"
msgstr "Firewallregeln"
#, python-format
msgid "Firewall group %s was successfully updated."
msgstr "Firewallgruppe %s wurde erfolgreich aktualisiert."
msgid "FirewallGroup"
msgstr "Firewall-Gruppe"
msgid "ICMP"
msgstr "ICMP"
msgid "ID"
msgstr "ID"
msgid "IP Version"
msgstr "IP Version"
msgid "IP Version for Firewall Rule"
msgstr "IP-Version der Firewall-Regel"
msgctxt "Current status of a Firewall Group"
msgid "Inactive"
msgstr "Inaktiv"
msgid "Ingress Policy"
msgstr "Eingangsrichtlinie"
msgid "Ingress Policy ID"
msgstr "Eingang Richtlinien-ID"
msgid "Insert Rule"
msgstr "Regel einfügen"
msgid "Insert Rule to Policy"
msgstr "Regel in Richtlinie hinzufügen"
msgid "Label"
msgstr "Beschreibung"
msgid "Name"
msgstr "Name"
msgid "No options available"
msgstr "Keine Optionen verfügbar"
msgid "None"
msgstr "Keine"
msgctxt "Current status of a Firewall Group"
msgid "Pending Create"
msgstr "Geplante Erstellung"
msgctxt "Current status of a Firewall Group"
msgid "Pending Delete"
msgstr "Geplante Löschung"
msgctxt "Current status of a Firewall Group"
msgid "Pending Update"
msgstr "Geplante Aktualisierung"
msgid "Policies"
msgstr "Richtlinien"
msgid "Policy"
msgstr "Richtlinie"
#, python-format
msgid "Policy %s was successfully updated."
msgstr "Richtlinie %s wurde wurde erfolgreich aktualisiert."
msgid "Ports"
msgstr "Ports"
msgid "Project ID"
msgstr "Projekt-ID"
msgid "Protocol"
msgstr "Protokoll"
msgid "Protocol for the firewall rule"
msgstr "Protokoll für die Firewallregel"
msgid "REJECT"
msgstr "Abweisen"
msgctxt "Action Name of a Firewall Rule"
msgid "REJECT"
msgstr "Abweisen"
msgid "Remove Port"
msgstr "Port entfernen"
msgid "Remove Port from Firewall Group"
msgstr "Port von der Firewallgruppe entfernen"
msgid "Remove Rule"
msgstr "Regel entfernen"
msgid "Remove Rule from Policy"
msgstr "Regel aus Richtlinie entfernen"
msgid "Remove port from FirewallGroup {{ name }}"
msgstr "Port aus Firewall-Gruppe entfernen {{ name }}"
#, python-format
msgid "Removed the port(s) from the firewall group %s successfully."
msgstr "Port(s) wurde(n) von der Firewall-Gruppe %s erfolgreich entfernt."
msgid "Rule"
msgstr "Regel"
#, python-format
msgid "Rule %(rule)s was successfully inserted to policy %(policy)s."
msgstr "Regel %(rule)s wurde erfolgreich in Richtlinie %(policy)s eingefügt ."
#, python-format
msgid "Rule %(rule)s was successfully removed from policy %(policy)s."
msgstr "Regel %(rule)s wurde erfolgreich aus Richtlinie %(policy)s entfernt."
#, python-format
msgid "Rule %s was successfully updated."
msgstr "Regel %s wurde erfolgreich aktualisiert."
msgid "Rules"
msgstr "Regeln"
msgid "Save Changes"
msgstr "Änderungen speichern"
msgid "Scheduled deletion of Firewall Group"
msgid_plural "Scheduled deletion of Firewall Groups"
msgstr[0] "Geplante Löschung der Firewall-Gruppe"
msgstr[1] "Geplante Löschung der Firewall-Gruppen"
msgid "Scheduled deletion of Policy"
msgid_plural "Scheduled deletion of Policies"
msgstr[0] "Geplante Löschung der Richtlinie"
msgstr[1] "Geplante Löschung von Richtlinien"
msgid "Scheduled deletion of Rule"
msgid_plural "Scheduled deletion of Rules"
msgstr[0] "Geplante Löschung der Regel"
msgstr[1] "Geplante Löschung von Regeln"
msgid "Select a Policy"
msgstr "Richtlinie auswählen"
msgid "Select ports for your firewall group."
msgstr "Wählen Sie Ports für Ihre Firewall-Gruppe."
msgid "Select rules for your policy."
msgstr "Regeln für Richtlinie auswählen."
msgid "Selected Ports"
msgstr "Ausgewählte Ports"
msgid "Selected Rules"
msgstr "Ausgewählte Regeln"
msgid "Shared"
msgstr "Geteilt"
msgid "Source IP"
msgstr "Quell-IP"
msgid "Source IP Address"
msgstr "Quell-IP-Adresse"
msgid "Source IP Address/Subnet"
msgstr "Quell-IP-Adresse oder Subnetz"
msgid "Source IP address or subnet"
msgstr "Quell-IP-Adresse oder Subnetz"
msgid "Source Port"
msgstr "Quell-Port"
msgid "Source Port/Port Range"
msgstr "Quell-Port/-Portbereich"
msgid "Source port (integer in [1, 65535] or range in a:b)"
msgstr "Quell-Port (Ganzzahl aus [1, 65535] oder Bereich als a:b)"
msgid ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgstr ""
"Quelle/Ziel Netzwekadresse und IP-Version sind nicht konsistent. Bitte "
"ändern Sie dies."
msgid "Status"
msgstr "Status"
msgid "TCP"
msgstr "TCP"
msgid "UDP"
msgstr "UDP"
msgctxt "Admin state of a Firewall Group"
msgid "UP"
msgstr "AKTIV"
#, python-format
msgid "Unable to add Firewall Group \"%s\"."
msgstr "Firewall-Gruppe \"%s\" konnte nicht hinzugefügt werden."
#, python-format
msgid "Unable to add Policy \"%s\"."
msgstr "Richtlinie \"%s\" konnte nicht hinzugefügt werden."
#, python-format
msgid "Unable to add Rule \"%s\"."
msgstr "Regel \"%s\" kann nicht hinzugefügt werden"
#, python-format
msgid "Unable to delete firewall group. %s"
msgstr "Firewall-Gruppe kann nicht gelöscht werden: %s"
#, python-format
msgid "Unable to delete policy. %s"
msgstr "Richtlinie %s konnte nicht gelöscht werden."
#, python-format
msgid "Unable to delete rule. %s"
msgstr "Regel %s kann nicht gelöscht werden."
msgid "Unable to retrieve firewall group details."
msgstr "Firewall-Gruppendetails können nicht abgerufen werden."
msgid "Unable to retrieve firewall group list."
msgstr "Firewall-Gruppenliste kann nicht abgerufen werden."
msgid "Unable to retrieve firewallgroup details."
msgstr "Konnte Firewall-Gruppendetails nicht abrufen."
msgid "Unable to retrieve policies list."
msgstr "Liste der Richtlinien kann nicht abgerufen werden."
msgid "Unable to retrieve policy details."
msgstr "Richtliniendetails können nicht abgerufen werden."
#, python-format
msgid "Unable to retrieve policy list (%s)."
msgstr "Richtlinienliste kann nicht abgerufen werden (%s)."
msgid "Unable to retrieve policy list."
msgstr "Liste der Richtlinien kann nicht abgerufen werden."
#, python-format
msgid "Unable to retrieve ports (%s)."
msgstr "Ports können nicht abgerufen werden (%s)."
msgid "Unable to retrieve rule details."
msgstr "Details der Regeln können nicht abgerufen werden. "
#, python-format
msgid "Unable to retrieve rules (%s)."
msgstr "Regeln können nicht abgerufen werden (%s)."
msgid "Unable to retrieve rules list."
msgstr "Liste der Regeln kann nicht abgerufen werden."
msgid "Value"
msgstr "Wert"
msgid "You may add ports to firewall group here."
msgstr "Hier können Sie Ports zur Firewallgruppe hinzufügen."
msgid "You may remove ports from firewall group here."
msgstr "Hier können Sie Ports von der Firewallgruppe entfernen."
msgid "You may update firewall group details here."
msgstr "Hier können Sie die Firewallgruppendetails bearbeiten."
msgid ""
"You may update policy details here. Use 'Insert Rule' or 'Remove Rule' links "
"instead to insert or remove a rule."
msgstr ""
"Hier können Sie Richtliniendetails aktualisieren. Wählen Sie die "
"Verknüpfungen 'Regel einfügen' oder 'Regel entfernen', um eine Regel "
"einzufügen oder zu entfernen."
msgid "You may update rule details here."
msgstr "Hier können Sie die Details der Regeln aktualisieren."

View File

@ -0,0 +1,633 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2019. #zanata
msgid ""
msgstr ""
"Project-Id-Version: neutron-fwaas-dashboard VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2019-02-19 16:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-01-26 03:30+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid "-"
msgstr "-"
msgid "ALLOW"
msgstr "ALLOW"
msgctxt "Action Name of a Firewall Rule"
msgid "ALLOW"
msgstr "ALLOW"
msgid "ANY"
msgstr "ANY"
msgid "Action"
msgstr "Action"
msgid "Action for the firewall rule"
msgstr "Action for the firewall rule"
msgctxt "Current status of a Firewall Group"
msgid "Active"
msgstr "Active"
msgid "Add"
msgstr "Add"
msgid "Add Firewall Group"
msgstr "Add Firewall Group"
msgid "Add New Firewall Group"
msgstr "Add New Firewall Group"
msgid "Add New Policy"
msgstr "Add New Policy"
msgid "Add New Rule"
msgstr "Add New Rule"
msgid "Add Policy"
msgstr "Add Policy"
msgid "Add Port"
msgstr "Add Port"
msgid "Add Port to Firewall Group"
msgstr "Add Port to Firewall Group"
msgid "Add Rule"
msgstr "Add Rule"
msgid "Add port to Firewall Group {{ name }}"
msgstr "Add port to Firewall Group {{ name }}"
#, python-format
msgid "Added Firewall Group\"%s\"."
msgstr "Added Firewall Group\"%s\"."
#, python-format
msgid "Added Policy \"%s\"."
msgstr "Added Policy \"%s\"."
#, python-format
msgid "Added Rule \"%s\"."
msgstr "Added Rule \"%s\"."
#, python-format
msgid "Added the port(s) to the firewall group %s successfully."
msgstr "Added the port(s) to the firewall group %s successfully."
msgid "Admin State"
msgstr "Admin State"
msgid "Admin State Up"
msgstr "Admin State Up"
msgid "After"
msgstr "After"
msgid "Audited"
msgstr "Audited"
msgid "Available Ports"
msgstr "Available Ports"
msgid "Available Rules"
msgstr "Available Rules"
msgid "Before"
msgstr "Before"
msgid "Choose port(s) from Available Ports. "
msgstr "Choose port(s) from Available Ports. "
msgid ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgstr ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgid ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgstr ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgid "Choose the rule you want to remove."
msgstr "Choose the rule you want to remove."
msgid "Create Firewall Group"
msgstr "Create Firewall Group"
msgid "Create a Firewall Group with selected ports."
msgstr "Create a Firewall Group with selected ports."
msgid ""
"Create a firewall group based on a policy.\n"
"\n"
"A firewall group represents a logical firewall resource that a tenant can "
"instantiate and manage. A firewall group must be associated with one policy, "
"all other fields are optional."
msgstr ""
"Create a firewall group based on a policy.\n"
"\n"
"A firewall group represents a logical firewall resource that a tenant can "
"instantiate and manage. A firewall group must be associated with one policy, "
"all other fields are optional."
msgid ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgstr ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgid ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgstr ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgid "Create a policy with selected rules."
msgstr "Create a policy with selected rules."
msgctxt "Current status of a Firewall Group"
msgid "Created"
msgstr "Created"
msgid "DENY"
msgstr "DENY"
msgctxt "Action Name of a Firewall Rule"
msgid "DENY"
msgstr "DENY"
msgctxt "Admin state of a Firewall Group"
msgid "DOWN"
msgstr "DOWN"
msgid "Delete Firewall Group"
msgid_plural "Delete Firewall Groups"
msgstr[0] "Delete Firewall Group"
msgstr[1] "Delete Firewall Groups"
msgid "Delete Policy"
msgid_plural "Delete Policies"
msgstr[0] "Delete Policy"
msgstr[1] "Delete Policies"
msgid "Delete Rule"
msgid_plural "Delete Rules"
msgstr[0] "Delete Rule"
msgstr[1] "Delete Rules"
msgid "Description"
msgstr "Description"
msgid "Description:"
msgstr "Description:"
msgid "Destination IP"
msgstr "Destination IP"
msgid "Destination IP Address"
msgstr "Destination IP Address"
msgid "Destination IP Address/Subnet"
msgstr "Destination IP Address/Subnet"
msgid "Destination IP address or subnet"
msgstr "Destination IP address or subnet"
msgid "Destination Port"
msgstr "Destination Port"
msgid "Destination Port/Port Range"
msgstr "Destination Port/Port Range"
msgid "Destination port (integer in [1, 65535] or range in a:b)"
msgstr "Destination port (integer in [1, 65535] or range in a:b)"
msgctxt "Current status of a Firewall Group"
msgid "Down"
msgstr "Down"
msgid "Edit Firewall Group"
msgstr "Edit Firewall Group"
msgid "Edit FirewallGroup {{ name }}"
msgstr "Edit FirewallGroup {{ name }}"
msgid "Edit Policy"
msgstr "Edit Policy"
msgid "Edit Policy {{ name }}"
msgstr "Edit Policy {{ name }}"
msgid "Edit Rule"
msgstr "Edit Rule"
msgid "Edit Rule {{ name }}"
msgstr "Edit Rule {{ name }}"
msgid "Egress Policy"
msgstr "Egress Policy"
msgid "Egress Policy ID"
msgstr "Egress Policy ID"
msgid "Enabled"
msgstr "Enabled"
msgctxt "Current status of a Firewall Group"
msgid "Error"
msgstr "Error"
#, python-format
msgid "Failed to add the port(s) to the firewall group %(name)s: %(reason)s"
msgstr "Failed to add the port(s) to the firewall group %(name)s: %(reason)s"
#, python-format
msgid "Failed to insert rule to policy %(name)s: %(reason)s"
msgstr "Failed to insert rule to policy %(name)s: %(reason)s"
#, python-format
msgid "Failed to remove rule from policy %(name)s: %(reason)s"
msgstr "Failed to remove rule from policy %(name)s: %(reason)s"
#, python-format
msgid ""
"Failed to remove the port(s) from the firewall group %(name)s: %(reason)s"
msgstr ""
"Failed to remove the port(s) from the firewall group %(name)s: %(reason)s"
#, python-format
msgid "Failed to retrieve available rules: %s"
msgstr "Failed to retrieve available rules: %s"
#, python-format
msgid "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgstr "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgid "Failed to retrieve port list of the firewall group."
msgstr "Failed to retrieve port list of the firewall group."
#, python-format
msgid "Failed to update firewall group %(name)s: %(reason)s"
msgstr "Failed to update firewall group %(name)s: %(reason)s"
#, python-format
msgid "Failed to update policy %(name)s: %(reason)s"
msgstr "Failed to update policy %(name)s: %(reason)s"
#, python-format
msgid "Failed to update rule %(name)s: %(reason)s"
msgstr "Failed to update rule %(name)s: %(reason)s"
msgid "Firewall Groups"
msgstr "Firewall Groups"
msgid "Firewall Policies"
msgstr "Firewall Policies"
msgid "Firewall Rules"
msgstr "Firewall Rules"
#, python-format
msgid "Firewall group %s was successfully updated."
msgstr "Firewall group %s was successfully updated."
msgid "FirewallGroup"
msgstr "FirewallGroup"
msgid "ICMP"
msgstr "ICMP"
msgid "ID"
msgstr "ID"
msgid "IP Version"
msgstr "IP Version"
msgid "IP Version for Firewall Rule"
msgstr "IP Version for Firewall Rule"
msgctxt "Current status of a Firewall Group"
msgid "Inactive"
msgstr "Inactive"
msgid "Ingress Policy"
msgstr "Ingress Policy"
msgid "Ingress Policy ID"
msgstr "Ingress Policy ID"
msgid "Insert Rule"
msgstr "Insert Rule"
msgid "Insert Rule to Policy"
msgstr "Insert Rule to Policy"
msgid "Label"
msgstr "Label"
msgid "Name"
msgstr "Name"
msgid "No options available"
msgstr "No options available"
msgid "None"
msgstr "None"
msgctxt "Current status of a Firewall Group"
msgid "Pending Create"
msgstr "Pending Create"
msgctxt "Current status of a Firewall Group"
msgid "Pending Delete"
msgstr "Pending Delete"
msgctxt "Current status of a Firewall Group"
msgid "Pending Update"
msgstr "Pending Update"
msgid "Policies"
msgstr "Policies"
msgid "Policy"
msgstr "Policy"
#, python-format
msgid "Policy %s was successfully updated."
msgstr "Policy %s was successfully updated."
msgid "Ports"
msgstr "Ports"
msgid "Project ID"
msgstr "Project ID"
msgid "Protocol"
msgstr "Protocol"
msgid "Protocol for the firewall rule"
msgstr "Protocol for the firewall rule"
msgid "REJECT"
msgstr "REJECT"
msgctxt "Action Name of a Firewall Rule"
msgid "REJECT"
msgstr "REJECT"
msgid "Remove Port"
msgstr "Remove Port"
msgid "Remove Port from Firewall Group"
msgstr "Remove Port from Firewall Group"
msgid "Remove Rule"
msgstr "Remove Rule"
msgid "Remove Rule from Policy"
msgstr "Remove Rule from Policy"
msgid "Remove port from FirewallGroup {{ name }}"
msgstr "Remove port from FirewallGroup {{ name }}"
#, python-format
msgid "Removed the port(s) from the firewall group %s successfully."
msgstr "Removed the port(s) from the firewall group %s successfully."
msgid "Rule"
msgstr "Rule"
#, python-format
msgid "Rule %(rule)s was successfully inserted to policy %(policy)s."
msgstr "Rule %(rule)s was successfully inserted to policy %(policy)s."
#, python-format
msgid "Rule %(rule)s was successfully removed from policy %(policy)s."
msgstr "Rule %(rule)s was successfully removed from policy %(policy)s."
#, python-format
msgid "Rule %s was successfully updated."
msgstr "Rule %s was successfully updated."
msgid "Rules"
msgstr "Rules"
msgid "Save Changes"
msgstr "Save Changes"
msgid "Scheduled deletion of Firewall Group"
msgid_plural "Scheduled deletion of Firewall Groups"
msgstr[0] "Scheduled deletion of Firewall Group"
msgstr[1] "Scheduled deletion of Firewall Groups"
msgid "Scheduled deletion of Policy"
msgid_plural "Scheduled deletion of Policies"
msgstr[0] "Scheduled deletion of Policy"
msgstr[1] "Scheduled deletion of Policies"
msgid "Scheduled deletion of Rule"
msgid_plural "Scheduled deletion of Rules"
msgstr[0] "Scheduled deletion of Rule"
msgstr[1] "Scheduled deletion of Rules"
msgid "Select a Policy"
msgstr "Select a Policy"
msgid "Select ports for your firewall group."
msgstr "Select ports for your firewall group."
msgid "Select rules for your policy."
msgstr "Select rules for your policy."
msgid "Selected Ports"
msgstr "Selected Ports"
msgid "Selected Rules"
msgstr "Selected Rules"
msgid "Shared"
msgstr "Shared"
msgid "Source IP"
msgstr "Source IP"
msgid "Source IP Address"
msgstr "Source IP Address"
msgid "Source IP Address/Subnet"
msgstr "Source IP Address/Subnet"
msgid "Source IP address or subnet"
msgstr "Source IP address or subnet"
msgid "Source Port"
msgstr "Source Port"
msgid "Source Port/Port Range"
msgstr "Source Port/Port Range"
msgid "Source port (integer in [1, 65535] or range in a:b)"
msgstr "Source port (integer in [1, 65535] or range in a:b)"
msgid ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgstr ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgid "Status"
msgstr "Status"
msgid "TCP"
msgstr "TCP"
msgid "UDP"
msgstr "UDP"
msgctxt "Admin state of a Firewall Group"
msgid "UP"
msgstr "UP"
#, python-format
msgid "Unable to add Firewall Group \"%s\"."
msgstr "Unable to add Firewall Group \"%s\"."
#, python-format
msgid "Unable to add Policy \"%s\"."
msgstr "Unable to add Policy \"%s\"."
#, python-format
msgid "Unable to add Rule \"%s\"."
msgstr "Unable to add Rule \"%s\"."
#, python-format
msgid "Unable to delete firewall group. %s"
msgstr "Unable to delete firewall group. %s"
#, python-format
msgid "Unable to delete policy. %s"
msgstr "Unable to delete policy. %s"
#, python-format
msgid "Unable to delete rule. %s"
msgstr "Unable to delete rule. %s"
msgid "Unable to retrieve firewall group details."
msgstr "Unable to retrieve firewall group details."
msgid "Unable to retrieve firewall group list."
msgstr "Unable to retrieve firewall group list."
msgid "Unable to retrieve firewallgroup details."
msgstr "Unable to retrieve Firewallgroup details."
msgid "Unable to retrieve policies list."
msgstr "Unable to retrieve policies list."
msgid "Unable to retrieve policy details."
msgstr "Unable to retrieve policy details."
#, python-format
msgid "Unable to retrieve policy list (%s)."
msgstr "Unable to retrieve policy list (%s)."
msgid "Unable to retrieve policy list."
msgstr "Unable to retrieve policy list."
#, python-format
msgid "Unable to retrieve ports (%s)."
msgstr "Unable to retrieve ports (%s)."
msgid "Unable to retrieve rule details."
msgstr "Unable to retrieve rule details."
#, python-format
msgid "Unable to retrieve rules (%s)."
msgstr "Unable to retrieve rules (%s)."
msgid "Unable to retrieve rules list."
msgstr "Unable to retrieve rules list."
msgid "Value"
msgstr "Value"
msgid "You may add ports to firewall group here."
msgstr "You may add ports to firewall group here."
msgid "You may remove ports from firewall group here."
msgstr "You may remove ports from firewall group here."
msgid "You may update firewall group details here."
msgstr "You may update firewall group details here."
msgid ""
"You may update policy details here. Use 'Insert Rule' or 'Remove Rule' links "
"instead to insert or remove a rule."
msgstr ""
"You may update policy details here. Use 'Insert Rule' or 'Remove Rule' links "
"instead to insert or remove a rule."
msgid "You may update rule details here."
msgstr "You may update rule details here."

View File

@ -0,0 +1,501 @@
# Adrien Cunin <adrien@adriencunin.fr>, 2016. #zanata
# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata
# Sylvie Chesneau <sissicdf@fr.ibm.com>, 2016. #zanata
# Cédric Savignan <liced@liced.fr>, 2017. #zanata
# JF Taltavull <jftalta@gmail.com>, 2017. #zanata
# Loic Nicolle <loic.nicolle@orange.com>, 2017. #zanata
# Pascal Larivée <pascal@larivee.photo>, 2017. #zanata
# Loic Nicolle <loic.nicolle@orange.com>, 2018. #zanata
msgid ""
msgstr ""
"Project-Id-Version: neutron-fwaas-dashboard VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2019-02-19 16:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2018-03-27 03:09+0000\n"
"Last-Translator: Loic Nicolle <loic.nicolle@orange.com>\n"
"Language-Team: French\n"
"Language: fr\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
msgid "-"
msgstr "-"
msgid "ALLOW"
msgstr "AUTORISER"
msgctxt "Action Name of a Firewall Rule"
msgid "ALLOW"
msgstr "AUTORISER"
msgid "ANY"
msgstr "TOUT"
msgid "Action"
msgstr "Action"
msgid "Action for the firewall rule"
msgstr "Action pour la règle de pare-feu"
msgctxt "Current status of a Firewall Group"
msgid "Active"
msgstr "Actif"
msgid "Add"
msgstr "Ajouter"
msgid "Add Firewall Group"
msgstr "Ajouter un groupe de pare-feux"
msgid "Add New Policy"
msgstr "Ajouter une nouvelle stratégie"
msgid "Add New Rule"
msgstr "Ajouter une nouvelle règle"
msgid "Add Policy"
msgstr "Ajouter une stratégie"
msgid "Add Rule"
msgstr "Ajouter une règle"
#, python-format
msgid "Added Policy \"%s\"."
msgstr "Stratégie \"%s\" ajoutée."
#, python-format
msgid "Added Rule \"%s\"."
msgstr "Règle \"%s\" ajoutée."
msgid "Admin State"
msgstr "État Administateur"
msgid "Admin State Up"
msgstr "Etat Admin activé"
msgid "After"
msgstr "Après"
msgid "Audited"
msgstr "Audité"
msgid "Available Ports"
msgstr "Ports disponibles"
msgid "Available Rules"
msgstr "Règles disponibles"
msgid "Before"
msgstr "Avant"
msgid ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgstr ""
"Choisissez une ou plusieurs règles en les faisant passer des règles "
"disponibles aux règles sélectionnées en cliquant sur le bouton ou par "
"glisser-déposer. Vous pouvez aussi changer l'ordre des règles par glisser-"
"déposer."
msgid ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgstr ""
"Choisissez la règle que vous souhaitez insérer. Spécifiez la règle qui doit "
"précéder immédiatement votre nouvelle règle, ou la règle qui doit suivre "
"immédiatement votre nouvelle règle. Si vous spécifiez les deux, le premier "
"critère est prioritaire."
msgid "Choose the rule you want to remove."
msgstr "Choisissez la règle que vous voulez enlever."
msgid "Create a Firewall Group with selected ports."
msgstr "Créer un groupe de pare-feux avec les ports sélectionnés."
msgid ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgstr ""
"Créer une stratégie de pare-feu avec une liste ordonnée de règles de pare-"
"feu.\n"
"\n"
"Une stratégie de pare-feu est un ensemble ordonné de règles de pare-feu. Si "
"le trafic correspond à la première règle, les autres règles ne sont pas "
"exécutées. Si le trafic ne correspond pas à la règle en cours, la règle "
"suivante est exécutée. Une stratégie de pare-feu comporte les attributs "
"suivants :\n"
"\n"
"<li>Partagé (shared) : Une stratégie de pare-feu peut être partagée entre "
"locataires. Elle peut ainsi faire partie d'un flux de travaux d'audit au "
"sein duquel la stratégie de pare-feu peut être auditée par l'entité "
"appropriée autorisée.</li><li>Audité (audited) : Lorsque l'attribut est "
"défini sur True, la stratégie de pare-feu a été auditée. Chaque fois qu'une "
"stratégie de pare-feu ou les règles de pare-feu associées sont modifiées, "
"cet attribut est défini sur False et devra être explicitement défini avec la "
"valeur True via une opération de mise à jour.</li>\n"
"La zone de nom est obligatoire, toutes les autres sont facultatives."
msgid ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgstr ""
"Créer une règle de pare-feu.\n"
"\n"
"Une règle de pare-feu est une association des attributs suivants :\n"
"\n"
"<li>Adresses IP : Adresses depuis/vers lesquelles le filtrage du trafic doit "
"s'appliquer.</li><li>Version d'IP : Type des paquets IP (IP V4/V6) à filtrer."
"</li><li>Protocole : Type des paquets (UDP, ICMP, TCP, Tout) à vérifier.</"
"li><li>Action : Type de filtrage requis ; Il peut s'agir de Rejeter/Refuser/"
"Autoriser les paquets de données.</li>\n"
"Les zones de protocole et d'action sont obligatoires, toutes les autres sont "
"facultatives."
msgid "Create a policy with selected rules."
msgstr "Créer une stratégie avec les règles sélectionnées."
msgctxt "Current status of a Firewall Group"
msgid "Created"
msgstr "Créé"
msgid "DENY"
msgstr "REFUSER"
msgctxt "Action Name of a Firewall Rule"
msgid "DENY"
msgstr "REFUSER"
msgctxt "Admin state of a Firewall Group"
msgid "DOWN"
msgstr "INACTIF"
msgid "Delete Policy"
msgid_plural "Delete Policies"
msgstr[0] "Supprimer la stratégie"
msgstr[1] "Supprimer les stratégies"
msgid "Delete Rule"
msgid_plural "Delete Rules"
msgstr[0] "Supprimer la règle"
msgstr[1] "Supprimer les règles"
msgid "Description"
msgstr "Description"
msgid "Description:"
msgstr "Description:"
msgid "Destination IP"
msgstr "IP de destination"
msgid "Destination IP Address"
msgstr "Adresse IP de destination"
msgid "Destination IP Address/Subnet"
msgstr "Adresse IP/Sous-réseau de destination"
msgid "Destination IP address or subnet"
msgstr "Adresse IP ou sous-réseau de destination"
msgid "Destination Port"
msgstr "Port de destination"
msgid "Destination Port/Port Range"
msgstr "Port/Plage de ports de destination"
msgid "Destination port (integer in [1, 65535] or range in a:b)"
msgstr "Port de destination (entier compris dans [1, 65535] ou plage a:b)"
msgctxt "Current status of a Firewall Group"
msgid "Down"
msgstr "Inactif"
msgid "Edit Policy"
msgstr "Editer la stratégie"
msgid "Edit Policy {{ name }}"
msgstr "Editer la stratégie {{ name }}"
msgid "Edit Rule"
msgstr "Éditer la règle"
msgid "Edit Rule {{ name }}"
msgstr "Editer la règle {{ name }}"
msgid "Egress Policy"
msgstr "Stratégie sortante"
msgid "Enabled"
msgstr "Activé"
msgctxt "Current status of a Firewall Group"
msgid "Error"
msgstr "Erreur"
#, python-format
msgid "Failed to insert rule to policy %(name)s: %(reason)s"
msgstr "Echec d'insertion de la règle dans la stratégie %(name)s : %(reason)s"
#, python-format
msgid "Failed to remove rule from policy %(name)s: %(reason)s"
msgstr "Echec de retrait de la règle de la stratégie %(name)s : %(reason)s"
#, python-format
msgid "Failed to retrieve available rules: %s"
msgstr "Impossible de récupérer les règles disponibles : %s"
#, python-format
msgid "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgstr ""
"Échec de la récupération des règles courantes de la stratégie %(name)s : "
"%(reason)s"
#, python-format
msgid "Failed to update policy %(name)s: %(reason)s"
msgstr "Echec de mise à jour de la stratégie %(name)s : %(reason)s"
#, python-format
msgid "Failed to update rule %(name)s: %(reason)s"
msgstr "Échec de la mise à jour de la règle %(name)s : %(reason)s"
msgid "Firewall Policies"
msgstr "Stratégies de pare-feu"
msgid "Firewall Rules"
msgstr "Règles de pare-feu"
msgid "ICMP"
msgstr "ICMP"
msgid "ID"
msgstr "ID"
msgid "IP Version"
msgstr "Version d'IP"
msgid "IP Version for Firewall Rule"
msgstr "Version d'IP pour la règle de pare-feu"
msgctxt "Current status of a Firewall Group"
msgid "Inactive"
msgstr "Inactif"
msgid "Ingress Policy"
msgstr "Stratégie entrante"
msgid "Insert Rule"
msgstr "Insérer une règle"
msgid "Insert Rule to Policy"
msgstr "Insérer une règle dans la stratégie"
msgid "Name"
msgstr "Nom"
msgid "None"
msgstr "Aucun"
msgctxt "Current status of a Firewall Group"
msgid "Pending Create"
msgstr "Création en attente"
msgctxt "Current status of a Firewall Group"
msgid "Pending Delete"
msgstr "Suppression en attente"
msgctxt "Current status of a Firewall Group"
msgid "Pending Update"
msgstr "Mise à jour en attente"
msgid "Policies"
msgstr "Stratégies"
msgid "Policy"
msgstr "Stratégie"
#, python-format
msgid "Policy %s was successfully updated."
msgstr "La stratégie %s a été mise à jour."
msgid "Ports"
msgstr "Ports"
msgid "Project ID"
msgstr "Project ID"
msgid "Protocol"
msgstr "Protocole"
msgid "Protocol for the firewall rule"
msgstr "Protocole pour la règle de pare-feu"
msgid "REJECT"
msgstr "REJETER"
msgctxt "Action Name of a Firewall Rule"
msgid "REJECT"
msgstr "REJETER"
msgid "Remove Port"
msgstr "Supprimer le port"
msgid "Remove Rule"
msgstr "Retirer la règle"
msgid "Remove Rule from Policy"
msgstr "Retirer une règle de la stratégie"
msgid "Rule"
msgstr "Règle"
#, python-format
msgid "Rule %(rule)s was successfully inserted to policy %(policy)s."
msgstr "La règle %(rule)s a été insérée dans la stratégie %(policy)s."
#, python-format
msgid "Rule %(rule)s was successfully removed from policy %(policy)s."
msgstr "La règle %(rule)s a été retirée de la stratégie %(policy)s."
#, python-format
msgid "Rule %s was successfully updated."
msgstr "La règle %s a été mise à jour."
msgid "Rules"
msgstr "Règles"
msgid "Save Changes"
msgstr "Enregistrer les changements"
msgid "Scheduled deletion of Policy"
msgid_plural "Scheduled deletion of Policies"
msgstr[0] "Suppression planifiée de la stratégie"
msgstr[1] "Suppression planifiée des stratégies"
msgid "Scheduled deletion of Rule"
msgid_plural "Scheduled deletion of Rules"
msgstr[0] "Suppression planifiée de la règle"
msgstr[1] "Suppression planifiée des règles"
msgid "Select a Policy"
msgstr "Sélectionner une stratégie"
msgid "Select rules for your policy."
msgstr "Sélectionnez des règles pour votre stratégie."
msgid "Selected Rules"
msgstr "Règles sélectionnées"
msgid "Shared"
msgstr "Partagé"
msgid "Source IP"
msgstr "IP source"
msgid "Source IP Address"
msgstr "Adresse IP source"
msgid "Source IP Address/Subnet"
msgstr "Adresse IP/Sous-réseau source"
msgid "Source IP address or subnet"
msgstr "Adresse IP ou sous-réseau source"
msgid "Source Port"
msgstr "Port source"
msgid "Source Port/Port Range"
msgstr "Port/plage de ports source"
msgid "Source port (integer in [1, 65535] or range in a:b)"
msgstr "Port source (entier compris dans [1,65535] ou plage a:b)"
msgid ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgstr ""
"La version d'IP et l'adresse réseau source/de destination ne sont pas "
"cohérentes. Corrigez-les en conséquence."
msgid "Status"
msgstr "Statut"
msgid "TCP"
msgstr "TCP"
msgid "UDP"
msgstr "UDP"
msgctxt "Admin state of a Firewall Group"
msgid "UP"
msgstr "ACTIF"
#, python-format
msgid "Unable to add Policy \"%s\"."
msgstr "Impossible d'ajouter la stratégie \"%s\"."
#, python-format
msgid "Unable to add Rule \"%s\"."
msgstr "Impossible d'ajouter la règle \"%s\"."
#, python-format
msgid "Unable to delete policy. %s"
msgstr "Impossible de supprimer la stratégie. %s"
#, python-format
msgid "Unable to delete rule. %s"
msgstr "Impossible de supprimer la règle %s"
msgid "Unable to retrieve policies list."
msgstr "Impossible de récupérer la liste des stratégies."
msgid "Unable to retrieve policy details."
msgstr "Impossible de récupérer les détails de la stratégie."
#, python-format
msgid "Unable to retrieve policy list (%s)."
msgstr "Impossible de récupérer la liste des stratégies (%s)."
msgid "Unable to retrieve policy list."
msgstr "Impossible de récupérer la liste des stratégies."
#, python-format
msgid "Unable to retrieve ports (%s)."
msgstr "Impossible de récupérer les ports (%s)."
msgid "Unable to retrieve rule details."
msgstr "Impossible de récupérer les détails de la règle."
#, python-format
msgid "Unable to retrieve rules (%s)."
msgstr "Impossible de récupérer les règles (%s)."
msgid "Unable to retrieve rules list."
msgstr "Impossible de récupérer la liste des règles."
msgid "You may update rule details here."
msgstr "Ici, vous pouvez mettre à jour les détails de la règle."

View File

@ -0,0 +1,637 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2016. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2017. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2018. #zanata
# Frank Kloeker <eumel@arcor.de>, 2019. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2019. #zanata
msgid ""
msgstr ""
"Project-Id-Version: neutron-fwaas-dashboard VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2019-03-27 14:25+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-04-03 11:53+0000\n"
"Last-Translator: Frank Kloeker <eumel@arcor.de>\n"
"Language-Team: Indonesian\n"
"Language: id\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid "-"
msgstr "-"
msgid "ALLOW"
msgstr "ALLOW"
msgctxt "Action Name of a Firewall Rule"
msgid "ALLOW"
msgstr "ALLOW (mengizinkan)"
msgid "ANY"
msgstr "ANY"
msgid "Action"
msgstr "Action"
msgid "Action for the firewall rule"
msgstr "Aksi aturan firewall"
msgctxt "Current status of a Firewall Group"
msgid "Active"
msgstr "Active"
msgid "Add"
msgstr "Menambahkan"
msgid "Add Firewall Group"
msgstr "Menambahkan Firewall Group"
msgid "Add New Firewall Group"
msgstr "Add New Firewall Group"
msgid "Add New Policy"
msgstr "Menambah kebijakan baru"
msgid "Add New Rule"
msgstr "Menambah aturan baru"
msgid "Add Policy"
msgstr "Add Policy (tambahkan kebiijakan)"
msgid "Add Port"
msgstr "Add Port"
msgid "Add Port to Firewall Group"
msgstr "Tambahkan Port ke Firewall Group"
msgid "Add Rule"
msgstr "Tambahkan Aturan"
msgid "Add port to Firewall Group {{ name }}"
msgstr "Tambahkan port ke Firewall Group {{ name }}"
#, python-format
msgid "Added Firewall Group\"%s\"."
msgstr "Ditambahkan Firewall Group\"%s\"."
#, python-format
msgid "Added Policy \"%s\"."
msgstr "Kebijakan ditambahkan \"%s\"."
#, python-format
msgid "Added Rule \"%s\"."
msgstr "Aturan ditambahkan \"%s\"."
#, python-format
msgid "Added the port(s) to the firewall group %s successfully."
msgstr "Berhasil menambahkan port ke grup firewall %s."
msgid "Admin State"
msgstr "Admin State"
msgid "Admin State Up"
msgstr "Admin State Up"
msgid "After"
msgstr "After (sesudah)"
msgid "Audited"
msgstr "Audited"
msgid "Available Ports"
msgstr "Available Ports"
msgid "Available Rules"
msgstr "Available Rules"
msgid "Before"
msgstr "Before (sebelum)"
msgid "Choose port(s) from Available Ports. "
msgstr "Pilih port dari Available Ports. "
msgid ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgstr ""
"Pilih aturan dari Available Rules ke Selected Rule dengan menekan tombol "
"atau seret dan lepaskan, Anda dapat mengubah pesanan mereka dengan drag dan "
"drop juga."
msgid ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgstr ""
"Pilih aturan yang ingin Anda sisipkan. Tentukan baik aturan yang ingin Anda "
"masukkan segera sebelumnya, atau aturan untuk memasukkan segera setelahnya. "
"Jika keduanya ditentukan, sebelumnya diutamakan."
msgid "Choose the rule you want to remove."
msgstr "Pilih aturan yang ingin Anda hapus."
msgid "Create Firewall Group"
msgstr "Membuat Firewall Group"
msgid "Create a Firewall Group with selected ports."
msgstr "Buat Firewall Group dengan port yang dipilih."
msgid ""
"Create a firewall group based on a policy.\n"
"\n"
"A firewall group represents a logical firewall resource that a tenant can "
"instantiate and manage. A firewall group must be associated with one policy, "
"all other fields are optional."
msgstr ""
"Buat grup firewall berdasarkan kebijakan.\n"
"\n"
"Grup firewall mewakili sumber daya firewall logis dimana tenant dapat "
"instantiate dan kelola. Grup firewall harus dikaitkan dengan satu kebijakan, "
"semua bidang lainnya opsional."
msgid ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgstr ""
"Membuat kebijakan firewall dengan daftar aturan firewall tersusun "
"berurutan.\n"
"\n"
"Sebuah kebijakan firewall adalah koleksi aturan firewall berurutan. Jadi "
"jika lalu lintas sesuai dengan aturan pertama, maka aturan lain tidak "
"dieksekusi. Jika lalu lintas tidak sesuai dengan aturan saat ini, maka "
"aturan berikutnya dieksekusi. Sebuah kebijakan firewall memiliki atribut "
"sebagai berikut:\n"
"\n"
"<li>Shared: Sebuah kebijakan firewall dapat digunakan bersama seluruh "
"penyewa (tenant). Dengan demikian kebijakan itu dapat juga menjadi bagian "
"dari alur kerja pemeriksaan dimana kebijakan firewall dapat diaudit oleh "
"entitas terkait yang berwenang.</li><li>Audited: Ketika diaudit diatur ke "
"True, ini menunjukkan bahwa kebijakan firewall telah diaudit. Setiap kali "
"kebijakan firewall atau aturan firewall yang terkait berubah, atribut ini "
"akan diatur ke False dan harus secara eksplisit diatur ke True melalui "
"operasi update.</li>\n"
"Kolom (field) nama diperlukan, semua yang lain adalah opsional."
msgid ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgstr ""
"Buat aturan firewall\n"
"\n"
"Aturan firewall adalah sebuah asosiasi atribut berikut:\n"
"\n"
"<li>IP Addresses: Alamat dari/ke dimana filtrasi lalu lintas perlu "
"diterapkan.</li><li>IP Version: Tipe paket IP (IP V4/V6) yang perlu disaring."
"</li><li>Protocol: Tipe paket (UDP, ICMP, TCP, lainnya) yang perlu diperiksa."
"</li><li>Action: Action adalah tipe filtrasi diperlukan, dapat Reject/Deny/"
"Allow paket data.</li>\n"
"Protokol dan action field (kolom aksi) yang diperlukan, semua yang lain "
"adalah opsional."
msgid "Create a policy with selected rules."
msgstr "Membuat kebijakan dengan aturan yang dipilih."
msgctxt "Current status of a Firewall Group"
msgid "Created"
msgstr "Created"
msgid "DENY"
msgstr "DENY (menyangkal)"
msgctxt "Action Name of a Firewall Rule"
msgid "DENY"
msgstr "DENY (menyangkal)"
msgctxt "Admin state of a Firewall Group"
msgid "DOWN"
msgstr "DOWN"
msgid "Delete Firewall Group"
msgid_plural "Delete Firewall Groups"
msgstr[0] "Delete Firewall Group"
msgid "Delete Policy"
msgid_plural "Delete Policies"
msgstr[0] "Delete Policy"
msgid "Delete Rule"
msgid_plural "Delete Rules"
msgstr[0] "Delete Rule"
msgid "Description"
msgstr "Deskripsi"
msgid "Description:"
msgstr "Deskripsi:"
msgid "Destination IP"
msgstr "IP Tujuan"
msgid "Destination IP Address"
msgstr "Destination IP Address"
msgid "Destination IP Address/Subnet"
msgstr "Tujuan subnet/alamat IP"
msgid "Destination IP address or subnet"
msgstr "Tujuan subnet atau alamat IP"
msgid "Destination Port"
msgstr "Port Tujuan"
msgid "Destination Port/Port Range"
msgstr "Destination Port/Port Range (tujuan port/ kisaran port)"
msgid "Destination port (integer in [1, 65535] or range in a:b)"
msgstr ""
"Destination (tujuan) port (integer dalam [1, 65535] atau dalam kisaran a:b)"
msgctxt "Current status of a Firewall Group"
msgid "Down"
msgstr "Down"
msgid "Edit Firewall Group"
msgstr "Edit Firewall Group"
msgid "Edit FirewallGroup {{ name }}"
msgstr "Edit FirewallGroup {{ name }}"
msgid "Edit Policy"
msgstr "Ubah Kebijakan"
msgid "Edit Policy {{ name }}"
msgstr "Edit Policy {{ name }}"
msgid "Edit Rule"
msgstr "Ubah Aturan"
msgid "Edit Rule {{ name }}"
msgstr "Edit Rule {{ name }}"
msgid "Egress Policy"
msgstr "Egress Policy"
msgid "Egress Policy ID"
msgstr "Egress Policy ID"
msgid "Enabled"
msgstr "Enabled (aktif)"
msgctxt "Current status of a Firewall Group"
msgid "Error"
msgstr "Error"
#, python-format
msgid "Failed to add the port(s) to the firewall group %(name)s: %(reason)s"
msgstr "Gagal menambahkan port(s) ke firewall group %(name)s: %(reason)s"
#, python-format
msgid "Failed to insert rule to policy %(name)s: %(reason)s"
msgstr "Gagal untuk memasukkan aturan kebijakan %(name)s: %(reason)s"
#, python-format
msgid "Failed to remove rule from policy %(name)s: %(reason)s"
msgstr "Gagal menghapus aturan dari kebijakan %(name)s: %(reason)s"
#, python-format
msgid ""
"Failed to remove the port(s) from the firewall group %(name)s: %(reason)s"
msgstr "Gagal menghapus port(s) dari firewall group %(name)s: %(reason)s"
#, python-format
msgid "Failed to retrieve available rules: %s"
msgstr "Gagal mengambil aturan yang tersedia: %s"
#, python-format
msgid "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgstr "Gagal mengambil aturan saat ini dalam kebijakan %(name)s: %(reason)s"
msgid "Failed to retrieve port list of the firewall group."
msgstr "Gagal mengambil daftar port dari grup firewall."
#, python-format
msgid "Failed to update firewall group %(name)s: %(reason)s"
msgstr "Gagal memperbarui grup firewall %(name)s: %(reason)s"
#, python-format
msgid "Failed to update policy %(name)s: %(reason)s"
msgstr "Gagal memperbarui kebijakan %(name)s: %(reason)s"
#, python-format
msgid "Failed to update rule %(name)s: %(reason)s"
msgstr "Gagal memperbarui aturan %(name)s: %(reason)s"
msgid "Firewall Groups"
msgstr "Firewall Groups"
msgid "Firewall Policies"
msgstr "Firewall Policies (kebijakan firewall)"
msgid "Firewall Rules"
msgstr " Firewall Rules (aturan firewall)"
#, python-format
msgid "Firewall group %s was successfully updated."
msgstr "Grup firewall %s berhasil diperbarui."
msgid "FirewallGroup"
msgstr "FirewallGroup"
msgid "ICMP"
msgstr "ICMP"
msgid "ID"
msgstr "ID"
msgid "IP Version"
msgstr "IP Version"
msgid "IP Version for Firewall Rule"
msgstr "IP Version untuk Firewall Rule"
msgctxt "Current status of a Firewall Group"
msgid "Inactive"
msgstr "Inactive"
msgid "Ingress Policy"
msgstr "Ingress Policy"
msgid "Ingress Policy ID"
msgstr "Ingress Policy ID"
msgid "Insert Rule"
msgstr "Insert Rule (menyisipkan aturan)"
msgid "Insert Rule to Policy"
msgstr "Sisipkan aturan ke kebijakan"
msgid "Label"
msgstr "Label"
msgid "Name"
msgstr "Name"
msgid "No options available"
msgstr "Tidak ada opsi yang tersedia"
msgid "None"
msgstr "None"
msgctxt "Current status of a Firewall Group"
msgid "Pending Create"
msgstr "Pending Create"
msgctxt "Current status of a Firewall Group"
msgid "Pending Delete"
msgstr "Pending Delete"
msgctxt "Current status of a Firewall Group"
msgid "Pending Update"
msgstr "Pending Update"
msgid "Policies"
msgstr "Kebijakan"
msgid "Policy"
msgstr "Policy (kebijakan)"
#, python-format
msgid "Policy %s was successfully updated."
msgstr "Kebijakan %s telah berhasil diperbarui."
msgid "Ports"
msgstr "Ports"
msgid "Project ID"
msgstr "Project ID"
msgid "Protocol"
msgstr "Protocol"
msgid "Protocol for the firewall rule"
msgstr "Protokol untuk aturan firewall"
msgid "REJECT"
msgstr "REJECT (menolak)"
msgctxt "Action Name of a Firewall Rule"
msgid "REJECT"
msgstr "REJECT (menolak)"
msgid "Remove Port"
msgstr "Remove Port"
msgid "Remove Port from Firewall Group"
msgstr "Hapus Port dari Firewall Group"
msgid "Remove Rule"
msgstr "Remove Rule (hapus aturan)"
msgid "Remove Rule from Policy"
msgstr "Buang aturan dari kebijakan"
msgid "Remove port from FirewallGroup {{ name }}"
msgstr "Hapus port dari FirewallGroup {{ name }}"
#, python-format
msgid "Removed the port(s) from the firewall group %s successfully."
msgstr "Port berhasil dihapus dari firewall group %s ."
msgid "Rule"
msgstr "Aturan"
#, python-format
msgid "Rule %(rule)s was successfully inserted to policy %(policy)s."
msgstr "Aturan %(rule)s berhasil dimasukkan ke kebijakan %(policy)s."
#, python-format
msgid "Rule %(rule)s was successfully removed from policy %(policy)s."
msgstr "Aturan %(rule)s berhasil dihapus dari kebijakan %(policy)s."
#, python-format
msgid "Rule %s was successfully updated."
msgstr "Aturan %s telah berhasil diperbarui."
msgid "Rules"
msgstr "Aturan"
msgid "Save Changes"
msgstr "Simpan perubahan"
msgid "Scheduled deletion of Firewall Group"
msgid_plural "Scheduled deletion of Firewall Groups"
msgstr[0] "Scheduled deletion of Firewall Group"
msgid "Scheduled deletion of Policy"
msgid_plural "Scheduled deletion of Policies"
msgstr[0] "Scheduled deletion of Policy"
msgid "Scheduled deletion of Rule"
msgid_plural "Scheduled deletion of Rules"
msgstr[0] "Scheduled deletion of Rule"
msgid "Select a Policy"
msgstr "Pilih kebijakan "
msgid "Select ports for your firewall group."
msgstr "Pilih port untuk grup firewall Anda."
msgid "Select rules for your policy."
msgstr "Pilih aturan untuk kebijakan Anda."
msgid "Selected Ports"
msgstr "Selected Ports"
msgid "Selected Rules"
msgstr "Selected Rules"
msgid "Shared"
msgstr "Shared"
msgid "Source IP"
msgstr "Source IP (IP sumber)"
msgid "Source IP Address"
msgstr "Source IP Address"
msgid "Source IP Address/Subnet"
msgstr "Source (asal) subnet/alamat IP"
msgid "Source IP address or subnet"
msgstr "Source (asal) subnet atau alamat IP"
msgid "Source Port"
msgstr "Port Sumber"
msgid "Source Port/Port Range"
msgstr "Source Port/Port Range (asal port/ kisaran port)"
msgid "Source port (integer in [1, 65535] or range in a:b)"
msgstr "Source (asal) port (integer dalam [1, 65535] atau dalam kisaran a:b)"
msgid ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgstr ""
"Sumber/tujuan alamat jaringan dan IP versi tidak konsisten. Harap membuat "
"mereka konsisten."
msgid "Status"
msgstr "Status"
msgid "TCP"
msgstr "TCP"
msgid "UDP"
msgstr "UDP"
msgctxt "Admin state of a Firewall Group"
msgid "UP"
msgstr "UP"
#, python-format
msgid "Unable to add Firewall Group \"%s\"."
msgstr "Tidak dapat menambahkan Firewall Group \"%s\"."
#, python-format
msgid "Unable to add Policy \"%s\"."
msgstr "Tidak dapat menambahkan kebijakan \"%s\"."
#, python-format
msgid "Unable to add Rule \"%s\"."
msgstr "Tidak dapat menambahkan Aturan \"%s\"."
#, python-format
msgid "Unable to delete firewall group. %s"
msgstr "Tidak dapat menghapus firewall group. %s"
#, python-format
msgid "Unable to delete policy. %s"
msgstr "Tidak dapat menghapus kebijakan. %s"
#, python-format
msgid "Unable to delete rule. %s"
msgstr "Tidak dapat menghapus aturan. %s"
msgid "Unable to retrieve firewall group details."
msgstr "Tidak dapat mengambil detail grup firewall."
msgid "Unable to retrieve firewall group list."
msgstr "Tidak dapat mengambil daftar grup firewall."
msgid "Unable to retrieve firewallgroup details."
msgstr "Tidak dapat mengambil rincian firewallgroup."
msgid "Unable to retrieve policies list."
msgstr "Tidak dapat mengambil daftar kebijakan."
msgid "Unable to retrieve policy details."
msgstr "Tidak dapat mengambil rincian kebijakan."
#, python-format
msgid "Unable to retrieve policy list (%s)."
msgstr "Tidak dapat mengambil daftar kebijakan (%s)."
msgid "Unable to retrieve policy list."
msgstr "Tidak dapat mengambil daftar kebijakan."
#, python-format
msgid "Unable to retrieve ports (%s)."
msgstr "Tidak dapat mengambil port (%s)."
msgid "Unable to retrieve rule details."
msgstr "Tidak dapat mengambil rincian aturan."
#, python-format
msgid "Unable to retrieve rules (%s)."
msgstr "Tidak dapat mengambil peraturan (%s)."
msgid "Unable to retrieve rules list."
msgstr "Tidak dapat mengambil daftar aturan."
msgid "Value"
msgstr "Value"
msgid "You may add ports to firewall group here."
msgstr "Anda dapat menambahkan port ke grup firewall di sini."
msgid "You may remove ports from firewall group here."
msgstr "Anda dapat menghapus port dari grup firewall di sini."
msgid "You may update firewall group details here."
msgstr "Anda dapat memperbarui rincian grup firewall di sini."
msgid ""
"You may update policy details here. Use 'Insert Rule' or 'Remove Rule' links "
"instead to insert or remove a rule."
msgstr ""
"Anda dapat memperbarui rincian kebijakan di sini. Gunakan tautan 'Insert "
"Rule' atau 'Remove Rule' sebagai gantinya untuk memasukkan atau menghapus "
"aturan."
msgid "You may update rule details here."
msgstr "Anda dapat memperbarui detail aturan di sini."

View File

@ -0,0 +1,633 @@
# Akihiro Motoki <amotoki@gmail.com>, 2017. #zanata
# Yuko Katabami <yukokatabami@gmail.com>, 2018. #zanata
# Takashi Kuroda <tkuroda@redhat.com>, 2019. #zanata
msgid ""
msgstr ""
"Project-Id-Version: neutron-fwaas-dashboard VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2019-03-19 10:41+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2019-03-20 03:16+0000\n"
"Last-Translator: Takashi Kuroda <tkuroda@redhat.com>\n"
"Language-Team: Japanese\n"
"Language: ja\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid "-"
msgstr "-"
msgid "ALLOW"
msgstr "ALLOW"
msgctxt "Action Name of a Firewall Rule"
msgid "ALLOW"
msgstr "ALLOW"
msgid "ANY"
msgstr "ANY"
msgid "Action"
msgstr "アクション"
msgid "Action for the firewall rule"
msgstr "ファイアウォールルールのアクション"
msgctxt "Current status of a Firewall Group"
msgid "Active"
msgstr "稼働中"
msgid "Add"
msgstr "追加"
msgid "Add Firewall Group"
msgstr "ファイアウォールグループの追加"
msgid "Add New Firewall Group"
msgstr "ファイアウォールグループの追加"
msgid "Add New Policy"
msgstr "ポリシーの追加"
msgid "Add New Rule"
msgstr "ルールの追加"
msgid "Add Policy"
msgstr "ポリシーの追加"
msgid "Add Port"
msgstr "ポートの追加"
msgid "Add Port to Firewall Group"
msgstr "ファイアウォールグループへのポートの追加"
msgid "Add Rule"
msgstr "ルールの追加"
msgid "Add port to Firewall Group {{ name }}"
msgstr "ファイアウォールグループ {{ name }} へのポートの追加"
#, python-format
msgid "Added Firewall Group\"%s\"."
msgstr "ファイアウォールグループ \"%s\" を追加しました。"
#, python-format
msgid "Added Policy \"%s\"."
msgstr "ポリシー \"%s\" を追加しました。"
#, python-format
msgid "Added Rule \"%s\"."
msgstr "ルール \"%s\" を追加しました。"
#, python-format
msgid "Added the port(s) to the firewall group %s successfully."
msgstr "ポートを正常にファイアウォールグループ %s に追加しました。"
msgid "Admin State"
msgstr "管理状態"
msgid "Admin State Up"
msgstr "管理状態有効"
msgid "After"
msgstr "後に挿入"
msgid "Audited"
msgstr "監査対象 (Audited)"
msgid "Available Ports"
msgstr "利用可能なポート"
msgid "Available Rules"
msgstr "利用可能なルール"
msgid "Before"
msgstr "前に挿入"
msgid "Choose port(s) from Available Ports. "
msgstr "以下の利用可能なポートからポートを選択してください。"
msgid ""
"Choose rule(s) from Available Rules to Selected Rule by push button or drag "
"and drop, you may change their order by drag and drop as well."
msgstr ""
"利用可能なルールから選択済みルールに、ボタンを押すかドラッグアンドドロップす"
"ることでルールを選択します。ドラッグアンドドロップでルールの順番を変更するこ"
"ともできます。"
msgid ""
"Choose the rule you want to insert. Specify either the rule you want to "
"insert immediately before, or the rule to insert immediately after. If both "
"are specified, the prior takes precedence."
msgstr ""
"挿入するルールを選択してください。ルールをどのルールの直前、または直後に挿入"
"するかを指定してください。両方指定した場合は指定したルールの直前に挿入されま"
"す。"
msgid "Choose the rule you want to remove."
msgstr "削除するルールを選択してください。"
msgid "Create Firewall Group"
msgstr "ファイアウォールグループの作成"
msgid "Create a Firewall Group with selected ports."
msgstr "ポートを選択してファイアウォールグループを作成します。"
msgid ""
"Create a firewall group based on a policy.\n"
"\n"
"A firewall group represents a logical firewall resource that a tenant can "
"instantiate and manage. A firewall group must be associated with one policy, "
"all other fields are optional."
msgstr ""
"ポリシーに基づいてファイアウォールグループを作成します。\n"
"\n"
"ファイアウォールグループは、テナントがインスタンス化して管理することのできる"
"論理的なファイアウォールリソースを表します。1 つのファイアウォールグループは "
"1 つのポリシーと関連付けられる必要があり、他のフィールドはすべて省略可能で"
"す。"
msgid ""
"Create a firewall policy with an ordered list of firewall rules.\n"
"\n"
"A firewall policy is an ordered collection of firewall rules. So if the "
"traffic matches the first rule, the other rules are not executed. If the "
"traffic does not match the current rule, then the next rule is executed. A "
"firewall policy has the following attributes:\n"
"\n"
"<li>Shared: A firewall policy can be shared across tenants. Thus it can also "
"be made part of an audit workflow wherein the firewall policy can be audited "
"by the relevant entity that is authorized.</li><li>Audited: When audited is "
"set to True, it indicates that the firewall policy has been audited. Each "
"time the firewall policy or the associated firewall rules are changed, this "
"attribute will be set to False and will have to be explicitly set to True "
"through an update operation.</li>\n"
"The name field is required, all others are optional."
msgstr ""
"ファイアウォールルールの順序付きリストでファイアウォールポリシーを作成しま"
"す。\n"
"\n"
"ファイアウォールポリシーは、ファイアウォールルールの順序付きコレクションなの"
"で、トラフィックが最初のルールに一致した場合には、他のルールは実行されませ"
"ん。トラフィックが現在のルールに一致しない場合には、次のルールが実行されま"
"す。ファイアウォールポリシーには、以下の属性があります。\n"
"\n"
"<li>共有: ファイアウォールポリシーをテナント間で共有できます。そのため、承認"
"済みの関連エンティティーによってファイアウォールポリシーを監査することができ"
"る監査ワークフローの一部にすることも可能です。</li><li>監査: 監査が True に設"
"定されている場合には、ファイアウォールポリシーが監査されることを意味します。"
"ファイアウォールポリシーまたは関連付けられたファイアウォールルールが変更され"
"るたびに、この属性は False に設定され、更新操作で明示的に True に設定する必要"
"があります。</li>\n"
"名前のフィールドは入力する必要があり、その他のフィールドはすべて省略可能で"
"す。"
msgid ""
"Create a firewall rule.\n"
"\n"
"A Firewall rule is an association of the following attributes:\n"
"\n"
"<li>IP Addresses: The addresses from/to which the traffic filtration needs "
"to be applied.</li><li>IP Version: The type of IP packets (IP V4/V6) that "
"needs to be filtered.</li><li>Protocol: Type of packets (UDP, ICMP, TCP, "
"Any) that needs to be checked.</li><li>Action: Action is the type of "
"filtration required, it can be Reject/Deny/Allow data packets.</li>\n"
"The protocol and action fields are required, all others are optional."
msgstr ""
"ファイアウォールルールを作成します。\n"
"\n"
"ファイアウォールルールは、以下の属性の組み合わせです。\n"
"\n"
"<li>IP アドレス: トラフィックフィルターを適用する必要があるアドレス (送信元/"
"送信先) です。</li><li>IP バージョン: フィルタリングする必要がある IP パケッ"
"トの種別 (IP V4/V6) です。</li><li>プロトコル: チェックされる必要があるパケッ"
"トの種別 (UDP、ICMP、TCP、Any) です。</li><li>アクション: アクションは必要な"
"フィルターの種別で、データパケットを REJECT/DENY/ALLOW できます。</li>\n"
"プロトコルとアクションは必須項目であり、他のフィールドはすべて省略可能です。"
msgid "Create a policy with selected rules."
msgstr "ルールを選択してポリシーを作成します。"
msgctxt "Current status of a Firewall Group"
msgid "Created"
msgstr "作成済み"
msgid "DENY"
msgstr "DENY"
msgctxt "Action Name of a Firewall Rule"
msgid "DENY"
msgstr "DENY"
msgctxt "Admin state of a Firewall Group"
msgid "DOWN"
msgstr "DOWN"
msgid "Delete Firewall Group"
msgid_plural "Delete Firewall Groups"
msgstr[0] "ファイアウォールグループの削除"
msgid "Delete Policy"
msgid_plural "Delete Policies"
msgstr[0] "ポリシーの削除"
msgid "Delete Rule"
msgid_plural "Delete Rules"
msgstr[0] "ルールの削除"
msgid "Description"
msgstr "説明"
msgid "Description:"
msgstr "説明:"
msgid "Destination IP"
msgstr "宛先 IP アドレス"
msgid "Destination IP Address"
msgstr "宛先 IP アドレス"
msgid "Destination IP Address/Subnet"
msgstr "宛先 IP アドレス/サブネット"
msgid "Destination IP address or subnet"
msgstr "宛先 IP アドレスまたはサブネット"
msgid "Destination Port"
msgstr "宛先ポート番号"
msgid "Destination Port/Port Range"
msgstr "宛先ポート/ポートの範囲"
msgid "Destination port (integer in [1, 65535] or range in a:b)"
msgstr "宛先ポート ([1, 65535] の整数か a:b 形式の範囲)"
msgctxt "Current status of a Firewall Group"
msgid "Down"
msgstr "停止中"
msgid "Edit Firewall Group"
msgstr "ファイアウォールグループの編集"
msgid "Edit FirewallGroup {{ name }}"
msgstr "ファイアウォールグループ {{ name }} の編集"
msgid "Edit Policy"
msgstr "ポリシーの編集"
msgid "Edit Policy {{ name }}"
msgstr "ポリシー {{ name }} の編集"
msgid "Edit Rule"
msgstr "ルールの編集"
msgid "Edit Rule {{ name }}"
msgstr "ルール {{ name }} の編集"
msgid "Egress Policy"
msgstr "送信ポリシー"
msgid "Egress Policy ID"
msgstr "送信ポリシー ID"
msgid "Enabled"
msgstr "有効"
msgctxt "Current status of a Firewall Group"
msgid "Error"
msgstr "エラー"
#, python-format
msgid "Failed to add the port(s) to the firewall group %(name)s: %(reason)s"
msgstr ""
"ポートのファイアウォールグループ %(name)s への追加に失敗しました: %(reason)s"
#, python-format
msgid "Failed to insert rule to policy %(name)s: %(reason)s"
msgstr "ポリシー %(name)s へのルールの挿入に失敗しました: %(reason)s"
#, python-format
msgid "Failed to remove rule from policy %(name)s: %(reason)s"
msgstr "ポリシー %(name)s からのルールの削除に失敗しました: %(reason)s"
#, python-format
msgid ""
"Failed to remove the port(s) from the firewall group %(name)s: %(reason)s"
msgstr ""
"ポートのファイアウォールグループ %(name)s からの削除に失敗しました: "
"%(reason)s"
#, python-format
msgid "Failed to retrieve available rules: %s"
msgstr "利用可能なルールの取得に失敗しました: %s"
#, python-format
msgid "Failed to retrieve current rules in policy %(name)s: %(reason)s"
msgstr "ポリシー %(name)s の現在のルールの取得に失敗しました: %(reason)s"
msgid "Failed to retrieve port list of the firewall group."
msgstr "ファイアウォールグループのポート一覧を取得できません。"
#, python-format
msgid "Failed to update firewall group %(name)s: %(reason)s"
msgstr "ファイアウォールグループ %(name)s の更新に失敗しました: %(reason)s"
#, python-format
msgid "Failed to update policy %(name)s: %(reason)s"
msgstr "ポリシー %(name)s の更新に失敗しました: %(reason)s"
#, python-format
msgid "Failed to update rule %(name)s: %(reason)s"
msgstr "ルール %(name)s の更新に失敗しました: %(reason)s"
msgid "Firewall Groups"
msgstr "ファイアウォールグループ"
msgid "Firewall Policies"
msgstr "ファイアウォールポリシー"
msgid "Firewall Rules"
msgstr "ファイアウォールルール"
#, python-format
msgid "Firewall group %s was successfully updated."
msgstr "ファイアウォールグループ %s が正常に更新されました。"
msgid "FirewallGroup"
msgstr "ファイアウォールグループ"
msgid "ICMP"
msgstr "ICMP"
msgid "ID"
msgstr "ID"
msgid "IP Version"
msgstr "IP バージョン"
msgid "IP Version for Firewall Rule"
msgstr "ファイアウォールルールの IP バージョン"
msgctxt "Current status of a Firewall Group"
msgid "Inactive"
msgstr "非稼働"
msgid "Ingress Policy"
msgstr "受信ポリシー"
msgid "Ingress Policy ID"
msgstr "受信ポリシー ID"
msgid "Insert Rule"
msgstr "ルールの挿入"
msgid "Insert Rule to Policy"
msgstr "ポリシーへのルールの挿入"
msgid "Label"
msgstr "ラベル"
msgid "Name"
msgstr "名前"
msgid "No options available"
msgstr "利用可能なオプションはありません"
msgid "None"
msgstr "なし"
msgctxt "Current status of a Firewall Group"
msgid "Pending Create"
msgstr "作成待ち"
msgctxt "Current status of a Firewall Group"
msgid "Pending Delete"
msgstr "削除待ち"
msgctxt "Current status of a Firewall Group"
msgid "Pending Update"
msgstr "更新待ち"
msgid "Policies"
msgstr "ポリシー"
msgid "Policy"
msgstr "ポリシー"
#, python-format
msgid "Policy %s was successfully updated."
msgstr "ポリシー %s が正常に更新されました。"
msgid "Ports"
msgstr "ポート"
msgid "Project ID"
msgstr "プロジェクト ID"
msgid "Protocol"
msgstr "プロトコル"
msgid "Protocol for the firewall rule"
msgstr "ファイアウォールルールのプロトコル"
msgid "REJECT"
msgstr "REJECT"
msgctxt "Action Name of a Firewall Rule"
msgid "REJECT"
msgstr "REJECT"
msgid "Remove Port"
msgstr "ポートの削除"
msgid "Remove Port from Firewall Group"
msgstr "ファイアウォールグループからのポートの削除"
msgid "Remove Rule"
msgstr "ルールの削除"
msgid "Remove Rule from Policy"
msgstr "ポリシーからのルールの削除"
msgid "Remove port from FirewallGroup {{ name }}"
msgstr "ファイアウォールグループ {{ name }} からのポートの削除"
#, python-format
msgid "Removed the port(s) from the firewall group %s successfully."
msgstr "ポートを正常にファイアウォールグループ %s から削除しました。"
msgid "Rule"
msgstr "ルール"
#, python-format
msgid "Rule %(rule)s was successfully inserted to policy %(policy)s."
msgstr "ルール %(rule)s のポリシー %(policy)s への挿入に成功しました。"
#, python-format
msgid "Rule %(rule)s was successfully removed from policy %(policy)s."
msgstr "ポリシー %(policy)s からのルール %(rule)s の削除に成功しました。"
#, python-format
msgid "Rule %s was successfully updated."
msgstr "ルール %s が正常に更新されました。"
msgid "Rules"
msgstr "ルール"
msgid "Save Changes"
msgstr "変更の保存"
msgid "Scheduled deletion of Firewall Group"
msgid_plural "Scheduled deletion of Firewall Groups"
msgstr[0] "ファイアウォールグループの削除を予約しました"
msgid "Scheduled deletion of Policy"
msgid_plural "Scheduled deletion of Policies"
msgstr[0] "ポリシーの削除を予約しました"
msgid "Scheduled deletion of Rule"
msgid_plural "Scheduled deletion of Rules"
msgstr[0] "ルールの削除を予約しました"
msgid "Select a Policy"
msgstr "ポリシーを選択してください"
msgid "Select ports for your firewall group."
msgstr "ファイアウォールグループを適用するポートを選択してください。"
msgid "Select rules for your policy."
msgstr "ポリシーに追加するルールの選択"
msgid "Selected Ports"
msgstr "選択済みポート"
msgid "Selected Rules"
msgstr "選択済みのルール"
msgid "Shared"
msgstr "共有"
msgid "Source IP"
msgstr "送信元 IP"
msgid "Source IP Address"
msgstr "送信元 IP アドレス"
msgid "Source IP Address/Subnet"
msgstr "送信元 IP アドレス/サブネット"
msgid "Source IP address or subnet"
msgstr "送信元 IP アドレスまたはサブネット"
msgid "Source Port"
msgstr "送信元ポート番号"
msgid "Source Port/Port Range"
msgstr "送信元ポート/ポートの範囲"
msgid "Source port (integer in [1, 65535] or range in a:b)"
msgstr "送信元ポート ([1, 65535] の整数か a:b 形式の範囲)"
msgid ""
"Source/Destination Network Address and IP version are inconsistent. Please "
"make them consistent."
msgstr ""
"送信元 / 送信先のネットワークアドレスと IP バージョンが一致していません。これ"
"らを一致させてください。"
msgid "Status"
msgstr "ステータス"
msgid "TCP"
msgstr "TCP"
msgid "UDP"
msgstr "UDP"
msgctxt "Admin state of a Firewall Group"
msgid "UP"
msgstr "UP"
#, python-format
msgid "Unable to add Firewall Group \"%s\"."
msgstr "ファイアウォールグループ \"%s\" を追加できません。"
#, python-format
msgid "Unable to add Policy \"%s\"."
msgstr "ポリシー \"%s\" を追加できません。"
#, python-format
msgid "Unable to add Rule \"%s\"."
msgstr "ルール \"%s\" を追加できません。"
#, python-format
msgid "Unable to delete firewall group. %s"
msgstr "ファイアウォールグループを削除できません: %s"
#, python-format
msgid "Unable to delete policy. %s"
msgstr "ポリシーを削除できません: %s"
#, python-format
msgid "Unable to delete rule. %s"
msgstr "ルールを削除できません: %s"
msgid "Unable to retrieve firewall group details."
msgstr "ファイアウォールグループの詳細を取得できません。"
msgid "Unable to retrieve firewall group list."
msgstr "ファイアウォールグループの一覧を取得できません。"
msgid "Unable to retrieve firewallgroup details."
msgstr "ファイアウォールグループの詳細を取得できません。"
msgid "Unable to retrieve policies list."
msgstr "ポリシー一覧を取得できません。"
msgid "Unable to retrieve policy details."
msgstr "ポリシーの詳細を取得できません。"
#, python-format
msgid "Unable to retrieve policy list (%s)."
msgstr "ポリシー覧を取得できません (%s)"
msgid "Unable to retrieve policy list."
msgstr "ポリシー一覧を取得できません。"
#, python-format
msgid "Unable to retrieve ports (%s)."
msgstr "ポートを取得できません (%s)"
msgid "Unable to retrieve rule details."
msgstr "ルールの詳細を取得できません。"
#, python-format
msgid "Unable to retrieve rules (%s)."
msgstr "ルール一覧を取得できません (%s)"
msgid "Unable to retrieve rules list."
msgstr "ルール一覧を取得できません。"
msgid "Value"
msgstr "値"
msgid "You may add ports to firewall group here."