Retire Packaging Deb project repos

This commit is part of a series to retire the Packaging Deb
project. Step 2 is to remove all content from the project
repos, replacing it with a README notification where to find
ongoing work, and how to recover the repo if needed at some
future point (as in
https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project).

Change-Id: Ia695114b58b3acc31bfb5857aa2483c9e92d7f92
This commit is contained in:
Tony Breeds 2017-09-12 15:43:00 -06:00
parent 4edc55fff8
commit 5ffa7838e9
182 changed files with 14 additions and 12390 deletions

View File

@ -1,7 +0,0 @@
[run]
branch = True
source = networking_nec
omit = networking_nec/tests/*,networking_nec/openstack/*
[report]
ignore_errors = True

27
.gitignore vendored
View File

@ -1,27 +0,0 @@
*.py[cod]
# Packages
*.egg-info
dist/
# Unit test / coverage reports
cover/
.coverage
.tox
.testrepository
.venv
# Translations
*.mo
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
.*sw?

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/networking-nec.git

View File

@ -1,3 +0,0 @@
# Format is:
# <preferred e-mail> <other e-mail 1>
# <preferred e-mail> <other e-mail 2>

View File

@ -1,89 +0,0 @@
# The format of this file isn't really documented; just use --generate-rcfile
[MASTER]
# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
#
# Note the 'openstack' below is intended to match only
# networking_nec.openstack.common. If we ever have another 'openstack'
# dirname, then we'll need to expand the ignore features in pylint :/
ignore=.git,tests,openstack
[MESSAGES CONTROL]
# NOTE(gus): This is a long list. A number of these are important and
# should be re-enabled once the offending code is fixed (or marked
# with a local disable)
disable=
# "F" Fatal errors that prevent further processing
# flake8 detects import-error
import-error,
# "I" Informational noise
locally-disabled,
# "E" Error for important programming issues (likely bugs)
# "W" Warnings for stylistic problems or minor programming issues
attribute-defined-outside-init,
broad-except,
fixme,
global-statement,
no-init,
protected-access,
unpacking-non-sequence,
unused-argument,
unused-import,
# "C" Coding convention violations
# pylint check is not compatible with flake8
bad-continuation,
invalid-name,
missing-docstring,
# "R" Refactor recommendations
duplicate-code,
interface-not-implemented,
no-self-use,
too-few-public-methods,
too-many-ancestors,
too-many-arguments,
too-many-return-statements,
[BASIC]
# Variable names can be 1 to 31 characters long, with lowercase and underscores
variable-rgx=[a-z_][a-z0-9_]{0,30}$
# Argument names can be 2 to 31 characters long, with lowercase and underscores
argument-rgx=[a-z_][a-z0-9_]{1,30}$
# Method names should be at least 3 characters long
# and be lowecased with underscores
method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$
# Module names matching neutron-* are ok (files in bin/)
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$
# Don't require docstrings on tests.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=79
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
# _ is used by our localization
dummy-variables-rgx=^(__[A-Za-z0-9_]*[A-Za-z0-9]|__)$
[CLASSES]
# List of interface methods to ignore, separated by a comma.
ignore-iface-methods=
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=
# should use openstack.common.jsonutils
json
[TYPECHECK]
# List of module names for which member attributes should not be checked
ignored-modules=six.moves,_MovedItems
[REPORTS]
# Tells whether to display a full report or only the messages
reports=no

View File

@ -1,8 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1 +0,0 @@
doc/source/contributing.rst

View File

@ -1,4 +0,0 @@
networking-nec Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

176
LICENSE
View File

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -1,6 +0,0 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

14
README Normal file
View File

@ -0,0 +1,14 @@
This project is no longer maintained.
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".
For ongoing work on maintaining OpenStack packages in the Debian
distribution, please see the Debian OpenStack packaging team at
https://wiki.debian.org/OpenStack/.
For any further questions, please email
openstack-dev@lists.openstack.org or join #openstack-dev on
Freenode.

View File

@ -1,33 +0,0 @@
===================================================
Neutron plugins/drivers for NEC networking products
===================================================
.. warning::
The current plugin, NEC OpenFlow plugin, is deprecated in
OpenStack Liberty release (2015.2).
A new driver for NEC NWA (Network Automation) product is coming.
Note that the production support will be continued based
on the production support policy.
``networking-nec`` library provides Neutron plugins/drivers
for `NEC SDN`_ networking products` (mainly OpenFlow related at now)
and `Trema`_ `Sliceable Switch`_ (reference implementation).
In 2015.1 release (Kilo development cycle) in OpenStack, Neutron
community decided to decompose vendor plugins/drivers from the neutron
code repo to address many pain points. NEC OpenFlow Neutron plugin is
maintained in a separate module.
* Documentation: https://wiki.openstack.org/wiki/Neutron/NEC_OpenFlow_Plugin
* Source:
* http://git.openstack.org/cgit/openstack/networking-nec
* https://github.com/openstack/networking-nec
* Bugs: http://bugs.launchpad.net/networking-nec
* Free software: Apache license
.. _NEC SDN: http://www.necam.com/SDN/
.. _Trema: https://github.com/trema/trema
.. _Sliceable Switch: https://github.com/trema/apps/tree/master/sliceable_switch

View File

@ -1,2 +0,0 @@
[python: **.py]

View File

@ -1 +0,0 @@
../doc/source/nwa/devstack.rst

View File

@ -1,57 +0,0 @@
#!/bin/bash
# Save trace setting
NEC_XTRACE=$(set +o | grep xtrace)
set +o xtrace
# source $TOP_DIR/lib/neutron_plugins/ovs_base
source $TOP_DIR/lib/neutron_plugins/openvswitch_agent
# The followig functions are from the above openvswitch_agent.
# If some change is needed, let's redefine the function.
#
# neutron_plugin_create_nova_conf
# neutron_plugin_install_agent_packages
# neutron_plugin_configure_debug_command
# neutron_plugin_configure_dhcp_agent
# neutron_plugin_configure_l3_agent
# neutron_plugin_configure_plugin_agent
# neutron_plugin_setup_interface_driver
# neutron_plugin_check_adv_test_requirements
# Neutron-server functions required by devstack neutron plugin interfaces.
function neutron_plugin_configure_common {
Q_PLUGIN_CONF_PATH=etc/neutron/plugins/nec
Q_PLUGIN_CONF_FILENAME=necnwa.ini
Q_PLUGIN_CLASS="necnwa"
if [ -n "$NECNWA_L3_PLUGIN" ]; then
_neutron_service_plugin_class_add $NECNWA_L3_PLUGIN
fi
local plugin_conf_src_abspath=${NETWORKING_NEC_DIR}/${Q_PLUGIN_CONF_PATH}
local plugin_conf_sys_abspath=/${Q_PLUGIN_CONF_PATH}
mkdir -p ${plugin_conf_sys_abspath}
cp ${plugin_conf_src_abspath}/${Q_PLUGIN_CONF_FILENAME} ${plugin_conf_sys_abspath}/
cp ${plugin_conf_src_abspath}/resource_group.json ${plugin_conf_sys_abspath}/
chmod 0644 /${Q_PLUGIN_CONF_PATH}/${Q_PLUGIN_CONF_FILENAME}
}
function neutron_plugin_configure_service {
iniset /$Q_PLUGIN_CONF_FILE NWA server_url $NECNWA_SERVER_URL
iniset /$Q_PLUGIN_CONF_FILE NWA access_key_id $NECNWA_ACCESS_KEY_ID
iniset /$Q_PLUGIN_CONF_FILE NWA secret_access_key $NECNWA_SECRET_ACCESS_KEY
iniset /$Q_PLUGIN_CONF_FILE NWA use_necnwa_router $NECNWA_USE_NECNWA_ROUTER
}
# NEC plugin specific functions
function start_nwa_agent {
run_process nwa-agt "$NEUTRON_BIN_DIR/neutron-necnwa-agent --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
}
function populate_nwa_database {
$NEUTRON_BIN_DIR/neutron-db-manage --subproject networking-nec --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
}
# Restore xtrace
$NEC_XTRACE

View File

@ -1,4 +0,0 @@
function has_neutron_plugin_security_group {
# 0 means True here
return 0
}

View File

@ -1,27 +0,0 @@
NETWORKING_NEC_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
function source_plugin {
if [[ "$Q_PLUGIN" == "nec" ]]; then
source $NETWORKING_NEC_DIR/devstack/lib/nec_plugin
fi
}
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
source_plugin
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
setup_develop $NETWORKING_NEC_DIR
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
# This must be done after neutron database is populated and
# before starting neutron server.
populate_nwa_database
# It needs to be started before starting neutron-server.
# run_phase extra is too late because create_neutron_initial_network
# will be called just after start_neutron_service_and_check.
start_nwa_agent
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
:
elif [[ "$1" == "unstack" ]]; then
source_plugin
elif [[ "$1" == "clean" ]]; then
source_plugin
fi

View File

@ -1,10 +0,0 @@
#!/bin/bash
NECNWA_SERVER_URL=${NECNWA_SERVER_URL:-}
NECNWA_ACCESS_KEY_ID=${NECNWA_ACCESS_KEY_ID:-}
NECNWA_SECRET_ACCESS_KEY=${NECNWA_SECRET_ACCESS_KEY:-}
NECNWA_USE_NECNWA_ROUTER=${NECNWA_USE_NECNWA_ROUTER:-True}
NECNWA_L3_PLUGIN=${NECNWA_L3_PLUGIN:-"necnwa_router"}
# In addition to the above, you can use configurartion options
# used in devstack/lib/neutron_plugins/openvswitch_agent.

View File

@ -1,75 +0,0 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
# 'sphinx.ext.intersphinx',
# 'oslosphinx'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'networking-nec'
copyright = u'2013, OpenStack Foundation'
# 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
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
# intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -1,20 +0,0 @@
============
Contributing
============
If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
http://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/networking-nec

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

View File

@ -1,59 +0,0 @@
.. networking-nec documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
===========================================
Neutron plugins for NEC networking products
===========================================
``networking-nec`` library provides Neutron plugins/drivers
for `NEC SDN <http://www.necam.com/SDN/>`_ networking products.
* Documentation: http://networking-nec.readthedocs.org/
* Source: http://git.openstack.org/cgit/openstack/networking-nec
* Bugs: http://bugs.launchpad.net/networking-nec
* License: Apache License 2.0
NEC NWA plugin
==============
In Mitaka release, NWA plugin was added as a new integration layer
with NEC NWA (Network Automation) product.
NWA plugin consists of layer-2 core plugin and layer-3 service plugin.
.. toctree::
:maxdepth: 1
nwa/readme
nwa/installation
nwa/settings
nwa/devstack
NEC OpenFlow plugin
===================
NEC OpenFlow plugin in Liberty or older releases supported
`NEC ProgrammableFlow controller <http://www.necam.com/SDN/>`_ and
`Trema <https://github.com/trema/trema>`_
`Sliceable Switch <https://github.com/trema/apps/tree/master/sliceable_switch>`_
(as reference implementation).
.. warning::
NEC OpenFlow plugin was deprecated in OpenStack Liberty release (2015.2)
and removed during Mitaka development cycle.
Note that the production support will be continued based
on the production support policy.
The documentation on NEC OpenFlow plugin is found at
http://networking-nec.readthedocs.org/en/stable-liberty/.
Developers Guide
================
.. toctree::
:maxdepth: 2
tips
contributing

View File

@ -1,47 +0,0 @@
.. _nwa-devstack:
===============================
DevStack support for NWA plugin
===============================
This DevStack external plugin installs NEC plugin library
so that Neutron NEC NWA plugin can be enabled.
To use this DevStack plugin, add the following to your local.conf::
enable_plugin networking-nec https://git.openstack.org/openstack/networking-nec [<branch>]
Examples
========
Minimum sample local.conf::
[[local|localrc]]
# Enable neutron services
disable_service n-net
enable_service neutron q-svc q-agt
enable_service q-dhcp
enable_service q-meta
# NEC plugin
Q_PLUGIN=nec
enable_plugin networking-nec https://git.openstack.org/openstack/networking-nec
# NWA server configurations
NECNWA_SERVER_URL="http://127.0.0.1:12081"
NECNWA_ACCESS_KEY_ID="mjivAk6O3G4Ko/0mD8mHUyQwqugEPgTe0FSli8REyN4="
NECNWA_SECRET_ACCESS_KEY="/3iSORtq1E3F+SQtQg6YN00eM3GUda0EKqWDUV/mvqo="
# Run neutron-nwa-agent
enable_service nwa-agt
[[post-config|/etc/neutron/dhcp_agent.ini]]
[DEFAULT]
enable_isolated_metadata = True
References
==========
* `DevStack externally hosted plugins`_
.. _DevStack externally hosted plugins: http://docs.openstack.org/developer/devstack/plugins.html#externally-hosted-plugins

View File

@ -1,30 +0,0 @@
==============================
Installation of NEC NWA plugin
==============================
Requirements
============
To use the NWA plugin, NWA made by NEC is needed.
After an OpenStack installation, you need to install networking-nec
Python package, configure the physical network by NWA and configure
the NWA plugin.
Running with DevStack
=====================
See :ref:`nwa-devstack`
Manual Installation
===================
The released versions of Python module is available at
https://pypi.python.org/pypi/networking-nec.
To install::
pip install networking-nec~=2.0
NEC NWA plugin is available from version ``2.0.0`` or later.
The ``2.y.z`` series of networking-nec supports Neutron Mitaka release.

View File

@ -1,22 +0,0 @@
==============================
Introduction of NEC NWA plugin
==============================
.. toctree::
:maxdepth: 1
Installation <installation>
Settings <settings>
DevStack support <devstack>
The NWA plugin consists of plugin driver and agent.
Using this plugin, you can operate an SDN controller (MasterScope
Network Automation) made by NEC from OpenStack CLI or Dashboard.
NWA can build a large scale layer 2 network which removes the 4K VLAN
limit.
So you can use the NWA plugin to create, update and delete the network
through OpenStack environment.
.. image:: ../images/necnwa-plugin-design.png
:width: 700px

View File

@ -1,187 +0,0 @@
===============================
Setting of NEC NWA plugin
===============================
This section describes the configurations of the releases of NEC NWA plugin.
neutron.conf
============
* **core_plugin**: Needs to be configured to ``necnwa`` to use NEC NWA
plugin as core plugin. ::
core_plugin = necnwa
* **service_plugin**: Needs to be configured to ``necnwa_router`` to use
NEC NWA plugin as service plugin. ::
service_plugin = necnwa_router
plugin specific configuration
=============================
It is usually placed at ``/etc/neutron/plugins/nec/necnwa.ini``.
[ml2] section
-------------
* **type_drivers**: Needs to be configured to ``vlan`` to use NEC NWA
plugin as type_drivers. ::
type_drivers = vlan
* **tenant_network_types**: Needs to be configured to ``vlan`` to use
NEC NWA plugin as tenant_network_types. ::
tenant_network_types = vlan
* **mechanism_drivers**: Needs to be configured to ``necnwa`` and
``openvswitch`` to use NEC NWA plugin as mechanism_drivers. ::
mechanism_drivers = necnwa,openvswitch
[ml2_type_vlan] section
-----------------------
* **network_vlan_ranges**: Specify the name of an available physical
network and a range of VIDs on that network available for allocation
to tenant networks. The physical network should be the same name of
NWA resource group name. ::
network_vlan_ranges = OpenStack/DC/APP:1000:2999,OpenStack/DC/HA1:10:2999,OpenStack/DC/HA2:10:2999
[ovs] section
-------------
* **bridge_mappings**: Specify list of <physical_network>:<bridge>
tuples, each specifying an OVS bridge used by the agent for a
physical network to which it is connected. ::
bridge_mappings = OpenStack/DC/HA1:br-eth1,OpenStack/DC/HA2:br-eth2
[NWA] section
-------------
* **server_url**: The URL of the http/https server listening for NWA
RESTful API::
server_url = http://192.168.122.1:12081
* **access_key_id**: The access key ID of NWA RESTful API server. The
access key consists of an access key ID and secret access key, which
are used to sign RESTful API requests that you make to NWA. ::
access_key_id = mjivAk6O3G4Ko/0mD8mHUyQwqugEPgTe0FSli8REyN4=
* **secret_access_key**: The secret access key of NWA Restful API
server. The access key consists of an access key ID and secret
access key, which are used to sign RESTful API requests that you
make to NWA. ::
secret_access_key = /3iSORtq1E3F+SQtQg6YN00eM3GUda0EKqWDUV/mvqo=
* **resource_group_name**: A default rerouce group name when NWA
tenant is created. ::
resource_group_name = OpenStack/DC/APP
* **scenario_polling_timer**: Specifies the polling interval of the
scenario in seconds. ::
scenario_polling_timer = 5
* **scenario_polling_count**: Specifies the polling counts of the
scenario. ::
scenario_polling_count = 300
* **region_name**: A region name (It is the prefix of NWA tenant name). ::
region_name = T01DC
* **resource_group_file**: Load the table of NWA resource group
from the file. ::
resource_group_file = resource_group.json
* **use_necnwa_router**: If you use OpenStack L3 Router instead of NEC NWA Router,
it set to False. The default value is True. ::
use_necnwa_router = True
* **use_neutron_vlan_id**: If you want to use a vlan id which is
assigned by neutron, it set to True. The default value is False. In
case of False, the vlan id will be assigned by NWA. ::
use_neutron_vlan_id = True
NWA resource group file
=======================
It is usually placed at
"/etc/neutron/plugins/nec/resource_group.json."
This file contains a table of NWA resource group. The format of the
file is JSON.
The ``physical_network`` is a name of physical network which is used
in neutron. It should be set to the same value as
``ResourceGroupName`` member.
The ``device_owner`` is the owner of the device in OpenStack.
It is specified as ``compute:AVAILABILITY_ZONE``, the VM that has a
nova boot option ``--available-zone`` is created on the physical
network corresponding with the device owner.
If the option ``--available-zone`` is not specified in nova boot,
regarded as ``compute:None`` has been specified.
All available DHCP agent in OpenStack specifies as ``network:dhcp``.
The ``ResourceGroupName`` is a name of NWA's resource group name.
::
[
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "compute:DC01_KVM01_ZONE01",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "compute:DC01_KVM02_ZONE02",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "compute:None",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "compute:None",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "network:dhcp",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "network:dhcp",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/APP",
"device_owner": "network:router_gateway",
"ResourceGroupName": "OpenStack/DC/APP"
},
{
"physical_network": "OpenStack/DC/APP",
"device_owner": "network:router_interface",
"ResourceGroupName": "OpenStack/DC/APP"
},
]

View File

@ -1,147 +0,0 @@
================
Development Tips
================
Release package
---------------
Create a specific release
~~~~~~~~~~~~~~~~~~~~~~~~~
The following steps are required to release a package.
* (Create a stable branch if necessary)
* Add a signed tag to the repository
.. code-block:: console
git checkout stable/xxxx (if necessary)
git tag -s <version number>
git show <version number>
git push gerrit <version number>
.. warning::
Before pushing a tag to gerrit, you are strongly suggested to
test whether a generated package works as expected.
.. code-block:: console
git checkout <version number>
python setup.py sdist
pip install dist/networking-nec-<version number>.tar.gz
To push a tag to gerrit, you must be a member of
``networking-nec-release`` gerrit group.
* Push a release package to PyPI.
.. code-block:: console
git checkout <version number>
python setup.py sdist upload
Once the upload succeeded, you can find a new release at
https://pypi.python.org/pypi/networking-nec.
Before uploading a package to PyPI, you need to create your PyPI
account and prepare a proper credential file ``~/.pypirc`` like below.
.. code-block:: ini
[distutils]
index-servers =
pypi
[pypi]
repository=https://pypi.python.org/pypi
username=<your username>
password=<your password>
Create a stable branch
~~~~~~~~~~~~~~~~~~~~~~
The detail is available at:
http://docs.openstack.org/infra/manual/drivers.html#release-management.
To create a (stable) branch, you must be a member of
``networking-nec-release`` gerrit group.
More information
~~~~~~~~~~~~~~~~
Most of the release process is explained in
`OpenStack Infrastructure User Manual
<http://docs.openstack.org/infra/manual/>`_.
Requirements update
-------------------
In OpenStack projects, requirements.txt and test-requirements.txt
should be synced with ``global-requirements.txt`` in
http://git.openstack.org/cgit/openstack/requirements/tree/.
To sync requirements manually:
1. Check out requirements repository:
.. code-block:: console
git clone https://git.openstack.org/openstack/requirements
2. Run update.py:
.. code-block:: console
cd requirements
tox -e venv -- python update.py <networking-nec top directory>
To sync it automatically, you need to:
* setup the jenkins job ``gate-{name}-requirements``
(it is usually unnecessary as ``python-jobs`` contains it),
* add ``check-requirements`` to ``zuul/layout.yaml`` in
project-config, and
* add ``openstack/networking-nec`` to ``projects.txt`` in the
requirements project.
Documentation
-------------
Build documentation
~~~~~~~~~~~~~~~~~~~
To build the documentation:
.. code-block:: console
tox -e docs
and the generated documentation will be found under ``doc/build/html``.
Publish documentation
~~~~~~~~~~~~~~~~~~~~~
The document is hosted by `Read The Docs <https://readthedocs.org/>`__
and the documentation is available at
http://networking-nec.readthedocs.org/en/latest/.
To publish the latest documentation,
visit the `project page <https://readthedocs.org/projects/networking-nec/>`__,
go to **Builds** and click **Build version** after selecting **latest**.
After completing the build, the status will be **Passed** and
you can see the new document.
If the build fails, investigate reasons of the failure.
Third party CI
--------------
* The master information about setting up and operating a third party CI
is available at
http://docs.openstack.org/infra/system-config/third_party.html.
It is better to check this site regularly.
* The status of your third party CI system should be available at
https://wiki.openstack.org/wiki/ThirdPartySystems.
For example, you have a planned power blackout, it is encouraged
to update the corresponding page.

View File

@ -1,29 +0,0 @@
[ml2]
type_drivers = vlan
tenant_network_types = vlan
mechanism_drivers = necnwa,openvswitch
path_mtu = 0
[ml2_type_flat]
[ml2_type_vlan]
network_vlan_ranges = OpenStack/DC/APP:1000:2999,OpenStack/DC/HA1:10:2999,OpenStack/DC/HA2:10:2999
[ml2_type_gre]
[ml2_type_vxlan]
[securitygroup]
enable_security_group = True
[NWA]
server_url = http://192.168.122.166:12081
access_key_id = mjivAk6O3G4Ko/0mD8mHUyQwqugEPgTe0FSli8REyN4=
secret_access_key = /3iSORtq1E3F+SQtQg6YN00eM3GUda0EKqWDUV/mvqo=
use_necnwa_router = True
use_neutron_vlan_id = False
resource_group_name = OpenStack/DC/APP
scenario_polling_timer = 5
scenario_polling_count = 300
region_name = T01DC
resource_group_file = resource_group.json

View File

@ -1,52 +0,0 @@
[
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "compute:DC01_KVM01_ZONE01",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "compute:DC01_KVM02_ZONE02",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "compute:None",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "compute:None",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/HA1",
"device_owner": "network:dhcp",
"ResourceGroupName": "OpenStack/DC/HA1"
},
{
"physical_network": "OpenStack/DC/HA2",
"device_owner": "network:dhcp",
"ResourceGroupName": "OpenStack/DC/HA2"
},
{
"physical_network": "OpenStack/DC/APP",
"device_owner": "network:router_gateway",
"ResourceGroupName": "OpenStack/DC/APP"
},
{
"physical_network": "OpenStack/DC/APP",
"device_owner": "network:router_interface",
"ResourceGroupName": "OpenStack/DC/APP"
},
{
"physical_network": "Common/BM/Pod2-Ironic",
"device_owner": "compute:DC01_BMT01_ZONE01",
"ResourceGroupName": "Common/BM/Pod2-Ironic"
},
{
"physical_network": "Common/BM/Pod2-Ironic",
"device_owner": "ironic:isolation",
"ResourceGroupName": "Common/BM/Pod2-Ironic"
}
]

View File

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pbr.version
__version__ = pbr.version.VersionInfo(
'networking_nec').version_string()

View File

@ -1,30 +0,0 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import oslo_i18n
_translators = oslo_i18n.TranslatorFactory(domain='networking_nec')
# The primary translation function using the well-known name "_"
_ = _translators.primary
# Translators for log levels.
#
# The abbreviated names are meant to reflect the usual use of a short
# name like '_'. The "L" is for "log" and the other letter comes from
# the level.
_LI = _translators.log_info
_LW = _translators.log_warning
_LE = _translators.log_error
_LC = _translators.log_critical

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import eventlet_utils
eventlet_utils.monkey_patch()

View File

@ -1,19 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from networking_nec.nwa.agent import nwa_agent
def main():
nwa_agent.main()

View File

@ -1,53 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import functools
from oslo_log import log
from oslo_utils import excutils
from networking_nec._i18n import _LE
LOG = log.getLogger(__name__)
def _get_full_class_name(cls):
return '%s.%s' % (cls.__module__,
getattr(cls, '__qualname__', cls.__name__))
def log_method_return_value(method):
@functools.wraps(method)
def wrapper(*args, **kwargs):
first_arg = args[0]
cls = (first_arg if isinstance(first_arg, type)
else first_arg.__class__)
data = {'class_name': _get_full_class_name(cls),
'method_name': method.__name__}
try:
ret = method(*args, **kwargs)
data['ret'] = ret
LOG.debug('%(class_name)s method %(method_name)s '
'call returned %(ret)s', data)
return ret
except Exception as e:
with excutils.save_and_reraise_exception():
data['exctype'] = e.__class__.__name__
data['reason'] = e
LOG.error(_LE('%(class_name)s method %(method_name)s '
'call raised %(exctype)s: %(reason)s'), data)
return wrapper

View File

@ -1,89 +0,0 @@
# Copyright 2015 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# pylint: disable=no-member
# Silence pylint not complain about alembic.context.
from logging import config as logging_config
from alembic import context
from neutron_lib.db import model_base
from oslo_config import cfg
from oslo_db.sqlalchemy import session
import sqlalchemy as sa
from sqlalchemy import event
MYSQL_ENGINE = None
NEC_VERSION_TABLE = 'alembic_version_networking_nec'
config = context.config
neutron_config = config.neutron_config
logging_config.fileConfig(config.config_file_name)
target_metadata = model_base.BASEV2.metadata
def set_mysql_engine():
try:
mysql_engine = neutron_config.command.mysql_engine
except cfg.NoSuchOptError:
mysql_engine = None
global MYSQL_ENGINE
MYSQL_ENGINE = (mysql_engine or
model_base.BASEV2.__table_args__['mysql_engine'])
def run_migrations_offline():
set_mysql_engine()
kwargs = {}
if neutron_config.database.connection:
kwargs['url'] = neutron_config.database.connection
else:
kwargs['dialect_name'] = neutron_config.database.engine
kwargs['version_table'] = NEC_VERSION_TABLE
context.configure(**kwargs)
with context.begin_transaction():
context.run_migrations()
@event.listens_for(sa.Table, 'after_parent_attach')
def set_storage_engine(target, parent):
if MYSQL_ENGINE:
target.kwargs['mysql_engine'] = MYSQL_ENGINE
def run_migrations_online():
set_mysql_engine()
engine = session.create_engine(neutron_config.database.connection)
connection = engine.connect()
context.configure(
connection=connection,
target_metadata=target_metadata,
version_table=NEC_VERSION_TABLE
)
try:
with context.begin_transaction():
context.run_migrations()
finally:
connection.close()
engine.dispose()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

View File

@ -1,20 +0,0 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
def upgrade():
${upgrades if upgrades else "pass"}

View File

@ -1 +0,0 @@
d86043b2d0f2

View File

@ -1,51 +0,0 @@
# Copyright 2016 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Add tables for necnwa
Revision ID: d86043b2d0f2
Revises: 978466bef2fe
Create Date: 2016-01-12 14:36:11.217570
"""
# revision identifiers, used by Alembic.
revision = 'd86043b2d0f2'
down_revision = '978466bef2fe'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table(
'nwa_tenant_key_value',
sa.Column('tenant_id', sa.String(length=36),
nullable=False, primary_key=True),
sa.Column('nwa_tenant_id', sa.String(length=64)),
sa.Column('json_key', sa.String(length=192),
nullable=False, primary_key=True),
sa.Column('json_value', sa.String(length=1024),
nullable=False, default='')
)
op.create_table(
'nwa_tenant_queue',
sa.Column('tenant_id', sa.String(length=36),
nullable=False, primary_key=True),
sa.Column('nwa_tenant_id', sa.String(length=64),
nullable=False, default=''),
sa.Column('topic', sa.String(length=122), nullable=False, default='')
)

View File

@ -1,30 +0,0 @@
# Copyright 2016 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""start networking-nec db migration
Revision ID: 978466bef2fe
Revises: None
Create Date: 2016-02-06 20:30:12.217571
"""
# revision identifiers, used by Alembic.
revision = '978466bef2fe'
down_revision = None
def upgrade():
pass

View File

@ -1,164 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import socket
import sys
import time
from neutron.agent import rpc as agent_rpc
from neutron.common import config as logging_config
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron import context as q_context
from oslo_config import cfg
from oslo_log import log as logging
from oslo_service import loopingcall
from networking_nec._i18n import _LE
from networking_nec.nwa.agent import proxy_l2
from networking_nec.nwa.agent import proxy_l3
from networking_nec.nwa.agent import proxy_tenant
from networking_nec.nwa.agent import server_manager
from networking_nec.nwa.common import constants as nwa_const
from networking_nec.nwa.l2.rpc import nwa_agent_callback
from networking_nec.nwa.l2.rpc import nwa_proxy_callback
from networking_nec.nwa.l2.rpc import tenant_binding_api
from networking_nec.nwa.l3.rpc import nwa_l3_proxy_callback
from networking_nec.nwa.nwalib import client as nwa_cli
LOG = logging.getLogger(__name__)
# pylint: disable=too-many-instance-attributes
class NECNWANeutronAgent(object):
rpc_servers = {}
topic = nwa_const.NWA_AGENT_TOPIC
def __init__(self, polling_interval):
"""Constructor.
@param polling_interval: interval (secs) to check the nwa.
"""
self.polling_interval = polling_interval
self.need_sync = True
self.conf = cfg.CONF
self.host = socket.gethostname()
self.agent_id = 'necnwa-q-agent.%s' % self.host
self.multi_dc = cfg.CONF.NWA.use_neutron_vlan_id
self.client = nwa_cli.NwaClient()
self.agent_state = {
'binary': 'neutron-necnwa-agent',
'host': cfg.CONF.host,
'topic': nwa_const.NWA_AGENT_TOPIC,
'configurations': {},
'agent_type': nwa_const.NWA_AGENT_TYPE,
'start_flag': True}
self.server_manager = server_manager.ServerManager(self.topic, self)
self.proxy_tenant = proxy_tenant.AgentProxyTenant(self, self.client)
self.proxy_l2 = proxy_l2.AgentProxyL2(self, self.client, self.multi_dc)
self.proxy_l3 = proxy_l3.AgentProxyL3(self, self.client, self.multi_dc)
self.setup_rpc()
LOG.debug('NWA Agent state %s', self.agent_state)
def setup_rpc(self):
"""setup_rpc """
self.context = q_context.get_admin_context_without_session()
self.nwa_l2_rpc = tenant_binding_api.TenantBindingServerRpcApi(
topics.PLUGIN
)
self.state_rpc = agent_rpc.PluginReportStateAPI(topics.REPORTS)
self.callback_nwa = nwa_agent_callback.NwaAgentRpcCallback(
self.context, self.server_manager)
self.callback_proxy = nwa_proxy_callback.NwaProxyCallback(
self.context, self.proxy_l2)
self.callback_l3 = nwa_l3_proxy_callback.NwaL3ProxyCallback(
self.context, self.proxy_l3)
# lbaas
self.lbaas_driver = None
self.callback_lbaas = None
if self.conf.NWA.lbaas_driver:
pass
# fwaas
self.fwaas_driver = None
self.callback_fwaas = None
if self.conf.NWA.fwaas_driver:
pass
# endpoints
self.endpoints = [self.callback_nwa,
self.callback_proxy,
self.callback_l3]
# create connection
self.conn = n_rpc.create_connection()
self.conn.create_consumer(self.topic, self.endpoints,
fanout=False)
self.conn.consume_in_threads()
report_interval = cfg.CONF.AGENT.report_interval
if report_interval:
heartbeat = loopingcall.FixedIntervalLoopingCall(
self._report_state)
heartbeat.start(interval=report_interval)
def _report_state(self):
try:
queues = self.server_manager.get_rpc_server_topics()
self.agent_state['configurations']['tenant_queues'] = len(queues)
self.state_rpc.report_state(self.context,
self.agent_state)
self.agent_state.pop('start_flag', None)
servers = self.server_manager.get_rpc_server_tenant_ids()
self.nwa_l2_rpc.update_tenant_rpc_servers(
self.context, servers
)
except Exception as e:
LOG.exception(_LE("Failed reporting state! %s"), e)
def loop_handler(self):
pass
def daemon_loop(self):
"""Main processing loop for NECNWA Plugin Agent."""
while True:
self.loop_handler()
time.sleep(self.polling_interval)
def main():
logging_config.init(sys.argv[1:])
logging_config.setup_logging()
polling_interval = cfg.CONF.AGENT.polling_interval
agent = NECNWANeutronAgent(polling_interval)
agent.daemon_loop()
if __name__ == "__main__":
main()

View File

@ -1,640 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import re
import time
from neutron.common import topics
from neutron.plugins.common import constants as plugin_const
from neutron.plugins.ml2 import driver_api as api
from oslo_log import helpers
from oslo_log import log as logging
import six
from networking_nec._i18n import _LE, _LI, _LW
from networking_nec.common import utils
from networking_nec.nwa.agent import proxy_tenant as tenant_util
from networking_nec.nwa.common import constants as nwa_const
from networking_nec.nwa.common import exceptions as nwa_exc
from networking_nec.nwa.l2.rpc import nwa_l2_server_api
from networking_nec.nwa.l2.rpc import tenant_binding_api
from networking_nec.nwa.nwalib import data_utils
LOG = logging.getLogger(__name__)
KEY_CREATE_TENANT_NW = 'CreateTenantNW'
WAIT_AGENT_NOTIFIER = 20
# WAIT_AGENT_NOTIFIER = 1
def check_vlan(network_id, nwa_data):
# dev_key = 'VLAN_' + network_id + '_.*_VlanID$'
# TFW, GDV: VLAN_' + network_id + '_.*_VlanID$
# TLB: VLAN_LB_' + network_id + '_.*_VlanID$
vlan_pat = re.compile(r'VLAN_.*' + network_id + '_.*_VlanID$')
matched = [k for k in nwa_data if vlan_pat.match(k)]
if matched:
LOG.debug("find device in network(ids=%s)", network_id)
return len(matched)
def count_device_id(device_id, nwa_data):
dev_pat = re.compile(r'DEV_' + device_id + '_')
matched = [k for k in nwa_data if dev_pat.match(k)]
if matched:
LOG.debug("found device with device_id=%s", device_id)
return len(matched)
def check_segment(network_id, res_name, nwa_data, dev_type):
dev_pat = re.compile(r'DEV_.*_' + network_id + '_' + res_name)
matched = [k for k in nwa_data
if dev_pat.match(k) and dev_type == nwa_data[k]]
if matched:
LOG.debug("find device in network(id=%(network_id)s),"
" resource_group_name=%(res_name)s, type=%(dev_type)s",
{'network_id': network_id,
'res_name': res_name,
'dev_type': dev_type})
return len(matched)
def check_segment_gd(network_id, res_name, nwa_data):
return check_segment(network_id, res_name, nwa_data,
nwa_const.NWA_DEVICE_GDV)
def check_segment_tfw(network_id, res_name, nwa_data):
return check_segment(network_id, res_name, nwa_data,
nwa_const.NWA_DEVICE_TFW)
def get_resource_group_name(nwa_info, nwa_data, dev_type):
device_id = nwa_info['device']['id']
network_id = nwa_info['network']['id']
mac = nwa_info['port']['mac']
found_mac = None
found_dev_type = None
dev_prefix = 'DEV_%s_%s_' % (device_id, network_id)
for k, v in six.iteritems(nwa_data):
if not k.startswith(dev_prefix):
continue
if v == mac:
found_mac = k[len(dev_prefix):]
elif v == dev_type:
found_dev_type = k[len(dev_prefix):]
if found_mac and found_dev_type:
return found_dev_type
class AgentProxyL2(object):
def __init__(self, agent_top, client, multi_dc=False):
self.nwa_tenant_rpc = tenant_binding_api.TenantBindingServerRpcApi(
topics.PLUGIN)
self.nwa_l2_rpc = nwa_l2_server_api.NwaL2ServerRpcApi(topics.PLUGIN)
self.agent_top = agent_top
self.client = client
self.multi_dc = multi_dc
@property
def proxy_tenant(self):
return self.agent_top.proxy_tenant
@utils.log_method_return_value
@helpers.log_method_call
def _create_tenant_nw(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
# get resource group name for NWA TenantNW.
resource_group_name = nwa_info['resource_group_name_nw']
nwa_data = kwargs.get('nwa_data')
if KEY_CREATE_TENANT_NW not in nwa_data:
LOG.debug("nwa_tenant_id=%(nwa_tenant_id)s, "
"resource_group_name_nw=%(resource_group_name)s",
{'nwa_tenant_id': nwa_tenant_id,
'resource_group_name': resource_group_name})
rcode, body = self.client.l2.create_tenant_nw(
nwa_tenant_id,
resource_group_name
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("CreateTenantNW succeed.")
nwa_data[KEY_CREATE_TENANT_NW] = True
return nwa_data
else:
LOG.error(_LE("CreateTenantNW Failed."))
raise nwa_exc.AgentProxyException(value=nwa_data)
@utils.log_method_return_value
def _delete_tenant_nw(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = kwargs.get('nwa_data')
rcode, body = self.client.l2.delete_tenant_nw(
nwa_tenant_id,
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("DeleteTenantNW SUCCEED.")
nwa_data.pop(KEY_CREATE_TENANT_NW)
else:
LOG.error(_LE("DeleteTenantNW %s."), body['status'])
raise nwa_exc.AgentProxyException(value=nwa_data)
return nwa_data
@utils.log_method_return_value
def _create_vlan(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
network_id = nwa_info['network']['id']
nw_vlan_key = data_utils.get_vlan_key(network_id)
if nw_vlan_key in nwa_data:
LOG.warning(_LW("aleady in vlan_key %s"), nw_vlan_key)
return nwa_data
rcode, body = self.client.l2.create_vlan(
nwa_tenant_id,
nwa_info['subnet']['netaddr'],
nwa_info['subnet']['mask'],
nwa_info['network']['vlan_type'],
openstack_network_id=network_id
)
if rcode == 200 and body['status'] == 'SUCCEED':
# create vlan succeed.
LOG.debug("CreateVlan succeed.")
data_utils.set_network_data(nwa_data, network_id, nwa_info,
body['resultdata']['LogicalNWName'])
data_utils.set_vlan_data(nwa_data, network_id,
body['resultdata']['VlanID'])
else:
# create vlan failed.
LOG.error(_LE("CreateVlan Failed."))
raise nwa_exc.AgentProxyException(value=nwa_data)
return nwa_data
@utils.log_method_return_value
def _delete_vlan(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
vlan_type = nwa_info['network']['vlan_type']
physical_network = nwa_info['physical_network']
network_id = nwa_info['network']['id']
# delete vlan
rcode, body = self.client.l2.delete_vlan(
nwa_tenant_id,
data_utils.get_vlan_logical_name(nwa_data, network_id),
vlan_type
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("DeleteVlan SUCCEED.")
data_utils.strip_network_data(nwa_data, network_id)
data_utils.strip_vlan_data(nwa_data, network_id)
self.nwa_l2_rpc.release_dynamic_segment_from_agent(
context, physical_network,
network_id
)
else:
LOG.debug("DeleteVlan FAILED.")
self.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id, nwa_data
)
raise nwa_exc.AgentProxyException(value=nwa_data)
return nwa_data
def _ensure_l2_network(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
network_id = nwa_info['network']['id']
LOG.debug("tenant_id=%(tenant_id)s, network_id=%(network_id)s, "
"device_owner=%(device_owner)s",
{'tenant_id': tenant_id,
'network_id': network_id,
'device_owner': nwa_info['device']['owner']})
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id
)
# create tenant
if not nwa_data:
nwa_data = self.proxy_tenant.create_tenant(context, **kwargs)
if not self.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id,
nwa_data, nwa_created=True):
return
# create tenant nw
if KEY_CREATE_TENANT_NW not in nwa_data:
# raise AgentProxyException if fail
self._create_tenant_nw(context, nwa_data=nwa_data, **kwargs)
# create vlan
nw_vlan_key = data_utils.get_network_key(network_id)
if nw_vlan_key not in nwa_data:
# raise AgentProxyException if fail
self._create_vlan(context, nwa_data=nwa_data, **kwargs)
return nwa_data
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def ensure_l2_network(self, context, **kwargs):
return self._ensure_l2_network(context, **kwargs)
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def create_general_dev(self, context, **kwargs):
"""Create GeneralDev wrapper.
@param context: contains user information.
@param kwargs:
@return: dict of status and msg.
"""
nwa_data = self._ensure_l2_network(context, **kwargs)
if not nwa_data:
return
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
network_id = nwa_info['network']['id']
resource_group_name = nwa_info['resource_group_name']
# create general dev
if not check_segment_gd(network_id, resource_group_name, nwa_data):
if self.multi_dc:
sync_vlan_id = self._create_connect_port
else:
sync_vlan_id = self._create_general_dev
# raise AgentProxyException if fail
nwa_data = sync_vlan_id(context, nwa_data=nwa_data, **kwargs)
else:
ret_val = self._create_general_dev_data(
nwa_data=nwa_data, **kwargs)
if ret_val:
nwa_data = ret_val
# agent waits for notifier issue for libviert.
time.sleep(WAIT_AGENT_NOTIFIER)
# create general dev end
ret = self.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id, nwa_data,
nwa_created=False
)
segment = {
api.PHYSICAL_NETWORK: nwa_info['physical_network'],
api.NETWORK_TYPE: plugin_const.TYPE_VLAN,
api.SEGMENTATION_ID: data_utils.get_vp_net_vlan_id(
nwa_data, network_id, resource_group_name,
nwa_const.NWA_DEVICE_GDV)
}
self.nwa_l2_rpc.update_port_state_with_notifier(
context, nwa_info['device']['id'], self.agent_top.agent_id,
nwa_info['port']['id'], segment, network_id
)
return ret
def _append_device_for_gdv(self, nwa_info, nwa_data):
network_id = nwa_info['network']['id']
device_id = nwa_info['device']['id']
resource_group_name = nwa_info['resource_group_name']
data_utils.set_gdv_device_data(nwa_data, device_id, nwa_info)
data_utils.set_gdv_interface_data(nwa_data, device_id, network_id,
resource_group_name, nwa_info)
return nwa_data
@utils.log_method_return_value
def _create_general_dev_data(self, **kwargs):
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
self._append_device_for_gdv(nwa_info, nwa_data)
return nwa_data
@utils.log_method_return_value
@helpers.log_method_call
def _create_general_dev(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
network_id = nwa_info['network']['id']
resource_group_name = nwa_info['resource_group_name']
port_type = None
rcode, body = self.client.l2.create_general_dev(
nwa_tenant_id,
resource_group_name,
data_utils.get_vlan_logical_name(nwa_data, network_id),
port_type=port_type
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("CreateGeneralDev SUCCEED")
vlan_key = data_utils.get_vlan_key(network_id)
if vlan_key not in nwa_data:
LOG.error(_LE("not create vlan."))
raise nwa_exc.AgentProxyException(value=nwa_data)
vlan_id = data_utils.get_vlan_id(network_id, nwa_data,
body['resultdata'])
data_utils.set_vp_net_data(nwa_data, network_id,
resource_group_name,
nwa_const.NWA_DEVICE_GDV,
vlan_id)
self._append_device_for_gdv(nwa_info, nwa_data)
else:
LOG.debug("CreateGeneralDev %s", body['status'])
raise nwa_exc.AgentProxyException(value=nwa_data)
return nwa_data
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def delete_general_dev(self, context, **kwargs):
"""Delete GeneralDev.
@param context: contains user information.
@param kwargs:
@return: dict of status and msg.
"""
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
network_id = nwa_info['network']['id']
resource_group_name = nwa_info['resource_group_name']
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id
)
# rpc return empty.
if not nwa_data:
LOG.error(_LE('nwa_tenant_binding not found.'
' tenant_id=%(tenant_id)s,'
' nwa_tenant_id=%(nwa_tenant_id)s'),
{'tenant_id': tenant_id,
'nwa_tenant_id': nwa_tenant_id})
return {'result': 'FAILED'}
if not resource_group_name:
resource_group_name = get_resource_group_name(
nwa_info, nwa_data, nwa_const.NWA_DEVICE_GDV)
if not resource_group_name:
LOG.debug('skip delete_general_dev.'
' No nwa device is associated with'
' the port %s', nwa_info.get('port'))
return {'result': 'FAILED'}
nwa_info['resource_group_name'] = resource_group_name
gd_count = check_segment_gd(network_id, resource_group_name, nwa_data)
if 1 < gd_count:
nwa_data = self._delete_general_dev_data(
nwa_data=nwa_data, **kwargs)
self._delete_general_dev_segment(context, nwa_data, nwa_info)
raise nwa_exc.AgentProxyException(value=nwa_data)
if self.multi_dc:
sync_vlan_id = self._delete_connect_port
else:
sync_vlan_id = self._delete_general_dev
# raise AgentProxyException if fail
nwa_data = sync_vlan_id(context, nwa_data=nwa_data, **kwargs)
# delete general dev end
return self._terminate_l2_network(context, nwa_data, **kwargs)
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def terminate_l2_network(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id)
return self._terminate_l2_network(context, nwa_data, **kwargs)
def _terminate_l2_network(self, context, nwa_data, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
network_id = nwa_info['network']['id']
# port check on segment.
if check_vlan(network_id, nwa_data):
raise nwa_exc.AgentProxyException(value=nwa_data)
# delete vlan
# raise AgentProxyException if fail
nwa_data = self._delete_vlan(context, nwa_data=nwa_data, **kwargs)
# delete vlan end.
# tenant network check.
for k in nwa_data:
if re.match('NW_.*', k):
raise nwa_exc.AgentProxyException(value=nwa_data)
LOG.info(_LI("delete_tenant_nw"))
# raise AgentProxyException if fail
nwa_data = self._delete_tenant_nw(context, nwa_data=nwa_data, **kwargs)
# delete tenant
LOG.info(_LI("delete_tenant"))
nwa_data = self.proxy_tenant.delete_tenant(
context,
nwa_data=nwa_data,
**kwargs
)
# delete tenant end.
# delete nwa_tenant binding.
LOG.info(_LI("delete_nwa_tenant_binding"))
return self.nwa_tenant_rpc.delete_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id
)
@utils.log_method_return_value
def _delete_general_dev_data(self, **kwargs):
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
device_id = nwa_info['device']['id']
network_id = nwa_info['network']['id']
resource_group_name = nwa_info['resource_group_name']
dev_key = data_utils.get_device_key(device_id)
if dev_key in nwa_data:
data_utils.strip_interface_data(
nwa_data, device_id, network_id, resource_group_name)
if count_device_id(device_id, nwa_data) == 1:
data_utils.strip_device_data(nwa_data, device_id)
if not check_segment_gd(network_id, resource_group_name, nwa_data):
data_utils.strip_vp_net_data(nwa_data, network_id,
resource_group_name,
nwa_const.NWA_DEVICE_GDV)
return nwa_data
def _delete_general_dev_segment(self, context, nwa_data, nwa_info):
network_id = nwa_info['network']['id']
physical_network = nwa_info['physical_network']
resource_group_name = nwa_info['resource_group_name']
if not check_segment_gd(network_id, resource_group_name, nwa_data):
self.nwa_l2_rpc.release_dynamic_segment_from_agent(
context, physical_network, network_id
)
@utils.log_method_return_value
@helpers.log_method_call
def _delete_general_dev(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
nwa_data = kwargs.get('nwa_data')
network_id = nwa_info['network']['id']
resource_group = nwa_info['resource_group_name']
# delete general dev
logical_name = data_utils.get_vlan_logical_name(nwa_data, network_id)
rcode, body = self.client.l2.delete_general_dev(
nwa_tenant_id,
resource_group,
logical_name,
)
if rcode != 200:
LOG.debug("DeleteGeneralDev Error: invalid response. rcode = %d",
rcode)
# error port send to plugin
raise nwa_exc.AgentProxyException(value=nwa_data)
if body['status'] == 'SUCCEED':
LOG.debug("DeleteGeneralDev SUCCEED")
nwa_data = self._delete_general_dev_data(**kwargs)
self._delete_general_dev_segment(context, nwa_data, nwa_info)
else:
LOG.debug("DeleteGeneralDev %s", body['status'])
raise nwa_exc.AgentProxyException(value=nwa_data)
# delete general dev end
return nwa_data
@utils.log_method_return_value
@helpers.log_method_call
def create_connect_port(self, context, **kwargs):
nwa_info = kwargs['nwa_info']
nwa_data = kwargs['nwa_data']
network_id = nwa_info['network']['id']
vlan_id = nwa_info['network']['vlan_id']
resource_group_name = nwa_info['resource_group_name']
rcode, body = self.client.l2.create_connect_port(
kwargs.get('nwa_tenant_id'),
resource_group_name,
data_utils.get_vlan_logical_name(nwa_data, network_id),
nwa_info['network']['vlan_type'],
vlan_id
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("CreateConnectPort SUCCEED")
return body
@utils.log_method_return_value
@helpers.log_method_call
def _create_connect_port(self, context, **kwargs):
body = self.create_connect_port(context, **kwargs)
if body:
nwa_data = kwargs['nwa_data']
nwa_info = kwargs['nwa_info']
network_id = nwa_info['network']['id']
vlan_id = nwa_info['network']['vlan_id']
resource_group_name = nwa_info['resource_group_name']
vlan_key = data_utils.get_vlan_key(network_id)
if vlan_key not in nwa_data:
LOG.error(_LE("not create vlan."))
raise nwa_exc.AgentProxyException(value=nwa_data)
data_utils.set_vp_net_data(nwa_data, network_id,
resource_group_name,
nwa_const.NWA_DEVICE_GDV,
vlan_id)
self._append_device_for_gdv(nwa_info, nwa_data)
else:
LOG.debug("CreateConnectPort %s", body['status'])
raise nwa_exc.AgentProxyException(value=nwa_data)
return nwa_data
@utils.log_method_return_value
@helpers.log_method_call
def delete_connect_port(self, context, **kwargs):
nwa_info = kwargs['nwa_info']
nwa_data = kwargs['nwa_data']
network_id = nwa_info['network']['id']
vlan_id = nwa_info['network']['vlan_id']
resource_group_name = nwa_info['resource_group_name']
rcode, body = self.client.l2.delete_connect_port(
kwargs['nwa_tenant_id'],
resource_group_name,
data_utils.get_vlan_logical_name(nwa_data, network_id),
nwa_info['network']['vlan_type'],
vlan_id
)
if rcode == 200 and body['status'] == 'SUCCEED':
LOG.debug("DeleteConnectPort SUCCEED")
return body
@utils.log_method_return_value
@helpers.log_method_call
def _delete_connect_port(self, context, **kwargs):
body = self.delete_connect_port(context, **kwargs)
if body:
nwa_data = self._delete_general_dev_data(**kwargs)
self._delete_general_dev_segment(context, nwa_data,
kwargs['nwa_info'])
else:
LOG.debug("DeleteConnectPort %s", body['status'])
raise nwa_exc.AgentProxyException(value=kwargs['nwa_data'])
return nwa_data

View File

@ -1,440 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import re
from neutron.common import topics
from neutron.plugins.common import constants as n_constants
from neutron.plugins.ml2 import driver_api as api
from neutron_lib import constants
from oslo_log import helpers
from oslo_log import log as logging
from networking_nec._i18n import _LE, _LW
from networking_nec.common import utils
from networking_nec.nwa.agent import proxy_l2 as l2
from networking_nec.nwa.agent import proxy_tenant as tenant_util
from networking_nec.nwa.common import constants as nwa_const
from networking_nec.nwa.common import exceptions as nwa_exc
from networking_nec.nwa.l2.rpc import nwa_l2_server_api
from networking_nec.nwa.l2.rpc import tenant_binding_api
from networking_nec.nwa.l3.rpc import nwa_l3_server_api
from networking_nec.nwa.nwalib import data_utils
LOG = logging.getLogger(__name__)
# pylint: disable=too-many-instance-attributes
class AgentProxyL3(object):
def __init__(self, agent_top, client, multi_dc=False,
tenant_fw_create_hook=None,
tenant_fw_delete_hook=None,
tenant_fw_connect_hook=None,
tenant_fw_disconnect_hook=None):
self.nwa_tenant_rpc = tenant_binding_api.TenantBindingServerRpcApi(
topics.PLUGIN)
self.nwa_l2_rpc = nwa_l2_server_api.NwaL2ServerRpcApi(topics.PLUGIN)
self.nwa_l3_rpc = nwa_l3_server_api.NwaL3ServerRpcApi(topics.L3PLUGIN)
self.agent_top = agent_top
self.client = client
self.multi_dc = multi_dc
self.tenant_fw_create_hook = tenant_fw_create_hook
self.tenant_fw_delete_hook = tenant_fw_delete_hook
self.tenant_fw_connect_hook = tenant_fw_connect_hook
self.tenant_fw_disconnect_hook = tenant_fw_disconnect_hook
@property
def proxy_tenant(self):
return self.agent_top.proxy_tenant
@property
def proxy_l2(self):
return self.agent_top.proxy_l2
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def create_tenant_fw(self, context, **kwargs):
nwa_data = self.proxy_l2.ensure_l2_network(context, **kwargs)
device_id = kwargs['nwa_info']['device']['id']
network_id = kwargs['nwa_info']['network']['id']
dev_key = data_utils.get_device_key(device_id)
net_key = data_utils.get_device_net_key(device_id, network_id)
if dev_key not in nwa_data:
nwa_data = self._create_tenant_fw(nwa_data, context, **kwargs)
elif net_key not in nwa_data:
nwa_data = self._update_tenant_fw(
context, connect='connect', nwa_data=nwa_data, **kwargs)
else:
LOG.warning(_LW("unknown device."))
if not nwa_data:
raise nwa_exc.AgentProxyException(value=kwargs['nwa_data'])
ret = self.proxy_tenant.update_tenant_binding(
context,
kwargs['tenant_id'], kwargs['nwa_tenant_id'],
nwa_data
)
resource_group_name_nw = kwargs['nwa_info']['resource_group_name_nw']
vlan_id = data_utils.get_vp_net_vlan_id(nwa_data, network_id,
resource_group_name_nw,
nwa_const.NWA_DEVICE_TFW)
self.nwa_l2_rpc.update_port_state_with_notifier(
context,
device_id,
self.agent_top.agent_id,
kwargs['nwa_info']['port']['id'],
{
api.PHYSICAL_NETWORK: kwargs['nwa_info']['physical_network'],
api.NETWORK_TYPE: n_constants.TYPE_VLAN,
api.SEGMENTATION_ID: vlan_id
},
network_id
)
return ret
@utils.log_method_return_value
def _create_tenant_fw(self, nwa_data, context, **kwargs):
if self.multi_dc:
self.proxy_l2.create_connect_port(context, nwa_data=nwa_data,
**kwargs)
device_id = kwargs['nwa_info']['device']['id']
network_id = kwargs['nwa_info']['network']['id']
rcode, body = self.client.l3.create_tenant_fw(
kwargs['nwa_tenant_id'],
kwargs['nwa_info']['resource_group_name'],
kwargs['nwa_info']['port']['ip'],
data_utils.get_vlan_logical_name(nwa_data, network_id),
kwargs['nwa_info']['network']['vlan_type']
)
if rcode != 200 or body['status'] != 'SUCCEED':
return None
LOG.debug("CreateTenantFW SUCCEED.")
tfw_name = body['resultdata']['TenantFWName']
resource_group_name_nw = kwargs['nwa_info']['resource_group_name_nw']
data_utils.set_tfw_device_data(nwa_data, device_id,
tfw_name, kwargs['nwa_info'])
data_utils.set_tfw_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw,
tfw_name, kwargs['nwa_info'])
vlan_id = data_utils.get_vlan_id(network_id, nwa_data,
body['resultdata'])
data_utils.set_vp_net_data(nwa_data, network_id,
resource_group_name_nw,
nwa_const.NWA_DEVICE_TFW,
vlan_id)
if self.tenant_fw_create_hook:
self.tenant_fw_create_hook(context, tfw_name, **kwargs)
return nwa_data
@utils.log_method_return_value
def _update_tenant_fw(self, context, **kwargs):
connect = kwargs.get('connect')
try:
if connect == 'connect':
self._update_tenant_fw_connect(context, **kwargs)
else: # connect == 'disconnect'
self._update_tenant_fw_disconnect(context, **kwargs)
except nwa_exc.AgentProxyException:
return
return kwargs['nwa_data']
def _update_tenant_fw_connect(self, context, **kwargs):
if self.multi_dc:
self.proxy_l2.create_connect_port(context, **kwargs)
nwa_data = kwargs.get('nwa_data')
device_id = kwargs['nwa_info']['device']['id']
network_id = kwargs['nwa_info']['network']['id']
rcode, body = self.client.l3.update_tenant_fw(
kwargs['nwa_tenant_id'],
data_utils.get_tfw_device_name(nwa_data, device_id),
kwargs['nwa_info']['port']['ip'],
data_utils.get_vlan_logical_name(nwa_data, network_id),
kwargs['nwa_info']['network']['vlan_type'],
connect='connect')
if rcode != 200 or body['status'] != 'SUCCEED':
raise nwa_exc.AgentProxyException(value=None)
LOG.debug("UpdateTenantFW succeed.")
resource_group_name_nw = kwargs['nwa_info']['resource_group_name_nw']
tfw_name = body['resultdata']['TenantFWName']
data_utils.set_tfw_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw,
tfw_name, kwargs['nwa_info'])
vlan_id = data_utils.get_vlan_id(network_id, nwa_data,
body['resultdata'])
data_utils.set_vp_net_data(nwa_data, network_id,
resource_group_name_nw,
nwa_const.NWA_DEVICE_TFW,
vlan_id)
if self.tenant_fw_connect_hook:
self.tenant_fw_connect_hook(context, tfw_name, **kwargs)
return nwa_data
@helpers.log_method_call
def _update_tenant_fw_disconnect(self, context, **kwargs):
"""Update Tenant FW
@param context: contains user information.
@param kwargs:
@return: nwa_data
@raise AgentProxyException
"""
if self.multi_dc:
self.proxy_l2.delete_connect_port(context, **kwargs)
nwa_data = kwargs.get('nwa_data')
device_id = kwargs['nwa_info']['device']['id']
network_id = kwargs['nwa_info']['network']['id']
device_name = data_utils.get_tfw_device_name(nwa_data, device_id)
if self.tenant_fw_disconnect_hook:
self.tenant_fw_disconnect_hook(context, device_name, **kwargs)
rcode, body = self.client.l3.update_tenant_fw(
kwargs['nwa_tenant_id'],
device_name,
kwargs['nwa_info']['port']['ip'],
data_utils.get_vlan_logical_name(nwa_data, network_id),
kwargs['nwa_info']['network']['vlan_type'],
connect='disconnect'
)
if rcode != 200 or body['status'] != 'SUCCEED':
LOG.error(_LE("UpdateTenantFW(disconnect) FAILED."))
info = {'status': 'FAILED',
'msg': 'UpdateTenantFW(disconnect) FAILED.'}
raise nwa_exc.AgentProxyException(value=info)
LOG.debug("UpdateTenantFW(disconnect) SUCCEED.")
resource_group_name_nw = kwargs['nwa_info']['resource_group_name_nw']
data_utils.strip_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw)
data_utils.strip_tfw_data_if_exist(nwa_data, device_id, network_id,
resource_group_name_nw)
if not l2.check_segment_tfw(network_id, resource_group_name_nw,
nwa_data):
data_utils.strip_vp_net_data(nwa_data, network_id,
resource_group_name_nw,
nwa_const.NWA_DEVICE_TFW)
return nwa_data
@helpers.log_method_call
def _delete_tenant_fw(self, context, **kwargs):
"""Delete Tenant FW
@param context: contains user information.
@param kwargs: nwa_tenant_id, nwa_tenant_id, nwa_info, nwa_data
@return: resutl(succeed = True, other = False), data(nwa_data or None)
"""
if self.multi_dc:
self.proxy_l2.delete_connect_port(context, **kwargs)
nwa_data = kwargs.get('nwa_data')
nwa_info = kwargs['nwa_info']
network_id = nwa_info['network']['id']
device_id = nwa_info['device']['id']
device_name = data_utils.get_tfw_device_name(nwa_data, device_id)
if self.tenant_fw_delete_hook:
self.tenant_fw_delete_hook(context, device_name, **kwargs)
rcode, body = self.client.l3.delete_tenant_fw(
kwargs['nwa_tenant_id'],
device_name,
'TFW'
)
if rcode != 200 or body['status'] != 'SUCCEED':
msg = _LE("DeleteTenantFW %s."), body['status']
LOG.error(msg)
raise nwa_exc.AgentProxyException(value=nwa_data)
LOG.debug("DeleteTenantFW SUCCEED.")
resource_group_name_nw = nwa_info['resource_group_name_nw']
# delete recode
data_utils.strip_device_data(nwa_data, device_id)
data_utils.strip_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw)
data_utils.strip_tfw_data_if_exist(nwa_data, device_id, network_id,
resource_group_name_nw)
if not l2.check_segment_tfw(network_id, resource_group_name_nw,
nwa_data):
data_utils.strip_vp_net_data(nwa_data, network_id,
resource_group_name_nw,
nwa_const.NWA_DEVICE_TFW)
return nwa_data
@utils.log_method_return_value
@helpers.log_method_call
@tenant_util.catch_exception_and_update_tenant_binding
def delete_tenant_fw(self, context, **kwargs):
"""Delete Tenant FireWall.
@param context: contains user information.
@param kwargs: tenant_id, nwa_tenant_id, nwa_info
@return: dict of status and msg.
"""
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_info = kwargs.get('nwa_info')
network_id = nwa_info['network']['id']
device_id = nwa_info['device']['id']
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id
)
# check tfw interface
tfwif = "^DEV_" + device_id + '_.*_TenantFWName$'
count = sum(not re.match(tfwif, k) is None for k in nwa_data.keys())
if 1 < count:
ret_val = self._update_tenant_fw(
context,
nwa_data=nwa_data,
connect='disconnect',
**kwargs
)
if not ret_val:
LOG.error(_LE("UpdateTenantFW disconnect FAILED"))
tfw_sgif = re.compile("^DEV_.*_" + network_id + '_TYPE$')
sgif_count = len([k for k in nwa_data if tfw_sgif.match(k)])
if sgif_count:
raise nwa_exc.AgentProxyException(value=nwa_data)
nwa_data = ret_val
elif count == 1:
# raise AgentProxyException if fail
nwa_data = self._delete_tenant_fw(
context, nwa_data=nwa_data, **kwargs)
else:
LOG.error(_LE("count miss match"))
raise nwa_exc.AgentProxyException(value=nwa_data)
return self.proxy_l2._terminate_l2_network(context,
nwa_data, **kwargs)
@helpers.log_method_call
def setting_nat(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
fip_id = kwargs['floating']['id']
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id)
try:
ret_val = self._setting_nat(context, nwa_data=nwa_data, **kwargs)
except nwa_exc.AgentProxyException:
self.nwa_l3_rpc.update_floatingip_status(
context, fip_id, constants.FLOATINGIP_STATUS_ERROR)
return
self.nwa_l3_rpc.update_floatingip_status(
context, fip_id, constants.FLOATINGIP_STATUS_ACTIVE)
return self.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id, ret_val)
@helpers.log_method_call
def _setting_nat(self, context, **kwargs):
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = kwargs.get('nwa_data')
floating = kwargs.get('floating')
# new code.(neet ut)
nat_key = 'NAT_' + floating['id']
if nat_key in nwa_data:
LOG.debug('already in use NAT key =%s', nat_key)
raise nwa_exc.AgentProxyException(value=None)
vlan_logical_name = data_utils.get_vlan_logical_name(
nwa_data, floating['floating_network_id'])
dev_name = data_utils.get_tfw_device_name(nwa_data,
floating['device_id'])
# setting nat
rcode, body = self.client.l3.setting_nat(
nwa_tenant_id,
vlan_logical_name, 'PublicVLAN',
floating['fixed_ip_address'],
floating['floating_ip_address'], dev_name, data=floating
)
if rcode != 200 or body['status'] != 'SUCCEED':
LOG.debug("SettingNat Error: invalid responce."
" rcode=%d status=%s" % (rcode, body))
raise nwa_exc.AgentProxyException(value=None)
else:
LOG.debug("SettingNat SUCCEED")
data_utils.set_floatingip_data(nwa_data, floating)
return nwa_data
@helpers.log_method_call
def delete_nat(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
fip_id = kwargs['floating']['id']
nwa_data = self.nwa_tenant_rpc.get_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id)
try:
ret_val = self._delete_nat(context, nwa_data=nwa_data, **kwargs)
except nwa_exc.AgentProxyException:
self.nwa_l3_rpc.update_floatingip_status(
context, fip_id, constants.FLOATINGIP_STATUS_ERROR)
return
self.nwa_l3_rpc.update_floatingip_status(
context, fip_id, constants.FLOATINGIP_STATUS_DOWN)
return self.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id, ret_val)
@helpers.log_method_call
def _delete_nat(self, context, **kwargs):
nwa_data = kwargs.get('nwa_data')
floating = kwargs.get('floating')
vlan_logical_name = data_utils.get_vlan_logical_name(
nwa_data, floating['floating_network_id'])
dev_name = data_utils.get_tfw_device_name(nwa_data,
floating['device_id'])
# setting nat
rcode, body = self.client.l3.delete_nat(
kwargs.get('nwa_tenant_id'),
vlan_logical_name, 'PublicVLAN',
floating['fixed_ip_address'],
floating['floating_ip_address'], dev_name, data=floating)
if rcode != 200 or body['status'] != 'SUCCEED':
LOG.debug("DeleteNat Error: invalid responce."
" rcode=%d status=%s" % (rcode, body))
raise nwa_exc.AgentProxyException(value=None)
else:
LOG.debug("DeleteNat SUCCEED")
data_utils.strip_floatingip_data(nwa_data, floating)
return nwa_data

View File

@ -1,109 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import topics
from oslo_log import log as logging
from oslo_serialization import jsonutils
from networking_nec._i18n import _LW
from networking_nec.common import utils
from networking_nec.nwa.common import exceptions as nwa_exc
from networking_nec.nwa.l2.rpc import tenant_binding_api
LOG = logging.getLogger(__name__)
def catch_exception_and_update_tenant_binding(method):
def wrapper(obj, context, **kwargs):
try:
return method(obj, context, **kwargs)
except nwa_exc.AgentProxyException as e:
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = e.value
return obj.proxy_tenant.update_tenant_binding(
context, tenant_id, nwa_tenant_id, nwa_data)
return wrapper
class AgentProxyTenant(object):
def __init__(self, agent_top, client):
self.agent_top = agent_top
self.client = client
self.nwa_tenant_rpc = tenant_binding_api.TenantBindingServerRpcApi(
topics.PLUGIN)
@utils.log_method_return_value
def create_tenant(self, context, **kwargs):
"""create tenant
@param context: contains user information.
@param kwargs: nwa_tenant_id
@return: succeed - dict of status, and information.
"""
nwa_tenant_id = kwargs.get('nwa_tenant_id')
status_code, __data = self.client.tenant.create_tenant(nwa_tenant_id)
if status_code in (200, 500): # success(200), already exists(500)
return {
'CreateTenant': True,
'NWA_tenant_id': nwa_tenant_id
}
raise nwa_exc.AgentProxyException(value=status_code)
@utils.log_method_return_value
def delete_tenant(self, context, **kwargs):
"""delete tenant.
@param context: contains user information.
@param kwargs: nwa_tenant_id
@return: result(succeed = (True, dict(empty) other = False, None)
"""
nwa_tenant_id = kwargs.get('nwa_tenant_id')
rcode, body = self.client.tenant.delete_tenant(nwa_tenant_id)
if rcode != 200:
LOG.warning(_LW('unexpected status code %s in delete_tenant'),
rcode)
return body
@utils.log_method_return_value
def update_tenant_binding(
self, context, tenant_id, nwa_tenant_id,
nwa_data, nwa_created=False
):
"""Update Tenant Binding on NECNWAL2Plugin.
@param context:contains user information.
@param tenant_id: Openstack Tenant UUID
@param nwa_tenant_id: NWA Tenand ID
@param nwa_data: nwa_tenant_binding data.
@param nwa_created: flag of operation. True = Create, False = Update
@return: dict of status and msg.
"""
LOG.debug("nwa_data=%s", jsonutils.dumps(
nwa_data,
indent=4,
sort_keys=True
))
if nwa_created:
return self.nwa_tenant_rpc.add_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id, nwa_data
)
return self.nwa_tenant_rpc.set_nwa_tenant_binding(
context, tenant_id, nwa_tenant_id, nwa_data
)

View File

@ -1,130 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import eventlet
from neutron.common import rpc as n_rpc
from oslo_config import cfg
from oslo_log import log as logging
from oslo_messaging.rpc.server import get_rpc_server
from oslo_messaging.target import Target
from networking_nec._i18n import _LW, _LI, _LE
from networking_nec.nwa.common import constants as nwa_const
LOG = logging.getLogger(__name__)
class ServerManager(object):
"""Implementation of nwa_agent_callback.NwaAgentRpcCallback."""
rpc_servers = {}
def __init__(self, topic, agent_top, size=1000):
super(ServerManager, self).__init__()
self.topic = topic
self.agent_top = agent_top
self.greenpool_size = size
self.greenpool = eventlet.greenpool.GreenPool(self.greenpool_size)
def get_rpc_server_topics(self):
return [v['topic'] for v in self.rpc_servers.values()]
def get_rpc_server_tenant_ids(self):
return [{'tenant_id': tid} for tid in self.rpc_servers]
def create_tenant_rpc_server(self, tid):
"""create_ blocking rpc server
@param tid: openstack tenant id
"""
ret = {}
if tid in self.rpc_servers:
LOG.warning(
_LW("already in message queue and server. queue=%s"),
self.rpc_servers[tid]['topic']
)
return {'result': 'FAILED'}
topic = "%s-%s" % (self.topic, tid)
target = Target(
topic=topic, server=cfg.CONF.host, fanout=False)
assert n_rpc.TRANSPORT is not None
serializer = n_rpc.RequestContextSerializer(None)
server = get_rpc_server(
n_rpc.TRANSPORT, target,
self.agent_top.endpoints,
'blocking', serializer
)
LOG.debug("RPCServer create: topic=%s", topic)
if self.greenpool.free() < 1:
self.greenpool_size += nwa_const.NWA_GREENPOOL_ADD_SIZE
self.greenpool.resize(self.greenpool_size)
LOG.info(_LI('RPCServer greenpool resize %s'), self.greenpool_size)
def server_start():
while True:
try:
LOG.debug('RPCServer thread %d start %s',
(self.greenpool.running(), server))
server.start()
LOG.debug('RPCServer thread end %s', server)
break
except Exception as e:
LOG.exception(_LE('RPCServer thread start failed: %s'), e)
self.rpc_servers[tid] = {
'thread': self.greenpool.spawn(server_start),
'server': server,
'topic': topic
}
eventlet.sleep(0)
LOG.info(_LI('RPCServer started: %(topic)s server=%(server)s'),
{'topic': topic, 'server': server})
ret['result'] = 'SUCCESS'
ret['tenant_id'] = tid
ret['topic'] = topic
return ret
def delete_tenant_rpc_server(self, tid):
if tid not in self.rpc_servers:
LOG.warning(_LW("rpc server not found. tid=%s"), tid)
return {'result': 'FAILED'}
LOG.debug('RPCServer delete: stop %s', tid)
self.rpc_servers[tid]['server'].stop()
LOG.debug('RPCServer delete: wait %s', tid)
self.rpc_servers[tid]['server'].wait()
LOG.debug('RPCServer delete: pop %s', tid)
self.rpc_servers.pop(tid)
LOG.debug('RPCServer delete: sleep %s', tid)
eventlet.sleep(0)
ret = {
'result': 'SUCCESS',
'tenant_id': tid
}
LOG.debug("RPCServer deleted: %s", ret)
return ret

View File

@ -1,100 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.agent.common import config
from oslo_config import cfg
from networking_nec._i18n import _
agent_opts = [
cfg.IntOpt('polling_interval', default=2,
help=_("The number of seconds the agent will wait between "
"polling for local device changes.")),
]
cfg.CONF.register_opts(agent_opts, "AGENT")
config.register_agent_state_opts_helper(cfg.CONF)
# nwa.ini
NWA_opts = [
cfg.StrOpt('server_url',
help=_("URL for NWA REST API.")),
cfg.StrOpt('access_key_id',
help=_("Access ID for NWA REST API.")),
cfg.StrOpt('secret_access_key',
help=_("Secret key for NWA REST API.")),
cfg.StrOpt('resource_group_name',
help=_(
"Resouce Group Name specified at creating tenant NW.")),
cfg.StrOpt('region_name',
help=_("RegionName for DC."),
default='RegionOne'),
cfg.IntOpt('scenario_polling_first_timer', default=2,
help=_("Timer value for the first scenario status polling.")),
cfg.IntOpt('scenario_polling_timer', default=10,
help=_("Timer value for polling scenario status.")),
cfg.IntOpt('scenario_polling_count', default=6,
help=_("Count value for polling scenario status.")),
cfg.BoolOpt('use_necnwa_router',
help=_("Using necnwa_router instead of the l3-router"),
default=True),
cfg.BoolOpt('use_neutron_vlan_id',
help=_("Using vlan id of neutron instead of NWA"),
default=False),
cfg.StrOpt('ironic_az_prefix',
help=_("The prefix name of device_owner used in ironic"),
default='BM_'),
cfg.BoolOpt('use_setting_fw_policy',
default=False,
help=_('Using setting_fw_policy as default')),
cfg.StrOpt('resource_group_file',
help=_("JSON file which defines relations between "
"physical network of OpenStack and NWA.")),
cfg.StrOpt('resource_group',
deprecated_for_removal=True,
deprecated_reason='In favor of resource_group_file option.',
help=_("""
Relations between physical network of OpenStack and NWA.
ex)
[
{
"physical_network": "physnet1",
"ResourceGroupName":"Core/Hypervisor/HV-RG01"
},
{ ... },
]""")),
cfg.StrOpt('lbaas_driver',
help=_("LBaaS Driver Name")),
cfg.StrOpt('fwaas_driver',
help=_("Firewall Driver Name")),
]
Scenario_opts = [
cfg.StrOpt('CreateTenantFW',
help=_("Scenario ID for the scenario CreateTenantFW.")),
cfg.StrOpt('CreateTenantNW',
help=_("Scenario ID for the scenario CreateTenantNW.")),
cfg.StrOpt('CreateVLAN',
help=_("Scenario ID for the scenario CreateVLAN.")),
cfg.StrOpt('CreateGeneralDev',
help=_(
"Scenario ID for the scenario CreateGeneralDev.")),
cfg.StrOpt('UpdateTenantFW',
help=_("Scenario ID for the scenario UpdateTenantFW.")),
cfg.StrOpt('SettingNAT',
help=_("Scenario ID for the scenario SettingNAT.")),
]
cfg.CONF.register_opts(NWA_opts, "NWA")
cfg.CONF.register_opts(Scenario_opts, "Scenario")

View File

@ -1,24 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
NWA_DEVICE_GDV = "GeneralDev"
NWA_DEVICE_TFW = "TenantFW"
NWA_AGENT_TOPIC = 'nwa_agent'
NWA_AGENT_TYPE = 'NEC NWA Agent'
NWA_FIREWALL_PLUGIN = 'NECNWAFWaaS'
# an incremental size if the remaining size is zero.
NWA_GREENPOOL_ADD_SIZE = 32

View File

@ -1,39 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib import exceptions as n_exc
from networking_nec._i18n import _
class NWAClientError(n_exc.NeutronException):
message = _('NWAClient Error %(msg)s')
class NWAUtilsError(n_exc.NeutronException):
message = _('NWAUtils Error %(msg)s')
class TenantNotFound(n_exc.NeutronException):
message = _('NWA Tenant %(tenant_id)s not found')
class ResourceGroupNameNotFound(n_exc.NotFound):
message = _("ResourceGroupName %(device_owner)s could not be found")
class AgentProxyException(Exception):
def __init__(self, value=None):
super(AgentProxyException, self).__init__()
self.value = value

View File

@ -1,66 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from networking_nec._i18n import _, _LE, _LW
# It is required to register nwa options
from networking_nec.nwa.common import config # noqa
LOG = logging.getLogger(__name__)
def get_nwa_tenant_id(tenant_id):
return cfg.CONF.NWA.region_name + tenant_id
def get_tenant_info(context):
tenant_id = context.network.current['tenant_id']
nwa_tenant_id = get_nwa_tenant_id(tenant_id)
return tenant_id, nwa_tenant_id
def load_json_from_file(name, json_file, json_str, default_value):
if json_file:
json_file_abspath = cfg.CONF.find_file(json_file)
if not json_file_abspath:
LOG.error(_LE('Failed to load %(name)s_file'
'"%(json_file)s": file not found'),
{'name': name, 'json_file': json_file})
raise cfg.Error(_('NECNWA option parse error'))
try:
with open(json_file_abspath) as f:
return jsonutils.loads(f.read())
except Exception as e:
LOG.error(_LE('Failed to load %(name)s_file '
'"%(json_file)s": %(reason)s'),
{'reason': e, 'name': name, 'json_file': json_file})
raise cfg.Error(_('NECNWA option parse error'))
elif json_str:
try:
return jsonutils.loads(json_str)
except Exception as e:
LOG.error(_LE('NECNWA option error during loading %(name)s '
'(%(data)s): %(reason)s'),
{'reason': e, 'name': name, 'data': json_str})
raise cfg.Error(_('NECNWA option parse error'))
else:
LOG.warning(_LW('%(name)s is not configured. '
'Make sure to set [NWA] %(name)s_file '
'in NWA plugin configuration file. '
'Using %(default)s as default value.'),
{'name': name, 'default': default_value})
return default_value

View File

@ -1,200 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.plugins.ml2 import models as models_ml2
import sqlalchemy as sa
from sqlalchemy import and_
from networking_nec.nwa.l2 import models as nmodels
class NWATenantBinding(object):
"""Relation between OpenStack Tenant ID and NWA Tenant ID."""
def __init__(self, tenant_id, nwa_tenant_id, value_json):
self.tenant_id = tenant_id
self.nwa_tenant_id = nwa_tenant_id
self.value_json = value_json
def __repr__(self):
return "<TenantBinding(%s,%s,%s)>" % (
self.tenant_id, self.nwa_tenant_id, self.value_json
)
def add_nwa_tenant_binding(session, tenant_id, nwa_tenant_id, json_value):
try:
if not isinstance(json_value, dict):
return False
nwa = session.query(nmodels.NWATenantKeyValue).filter(
nmodels.NWATenantKeyValue.tenant_id == tenant_id).all()
if nwa:
return False
with session.begin(subtransactions=True):
for json_key, json_value in json_value.items():
item = nmodels.NWATenantKeyValue(tenant_id, nwa_tenant_id,
json_key, json_value)
session.add(item)
return True
except sa.orm.exc.NoResultFound:
return False
def convert_if_special_value(s):
if s == 'True' or s == '1':
return True
if s == 'False' or s == '0':
return False
return s
def get_nwa_tenant_binding(session, tenant_id, nwa_tenant_id):
try:
value_json = {
nwa.json_key: convert_if_special_value(nwa.json_value)
for nwa in session.query(nmodels.NWATenantKeyValue).filter(
nmodels.NWATenantKeyValue.tenant_id == tenant_id).filter(
nmodels.NWATenantKeyValue.nwa_tenant_id ==
nwa_tenant_id).all()
}
if value_json:
return NWATenantBinding(tenant_id, nwa_tenant_id, value_json)
else:
return None
except sa.orm.exc.NoResultFound:
return None
def set_nwa_tenant_binding(session, tenant_id, nwa_tenant_id, value_json):
item = get_nwa_tenant_binding(session, tenant_id, nwa_tenant_id)
if not item:
return False
_json = item.value_json
if not isinstance(_json, dict):
return False
if not isinstance(value_json, dict):
return False
with session.begin(subtransactions=True):
for key, value in value_json.items():
if key in _json:
if value != _json[key]:
# update
item = session.query(nmodels.NWATenantKeyValue).filter(
and_(nmodels.NWATenantKeyValue.tenant_id == tenant_id,
nmodels.NWATenantKeyValue.json_key == key)).one()
item.json_value = value
else:
# insert
# item = nmodels.NWATenantKeyValue(
# tenant_id, nwa_tenant_id, key, value)
# session.add(item)
insert = ("INSERT INTO nwa_tenant_key_value (tenant_id,"
"nwa_tenant_id,json_key,json_value) "
" VALUES (\'%s\',\'%s\',\'%s\',\'%s\') "
"ON DUPLICATE KEY UPDATE "
" json_value=\'%s\'" % (tenant_id, nwa_tenant_id,
key, value, value))
session.execute(insert)
for key, value in _json.items():
if key not in value_json:
# delete
item = session.query(nmodels.NWATenantKeyValue).filter(
and_(nmodels.NWATenantKeyValue.tenant_id == tenant_id,
nmodels.NWATenantKeyValue.json_key == key)).one()
session.delete(item)
return True
def del_nwa_tenant_binding(session, tenant_id, nwa_tenant_id):
try:
with session.begin(subtransactions=True):
item = get_nwa_tenant_binding(session, tenant_id, nwa_tenant_id)
if not item:
return False
with session.begin(subtransactions=True):
session.query(nmodels.NWATenantKeyValue).filter(
and_(nmodels.NWATenantKeyValue.tenant_id == tenant_id,
nmodels.NWATenantKeyValue.nwa_tenant_id ==
nwa_tenant_id)).delete()
return True
except sa.orm.exc.NoResultFound:
return False
def ensure_port_binding(session, port_id):
with session.begin(subtransactions=True):
try:
record = (session.query(models_ml2.PortBindingLevel).
filter_by(port_id=port_id).
one())
except sa.orm.exc.NoResultFound:
# for kilo(re mearge)
record = (session.query(models_ml2.PortBinding).
filter_by(port_id=port_id).
one())
return record
def add_nwa_tenant_queue(session, tenant_id, nwa_tenant_id='', topic=''):
try:
nwa = session.query(nmodels.NWATenantQueue).filter(
nmodels.NWATenantQueue.tenant_id == tenant_id).all()
if nwa:
return False
with session.begin(subtransactions=True):
nwa = nmodels.NWATenantQueue(
tenant_id,
nwa_tenant_id,
topic
)
session.add(nwa)
return True
except sa.orm.exc.NoResultFound:
return False
def get_nwa_tenant_queue(session, tenant_id):
try:
queue = session.query(nmodels.NWATenantQueue).filter(
nmodels.NWATenantQueue.tenant_id == tenant_id).one()
if queue:
return queue
else:
return None
except sa.orm.exc.NoResultFound:
return None
def get_nwa_tenant_queues(session):
try:
queues = session.query(nmodels.NWATenantQueue).all()
return queues
except sa.orm.exc.NoResultFound:
return None
def del_nwa_tenant_queue(session, tenant_id):
try:
with session.begin(subtransactions=True):
item = get_nwa_tenant_queue(session, tenant_id)
if not item:
return False
with session.begin(subtransactions=True):
session.query(nmodels.NWATenantQueue).filter(
nmodels.NWATenantQueue.tenant_id == tenant_id
).delete()
return True
except sa.orm.exc.NoResultFound:
return False

View File

@ -1,261 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import constants as neutron_const
from neutron.common import utils
from neutron.db import segments_db as db_ml2
from neutron.extensions import portbindings
from neutron.extensions import providernet as prov_net
from neutron.plugins.common import constants as plugin_const
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2.drivers.openvswitch.mech_driver \
import mech_openvswitch as ovs
from neutron_lib import constants
from oslo_config import cfg
from oslo_log import log as logging
from networking_nec._i18n import _LW
from networking_nec.nwa.common import exceptions as nwa_exc
from networking_nec.nwa.common import utils as nwa_com_utils
from networking_nec.nwa.l2 import utils as nwa_l2_utils
from networking_nec.nwa.l3 import db_api as nwa_l3_db
from networking_nec.nwa.l3.rpc import nwa_l3_proxy_api
LOG = logging.getLogger(__name__)
class NECNWAMechanismDriver(ovs.OpenvswitchMechanismDriver):
def initialize(self):
self.resource_groups = nwa_com_utils.load_json_from_file(
'resource_group', cfg.CONF.NWA.resource_group_file,
cfg.CONF.NWA.resource_group, default_value=[])
self.necnwa_router = cfg.CONF.NWA.use_necnwa_router
self.multi_dc = cfg.CONF.NWA.use_neutron_vlan_id
def _get_l2api_proxy(self, context, tenant_id):
proxy = context._plugin.get_nwa_proxy(tenant_id,
context._plugin_context)
return proxy
def _get_l3api_proxy(self, context, tenant_id):
proxy = context._plugin.get_nwa_proxy(tenant_id,
context.network._plugin_context)
return nwa_l3_proxy_api.NwaL3ProxyApi(proxy.client)
def is_router(self, device_owner):
return device_owner in (constants.DEVICE_OWNER_ROUTER_INTF,
constants.DEVICE_OWNER_ROUTER_GW)
def create_port_precommit(self, context):
if not self.necnwa_router:
return
device_owner = context._port['device_owner']
if not self.is_router(device_owner):
LOG.warning(_LW("device owner missmatch device_owner=%s"),
device_owner)
return
self._l3_create_tenant_fw(context)
physical_network = self._find_nwa_physical_network(context)
if physical_network:
self._bind_segment_to_vif_type(context, physical_network)
def update_port_precommit(self, context):
new_port = context.current
orig_port = context.original
if (not new_port['device_id'] and orig_port['device_id'] and
not new_port['device_owner'] and orig_port['device_owner']):
# device_id and device_owner are clear on VM deleted.
LOG.debug('original_port=%s', context.original)
LOG.debug('updated_port=%s', context.current)
self._l2_delete_general_dev(context, use_original_port=True)
def delete_port_precommit(self, context):
tenant_id, nwa_tenant_id = nwa_com_utils.get_tenant_info(context)
device_owner = context._port['device_owner']
device_id = context._port['device_id']
LOG.debug("tenant_id=%(tid)s, nwa_tenant_id=%(nid)s, "
"device_owner=%(dev)s",
{'tid': tenant_id, 'nid': nwa_tenant_id,
'dev': device_owner})
if self.necnwa_router and self.is_router(device_owner):
self._l3_delete_tenant_fw(context)
elif device_owner == constants.DEVICE_OWNER_FLOATINGIP:
pass
elif device_owner == '' and device_id == '':
pass
else:
self._l2_delete_general_dev(context)
def try_to_bind_segment_for_agent(self, context, segment, agent):
device_owner = context._port['device_owner']
if not self.necnwa_router or not self.is_router(device_owner):
physical_network = self._find_nwa_physical_network(context, agent)
if physical_network:
self._bind_segment_to_vif_type(context, physical_network)
self._bind_port_nwa_debug_message(context)
self._l2_create_general_dev(context)
return True
LOG.warning(_LW("binding segment not found for agent=%s"), agent)
return super(
NECNWAMechanismDriver, self
).try_to_bind_segment_for_agent(context, segment, agent)
def _find_nwa_physical_network(self, context, ovs_agent=None):
mappings = {}
if ovs_agent:
mappings = ovs_agent['configurations'].get('bridge_mappings', {})
for res in self.resource_groups:
if ovs_agent and res['ResourceGroupName'] not in mappings:
continue
if res['device_owner'] == context._port['device_owner']:
return res['ResourceGroupName']
def _bind_segment_to_vif_type(self, context, physical_network):
if self.multi_dc:
return
network_id = context.network.current['id']
session = context.network._plugin_context.session
dummy_segment = db_ml2.get_dynamic_segment(
session, network_id, physical_network=physical_network)
LOG.debug("1st: dummy segment is %s", dummy_segment)
if not dummy_segment:
dummy_segment = {
api.PHYSICAL_NETWORK: physical_network,
api.NETWORK_TYPE: plugin_const.TYPE_VLAN,
api.SEGMENTATION_ID: 0
}
db_ml2.add_network_segment(
session, network_id, dummy_segment, is_dynamic=True)
LOG.debug("2nd: dummy segment is %s", dummy_segment)
context.set_binding(dummy_segment[api.ID],
self.vif_type,
{portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True})
def _bind_port_nwa_debug_message(self, context):
network_name, network_id = nwa_l2_utils.get_network_info(context)
device_owner = context._port['device_owner']
subnet_ids = []
if 'fixed_ips' in context._port:
for fixed_ip in context._port['fixed_ips']:
subnet_ids.append(fixed_ip['subnet_id'])
segmentation_id = 0
if prov_net.PHYSICAL_NETWORK in context.network.current:
segmentation_id = context.network.current[prov_net.SEGMENTATION_ID]
else:
for provider in context.network.current['segments']:
if (provider.get(prov_net.PHYSICAL_NETWORK) ==
nwa_l2_utils.get_physical_network(
device_owner, self.resource_groups)):
segmentation_id = provider[prov_net.SEGMENTATION_ID]
break
LOG.debug("provider segmentation_id = %s", segmentation_id)
LOG.debug("_bind_port_nwa %(network_name)s "
"%(network_id)s %(device_id)s %(device_owner)s "
"%(port_id)s %(mac_address)s %(subnet_ids)s "
"%(segmentation_id)s",
{'network_name': network_name,
'network_id': network_id,
'device_id': context._port['device_id'],
'device_owner': device_owner,
'port_id': context._port['id'],
'mac_address': context._port['mac_address'],
'subnet_ids': subnet_ids,
'segmentation_id': segmentation_id})
def _l2_create_general_dev(self, context):
kwargs = self._make_l2api_kwargs(context)
proxy = self._get_l2api_proxy(context, kwargs['tenant_id'])
proxy.create_general_dev(context.network._plugin_context, **kwargs)
def _l2_delete_general_dev(self, context, use_original_port=False):
try:
kwargs = self._make_l2api_kwargs(
context, use_original_port=use_original_port)
self._l2_delete_segment(context, kwargs['nwa_info'])
proxy = self._get_l2api_proxy(context, kwargs['tenant_id'])
kwargs['nwa_info'] = self._revert_dhcp_agent_device_id(
context, kwargs['nwa_info'])
proxy.delete_general_dev(context.network._plugin_context, **kwargs)
except nwa_exc.TenantNotFound as e:
LOG.warning(_LW("skip delete_general_dev: %s"), e)
def _make_l2api_kwargs(self, context, use_original_port=False):
tenant_id, nwa_tenant_id = nwa_com_utils.get_tenant_info(context)
nwa_info = nwa_l2_utils.portcontext_to_nwa_info(
context, self.resource_groups, use_original_port)
return {
'tenant_id': tenant_id,
'nwa_tenant_id': nwa_tenant_id,
'nwa_info': nwa_info
}
def _revert_dhcp_agent_device_id(self, context, nwa_info):
device_owner = context._port['device_owner']
device_id = context._port['device_id']
if device_owner == constants.DEVICE_OWNER_DHCP and \
device_id == neutron_const.DEVICE_ID_RESERVED_DHCP_PORT:
# get device_id of dhcp agent even if it is reserved.
nwa_info['device']['id'] = utils.get_dhcp_agent_device_id(
context.network.current['id'],
context._port.get('binding:host_id')
)
return nwa_info
def _l2_delete_segment(self, context, nwa_info):
session = context.network._plugin_context.session
del_segment = db_ml2.get_dynamic_segment(
session,
context.network.current['id'],
physical_network=nwa_info['physical_network'])
if del_segment:
LOG.debug('delete_network_segment %s', del_segment)
db_ml2.delete_network_segment(session, del_segment['id'])
def _l3_create_tenant_fw(self, context):
device_owner = context._port['device_owner']
grplst = [res['device_owner'] for res in self.resource_groups]
if device_owner not in grplst:
raise nwa_exc.ResourceGroupNameNotFound(device_owner=device_owner)
kwargs = self._make_l3api_kwargs(context)
proxy = self._get_l3api_proxy(context, kwargs['tenant_id'])
proxy.create_tenant_fw(context.network._plugin_context, **kwargs)
def _l3_delete_tenant_fw(self, context):
kwargs = self._make_l3api_kwargs(context)
proxy = self._get_l3api_proxy(context, kwargs['tenant_id'])
proxy.delete_tenant_fw(context.network._plugin_context, **kwargs)
def _make_l3api_kwargs(self, context):
rt_tid = nwa_l3_db.get_tenant_id_by_router(
context.network._plugin_context.session,
context._port['device_id']
)
nwa_rt_tid = nwa_com_utils.get_nwa_tenant_id(rt_tid)
nwa_info = nwa_l2_utils.portcontext_to_nwa_info(
context, self.resource_groups)
nwa_info['tenant_id'] = rt_tid # overwrite by router's
nwa_info['nwa_tenant_id'] = nwa_rt_tid # tenant_id and nwa_tenant_id
return {
'tenant_id': rt_tid,
'nwa_tenant_id': nwa_rt_tid,
'nwa_info': nwa_info
}

View File

@ -1,61 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.db import model_base
import sqlalchemy as sa
class NWATenantKeyValue(model_base.BASEV2):
"""Key and value database of NWW tenant"""
__tablename__ = 'nwa_tenant_key_value'
tenant_id = sa.Column(sa.String(36), primary_key=True)
nwa_tenant_id = sa.Column(sa.String(64))
json_key = sa.Column(sa.String(192), nullable=False,
default='', primary_key=True)
json_value = sa.Column(sa.String(1024), nullable=False,
default='')
def __init__(self, tenant_id, nwa_tenant_id, json_key, json_value):
self.tenant_id = tenant_id
self.nwa_tenant_id = nwa_tenant_id
self.json_key = json_key
self.json_value = json_value
def __repr__(self):
return "<TenantKeyValue(%s,%s,%s)>" % (
self.tenant_id, self.nwa_tenant_id,
{self.json_key: self.json_value}
)
class NWATenantQueue(model_base.BASEV2):
"""Queue for each NWA Tenant between server and agent"""
__tablename__ = 'nwa_tenant_queue'
tenant_id = sa.Column(sa.String(36), primary_key=True)
nwa_tenant_id = sa.Column(sa.String(64))
topic = sa.Column(sa.String(128), default='')
def __init__(self, tenant_id, nwa_tenant_id, topic):
self.tenant_id = tenant_id
self.nwa_tenant_id = nwa_tenant_id
self.topic = topic
def __repr__(self):
return "<TenantQueue(%s,%s,%s)>" % (
self.tenant_id,
self.nwa_tenant_id,
self.topic
)

View File

@ -1,183 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api.rpc.handlers import dhcp_rpc
from neutron.api.rpc.handlers import metadata_rpc
from neutron.api.rpc.handlers import securitygroups_rpc
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.db import agents_db
from neutron.db import segments_db as db_ml2
from neutron.extensions import multiprovidernet as mpnet
from neutron.extensions import providernet as provider
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2 import plugin as ml2_plugin
from oslo_log import log as logging
from networking_nec._i18n import _LE, _LI, _LW
from networking_nec.nwa.common import constants as nwa_const
from networking_nec.nwa.l2 import db_api as necnwa_api
from networking_nec.nwa.l2.rpc import ml2_server_callback
from networking_nec.nwa.l2.rpc import nwa_agent_api
from networking_nec.nwa.l2.rpc import nwa_l2_server_callback
from networking_nec.nwa.l2.rpc import nwa_proxy_api
from networking_nec.nwa.l2.rpc import tenant_binding_callback
LOG = logging.getLogger(__name__)
class NECNWAL2Plugin(ml2_plugin.Ml2Plugin):
def __init__(self):
super(NECNWAL2Plugin, self).__init__()
self._nwa_agent_rpc_setup()
def _nwa_agent_rpc_setup(self):
self.nwa_rpc = nwa_agent_api.NECNWAAgentApi(
nwa_const.NWA_AGENT_TOPIC
)
self.nwa_proxies = {}
def start_rpc_listeners(self):
self.endpoints = [
ml2_server_callback.NwaML2ServerRpcCallbacks(
self.notifier, self.type_manager),
nwa_l2_server_callback.NwaL2ServerRpcCallback(),
tenant_binding_callback.TenantBindingServerRpcCallback(),
securitygroups_rpc.SecurityGroupServerRpcCallback(),
dhcp_rpc.DhcpRpcCallback(),
agents_db.AgentExtRpcCallback(),
metadata_rpc.MetadataRpcCallback()]
self.topic = topics.PLUGIN
self.conn = n_rpc.create_connection()
self.conn.create_consumer(self.topic, self.endpoints,
fanout=False)
return self.conn.consume_in_threads()
def _extend_network_dict_provider(self, context, network):
if 'id' not in network:
LOG.debug("Network has no id")
network[provider.NETWORK_TYPE] = None
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
return
net_id = network['id']
segments = db_ml2.get_network_segments(
context.session, net_id, filter_dynamic=True)
if not segments:
LOG.debug("Network %s has no segments", net_id)
network[provider.NETWORK_TYPE] = None
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
elif len(segments) > 1:
network[mpnet.SEGMENTS] = [
{provider.NETWORK_TYPE: segment[api.NETWORK_TYPE],
provider.PHYSICAL_NETWORK: segment[api.PHYSICAL_NETWORK],
provider.SEGMENTATION_ID: segment[api.SEGMENTATION_ID]}
for segment in segments]
else:
segment = segments[0]
network[provider.NETWORK_TYPE] = segment[api.NETWORK_TYPE]
network[provider.PHYSICAL_NETWORK] = segment[api.PHYSICAL_NETWORK]
network[provider.SEGMENTATION_ID] = segment[api.SEGMENTATION_ID]
# pylint: disable=redefined-builtin
def get_network(self, context, id, fields=None):
session = context.session
with session.begin(subtransactions=True):
network = self._get_network(context, id)
result = self._make_network_dict(network, fields)
self._extend_network_dict_provider(context, result)
return self._fields(result, fields)
def get_networks(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None, page_reverse=False):
return super(
NECNWAL2Plugin,
self
).get_networks(context, filters, None, sorts,
limit, marker, page_reverse)
def _create_nwa_agent_tenant_queue(self, context, tenant_id):
if (
self._is_alive_nwa_agent(context) and
necnwa_api.get_nwa_tenant_queue(
context.session,
tenant_id
) is None
):
self.nwa_rpc.create_server(context, tenant_id)
necnwa_api.add_nwa_tenant_queue(context.session, tenant_id)
else:
LOG.warning(_LW('%s is not alive.'),
nwa_const.NWA_AGENT_TYPE)
def create_network(self, context, network):
result = super(NECNWAL2Plugin,
self).create_network(context, network)
self._create_nwa_agent_tenant_queue(context, context.tenant_id)
return result
def delete_network(self, context, id):
result = super(NECNWAL2Plugin,
self).delete_network(context, id)
return result
def create_port(self, context, port):
result = super(NECNWAL2Plugin,
self).create_port(context, port)
return result
def get_nwa_topics(self, context, tid):
rss = self.nwa_rpc.get_nwa_rpc_servers(context)
if isinstance(rss, dict) and rss.get('nwa_rpc_servers'):
return [t.get('topic') for t in rss['nwa_rpc_servers']
if t.get('tenant_id') == tid]
else:
return []
def get_nwa_proxy(self, tid, context=None):
if tid not in self.nwa_proxies:
self.nwa_proxies[tid] = nwa_proxy_api.NECNWAProxyApi(
nwa_const.NWA_AGENT_TOPIC, tid
)
if context:
self._create_nwa_agent_tenant_queue(context, tid)
nwa_topics = self.get_nwa_topics(context, tid)
if len(nwa_topics) == 1:
LOG.info(_LI('NWA tenant queue: new topic is %s'),
str(nwa_topics[0]))
else:
LOG.warning(_LW('NWA tenant queue is not created. tid=%s'),
tid)
LOG.debug('proxy tid=%s', tid)
return self.nwa_proxies[tid]
def _is_alive_nwa_agent(self, context):
agents = self.get_agents(
context,
filters={'agent_type': [nwa_const.NWA_AGENT_TYPE]}
)
return any(agent['alive'] for agent in agents)
# This needs to be defined to avoid pylint abstract-method check.
def get_port_from_device(self, context, device):
LOG.error(_LE('This method should not be called. '
'get_ports_from_devices is used.'))

View File

@ -1,128 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from neutron.extensions import portbindings
from neutron.extensions import portsecurity as psec
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2 import rpc
from neutron.services.qos import qos_consts
from neutron_lib import constants
from neutron_lib.plugins import directory
from oslo_log import log as logging
from networking_nec._i18n import _LW, _LI
LOG = logging.getLogger(__name__)
class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
RPC_VERSION = '1.0'
def __init__(self, notifier, type_manager, necnwa_router=True):
super(NwaML2ServerRpcCallbacks, self).__init__(notifier, type_manager)
self.necnwa_router = cfg.CONF.NWA.use_necnwa_router
def get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details."""
agent_id = kwargs.get('agent_id')
device = kwargs.get('device')
host = kwargs.get('host')
# cached networks used for reducing number of network db calls
# for server internal usage only
cached_networks = kwargs.get('cached_networks')
LOG.debug("Device %(device)s details requested by agent "
"%(agent_id)s with host %(host)s",
{'device': device, 'agent_id': agent_id, 'host': host})
plugin = directory.get_plugin()
port_id = plugin._device_to_port_id(rpc_context, device)
port_context = plugin.get_bound_port_context(rpc_context,
port_id,
host,
cached_networks)
if not port_context:
LOG.debug("Device %(device)s requested by agent "
"%(agent_id)s not found in database",
{'device': device, 'agent_id': agent_id})
return {'device': device}
segment = port_context.bottom_bound_segment
port = port_context.current
# caching information about networks for future use
if cached_networks is not None:
if port['network_id'] not in cached_networks:
cached_networks[port['network_id']] = (
port_context.network.current)
if not segment:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s on network %(network_id)s not "
"bound, vif_type: %(vif_type)s"),
{'device': device,
'agent_id': agent_id,
'network_id': port['network_id'],
'vif_type': port_context.vif_type})
return {'device': device}
if segment['segmentation_id'] == 0:
entry = {'device': device}
LOG.info(_LI('The segmentation_id is not yet finalized, '
'it is replaced to return %s'), entry)
return entry
if not host or host == port_context.host:
new_status = (constants.PORT_STATUS_BUILD if port['admin_state_up']
else constants.PORT_STATUS_DOWN)
if (
port['status'] != new_status and
port['status'] != constants.PORT_STATUS_ACTIVE
):
plugin.update_port_status(rpc_context,
port_id,
new_status,
host,
port_context.network.current)
network_qos_policy_id = port_context.network._network.get(
qos_consts.QOS_POLICY_ID)
entry = {'device': device,
'network_id': port['network_id'],
'port_id': port['id'],
'mac_address': port['mac_address'],
'admin_state_up': port['admin_state_up'],
'network_type': segment[api.NETWORK_TYPE],
'segmentation_id': segment[api.SEGMENTATION_ID],
'physical_network': segment[api.PHYSICAL_NETWORK],
'fixed_ips': port['fixed_ips'],
'device_owner': port['device_owner'],
'allowed_address_pairs': port['allowed_address_pairs'],
'port_security_enabled': port.get(psec.PORTSECURITY, True),
'qos_policy_id': port.get(qos_consts.QOS_POLICY_ID),
'network_qos_policy_id': network_qos_policy_id,
'profile': port[portbindings.PROFILE]}
if 'security_groups' in port:
entry['security_groups'] = port['security_groups']
LOG.debug("Returning: %s", entry)
return entry
def update_device_up(self, rpc_context, **kwargs):
"""Device is up on agent."""
if self.necnwa_router:
return
super(NwaML2ServerRpcCallbacks, self).update_device_up(rpc_context,
**kwargs)

View File

@ -1,38 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import rpc as n_rpc
import oslo_messaging
class NECNWAAgentApi(object):
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic):
target = oslo_messaging.Target(topic=topic,
version=self.BASE_RPC_API_VERSION)
self.client = n_rpc.get_client(target)
def create_server(self, context, tenant_id):
cctxt = self.client.prepare()
return cctxt.cast(context, 'create_server', tenant_id=tenant_id)
def delete_server(self, context, tenant_id):
cctxt = self.client.prepare()
return cctxt.cast(context, 'delete_server', tenant_id=tenant_id)
def get_nwa_rpc_servers(self, context):
cctxt = self.client.prepare()
return cctxt.call(context, 'get_nwa_rpc_servers')

View File

@ -1,45 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import helpers
import oslo_messaging
class NwaAgentRpcCallback(object):
target = oslo_messaging.Target(version='1.0')
def __init__(self, context, agent):
self.context = context
self.agent = agent
@helpers.log_method_call
def get_nwa_rpc_servers(self, context, **kwargs):
return {'nwa_rpc_servers':
[
{
'tenant_id': k,
'topic': v['topic']
} for k, v in self.agent.rpc_servers.items()
]}
@helpers.log_method_call
def create_server(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
return self.agent.create_tenant_rpc_server(tenant_id)
@helpers.log_method_call
def delete_server(self, context, **kwargs):
tenant_id = kwargs.get('tenant_id')
return self.agent.delete_tenant_rpc_server(tenant_id)

View File

@ -1,89 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import rpc as n_rpc
from neutron.plugins.ml2 import driver_api as api
import oslo_messaging
class NwaL2ServerRpcApi(object):
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic):
target = oslo_messaging.Target(topic=topic,
version=self.BASE_RPC_API_VERSION)
self.client = n_rpc.get_client(target)
def get_nwa_network_by_port_id(self, context, port_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'get_nwa_network_by_port_id',
port_id=port_id
)
def get_nwa_network_by_subnet_id(self, context, subnet_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'get_nwa_network_by_subnet_id',
subnet_id=subnet_id
)
def get_nwa_network(self, context, network_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'get_nwa_network',
network_id=network_id
)
def get_nwa_networks(self, context, tenant_id, nwa_tenant_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'get_nwa_networks',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id
)
def update_port_state_with_notifier(self, context, device, agent_id,
port_id, segment, network_id):
physical_network = segment[api.PHYSICAL_NETWORK]
network_type = segment[api.NETWORK_TYPE]
segmentation_id = segment[api.SEGMENTATION_ID]
cctxt = self.client.prepare()
return cctxt.call(
context,
'update_port_state_with_notifier',
device=device,
agent_id=agent_id,
port_id=port_id,
network_id=network_id,
network_type=network_type,
segmentation_id=segmentation_id,
physical_network=physical_network
)
def release_dynamic_segment_from_agent(self, context, physical_network,
network_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'release_dynamic_segment_from_agent',
network_id=network_id,
physical_network=physical_network
)

View File

@ -1,138 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.db import api as db_api
from neutron.db.models import segment as segments_db
from neutron.db import models_v2
from neutron.db import segments_db as db_ml2
from neutron_lib import constants
from neutron_lib.plugins import directory
from oslo_log import helpers
from oslo_log import log as logging
import oslo_messaging
from sqlalchemy.orm import exc as sa_exc
from networking_nec._i18n import _LE
LOG = logging.getLogger(__name__)
class NwaL2ServerRpcCallback(object):
target = oslo_messaging.Target(version='1.0')
def get_nwa_network_by_port_id(self, rpc_context, **kwargs):
plugin = directory.get_plugin()
port_id = kwargs.get('port_id')
port = plugin.get_port(rpc_context, port_id)
network = plugin.get_network(rpc_context, port['network_id'])
return network
def get_nwa_network_by_subnet_id(self, rpc_context, **kwargs):
plugin = directory.get_plugin()
subnet_id = kwargs.get('subnet_id')
subnet = plugin.get_subnet(rpc_context, subnet_id)
network = plugin.get_network(rpc_context, subnet['network_id'])
return network
def get_nwa_network(self, rpc_context, **kwargs):
plugin = directory.get_plugin()
net_id = kwargs.get('network_id')
network = plugin.get_network(rpc_context, net_id)
return network
def get_nwa_networks(self, rpc_context, **kwargs):
plugin = directory.get_plugin()
networks = plugin.get_networks(rpc_context)
return networks
@helpers.log_method_call
def update_port_state_with_notifier(self, rpc_context, **kwargs):
port_id = kwargs.get('port_id')
network_id = kwargs.get('network_id')
network_type = kwargs.get('network_type')
segmentation_id = kwargs.get('segmentation_id')
physical_network = kwargs.get('physical_network')
# 1 update segment
session = db_api.get_session()
with session.begin(subtransactions=True):
try:
query = (session.query(segments_db.NetworkSegment).
filter_by(network_id=network_id))
query = query.filter_by(physical_network=physical_network)
query = query.filter_by(is_dynamic=True)
record = query.one()
record.segmentation_id = segmentation_id
except sa_exc.NoResultFound:
pass
# 2 change port state
plugin = directory.get_plugin()
plugin.update_port_status(
rpc_context,
port_id,
constants.PORT_STATUS_ACTIVE
)
# 3 serch db from port_id
session = db_api.get_session()
port = None
with session.begin(subtransactions=True):
try:
port_db = (session.query(models_v2.Port).
enable_eagerloads(False).
filter(models_v2.Port.id.startswith(port_id)).
one())
port = plugin._make_port_dict(port_db)
except sa_exc.NoResultFound:
LOG.error(_LE("Can't find port with port_id %s"),
port_id)
except sa_exc.MultipleResultsFound:
LOG.error(_LE("Multiple ports have port_id starting with %s"),
port_id)
# 4 send notifier
if port is not None:
LOG.debug("notifier port_update %(net_type)s, %(seg_id)s, "
"%(physnet)s",
{'net_type': network_type,
'seg_id': segmentation_id,
'physnet': physical_network})
plugin.notifier.port_update(
rpc_context, port,
network_type,
segmentation_id,
physical_network
)
return {}
def release_dynamic_segment_from_agent(self, context, **kwargs):
network_id = kwargs.get('network_id')
physical_network = kwargs.get('physical_network')
session = db_api.get_session()
del_segment = db_ml2.get_dynamic_segment(
session, network_id, physical_network=physical_network,
)
if del_segment:
LOG.debug("release_dynamic_segment segment=%s", del_segment)
if del_segment['segmentation_id'] != 0:
db_ml2.delete_network_segment(session, del_segment['id'])

View File

@ -1,57 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import rpc as n_rpc
import oslo_messaging
class NECNWAProxyApi(object):
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic, tenant_id):
target = oslo_messaging.Target(topic='%s-%s' % (topic, tenant_id),
version=self.BASE_RPC_API_VERSION)
self._client = n_rpc.get_client(target)
@property
def client(self):
return self._client
def _send_msg(self, context, msg, blocking=False):
cctxt = self.client.prepare()
if blocking:
return cctxt.call(context, msg)
else:
return cctxt.cast(context, msg)
def create_general_dev(self, context, tenant_id, nwa_tenant_id, nwa_info):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'create_general_dev',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_info=nwa_info
)
def delete_general_dev(self, context, tenant_id, nwa_tenant_id, nwa_info):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'delete_general_dev',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_info=nwa_info
)

View File

@ -1,44 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
import oslo_messaging
from oslo_serialization import jsonutils
LOG = logging.getLogger(__name__)
class NwaProxyCallback(object):
target = oslo_messaging.Target(version='1.0')
def __init__(self, context, agent):
super(NwaProxyCallback, self).__init__()
self.context = context
self.agent = agent
def create_general_dev(self, context, **kwargs):
LOG.debug("Rpc callback kwargs=%s", jsonutils.dumps(
kwargs,
indent=4,
sort_keys=True
))
return self.agent.create_general_dev(context, **kwargs)
def delete_general_dev(self, context, **kwargs):
LOG.debug("Rpc callback kwargs=%s", jsonutils.dumps(
kwargs,
indent=4,
sort_keys=True
))
return self.agent.delete_general_dev(context, **kwargs)

View File

@ -1,75 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import rpc as n_rpc
import oslo_messaging
class TenantBindingServerRpcApi(object):
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic):
target = oslo_messaging.Target(topic=topic,
version=self.BASE_RPC_API_VERSION)
self.client = n_rpc.get_client(target)
def get_nwa_tenant_binding(self, context, tenant_id, nwa_tenant_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'get_nwa_tenant_binding',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id
)
def add_nwa_tenant_binding(self, context, tenant_id,
nwa_tenant_id, nwa_data):
cctxt = self.client.prepare()
return cctxt.call(
context,
'add_nwa_tenant_binding',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_data=nwa_data
)
def set_nwa_tenant_binding(self, context, tenant_id,
nwa_tenant_id, nwa_data):
cctxt = self.client.prepare()
return cctxt.call(
context,
'set_nwa_tenant_binding',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_data=nwa_data
)
def delete_nwa_tenant_binding(self, context, tenant_id,
nwa_tenant_id):
cctxt = self.client.prepare()
return cctxt.call(
context,
'delete_nwa_tenant_binding',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id
)
def update_tenant_rpc_servers(self, context, rpc_servers):
cctxt = self.client.prepare()
return cctxt.call(
context,
'update_tenant_rpc_servers',
servers=rpc_servers
)

View File

@ -1,137 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.db import api as db_api
from neutron_lib.plugins import directory
from oslo_log import helpers
from oslo_log import log as logging
import oslo_messaging
from oslo_serialization import jsonutils
from networking_nec._i18n import _LI
from networking_nec.nwa.l2 import db_api as necnwa_api
LOG = logging.getLogger(__name__)
class TenantBindingServerRpcCallback(object):
target = oslo_messaging.Target(version='1.0')
@helpers.log_method_call
def get_nwa_tenant_binding(self, rpc_context, **kwargs):
"""get nwa_tenant_binding from neutorn db.
@param rpc_context: rpc context.
@param kwargs: tenant_id, nwa_tenant_id
@return: success = dict of nwa_tenant_binding, error = dict of empty.
"""
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
session = db_api.get_session()
with session.begin(subtransactions=True):
recode = necnwa_api.get_nwa_tenant_binding(
session, tenant_id, nwa_tenant_id
)
if recode is not None:
LOG.debug(
"nwa_data=%s", jsonutils.dumps(
recode.value_json, indent=4, sort_keys=True)
)
return recode.value_json
return {}
@helpers.log_method_call
def add_nwa_tenant_binding(self, rpc_context, **kwargs):
"""get nwa_tenant_binding from neutorn db.
@param rpc_context: rpc context.
@param kwargs: tenant_id, nwa_tenant_id
@return: dict of status
"""
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = kwargs.get('nwa_data')
session = db_api.get_session()
with session.begin(subtransactions=True):
if necnwa_api.add_nwa_tenant_binding(
session,
tenant_id,
nwa_tenant_id,
nwa_data
):
return {'status': 'SUCCESS'}
return {'status': 'FAILED'}
@helpers.log_method_call
def set_nwa_tenant_binding(self, rpc_context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
nwa_data = kwargs.get('nwa_data')
LOG.debug(
"nwa_data=%s", jsonutils.dumps(nwa_data, indent=4, sort_keys=True)
)
session = db_api.get_session()
with session.begin(subtransactions=True):
if necnwa_api.set_nwa_tenant_binding(
session,
tenant_id,
nwa_tenant_id,
nwa_data
):
return {'status': 'SUCCESS'}
return {'status': 'FAILED'}
@helpers.log_method_call
def delete_nwa_tenant_binding(self, rpc_context, **kwargs):
tenant_id = kwargs.get('tenant_id')
nwa_tenant_id = kwargs.get('nwa_tenant_id')
session = db_api.get_session()
with session.begin(subtransactions=True):
if necnwa_api.del_nwa_tenant_binding(
session,
tenant_id,
nwa_tenant_id
):
return {'status': 'SUCCESS'}
return {'status': 'FAILED'}
def update_tenant_rpc_servers(self, rpc_context, **kwargs):
session = db_api.get_session()
with session.begin(subtransactions=True):
q_tids = [q.tenant_id
for q in necnwa_api.get_nwa_tenant_queues(session)]
plugin = directory.get_plugin()
tenant_ids = [server['tenant_id'] for server in kwargs['servers']]
ret = []
for tenant_id in set(q_tids) - set(tenant_ids):
LOG.info(_LI("RPCServer only db tid=%s, send create_server"),
tenant_id)
plugin.nwa_rpc.create_server(rpc_context, tenant_id)
ret.append({'tenant_id': tenant_id})
for tenant_id in set(tenant_ids) - set(q_tids):
LOG.info(_LI("RPCServer only agent tid=%s, send delete_server"),
tenant_id)
plugin.nwa_rpc.delete_server(rpc_context, tenant_id)
return {'servers': ret}

View File

@ -1,150 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.db.models import external_net as external_net_db
from neutron.db import segments_db as db_ml2
from neutron.plugins.ml2 import driver_api as api
from neutron_lib import constants
from oslo_config import cfg
from oslo_log import log as logging
from sqlalchemy.orm import exc as sa_exc
from networking_nec.nwa.common import utils as nwa_com_utils
LOG = logging.getLogger(__name__)
def get_network_info(context):
name = context.network.current['name']
network_id = context.network.current['id']
return name, network_id
def get_physical_network(device_owner, resource_groups,
resource_group_name=None):
for physnet in resource_groups:
physnets = [physnet['physical_network'] for physnet in resource_groups
if (physnet['device_owner'] == device_owner and
(not resource_group_name or
physnet['ResourceGroupName'] == resource_group_name))]
if physnets:
return physnets[0]
return None
def is_external_network(context, net_id):
if hasattr(context, 'session'):
session = context.session
else:
session = context.network._plugin_context.session
try:
session.query(
external_net_db.ExternalNetwork).filter_by(
network_id=net_id
).one()
return True
except sa_exc.NoResultFound:
return False
def get_vlan_id_of_physical_network(context, network_id, physical_network):
if hasattr(context, 'session'):
session = context.session
else:
session = context.network._plugin_context.session
segments = db_ml2.get_network_segments(session, network_id)
if not segments:
return ''
for segment in segments:
if segment[api.PHYSICAL_NETWORK] == physical_network:
return str(segment[api.SEGMENTATION_ID])
return str(segments[0][api.SEGMENTATION_ID])
# pylint: disable=too-many-locals
def portcontext_to_nwa_info(context, resource_groups,
use_original_port=False):
tenant_id, nwa_tenant_id = nwa_com_utils.get_tenant_info(context)
network_name, network_id = get_network_info(context)
port = context.original if use_original_port else context.current
device_owner = port['device_owner']
resource_group_name = _get_resource_group_name(context, resource_groups,
use_original_port)
physical_network = get_physical_network(device_owner, resource_groups,
resource_group_name)
vlan_id = get_vlan_id_of_physical_network(context, network_id,
physical_network)
vlan_type = 'PublicVLAN' if is_external_network(context, network_id) \
else 'BusinessVLAN'
dbcontext = context._plugin_context
nwa_info = {
'tenant_id': tenant_id,
'nwa_tenant_id': nwa_tenant_id,
'network': {'id': network_id,
'name': network_name,
'vlan_id': vlan_id,
'vlan_type': vlan_type},
'device': {'owner': device_owner,
'id': port['device_id']},
}
if port['fixed_ips']:
subnet_id = port['fixed_ips'][0]['subnet_id']
subnet = context._plugin.get_subnet(dbcontext, subnet_id)
nwa_info['subnet'] = {'id': subnet_id,
'netaddr': subnet['cidr'].split('/')[0],
'mask': subnet['cidr'].split('/')[1]}
nwa_info['port'] = {'id': port['id'],
'ip': port['fixed_ips'][0]['ip_address'],
'mac': port['mac_address']}
else:
nwa_info['subnet'] = {'id': '',
'netaddr': '',
'mask': ''}
nwa_info['port'] = {'id': port['id'],
'ip': '',
'mac': port['mac_address']}
nwa_info['resource_group_name'] = resource_group_name
nwa_info['resource_group_name_nw'] = cfg.CONF.NWA.resource_group_name
nwa_info['physical_network'] = physical_network
return nwa_info
# Private methods
def _get_resource_group_name(context, resource_groups,
use_original_port=False):
port = context.original if use_original_port else context.current
device_owner = port['device_owner']
for agent in context.host_agents(constants.AGENT_TYPE_OVS):
if agent['alive']:
mappings = agent['configurations'].get('bridge_mappings', {})
for res_grp in resource_groups:
if not res_grp['ResourceGroupName'] in mappings:
continue
if res_grp['device_owner'] == device_owner:
return res_grp['ResourceGroupName']
if (device_owner == constants.DEVICE_OWNER_ROUTER_INTF or
device_owner == constants.DEVICE_OWNER_ROUTER_GW):
for res_grp in resource_groups:
if res_grp['device_owner'] == device_owner:
return res_grp['ResourceGroupName']
return None

View File

@ -1,31 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy.orm import exc as sa_exc
from neutron.db.models import l3 as l3_db
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
def get_tenant_id_by_router(session, router_id):
with session.begin(subtransactions=True):
try:
router = session.query(l3_db.Router).filter_by(id=router_id).one()
rt_tid = router.tenant_id
LOG.debug("rt_tid=%s", rt_tid)
return rt_tid
except sa_exc.NoResultFound:
LOG.debug("router not found %s", router_id)

View File

@ -1,229 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sa
from sqlalchemy import or_
from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api
from neutron.api.rpc.handlers import l3_rpc
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.db import common_db_mixin
from neutron.db import extraroute_db
from neutron.db import l3_agentschedulers_db
from neutron.db import l3_gwmode_db
from neutron.db.models import l3 as l3_db
from neutron.plugins.common import constants
from neutron.plugins.ml2 import driver_context
from neutron.services import service_base
from neutron_lib import constants as n_const
from neutron_lib import exceptions as exc
from oslo_config import cfg
from oslo_log import helpers
from oslo_log import log as logging
from networking_nec._i18n import _LI, _LW, _LE
from networking_nec.nwa.common import utils as nwa_com_utils
from networking_nec.nwa.l2 import db_api as nwa_db
from networking_nec.nwa.l2 import utils as nwa_l2_utils
from networking_nec.nwa.l3 import db_api as nwa_l3_db
from networking_nec.nwa.l3.rpc import nwa_l3_proxy_api
from networking_nec.nwa.l3.rpc import nwa_l3_server_callback
LOG = logging.getLogger(__name__)
class NECNWAL3Plugin(service_base.ServicePluginBase,
common_db_mixin.CommonDbMixin,
extraroute_db.ExtraRoute_db_mixin,
l3_gwmode_db.L3_NAT_db_mixin,
l3_agentschedulers_db.L3AgentSchedulerDbMixin):
supported_extension_aliases = ["router", "ext-gw-mode",
"extraroute"]
def __init__(self):
super(NECNWAL3Plugin, self).__init__()
# l3_db.subscribe()
self.start_rpc_listeners()
self.nwa_proxies = {}
self.resource_groups = nwa_com_utils.load_json_from_file(
'resource_group', cfg.CONF.NWA.resource_group_file,
cfg.CONF.NWA.resource_group, default_value=[])
@helpers.log_method_call
def start_rpc_listeners(self):
# RPC support
self.topic = topics.L3PLUGIN
self.conn = n_rpc.create_connection()
self.agent_notifiers.update(
{n_const.AGENT_TYPE_L3: l3_rpc_agent_api.L3AgentNotifyAPI()})
self.endpoints = [l3_rpc.L3RpcCallback(),
nwa_l3_server_callback.NwaL3ServerRpcCallback()]
self.conn.create_consumer(self.topic, self.endpoints,
fanout=False)
return self.conn.consume_in_threads()
def get_plugin_type(self):
return constants.L3_ROUTER_NAT
def get_plugin_description(self):
"""Returns string description of the plugin."""
return "NEC NWA Plugin based routing"
@helpers.log_method_call
def create_floatingip(self, context, floatingip,
initial_status=n_const.FLOATINGIP_STATUS_DOWN):
return super(NECNWAL3Plugin, self).create_floatingip(
context, floatingip, initial_status)
def _delete_nat(self, context, fip):
if not fip['router_id'] or not fip['fixed_ip_address']:
LOG.debug('already deleted %s', fip)
return
tenant_id = nwa_l3_db.get_tenant_id_by_router(
context.session, fip['router_id']
)
nwa_tenant_id = nwa_com_utils.get_nwa_tenant_id(tenant_id)
fl_data = {
'floating_ip_address': fip['floating_ip_address'],
'fixed_ip_address': fip['fixed_ip_address'],
'id': fip['id'],
'device_id': fip['router_id'],
'floating_network_id': fip['floating_network_id'],
'tenant_id': fip['tenant_id']
}
LOG.info(_LI('delete_nat fl_data=%s'), fl_data)
proxy = self._get_nwa_proxy(self, tenant_id)
proxy.delete_nat(
context, tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
floating=fl_data
)
# pylint: disable=arguments-differ
@helpers.log_method_call
def disassociate_floatingips(self, context, port_id, do_notify=True):
floating_ips = context.session.query(l3_db.FloatingIP).filter(
or_(l3_db.FloatingIP.fixed_port_id == port_id,
l3_db.FloatingIP.floating_port_id == port_id)
)
if not floating_ips:
LOG.warning(_LW('floatingip not found %s'), port_id)
for fip in floating_ips:
self._delete_nat(context, fip)
router_ids = super(NECNWAL3Plugin, self).disassociate_floatingips(
context, port_id, do_notify)
return router_ids
@helpers.log_method_call
def update_floatingip(self, context, fpid, floatingip):
port_id_specified = 'port_id' in floatingip['floatingip']
if not port_id_specified:
LOG.error(_LE("port_id key is not found in %s"), floatingip)
raise exc.PortNotFound(port_id=None)
port_id = floatingip['floatingip'].get('port_id')
try:
if port_id_specified and not port_id:
floating = context.session.query(l3_db.FloatingIP).filter_by(
id=fpid).one()
self._delete_nat(context, floating)
except sa.orm.exc.NoResultFound:
raise exc.PortNotFound(port_id=port_id)
ret = super(NECNWAL3Plugin, self).update_floatingip(
context, fpid, floatingip)
try:
if port_id_specified and port_id:
floating = context.session.query(l3_db.FloatingIP).filter_by(
id=fpid).one()
tenant_id = nwa_l3_db.get_tenant_id_by_router(
context.session,
floating['router_id']
)
nwa_tenant_id = nwa_com_utils.get_nwa_tenant_id(tenant_id)
fl_data = {
'floating_ip_address': floating['floating_ip_address'],
'fixed_ip_address': floating['fixed_ip_address'],
'id': fpid, 'device_id': floating['router_id'],
'floating_network_id': floating['floating_network_id'],
'tenant_id': floating['tenant_id'],
'floating_port_id': floating['floating_port_id']
}
LOG.info(_LI('setting_nat fl_data is %s'), fl_data)
proxy = self._get_nwa_proxy(self, tenant_id)
proxy.setting_nat(
context, tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
floating=fl_data
)
except sa.orm.exc.NoResultFound:
raise exc.PortNotFound(port_id=port_id)
return ret
def add_router_interface(self, context, router_id, interface_info):
ret = super(NECNWAL3Plugin, self).add_router_interface(
context,
router_id,
interface_info
)
if 'port_id' in interface_info:
self._add_router_interface_by_port(
self, context, router_id, interface_info
)
return ret
def _add_router_interface_by_port(self, plugin, context, router_id,
interface_info):
try:
session = context.session
port = plugin._core_plugin._get_port(context,
interface_info['port_id'])
network = plugin._core_plugin.get_network(context,
port['network_id'])
binding = nwa_db.ensure_port_binding(session, port['id'])
port_context = driver_context.PortContext(plugin._core_plugin,
context, port,
network, binding, None)
nwa_info = nwa_l2_utils.portcontext_to_nwa_info(
port_context, self.resource_groups)
rt_tid = nwa_l3_db.get_tenant_id_by_router(
session, router_id
)
nwa_rt_tid = nwa_com_utils.get_nwa_tenant_id(rt_tid)
nwa_info['tenant_id'] = rt_tid
nwa_info['nwa_tenant_id'] = nwa_rt_tid
proxy = self._get_nwa_proxy(plugin, rt_tid)
proxy.create_tenant_fw(
port_context.network._plugin_context,
rt_tid,
nwa_rt_tid,
nwa_info
)
except Exception as e:
LOG.exception(_LE("create tenant firewall %s"), e)
def _get_nwa_proxy(self, plugin, tenant_id):
proxy = plugin._core_plugin.get_nwa_proxy(tenant_id)
return nwa_l3_proxy_api.NwaL3ProxyApi(proxy.client)

View File

@ -1,63 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
class NwaL3ProxyApi(object):
def __init__(self, client):
self.client = client
def create_tenant_fw(self, context, tenant_id, nwa_tenant_id, nwa_info):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'create_tenant_fw',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_info=nwa_info
)
def delete_tenant_fw(self, context, tenant_id, nwa_tenant_id, nwa_info):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'delete_tenant_fw',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
nwa_info=nwa_info
)
def setting_nat(self, context, tenant_id, nwa_tenant_id, floating):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'setting_nat',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
floating=floating
)
def delete_nat(self, context, tenant_id, nwa_tenant_id, floating):
cctxt = self.client.prepare()
return cctxt.cast(
context,
'delete_nat',
tenant_id=tenant_id,
nwa_tenant_id=nwa_tenant_id,
floating=floating
)

View File

@ -1,44 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import helpers
from oslo_log import log as logging
import oslo_messaging
LOG = logging.getLogger(__name__)
class NwaL3ProxyCallback(object):
target = oslo_messaging.Target(version='1.0')
def __init__(self, context, agent):
self.context = context
self.agent = agent
@helpers.log_method_call
def create_tenant_fw(self, context, **kwargs):
return self.agent.create_tenant_fw(context, **kwargs)
@helpers.log_method_call
def delete_tenant_fw(self, context, **kwargs):
return self.agent.delete_tenant_fw(context, **kwargs)
@helpers.log_method_call
def setting_nat(self, context, **kwargs):
return self.agent.setting_nat(context, **kwargs)
@helpers.log_method_call
def delete_nat(self, context, **kwargs):
return self.agent.delete_nat(context, **kwargs)

View File

@ -1,38 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import rpc as n_rpc
from oslo_log import log as logging
import oslo_messaging
LOG = logging.getLogger(__name__)
class NwaL3ServerRpcApi(object):
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic):
target = oslo_messaging.Target(topic=topic,
version=self.BASE_RPC_API_VERSION)
self.client = n_rpc.get_client(target)
def update_floatingip_status(self, context, floatingip_id, status):
cctxt = self.client.prepare()
return cctxt.call(
context,
'update_floatingip_status',
floatingip_id=floatingip_id,
status=status
)

View File

@ -1,45 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.extensions import l3
from neutron_lib import constants
from neutron_lib.plugins import directory
from oslo_log import log as logging
import oslo_messaging
LOG = logging.getLogger(__name__)
class NwaL3ServerRpcCallback(object):
target = oslo_messaging.Target(version='1.0')
@property
def l3plugin(self):
if not hasattr(self, '_l3plugin'):
self._l3plugin = directory.get_plugin(constants.L3)
return self._l3plugin
def update_floatingip_status(self, context, floatingip_id, status):
'''Update operational status for a floating IP.'''
with context.session.begin(subtransactions=True):
LOG.debug('New status for floating IP %s: %s' %
(floatingip_id, status))
try:
self.l3plugin.update_floatingip_status(context,
floatingip_id,
status)
except l3.FloatingIPNotFound:
LOG.debug("Floating IP: %s no longer present.",
floatingip_id)

View File

@ -1,33 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from networking_nec.nwa.nwalib import client_fwaas
from networking_nec.nwa.nwalib import client_l2
from networking_nec.nwa.nwalib import client_l3
from networking_nec.nwa.nwalib import client_lbaas
from networking_nec.nwa.nwalib import client_tenant
from networking_nec.nwa.nwalib import nwa_restclient
class NwaClient(nwa_restclient.NwaRestClient):
'''Client class of NWA. '''
def __init__(self, *args, **kwargs):
super(NwaClient, self).__init__(*args, **kwargs)
self.tenant = client_tenant.NwaClientTenant(self)
self.l2 = client_l2.NwaClientL2(self)
self.l3 = client_l3.NwaClientL3(self)
self.fwaas = client_fwaas.NwaClientFWaaS(self)
self.lbaas = client_lbaas.NwaClientLBaaS(self)

View File

@ -1,40 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from debtcollector import removals
class NwaClientFWaaS(object):
def __init__(self, client):
self.client = client
@removals.remove(
message='It is no longer async. Use setting_fw_policy instead.')
def setting_fw_policy_async(self, tenant_id, fw_name, props):
return self.setting_fw_policy(tenant_id, fw_name, props)
def setting_fw_policy(self, tenant_id, fw_name, props):
body = {
'TenantID': tenant_id,
'DCResourceType': 'TFW_Policy',
'DCResourceOperation': 'Setting',
'DeviceInfo': {
'Type': 'TFW',
'DeviceName': fw_name,
},
'Property': props
}
return self.client.call_workflow(
tenant_id, self.client.post, 'SettingFWPolicy', body)

View File

@ -1,148 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from networking_nec._i18n import _LW
LOG = logging.getLogger(__name__)
class NwaClientL2(object):
def __init__(self, client):
self.client = client
# --- Tenant Network ---
def create_tenant_nw(self, tenant_id, dc_resource_group_name):
body = {
"TenantID": tenant_id,
"CreateNW_DCResourceGroupName": dc_resource_group_name,
'CreateNW_OperationType': 'CreateTenantNW'
}
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateTenantNW', body
)
def delete_tenant_nw(self, tenant_id):
body = {
"TenantID": tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteTenantNW', body
)
# --- VLan ---
def create_vlan(self, tenant_id, ipaddr, mask,
vlan_type='BusinessVLAN', openstack_network_id=None):
body = {
'TenantID': tenant_id,
'CreateNW_VlanType1': vlan_type,
'CreateNW_IPSubnetAddress1': ipaddr,
'CreateNW_IPSubnetMask1': mask
}
if openstack_network_id:
body['CreateNW_VlanLogicalID1'] = openstack_network_id
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateVLAN', body
)
def delete_vlan(self, tenant_id, logical_name, vlan_type='BusinessVLAN'):
body = {
'TenantID': tenant_id,
'DeleteNW_VlanLogicalName1': logical_name,
'DeleteNW_VlanType1': vlan_type
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteVLAN', body
)
# --- General Dev ---
def create_general_dev(self, tenant_id, dc_resource_group_name,
logical_name, vlan_type='BusinessVLAN',
port_type=None, openstack_network_id=None):
body = {
'CreateNW_DeviceType1': 'GeneralDev',
'TenantID': tenant_id,
'CreateNW_VlanLogicalName1': logical_name,
'CreateNW_VlanType1': vlan_type,
'CreateNW_DCResourceGroupName': dc_resource_group_name
}
if logical_name and openstack_network_id:
LOG.warning(_LW('VLAN logical name and id to be specified '
'in the exclusive.'))
if openstack_network_id:
body['CreateNW_VlanLogicalID1'] = openstack_network_id
if port_type:
body['CreateNW_PortType1'] = port_type
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateGeneralDev', body
)
def delete_general_dev(self, tenant_id, dc_resource_group_name,
logical_name, vlan_type='BusinessVLAN',
port_type=None, openstack_network_id=None):
body = {
'DeleteNW_DeviceType1': 'GeneralDev',
'TenantID': tenant_id,
'DeleteNW_VlanLogicalName1': logical_name,
'DeleteNW_VlanType1': vlan_type,
'DeleteNW_DCResourceGroupName': dc_resource_group_name
}
if logical_name and openstack_network_id:
LOG.warning(_LW('VLAN logical name and id to be specified '
'in the exclusive.'))
if openstack_network_id:
body['DeleteNW_VlanLogicalID1'] = openstack_network_id
if port_type:
body['DeleteNW_PortType1'] = port_type
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteGeneralDev', body
)
# --- Connect Port ---
def create_connect_port(self, tenant_id, dc_resource_group_name,
logical_name, vlan_type, vlan_id):
body = {
'CreateNW_DCResourceGroupName': dc_resource_group_name,
'CreateNW_DeviceType1': 'GeneralDev',
'CreateNW_OperationType': 'CreateConnectPort',
'CreateNW_VlanID1': vlan_id,
'CreateNW_VlanLogicalName1': logical_name,
'CreateNW_VlanType1': vlan_type,
'TenantID': tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateConnectPort', body
)
def delete_connect_port(self, tenant_id, dc_resource_group_name,
logical_name, vlan_type, vlan_id):
body = {
'DeleteNW_DCResourceGroupName': dc_resource_group_name,
'DeleteNW_DeviceType1': 'GeneralDev',
'DeleteNW_OperationType': 'DeleteConnectPort',
'DeleteNW_VlanID1': vlan_id,
'DeleteNW_VlanLogicalName1': logical_name,
'DeleteNW_VlanType1': vlan_type,
'TenantID': tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteConnectPort', body
)

View File

@ -1,117 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from networking_nec._i18n import _LE
LOG = logging.getLogger(__name__)
class NwaClientL3(object):
def __init__(self, client):
self.client = client
# --- Tenant FW ---
def create_tenant_fw(self, tenant_id, dc_resource_group_name,
vlan_devaddr, vlan_logical_name,
vlan_type='BusinessVLAN', router_id=None):
body = {
'CreateNW_DeviceType1': 'TFW',
'TenantID': tenant_id,
'CreateNW_Vlan_DeviceAddress1': vlan_devaddr,
'CreateNW_VlanLogicalName1': vlan_logical_name,
'CreateNW_VlanType1': vlan_type,
'CreateNW_DCResourceGroupName': dc_resource_group_name
}
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateTenantFW', body)
def update_tenant_fw(self, tenant_id, device_name, vlan_devaddr,
vlan_logical_name, vlan_type,
connect=None, router_id=None):
body = {
'ReconfigNW_DeviceName1': device_name,
'ReconfigNW_DeviceType1': 'TFW',
'ReconfigNW_Vlan_DeviceAddress1': vlan_devaddr,
'ReconfigNW_VlanLogicalName1': vlan_logical_name,
'ReconfigNW_VlanType1': vlan_type,
'TenantID': tenant_id
}
if connect:
body['ReconfigNW_Vlan_ConnectDevice1'] = connect
return self.client.call_workflow(
tenant_id, self.client.post, 'UpdateTenantFW', body)
def delete_tenant_fw(self, tenant_id, device_name, device_type,
router_id=None):
body = {
'DeleteNW_DeviceName1': device_name,
'DeleteNW_DeviceType1': device_type,
'TenantID': tenant_id
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteTenantFW', body)
# --- Nat ---
def setting_nat(self, tenant_id, vlan_logical_name, vlan_type,
local_ip, global_ip, dev_name, data=None, router_id=None):
body = {
'ReconfigNW_DeviceName1': dev_name,
'ReconfigNW_DeviceType1': 'TFW',
'ReconfigNW_VlanLogicalName1': vlan_logical_name,
'ReconfigNW_VlanType1': vlan_type,
'LocalIP': local_ip,
'GlobalIP': global_ip,
'TenantID': tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'SettingNAT', body)
def delete_nat(self, tenant_id, vlan_logical_name, vlan_type,
local_ip, global_ip, dev_name, data=None, router_id=None):
body = {
'DeleteNW_DeviceName1': dev_name,
'DeleteNW_DeviceType1': 'TFW',
'DeleteNW_VlanLogicalName1': vlan_logical_name,
'DeleteNW_VlanType1': vlan_type,
'LocalIP': local_ip,
'GlobalIP': global_ip,
'TenantID': tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteNAT', body)
def update_nat(self, tenant_id, vlan_logical_name, vlan_type,
local_ip, global_ip, dev_name, data=None, router_id=None):
try:
http_status, rj = self.delete_nat(tenant_id,
vlan_logical_name, vlan_type,
local_ip, global_ip, dev_name,
data=data)
except Exception as e:
LOG.exception(_LE('%s'), e)
http_status = -1
rj = None
self.setting_nat(tenant_id, vlan_logical_name, vlan_type,
local_ip, global_ip, dev_name,
data=data, router_id=router_id)
return http_status, rj

View File

@ -1,84 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import re
class NwaClientLBaaS(object):
def __init__(self, client):
self.client = client
def create_tenant_lb(self, tenant_id,
dc_resource_group_name,
vlan_logical_name, vlan_type, vif_ipaddr):
body = {
'CreateNW_DeviceType1': 'LB',
'TenantID': tenant_id,
'CreateNW_Vlan_DeviceAddress1': vif_ipaddr,
'CreateNW_VlanLogicalName1': vlan_logical_name,
'CreateNW_VlanType1': vlan_type,
'CreateNW_DCResourceGroupName': dc_resource_group_name
}
return self.client.call_workflow(
tenant_id, self.client.post, 'CreateTenantLB', body)
def delete_tenant_lb(self, tenant_id, device_name):
body = {
'DeleteNW_DeviceName1': device_name,
'DeleteNW_DeviceType1': 'LB',
'TenantID': tenant_id,
}
return self.client.call_workflow(
tenant_id, self.client.post, 'DeleteTenantLB', body)
def update_tenant_lbn(self, tenant_id,
device_name, actions):
body = {
'ReconfigNW_DeviceName1': device_name,
'ReconfigNW_DeviceType1': 'LB',
'TenantID': tenant_id
}
for n, a in enumerate(actions):
i = str(n + 1)
if a[0] is not None:
body['ReconfigNW_Vlan_ConnectDevice' + i] = a[0]
lwn = a[1]
body['ReconfigNW_VlanLogicalName' + i] = lwn
if len(a) > 2:
body['ReconfigNW_Vlan_DeviceAddress' + i] = a[2]
if len(a) > 3:
body['ReconfigNW_VlanType' + i] = a[3]
else:
if re.search(lwn, '_PublicVLAN_'):
body['ReconfigNW_VlanType' + i] = 'PublicVLAN'
else:
body['ReconfigNW_VlanType' + i] = 'BusinessVLAN'
return self.client.call_workflow(
tenant_id, self.client.post, 'UpdateTenantLB', body)
def setting_lb_policy(self, tenant_id, lb_name, props):
body = {
'TenantID': tenant_id,
'DCResourceType': 'LB_Policy',
'DCResourceOperation': 'Setting',
'DeviceInfo': {
'Type': 'LB',
'DeviceName': lb_name,
},
'Property': props
}
return self.client.call_workflow(
tenant_id, self.client.post, 'SettingLBPolicy', body)

View File

@ -1,33 +0,0 @@
# Copyright 2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from networking_nec.nwa.nwalib import semaphore as nwa_sem
class NwaClientTenant(object):
def __init__(self, client):
self.client = client
def create_tenant(self, tenant_id):
body = {
'TenantName': tenant_id,
}
return self.client.post('/umf/tenant/' + tenant_id, body)
def delete_tenant(self, tenant_id):
status_code, data = self.client.delete('/umf/tenant/' + tenant_id)
if status_code == 200:
nwa_sem.Semaphore.delete_tenant_semaphore(tenant_id)
return status_code, data

View File

@ -1,189 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from networking_nec.nwa.common import constants as nwa_const
VLAN_OWN_GDV = 'GD'
VLAN_OWN_TFW = 'TFW'
NWA_DEVICE_MAP = {
nwa_const.NWA_DEVICE_GDV: VLAN_OWN_GDV,
nwa_const.NWA_DEVICE_TFW: VLAN_OWN_TFW,
}
def get_network_key(network_id):
return 'NW_' + network_id
def get_vlan_key(network_id):
return 'VLAN_' + network_id
def get_device_key(device_id):
return 'DEV_' + device_id
def get_tfw_device_name(nwa_data, device_id):
return nwa_data['DEV_' + device_id + '_TenantFWName']
def get_device_net_key(device_id, network_id):
return 'DEV_%s_%s' % (device_id, network_id)
def get_vlan_logical_name(nwa_data, network_id):
return nwa_data['NW_' + network_id + '_nwa_network_name']
def get_vlan_id(network_id, nwa_data, resultdata):
vlan_key = 'VLAN_' + network_id
if nwa_data[vlan_key + '_CreateVlan'] == '':
return resultdata['VlanID']
else:
return nwa_data[vlan_key + '_VlanID']
def get_vp_net_vlan_id(nwa_data, network_id, resource_group_name_nw,
device_type):
seg_key = 'VLAN_%s_%s_%s' % (network_id, resource_group_name_nw,
NWA_DEVICE_MAP[device_type])
return int(nwa_data[seg_key + '_VlanID'], 10)
def set_network_data(nwa_data, network_id, nwa_info, logical_name):
nw_net = 'NW_' + network_id
nwa_data[nw_net] = nwa_info['network']['name']
nwa_data[nw_net + '_network_id'] = network_id
nwa_data[nw_net + '_subnet_id'] = nwa_info['subnet']['id']
nwa_data[nw_net + '_subnet'] = nwa_info['subnet']['netaddr']
nwa_data[nw_net + '_nwa_network_name'] = logical_name
def strip_network_data(nwa_data, network_id):
nw_net = 'NW_' + network_id
nwa_data.pop(nw_net)
nwa_data.pop(nw_net + '_network_id')
nwa_data.pop(nw_net + '_subnet_id')
nwa_data.pop(nw_net + '_subnet')
nwa_data.pop(nw_net + '_nwa_network_name')
def set_vlan_data(nwa_data, network_id, vlan_id):
vp_net = 'VLAN_' + network_id
nwa_data[vp_net] = 'physical_network'
nwa_data[vp_net + '_VlanID'] = vlan_id
nwa_data[vp_net + '_CreateVlan'] = ''
def strip_vlan_data(nwa_data, network_id):
vp_net = 'VLAN_' + network_id
nwa_data.pop(vp_net)
nwa_data.pop(vp_net + '_VlanID')
nwa_data.pop(vp_net + '_CreateVlan')
def set_gdv_device_data(nwa_data, device_id, nwa_info):
dev_key = 'DEV_%s' % device_id
nwa_data[dev_key] = 'device_id'
nwa_data[dev_key + '_device_owner'] = nwa_info['device']['owner']
def set_tfw_device_data(nwa_data, device_id, tfw_name, nwa_info):
dev_key = 'DEV_%s' % device_id
nwa_data[dev_key] = 'device_id'
nwa_data[dev_key + '_device_owner'] = nwa_info['device']['owner']
nwa_data[dev_key + '_TenantFWName'] = tfw_name
def strip_device_data(nwa_data, device_id):
dev_key = 'DEV_%s' % device_id
nwa_data.pop(dev_key)
nwa_data.pop(dev_key + '_device_owner')
nwa_data.pop(dev_key + '_TenantFWName', None)
def set_gdv_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw, nwa_info):
net_key = 'DEV_%s_%s' % (device_id, network_id)
nwa_data[net_key] = nwa_info['network']['name']
nwa_data[net_key + '_ip_address'] = nwa_info['port']['ip']
nwa_data[net_key + '_mac_address'] = nwa_info['port']['mac']
nwa_data[net_key + '_' + resource_group_name_nw] = nwa_const.NWA_DEVICE_GDV
def set_tfw_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw, tfw_name, nwa_info):
net_key = 'DEV_%s_%s' % (device_id, network_id)
nwa_data[net_key] = nwa_info['network']['name']
nwa_data[net_key + '_ip_address'] = nwa_info['port']['ip']
nwa_data[net_key + '_mac_address'] = nwa_info['port']['mac']
nwa_data[net_key + '_TenantFWName'] = tfw_name
nwa_data[net_key + '_' + resource_group_name_nw] = nwa_const.NWA_DEVICE_TFW
def strip_interface_data(nwa_data, device_id, network_id,
resource_group_name_nw):
net_key = 'DEV_%s_%s' % (device_id, network_id)
nwa_data.pop(net_key)
nwa_data.pop(net_key + '_ip_address')
nwa_data.pop(net_key + '_mac_address')
nwa_data.pop(net_key + '_TenantFWName', None)
nwa_data.pop(net_key + '_' + resource_group_name_nw)
def set_vp_net_data(nwa_data, network_id, resource_group_name_nw, device_type,
vlan_id):
seg_key = ('VLAN_%(network_id)s_%(group)s_%(dev_type)s' %
{'network_id': network_id,
'group': resource_group_name_nw,
'dev_type': NWA_DEVICE_MAP[device_type]})
nwa_data[seg_key] = 'physical_network'
nwa_data[seg_key + '_VlanID'] = vlan_id
def strip_vp_net_data(nwa_data, network_id, resource_group_name_nw,
device_type):
seg_key = ('VLAN_%(network_id)s_%(group)s_%(dev_type)s' %
{'network_id': network_id,
'group': resource_group_name_nw,
'dev_type': NWA_DEVICE_MAP[device_type]})
nwa_data.pop(seg_key)
nwa_data.pop(seg_key + '_VlanID')
def strip_tfw_data_if_exist(nwa_data, device_id, network_id,
resource_group_name_nw):
tfw_key = 'VLAN_%s_%s_TFW_FW_TFW%s' % (network_id,
resource_group_name_nw,
device_id)
if tfw_key in nwa_data:
nwa_data.pop(tfw_key)
def set_floatingip_data(nwa_data, floating):
fip_key = 'NAT_' + floating['id']
nwa_data[fip_key] = floating['device_id']
nwa_data[fip_key + '_network_id'] = floating['floating_network_id']
nwa_data[fip_key + '_floating_ip_address'] = \
floating['floating_ip_address']
nwa_data[fip_key + '_fixed_ip_address'] = floating['fixed_ip_address']
def strip_floatingip_data(nwa_data, floating):
fip_key = 'NAT_' + floating['id']
nwa_data.pop(fip_key)
nwa_data.pop(fip_key + '_network_id')
nwa_data.pop(fip_key + '_floating_ip_address')
nwa_data.pop(fip_key + '_fixed_ip_address')

View File

@ -1,25 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class NwaException(Exception):
'''Raised when there is an error in Nwa. '''
def __init__(self, http_status, errmsg, orgexc=None):
super(NwaException, self).__init__()
self.http_status = http_status
self.errmsg = errmsg
self.orgexc = orgexc
def __str__(self):
return 'http status: %s, %s' % (self.http_status, self.errmsg)

View File

@ -1,271 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import base64
import copy
import hashlib
import hmac
import re
import eventlet
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
import six
from six.moves.urllib import parse as urlparse
from networking_nec._i18n import _LI, _LW, _LE
from networking_nec.nwa.common import config as nwaconf
from networking_nec.nwa.nwalib import exceptions as nwa_exc
from networking_nec.nwa.nwalib import restclient
from networking_nec.nwa.nwalib import semaphore as nwa_sem
from networking_nec.nwa.nwalib import workflow
LOG = logging.getLogger(__name__)
cfgNWA = nwaconf.cfg.CONF.NWA
CRLF = '\x0D\x0A'
class NwaRestClient(restclient.RestClient):
'''Client class of NWA rest. '''
workflow_list_is_loaded = False
def __init__(self, host=None, port=None, use_ssl=True, auth=None,
access_key_id=None, secret_access_key=None, **kwargs):
load_workflow_list = kwargs.pop('load_workflow_list', True)
if auth is None:
auth = self._define_auth_function(access_key_id, secret_access_key)
if not host or not port:
if not cfgNWA.server_url:
raise cfg.Error("'server_url' or (host, port) "
"must be specified.")
host, port, use_ssl = self._parse_server_url(cfgNWA.server_url)
super(NwaRestClient, self).__init__(host, port, use_ssl, auth,
**kwargs)
self._post_data = None
self.workflow_first_wait = cfg.CONF.NWA.scenario_polling_first_timer
self.workflow_wait_sleep = cfg.CONF.NWA.scenario_polling_timer
self.workflow_retry_count = cfg.CONF.NWA.scenario_polling_count
LOG.info(_LI('NWA init: workflow wait: %(first_wait)ss + '
'%(wait_sleep)ss x %(retry_count)s times.'),
{'first_wait': self.workflow_first_wait,
'wait_sleep': self.workflow_wait_sleep,
'retry_count': self.workflow_retry_count})
if load_workflow_list and not NwaRestClient.workflow_list_is_loaded:
self.update_workflow_list()
NwaRestClient.workflow_list_is_loaded = True
def _parse_server_url(self, url):
url_parts = urlparse.urlparse(url)
return (url_parts.hostname,
url_parts.port,
url_parts.scheme == 'https')
def _define_auth_function(self, access_key_id, secret_access_key):
access_key_id = access_key_id or cfgNWA.access_key_id
secret_access_key = secret_access_key or cfgNWA.secret_access_key
if not access_key_id or not secret_access_key:
# XXX: Don't we need to raise an error?
# raise cfg.Error('access_key_id and secret_access_key must '
# 'be specified.')
return
def azure_auth(datestr, path):
signature = hmac.new(
encodeutils.safe_encode(secret_access_key),
encodeutils.safe_encode(datestr + CRLF + path),
hashlib.sha256
).digest()
return (encodeutils.safe_encode('SharedKeyLite %s:'
% access_key_id) +
base64.b64encode(signature))
return azure_auth
def workflow_polling_log_post_data(self, url, body):
self._post_data = (url, body)
def _log_rest_request(self, method, url, body):
name = workflow.NwaWorkflow.name(url)
body_str = ''
if isinstance(body, dict):
body_str = jsonutils.dumps(body, sort_keys=True)
if name:
LOG.info(_LI('NWA workflow: %(name)s %(body)s'),
{'name': name, 'body': body_str})
else:
LOG.info(_LI('NWA %(method)s %(url)s %(body)s'),
{'method': method,
'url': self._url(url),
'body': body_str})
def _log_workflow_success(self, data):
name = ''
if self._post_data:
post_url = self._post_data[0]
name = (workflow.NwaWorkflow.name(post_url) or post_url)
LOG.info(_LI("NWA workflow: %(name)s %(workflow)s"),
{'name': name,
'workflow': jsonutils.dumps(data, indent=4, sort_keys=True)})
def _log_workflow_error(self, data):
errno = workflow.NwaWorkflow.get_errno_from_resultdata(data)
if not self._post_data:
return ''
post_url, post_body = self._post_data
if isinstance(post_body, dict):
post_body = jsonutils.dumps(post_body, indent=4, sort_keys=True)
name = (workflow.NwaWorkflow.name(post_url) or post_url)
reason = workflow.NwaWorkflow.strerror(errno)
LOG.error(_LE("NWA workflow: %(name)s reason(%(errno)s)=%(reason)s "
"request=%(request)s, response=%(response)s"),
{'name': name,
'errno': errno,
'reason': reason,
'request': post_body,
'response': jsonutils.dumps(data, indent=4, sort_keys=True)
})
def _log_rest_response(self, status_code, data):
status = ''
progress = ''
if isinstance(data, dict) and data.get('status'):
status = data.get('status')
progress = data.get('progress')
LOG.info(_LI("NWA HTTP %(code)s %(status)s %(progress)s"),
{'code': status_code,
'status': status, 'progress': progress})
if status == 'FAILED':
self._log_workflow_error(data)
elif status == 'SUCCEED':
self._log_workflow_success(data)
def rest_api(self, method, url, body=None):
status_code = 200
try:
self._log_rest_request(method, url, body)
status_code, data = super(NwaRestClient,
self).rest_api(method, url, body)
self._log_rest_response(status_code, data)
return status_code, data
except nwa_exc.NwaException as e:
status_code = e.http_status
return status_code, None
def workflowinstance(self, execution_id):
return self.get('/umf/workflowinstance/' + execution_id)
def stop_workflowinstance(self, execution_id):
return self.delete('/umf/workflowinstance/' + execution_id)
def workflow_kick_and_wait(self, call, url, body):
http_status = -1
rj = None
(http_status, rj) = call(url, body)
if not isinstance(rj, dict):
return (http_status, None)
exeid = rj.get('executionid')
if not isinstance(exeid, six.string_types):
LOG.error(_LE('Invalid executin id %s'), exeid)
try:
wait_time = self.workflow_first_wait
eventlet.sleep(wait_time)
for __ in range(self.workflow_retry_count):
(http_status, rw) = self.workflowinstance(exeid)
if not isinstance(rw, dict):
LOG.error(
_LE('NWA workflow: failed %(http_status)s %(body)s'),
{'http_status': http_status, 'body': rw}
)
return (http_status, None)
if rw.get('status') != 'RUNNING':
LOG.debug('%s', rw)
return (http_status, rw)
eventlet.sleep(wait_time)
wait_time = self.workflow_wait_sleep
LOG.warning(_LW('NWA workflow: retry over. retry count is %s.'),
self.workflow_retry_count)
except Exception as e:
LOG.error(_LE('NWA workflow: %s'), e)
return (http_status, None)
def call_workflow(self, tenant_id, post, name, body):
url = workflow.NwaWorkflow.path(name)
try:
wkf = nwa_sem.Semaphore.get_tenant_semaphore(tenant_id)
if wkf.sem.locked():
LOG.info(_LI('NWA sem %s(count)s: %(name)s %(url)s %(body)s'),
{'count': wkf.sem.balance,
'name': post.__name__,
'url': url,
'body': body})
with wkf.sem:
n = copy.copy(self)
n.workflow_polling_log_post_data(url, body)
http_status, rj = n.workflow_kick_and_wait(post, url, body)
return http_status, rj
except Exception as e:
LOG.exception(_LE('%s'), e)
return -1, None
def wait_workflow_done(self, thr):
LOG.debug('*** start wait')
thr.wait()
LOG.debug('*** end wait')
def get_tenant_resource(self, tenant_id):
return self.get('/umf/reserveddcresource/' + tenant_id)
def get_dc_resource_groups(self, group=None):
if not group:
url = '/umf/dcresource/groups'
else:
url = '/umf/dcresource/groups/' + str(group)
return self.get(url)
def get_reserved_dc_resource(self, tenant_id):
url = '/umf/reserveddcresource/' + str(tenant_id)
return self.get(url)
def get_workflow_list(self):
try:
url = '/umf/workflow/list'
return self.get(url)
except Exception as e:
LOG.warning(_LW('The initial worklist is not updated,'
' using default worklist. (%s)'), e)
return None, None
def update_workflow_list(self):
__, rj = self.get_workflow_list()
nameid = {}
if isinstance(rj, dict) and rj.get('Workflows'):
def new_nameid(wf):
path = wf.get('Path')
if isinstance(path, six.string_types):
m = re.search(r'\\([a-zA-Z0-9_]+)$', path)
if m:
key = str(m.group(1))
nameid[key] = str(wf.get('Id'))
for _wf in rj.get('Workflows'):
new_nameid(_wf)
workflow.NwaWorkflow.update_nameid(nameid)

View File

@ -1,148 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
from oslo_log import log as logging
from oslo_serialization import jsonutils
import requests
from networking_nec._i18n import _, _LI
from networking_nec.nwa.nwalib import exceptions as nwa_exc
LOG = logging.getLogger(__name__)
DATE_HEADER_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
UMF_API_VERSION = '2.0.2.1.201502'
OLD_UMF_API_VERSION = '2.0.2.201402'
# datetime.datetime.utcnow cannot be mocked.
# It is required to mock utcnow in unit test.
def utcnow():
return datetime.datetime.utcnow()
class RestClient(object):
"""A HTTP/HTTPS client for NEC NWA Drivers."""
def __init__(self, host=None, port=None, use_ssl=True, auth=None,
umf_api_version=UMF_API_VERSION):
"""Creates a new client to some NWA.
:param host: The host where service resides
:param port: The port where service resides
:param use_ssl: True to use SSL, False to use HTTP
:param: auth: function to generate Authorization header.
"""
self.host = host
self.port = port
self.use_ssl = use_ssl
self.auth = auth
self.umf_api_version = umf_api_version
LOG.info(
_LI('NWA init: host=%(host)s port=%(port)s use_ssl=%(use_ssl)s '
'auth=%(auth)s'),
{'host': self.host, 'port': self.port, 'use_ssl': self.use_ssl,
'auth': self.auth}
)
LOG.info(_LI('NWA init: umf api version: %s'),
self.umf_api_version)
def _url(self, path):
protocol = "http"
if self.use_ssl:
protocol = "https"
return '%s://%s:%s%s' % (protocol, self.host, self.port, path)
def _make_headers(self, path):
datestr = utcnow().strftime(DATE_HEADER_FORMAT)
headers = {
# XXX: If auth is None, RestClient will be broken.
'Authorization': self.auth(datestr, path),
'Content-Type': 'application/json',
'Date': datestr,
'X-UMF-API-Version': self.umf_api_version
}
return headers
def _send_receive(self, method, path, body=None):
scheme = "http"
if self.use_ssl:
scheme = "https"
url = "%s://%s:%d%s" % (scheme, self.host, int(self.port), path)
headers = self._make_headers(path)
LOG.debug('NWA HTTP Headers %s', headers)
res = requests.request(method, url, data=body, headers=headers,
verify=False, proxies={'no': 'pass'})
return res
def rest_api(self, method, url, body=None):
if isinstance(body, dict):
body = jsonutils.dumps(body, indent=4, sort_keys=True)
LOG.debug("NWA %(method)s %(host)s:%(port)s%(url)s body=%(body)s",
{'method': method, 'host': self.host, 'port': self.port,
'url': url, 'body': body})
status_code = -1
try:
res = self._send_receive(method, url, body)
except requests.exceptions.RequestException as e:
msg = _("NWA Failed to connect %(host)s:%(port)s: %(reason)s")
msg_params = {'host': self.host,
'port': self.port,
'reason': e}
LOG.error(msg, msg_params)
raise nwa_exc.NwaException(status_code, msg % msg_params, e)
data = res.text
LOG.debug("NWA returns: httpStatus=%(status)s body=%(data)s",
{'status': res.status_code,
'data': data})
try:
data = jsonutils.loads(data)
except (ValueError, TypeError):
pass
status_code = int(res.status_code)
if 200 <= status_code and status_code <= 209:
return (status_code, data)
else:
msg = _("NWA failed: %(method)s %(host)s:%(port)s%(url)s "
"(HTTP/1.1 %(status_code)s %(reason)s) body=%(data)s")
msg_params = {'method': method,
'host': self.host,
'port': self.port,
'url': url,
'status_code': res.status_code,
'reason': res.reason,
'data': data}
LOG.warning(msg, msg_params)
raise nwa_exc.NwaException(status_code, msg % msg_params)
def get(self, url):
return self.rest_api("GET", url)
def post(self, url, body=None):
return self.rest_api("POST", url, body=body)
def put(self, url, body=None):
return self.rest_api("PUT", url, body=body)
def delete(self, url):
return self.rest_api("DELETE", url)

View File

@ -1,62 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import eventlet
from oslo_log import log as logging
import six
from networking_nec._i18n import _, _LI
LOG = logging.getLogger(__name__)
class Thread(object):
def __init__(self, thread):
self.thread = thread
def stop(self):
self.thread.kill()
def wait(self):
return self.thread.wait()
class Semaphore(object):
lock = eventlet.semaphore.Semaphore(1)
tenants = {}
@classmethod
def get_tenant_semaphore(cls, tenant_id):
if not isinstance(tenant_id, six.string_types) or tenant_id == '':
raise TypeError(_('%s is not a string') % tenant_id)
with Semaphore.lock:
if tenant_id not in Semaphore.tenants:
LOG.info(_LI('create semaphore for %s'), tenant_id)
Semaphore.tenants[tenant_id] = Semaphore()
return Semaphore.tenants[tenant_id]
@classmethod
def delete_tenant_semaphore(cls, tenant_id):
with Semaphore.lock:
if tenant_id in Semaphore.tenants:
LOG.info(_LI('delete semaphore for %s'), tenant_id)
del Semaphore.tenants[tenant_id]
def __init__(self):
self._sem = eventlet.semaphore.Semaphore(1)
@property
def sem(self):
return self._sem

View File

@ -1,178 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import re
import six
class NwaWorkflow(object):
'''Workflow definition of NWA. '''
_path_prefix = '/umf/workflow/'
_nameid_initialized = False
_nameid = {
'CreateTenantNW': '40030001',
'DeleteTenantNW': '40030016',
'CreateVLAN': '40030002',
'DeleteVLAN': '40030018',
'CreateGeneralDev': '40030021',
'DeleteGeneralDev': '40030022',
'CreateTenantFW': '40030019',
'UpdateTenantFW': '40030009',
'DeleteTenantFW': '40030020',
'SettingNAT': '40030005',
'DeleteNAT': '40030011',
'SettingFWPolicy': '40030081',
'SettingLBPolicy': '40030091',
'CreateTenantLB': '40030092',
'UpdateTenantLB': '40030093',
'DeleteTenantLB': '40030094',
'CreateConnectPort': '50000001',
'DeleteConnectPort': '50000002',
}
_errno = {
'1': 'Unknown parent node',
'2': 'Already exists',
'3': 'Resources are insufficient',
'4': 'Unknown node',
'5': 'Can not access the file',
'6': 'Unknown parameters',
'7': 'Undefined parameters',
'8': 'Permission error',
'9': 'It is not possible to remove because it is in use',
'10': 'An error occurred while deleting the node',
'11': 'Execution environment is invalid',
'31': 'Specified IP subnet does not exist',
'32': 'Specified IP address does not exist',
'33': 'Can not allocate IP subnet to be paid out',
'34': 'IP subnet will not exceed the threshold',
'101': 'An unknown error has occurred',
'102': 'An internal error has occurred',
'103': 'Failed to connect to CMDB',
'104': 'Out of memory',
'105': 'An error occurred in the select process to the CMDB',
'106': 'An error occurred in the update process to the CMDB',
'107': 'An error occurred in the insert process to the CMDB',
'108': 'Input parameter is invalid',
'109': 'An error occurred in the file processing',
'110': 'An error occurred in the delete process to the CMDB',
'201': 'There is no free VLAN ID',
'202': 'Exceeded the threshold of VLAN',
'203': 'Exceeded the threshold ot Tenant equipment',
'204': 'Resource group is not specified in the input',
'205': 'Tenant-ID is not specified in the input',
'206': 'Tenant-Network is already created',
'207': 'There is no available devices',
'208': 'IP address depletion for assignment of LB',
'209': 'The device in the cluster group is 0 or 2 or more',
'210': 'The device in the cluster group is 0',
'211': 'There is no specified resource group',
'212': 'There is no character "/" in the resource group name',
'213': 'Tenant-FW is not specified one',
'214': 'Tenant-FW is specified two or more',
'215': 'Can not be extended because there is no PFS',
'216': 'Logical NW name is not specified',
'217': 'There is no Registered SSL-VPN equipment',
'218': 'Tenant network is not yet created',
'219': 'There is no free LoadBalancer',
'220': 'Can not get the physical server uuid',
'221': 'There is no deletion of VLAN',
'222': 'Tenant ID in use is still exists',
'223': 'Tenant-FW not found',
'224': 'There is no specified device name',
'225': 'Can not get the information of tenant vlan',
'226': 'There is no specified logical NW',
'227': 'Can not get the device information of the tenant in use',
'228': 'For updated is in use, it could not be updated',
'229': 'For deletion is in use, it could not be deleted',
'230': 'Exceeded the threshold',
'231': 'Exceeded the allocation possible number',
'232': 'Exceeded the allocation range',
'233': 'Authentication setting is incorrect',
'234': 'Usable IP address range setting of is invalid',
'235': 'IP address specified is invalid',
'236': 'There is no available for allocation Tenant FW',
'237': 'IP address depletion for assignment of FW',
'238': 'IP address is invalid',
'239': 'Can not set the number of records to zero',
'240': 'The specification does not include a payout already IP subnet',
'241': 'Not specified LogicalPort under the same controller or domain',
'242': 'IP address depletion for assignment of SSL',
'243': 'IP address is invalid',
'244': 'The type of controller is invalid',
'245': 'Device or VDOM name is invalid specified',
'246': 'Exceeds the upper limit of naming convention',
'251': 'In the same tenant, scenario there are still concurrent or '
'reservation ID',
'252': '(unused)',
'253': 'The preceding scenario, can not be reserved',
'254': 'Can not get the reserved id because of the preceding scenario',
'298': 'Resources are insufficient',
'299': 'Unknown error',
}
@staticmethod
def init(name):
pass # pragma: no cover
@staticmethod
def path(name):
"""Returns path of workflow.
:param name: The name of workflow.
"""
return '%s%s/execute' % (NwaWorkflow._path_prefix,
NwaWorkflow._nameid[name])
@staticmethod
def name(path):
"""Returns name of workflow.
:param name: The name of workflow.
"""
wid = path[len(NwaWorkflow._path_prefix):-len('/execute')]
for (name, _id) in NwaWorkflow._nameid.items():
if _id == wid:
return name
return None
@staticmethod
def strerror(errno):
"""Returns error name of errno.
:param errno: The number of error.
"""
return NwaWorkflow._errno.get(errno)
@staticmethod
def get_errno_from_resultdata(data):
resultdata = data.get('resultdata')
if resultdata:
errmsg = resultdata.get('ErrorMessage')
if isinstance(errmsg, six.string_types):
m = re.search(r'ErrorNumber=(\d+)', errmsg)
if m:
return m.group(1)
m = re.search(r'ReservationErrorCode = (\d+)', errmsg, re.M)
if m:
return m.group(1)
return None
@staticmethod
def update_nameid(new_nameid):
if NwaWorkflow._nameid_initialized:
return
if new_nameid:
NwaWorkflow._nameid = new_nameid
NwaWorkflow._nameid_initialized = True

View File

@ -1,61 +0,0 @@
# Copyright 2015-2016 NEC Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from neutron.common import rpc
from neutron.tests import base
from oslo_config import cfg
from networking_nec.nwa.agent import nwa_agent
def _init_nwa_client_patch(mocked_nwacli):
succeed = (200, {
'status': 'SUCCEED',
'resultdata': {
'LogicalNWName': 'LNW_BusinessVLAN_4000',
'TenantFWName': 'T1',
'VlanID': '4000',
}
})
mocked_nwacli.tenant.create_tenant.return_value = succeed
mocked_nwacli.tenant.delete_tenant.return_value = succeed
mocked_nwacli.l2.create_general_dev.return_value = succeed
mocked_nwacli.l2.create_tenant_nw.return_value = succeed
mocked_nwacli.l2.create_vlan.return_value = succeed
mocked_nwacli.l2.create_connect_port.return_value = succeed
mocked_nwacli.l2.delete_general_dev.return_value = succeed
mocked_nwacli.l2.delete_tenant_nw.return_value = succeed
mocked_nwacli.l2.delete_vlan.return_value = succeed
mocked_nwacli.l2.delete_connect_port.return_value = succeed
class TestNWAAgentBase(base.BaseTestCase):
@mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall')
@mock.patch('neutron.common.rpc.Connection.consume_in_threads')
@mock.patch('neutron.common.rpc.create_connection')
@mock.patch('neutron.agent.rpc.PluginReportStateAPI')
@mock.patch('neutron.common.rpc.get_client')
def setUp(self, f1, f2, f3, f4, f5):
super(TestNWAAgentBase, self).setUp()
cli = mock.patch('networking_nec.nwa.nwalib.client.NwaClient').start()
self.nwacli = cli.return_value
_init_nwa_client_patch(self.nwacli)
self.agent = nwa_agent.NECNWANeutronAgent(10)
rpc.init(cfg.ConfigOpts())

View File

@ -1,26 +0,0 @@
{
"device": {
"id": "6b34210c-bd74-47f0-8dc3-3bad9bc333c3",
"owner": "network:router_interface"
},
"network": {
"id": "546a8551-5c2b-4050-a769-cc3c962fc5cf",
"name": "net100",
"vlan_id": "123",
"vlan_type": "BusinessVLAN"
},
"physical_network": "OpenStack/DC1/APP",
"port": {
"id": "5174b4d2-f4dc-4292-9d9e-7862f885abdf",
"ip": "192.168.100.1",
"mac": "fa:16:3e:45:98:7d"
},
"resource_group": "OpenStack/DC1/APP",
"resource_group_name": "OpenStack/DC1",
"resource_group_name_nw": "OpenStack/DC1",
"subnet": {
"id": "7dabadaa-06fc-45fb-af0b-33384cf291c4",
"mask": "24",
"netaddr": "192.168.100.0"
}
}

Some files were not shown because too many files have changed in this diff Show More