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:
parent
4edc55fff8
commit
5ffa7838e9
|
@ -1,7 +0,0 @@
|
|||
[run]
|
||||
branch = True
|
||||
source = networking_nec
|
||||
omit = networking_nec/tests/*,networking_nec/openstack/*
|
||||
|
||||
[report]
|
||||
ignore_errors = True
|
|
@ -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?
|
|
@ -1,4 +0,0 @@
|
|||
[gerrit]
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/networking-nec.git
|
3
.mailmap
3
.mailmap
|
@ -1,3 +0,0 @@
|
|||
# Format is:
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
89
.pylintrc
89
.pylintrc
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
doc/source/contributing.rst
|
|
@ -1,4 +0,0 @@
|
|||
networking-nec Style Commandments
|
||||
===============================================
|
||||
|
||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
|
176
LICENSE
176
LICENSE
|
@ -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.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
include AUTHORS
|
||||
include ChangeLog
|
||||
exclude .gitignore
|
||||
exclude .gitreview
|
||||
|
||||
global-exclude *.pyc
|
|
@ -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.
|
33
README.rst
33
README.rst
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
../doc/source/nwa/devstack.rst
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
function has_neutron_plugin_security_group {
|
||||
# 0 means True here
|
||||
return 0
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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}
|
|
@ -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 |
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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"
|
||||
},
|
||||
]
|
|
@ -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.
|
|
@ -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
|
|
@ -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"
|
||||
}
|
||||
]
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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"}
|
|
@ -1 +0,0 @@
|
|||
d86043b2d0f2
|
|
@ -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='')
|
||||
)
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
)
|
|
@ -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
|
|
@ -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")
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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.'))
|
|
@ -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)
|
|
@ -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')
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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'])
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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}
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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')
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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())
|
|
@ -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
Loading…
Reference in New Issue