41 changed files with 4328 additions and 0 deletions
@ -0,0 +1,7 @@
|
||||
[run] |
||||
branch = True |
||||
source = networking_ale_omniswitch |
||||
omit = networking_ale_omniswitch/openstack/* |
||||
|
||||
[report] |
||||
ignore-errors = True |
@ -0,0 +1,54 @@
|
||||
*.py[cod] |
||||
|
||||
# C extensions |
||||
*.so |
||||
|
||||
# Packages |
||||
*.egg |
||||
*.egg-info |
||||
dist |
||||
build |
||||
.eggs |
||||
eggs |
||||
parts |
||||
bin |
||||
var |
||||
sdist |
||||
develop-eggs |
||||
.installed.cfg |
||||
lib |
||||
lib64 |
||||
|
||||
# Installer logs |
||||
pip-log.txt |
||||
|
||||
# Unit test / coverage reports |
||||
.coverage |
||||
.tox |
||||
nosetests.xml |
||||
.testrepository |
||||
.venv |
||||
|
||||
# Translations |
||||
*.mo |
||||
|
||||
# Mr Developer |
||||
.mr.developer.cfg |
||||
.project |
||||
.pydevproject |
||||
|
||||
# Complexity |
||||
output/*.html |
||||
output/*/index.html |
||||
|
||||
# Sphinx |
||||
doc/build |
||||
|
||||
# pbr generates these |
||||
AUTHORS |
||||
ChangeLog |
||||
|
||||
# Editors |
||||
*~ |
||||
.*.swp |
||||
.*sw? |
@ -0,0 +1,3 @@
|
||||
# Format is: |
||||
# <preferred e-mail> <other e-mail 1> |
||||
# <preferred e-mail> <other e-mail 2> |
@ -0,0 +1,7 @@
|
||||
[DEFAULT] |
||||
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ |
||||
OS_STDERR_CAPTURE=${OS_STDERR_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 |
@ -0,0 +1,17 @@
|
||||
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 |
||||
|
||||
If you already have a good understanding of how the system works and your |
||||
OpenStack accounts are set up, you can skip to the development workflow |
||||
section of this documentation to learn how changes to OpenStack should be |
||||
submitted for review via the Gerrit tool: |
||||
|
||||
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-ale-omniswitch |
@ -0,0 +1,4 @@
|
||||
networking-ale-omniswitch Style Commandments |
||||
=============================================== |
||||
|
||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ |
@ -0,0 +1,176 @@
|
||||
|
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
@ -0,0 +1,6 @@
|
||||
include AUTHORS |
||||
include ChangeLog |
||||
exclude .gitignore |
||||
exclude .gitreview |
||||
|
||||
global-exclude *.pyc |
@ -0,0 +1,16 @@
|
||||
=============================== |
||||
networking-ale-omniswitch |
||||
=============================== |
||||
|
||||
Networking Alcatel-Lucent Omniswitch contains the Alcatel-Lucent |
||||
Omniswitch vendor code for Openstack Neutron |
||||
|
||||
* Free software: Apache license |
||||
* Documentation: http://docs.openstack.org/developer/networking-ale-omniswitch |
||||
* Source: http://git.openstack.org/cgit/openstack/networking-ale-omniswitch |
||||
* Bugs: http://bugs.launchpad.net/networking-ale-omniswitch |
||||
|
||||
Features |
||||
-------- |
||||
|
||||
* TODO |
@ -0,0 +1,75 @@
|
||||
# -*- 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-ale-omniswitch' |
||||
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} |
@ -0,0 +1,4 @@
|
||||
============ |
||||
Contributing |
||||
============ |
||||
.. include:: ../../CONTRIBUTING.rst |
@ -0,0 +1,25 @@
|
||||
.. networking-ale-omniswitch 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. |
||||
|
||||
Welcome to networking-ale-omniswitch's documentation! |
||||
======================================================== |
||||
|
||||
Contents: |
||||
|
||||
.. toctree:: |
||||
:maxdepth: 2 |
||||
|
||||
readme |
||||
installation |
||||
usage |
||||
contributing |
||||
|
||||
Indices and tables |
||||
================== |
||||
|
||||
* :ref:`genindex` |
||||
* :ref:`modindex` |
||||
* :ref:`search` |
||||
|
@ -0,0 +1,12 @@
|
||||
============ |
||||
Installation |
||||
============ |
||||
|
||||
At the command line:: |
||||
|
||||
$ pip install networking-ale-omniswitch |
||||
|
||||
Or, if you have virtualenvwrapper installed:: |
||||
|
||||
$ mkvirtualenv networking-ale-omniswitch |
||||
$ pip install networking-ale-omniswitch |
@ -0,0 +1,7 @@
|
||||
======== |
||||
Usage |
||||
======== |
||||
|
||||
To use networking-ale-omniswitch in a project:: |
||||
|
||||
import networking_ale_omniswitch |
@ -0,0 +1,91 @@
|
||||
# Mods %%25/10/2013-14:14%% %%OpenStackInstall%% %%init_quantum.sh%% |
||||
|
||||
##### OpenStack OmniSwitch Network Plug-in Configuration Parameters ##### |
||||
|
||||
[ml2_ale_omniswitch] |
||||
# This section provides details about the OmniSwitch devices and other configuration options. |
||||
|
||||
# OMNI_EDGE_DEVICES: |
||||
# The list of OmniSwitch edge devices. The format of the 'omni_edge_devices' is as follows: |
||||
# omni_edge_devices = <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<compute-interfaces>:<core-interfaces>, |
||||
# <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<compute-interfaces>:<core-interfaces>, |
||||
# ... |
||||
# ... |
||||
# <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<compute-interfaces>:<core-interfaces> |
||||
# |
||||
# where, 'switch-ip' is the management ip address of the edge switch. |
||||
# 'switch-type' is the type of the switch; |
||||
# possible values are: OS6900, OS10K, OS6850E, OS6855, OS6450, OS9000 or OS6860. |
||||
# 'user-name' is the user login for the switch. |
||||
# 'password' is the password credentials for the above user-name. |
||||
# 'command-prompt' is the command prompt string set for the switch. |
||||
# 'access-method' is the mechanism to be used to access the switch; |
||||
# possible values are: REST or TELNET depending on device support. |
||||
# (Note: see SWITCH_ACCESS_METHOD for more.) |
||||
# 'compute-interfaces' are the interfaces on the edge switch connected to 'compute' nodes. |
||||
# 'core-interfaces' are the interfaces on the edge switch connected to the core switch of the network. |
||||
# |
||||
# Note: Device entries are separated by comma (,) and many devices may be added to the list. |
||||
# Interfaces are separated by space (' ') and many interfaces may be added to the list. |
||||
# Interfaces should be in the format corresponding to the platform used: |
||||
# Possible values for OS6900 and OS10K: slot/port, chassis/slot/port or linkagg_id. |
||||
# For example, |
||||
# 1/2 if it is a standalone unit, represents slot/port |
||||
# 1/2/3 if it is a VC, represents chassis/slot/port |
||||
# 1 if it is a linkagg, represents linkagg_id |
||||
# Possible values for OS6850E, OS6855, OS9000 and OS6450: slot/port or linkagg_id. |
||||
# For example, |
||||
# 1/2 represents slot/port |
||||
# 1 if it is a linkagg, represents linkagg_id |
||||
# Possible values for OS6860: chassis/slot/port or linkagg_id. |
||||
# For example, |
||||
# 1/2/3 if it is a standalone unit or VC, represents chassis/slot/port |
||||
# 1 if it is a linkagg, represents linkagg_id |
||||
# |
||||
# Each item in the entry is separated by colon (:). |
||||
# For user-name, password and command-prompt the default values 'admin', 'switch', '->' will be |
||||
# used if empty but still separated by colon (:). |
||||
# |
||||
# For example, |
||||
# omni_edge_devices = 10.255.222.10:OS6900:admin:switch:->:TELNET:1/1 1/2:1/20 1/21, |
||||
# 10.255.222.10:OS6850E:jhonc:alcatel123:Campus-Edge1->:TELNET:1/1 1/2:1/20 1/21, |
||||
# 10.255.222.10:OS10K: : : :REST:1/1 1/2:1/20 1/21 |
||||
#omni_edge_devices = 10.255.222.10:OS6900: : : :TELNET:1/3:1/19, |
||||
# 10.255.222.12:OS6900: : : :TELNET:1/2:1/20 |
||||
omni_edge_devices = 10.255.222.10:OS6900: : : :TELNET::1/19, |
||||
10.255.222.12:OS6900: : : :TELNET:1/2:1/20 |
||||
|
||||
# OMNI_CORE_DEVICES: |
||||
# The list of OmniSwitch core devices. The format of the 'omni_core_devices' is as follows: |
||||
# omni_core_devices = <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<interfaces>, |
||||
# <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<interfaces>, |
||||
# ... |
||||
# ... |
||||
# <switch-ip>:<switch-type>:<user-name>:<password>:<command-prompt>:<access-method>:<interfaces> |
||||
# |
||||
# Note: The description and format of the individual items are same as edge devices except for 'interfaces'. |
||||
# Here, 'interfaces' are the interfaces on the core switch connected to edge switches |
||||
# and/or other core switches. |
||||
# |
||||
# For example, |
||||
# omni_core_devices = 10.255.222.20:OS10K:admin:switch:->:REST:1/20 1/21, |
||||
# 10.255.222.30:OS6850E:jhonc:alcatel123:Campus-Edge1->:TELNET:1/20 1/21, |
||||
# 10.255.222.40:OS9000: : : :REST:1/1 1/2 |
||||
omni_core_devices = 10.255.222.11:OS6900: : : :TELNET:1/19 1/20 |
||||
|
||||
# DHCP_SERVER_INTERFACE: |
||||
# The edge switch's ip address and the interface connected to the network node of the OpenStack setup |
||||
# (the dhcp-server is running on the network node). |
||||
# The format of the 'dhcp_server_interface' is the same as a core device, but with only one entry. |
||||
# For example, |
||||
# dhcp_server_interface = 10.255.222.20:OS10K:admin:switch:->:TELNET:1/20 1/21 |
||||
dhcp_server_interface = 10.255.222.10:OS6900: : : :TELNET:1/3 |
||||
|
||||
# SWITCH_SAVE_CONFIG_INTERVAL: |
||||
# This is used to specify how often (in seconds) the config changes in the switches are to be saved. |
||||
# The valid range is 600 - 1800 seconds. If value is out of range, it will default to 600 seconds. |
||||
switch_save_config_interval = 600 |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
# -*- 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_ale_omniswitch').version_string() |
@ -0,0 +1,25 @@
|
||||
#!/bin/env python |
||||
# |
||||
# Copyright 2014 Alcatel-Lucent Enterprise. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
||||
# except in compliance with the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License |
||||
# is distributed on an "AS IS" BASIS, WITHOUT 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 |
||||
|
||||
device_opts = [ |
||||
cfg.ListOpt('omni_edge_devices', default=[], help=""), |
||||
cfg.ListOpt('omni_core_devices', default=[], help=""), |
||||
cfg.StrOpt('dhcp_server_interface', default='', help=""), |
||||
cfg.IntOpt('switch_save_config_interval', default=600, help="") |
||||
] |
||||
|
||||
cfg.CONF.register_opts(device_opts, "ml2_ale_omniswitch") |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
||||
# |
||||
# Copyright 2014 Alcatel-Lucent Enterprise. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
||||
# except in compliance with the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License |
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
||||
# either express or implied. See the License for the specific language governing permissions |
||||
# and limitations under the License. |
||||
|
||||
|
||||
""" Constants used in OmniSwitch Neutron Network plug-in """ |
||||
|
||||
# Used by Mechanism Driver # |
||||
OMNI_DEVICE_PLUGIN = 'networking_ale_omniswitch.omniswitch_device_plugin.OmniSwitchDevicePluginV2' |
||||
|
||||
# Used by Device Plug-in # |
||||
OMNI_CFG_DEV_IP = 0 |
||||
OMNI_CFG_DEV_TYPE = 1 |
||||
OMNI_CFG_DEV_LOGIN = 2 |
||||
OMNI_CFG_DEV_PASSWORD = 3 |
||||
OMNI_CFG_DEV_PROMPT = 4 |
||||
OMNI_CFG_DEV_ACCESS_METHOD = 5 |
||||
OMNI_CFG_DEV_EDGE2COMPUTE_IF = 6 |
||||
OMNI_CFG_DEV_EDGE2CORE_IF = 7 |
||||
|
||||
OMNI_CFG_DEV_CORE_IF = 6 |
||||
OMNI_CFG_DHCP_SERVER_IF = 6 |
||||
|
||||
OMNISWITCH_6XX = 1 |
||||
OMNISWITCH_7XX = 2 |
||||
OMNISWITCH_8XX = 3 |
||||
|
||||
OMNISWITCH_OS6900 = "OS6900" |
||||
OMNISWITCH_OS10K = "OS10K" |
||||
OMNISWITCH_OS6850E = "OS6850E" |
||||
OMNISWITCH_OS6855 = "OS6855" |
||||
OMNISWITCH_OS6450 = "OS6450" |
||||
OMNISWITCH_OS9000 = "OS9000" |
||||
OMNISWITCH_OS6860 = "OS6860" |
||||
|
||||
OMNI_CFG_CORE_MVRP = "MVRP" |
||||
OMNI_CFG_CORE_VPA = "VPA" |
||||
OMNI_CFG_CORE_SPB = "SPB" |
||||
|
||||
OMNI_CFG_HOST_CLASS_MAC = "MAC_ADDRESS" |
||||
OMNI_CFG_HOST_CLASS_VTAG = "VLAN_TAG" |
||||
OMNI_CFG_HOST_CLASS_VPA = "VPA" |
||||
|
||||
OMNI_CFG_SWITCH_ACCESS_REST = "REST" |
||||
OMNI_CFG_SWITCH_ACCESS_TELNET = "TELNET" |
||||
|
||||
OMNI_CFG_CREATE = 1 |
||||
OMNI_CFG_DELETE = 0 |
||||
OMNI_CFG_UPDATE = 2 |
||||
|
||||
OMNI_CFG_ENABLE = "ENABLE" |
||||
OMNI_CFG_DISABLE = "DISABLE" |
||||
|
||||
OMNI_CFG_SAVE_INTERVAL_MIN = 600 |
||||
OMNI_CFG_SAVE_INTERVAL_MAX = 1800 |
||||
|
||||
# Used by Telnet/CLI driver |
||||
OMNI_CLI_PROMPT = "->" |
||||
OMNI_CLI_PROMPT_TIMEOUT = 1 |
||||
OMNI_CLI_SMALL_TIMEOUT = 2 |
||||
OMNI_CLI_MEDIUM_TIMEOUT = 5 |
||||
OMNI_CLI_LONG_TIMEOUT = 10 |
||||
|
||||
# Used by RESTful driver # |
||||
|
||||
# Used by SSH driver # |
||||
MAX_SSH_RECV_BUFF = 4096 |
@ -0,0 +1,587 @@
|
||||
# Copyright 2014 Alcatel-Lucent Enterprise. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
||||
# except in compliance with the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License |
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
||||
# either express or implied. See the License for the specific language governing permissions |
||||
# and limitations under the License. |
||||
|
||||
|
||||
import logging |
||||
import threading |
||||
|
||||
from eventlet import GreenPool as Pool |
||||
from oslo_config import cfg |
||||
|
||||
from networking_ale_omniswitch import config # noqa |
||||
from networking_ale_omniswitch import omniswitch_constants as omni_const |
||||
from networking_ale_omniswitch.omniswitch_restful_driver import OmniSwitchRestfulDriver |
||||
from networking_ale_omniswitch.omniswitch_telnet_driver import OmniSwitchTelnetDriver |
||||
|
||||
|
||||
LOG = logging.getLogger(__name__) |
||||
|
||||
|
||||
class OmniSwitchDevicePluginV2(object): |
||||
|
||||
"""Name: OmniSwitchDevicePluginV2 |
||||
Description: OpenStack Neutron plugin for Alcatel-Lucent OmniSwitch Data networking |
||||
devices. |
||||
|
||||
Details: It is one of the device plugin in the OmniSwitch multi-plugin design. |
||||
This implements the Neutron Network APIs (ver 2.0) for OmniSwitch |
||||
devices. This is instantiated by the OmniSwitchNetworkPluginV2 which is |
||||
core plugin for Neutron server. This uses the device specific |
||||
communication mechanism for interfacing with different types of |
||||
OmniSwitch devices. |
||||
""" |
||||
|
||||
def __init__(self): |
||||
|
||||
# list of omni devices from 'omni_network_plugin.ini' file |
||||
self.edge_device_list = [] |
||||
# list of device driver instances (ddi) corresponding to each of the device in edge_device_list |
||||
self.edge_ddi_list = {} |
||||
# list of omni core devices from 'omni_network_plugin.ini' file |
||||
self.core_device_list = [] |
||||
# list of device driver instances (ddi) corresponding to each of the device in core_device_list |
||||
self.core_ddi_list = {} |
||||
# details of the edge switch which is connected to network node where dhcp-server is running |
||||
self.dhcp_service = [] |
||||
self.dhcp_if_inst = None |
||||
# interval(in secs) at which the config will be saved in the switches |
||||
self.switch_save_config_interval = 0 |
||||
|
||||
# some init general init status vars |
||||
self.db_option = None |
||||
self.init_config_applied = None |
||||
|
||||
# used for tracking whether to do write memory in the switch or not |
||||
self.edge_config_changed = 0 |
||||
self.core_config_changed = 0 |
||||
|
||||
self._load_config() |
||||
self._load_edge_ddi() |
||||
self._load_core_ddi() |
||||
self._load_dhcp_if_inst() |
||||
self._start_save_config_thread() |
||||
|
||||
def _load_config(self): |
||||
"""loads the OmniSwitch device list from the config file and instantiates |
||||
the appropriate device specific driver to communicate with it. |
||||
""" |
||||
|
||||
# OMNI_EDGE_DEVICES |
||||
for device in cfg.CONF.ml2_ale_omniswitch.omni_edge_devices: |
||||
device_specs = [x.strip() for x in device.split(':')] |
||||
self.edge_device_list.append(device_specs) |
||||
|
||||
# OMNI_CORE_DEVICES |
||||
if cfg.CONF.ml2_ale_omniswitch.omni_core_devices != [] and cfg.CONF.ml2_ale_omniswitch.omni_core_devices != ['']: |
||||
for device in cfg.CONF.ml2_ale_omniswitch.omni_core_devices: |
||||
device_specs = [x.strip() for x in device.split(':')] |
||||
self.core_device_list.append(device_specs) |
||||
|
||||
# DHCP_SERVER_INTERFACE |
||||
self.dhcp_service = [x.strip() for x in cfg.CONF.ml2_ale_omniswitch.dhcp_server_interface.split(':')] |
||||
if self.dhcp_service == [] or self.dhcp_service == ['']: |
||||
self.dhcp_service = None |
||||
|
||||
self.switch_save_config_interval = cfg.CONF.ml2_ale_omniswitch.switch_save_config_interval |
||||
if (self.switch_save_config_interval < omni_const.OMNI_CFG_SAVE_INTERVAL_MIN or |
||||
self.switch_save_config_interval > omni_const.OMNI_CFG_SAVE_INTERVAL_MAX): |
||||
LOG.info("switch_save_config_interval %d is out of valid range(%d - %d)... default to %d", |
||||
self.switch_save_config_interval, |
||||
omni_const.OMNI_CFG_SAVE_INTERVAL_MIN, |
||||
omni_const.OMNI_CFG_SAVE_INTERVAL_MAX, |
||||
omni_const.OMNI_CFG_SAVE_INTERVAL_MIN) |
||||
self.switch_save_config_interval = omni_const.OMNI_CFG_SAVE_INTERVAL_MIN |
||||
|
||||
def _load_edge_ddi(self): |
||||
for device in self.edge_device_list: |
||||
drv_type = self._get_driver_type(device[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
|
||||
if self.omniswitch_6xx(device): |
||||
if self.device_access_rest(device): |
||||
LOG.info("ALERT: This device (%s) does not support REST interface.\ |
||||
Instead TELNET interface will be used!", device[omni_const.OMNI_CFG_DEV_IP]) |
||||
self.edge_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchTelnetDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD], |
||||
device[omni_const.OMNI_CFG_DEV_PROMPT])) |
||||
# for both 7XX and 8XX |
||||
elif self.switch_access_rest(device): |
||||
self.edge_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchRestfulDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD])) |
||||
else: |
||||
self.edge_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchTelnetDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD])) |
||||
|
||||
LOG.info("_load_edge_ddi done!") |
||||
|
||||
def _load_core_ddi(self): |
||||
if len(self.core_device_list) == 0: |
||||
return |
||||
|
||||
for device in self.core_device_list: |
||||
drv_type = self._get_driver_type(device[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
|
||||
if self.omniswitch_6xx(device): |
||||
if self.device_access_rest(device): |
||||
LOG.info("ALERT: This device (%s) does not support REST interface.\ |
||||
Instead TELNET interface will be used!", device[omni_const.OMNI_CFG_DEV_IP]) |
||||
self.core_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchTelnetDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD], |
||||
device[omni_const.OMNI_CFG_DEV_PROMPT])) |
||||
# for both 7XX and 8XX |
||||
elif self.switch_access_rest(device): |
||||
self.core_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchRestfulDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD])) |
||||
else: |
||||
self.core_ddi_list.setdefault(device[omni_const.OMNI_CFG_DEV_IP], |
||||
OmniSwitchTelnetDriver(device[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
device[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
device[omni_const.OMNI_CFG_DEV_PASSWORD])) |
||||
LOG.info("_load_core_ddi done!") |
||||
|
||||
def _load_dhcp_if_inst(self): |
||||
if not self.dhcp_service: |
||||
return |
||||
drv_type = self._get_driver_type(self.dhcp_service[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
if self.omniswitch_6xx(self.dhcp_service): |
||||
if self.device_access_rest(self.dhcp_service): |
||||
LOG.info("ALERT: This device (%s) does not support REST interface.\ |
||||
Instead TELNET interface will be used!", self.dhcp_service[omni_const.OMNI_CFG_DEV_IP]) |
||||
self.dhcp_if_inst = OmniSwitchTelnetDriver(self.dhcp_service[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_PASSWORD], |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_PROMPT]) |
||||
else: # for both 7XX and 8XX |
||||
if self.device_access_rest(self.dhcp_service): |
||||
self.dhcp_if_inst = OmniSwitchRestfulDriver(self.dhcp_service[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_PASSWORD]) |
||||
else: |
||||
self.dhcp_if_inst = OmniSwitchTelnetDriver(self.dhcp_service[omni_const.OMNI_CFG_DEV_IP], drv_type, |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_LOGIN], |
||||
self.dhcp_service[omni_const.OMNI_CFG_DEV_PASSWORD]) |
||||
|
||||
LOG.info("_load_dhcp_if_inst done!") |
||||
|
||||
def _start_save_config_thread(self): |
||||
SaveConfigThread(self).start() |
||||
|
||||
def _config_vpa_core(self, vlan_id, action, net_name=''): |
||||
pool = Pool(size=(len(self.core_device_list) + len(self.edge_device_list))) |
||||
|
||||
def config_vpa_core_device(device): |
||||
if device[omni_const.OMNI_CFG_DEV_CORE_IF].strip(): |
||||
if action == omni_const.OMNI_CFG_CREATE: |
||||
self.core_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]].create_vlan_locked(vlan_id, net_name) |
||||
if_list = device[omni_const.OMNI_CFG_DEV_CORE_IF].split(' ') |
||||
for port in if_list: |
||||
self.core_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]].create_vpa(vlan_id, port) |
||||
elif action == omni_const.OMNI_CFG_UPDATE: |
||||
self.core_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]].update_vlan_locked(vlan_id, net_name) |
||||
elif action == omni_const.OMNI_CFG_DELETE: |
||||
LOG.info("vpa core delete vlan!") |
||||
self.core_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]].delete_vlan_locked(vlan_id) |
||||
|
||||
def config_vpa_edge_device(device): |
||||
if device[omni_const.OMNI_CFG_DEV_EDGE2CORE_IF].strip(): |
||||
if_list = device[omni_const.OMNI_CFG_DEV_EDGE2CORE_IF].split(' ') |
||||
for port in if_list: |
||||
self.edge_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]].create_vpa(vlan_id, port) |
||||
|
||||
output = list() |
||||
for result in pool.imap(config_vpa_core_device, self.core_device_list): |
||||
output.append(result) |
||||
if action == omni_const.OMNI_CFG_CREATE: |
||||
for result in pool.imap(config_vpa_edge_device, self.edge_device_list): |
||||
output.append(result) |
||||
return True |
||||
|
||||
def _config_vpa_edge(self, edge_ddi_obj, vlan_id, action): |
||||
compute_if = self._get_edge2compute_if(edge_ddi_obj.get_ip()) |
||||
if compute_if.strip(): |
||||
if_list = compute_if.split(' ') |
||||
for port in if_list: |
||||
if action == omni_const.OMNI_CFG_CREATE: |
||||
edge_ddi_obj.create_vpa(vlan_id, port) |
||||
elif action == omni_const.OMNI_CFG_DELETE: |
||||
edge_ddi_obj.delete_vpa(vlan_id, port) |
||||
|
||||
return True |
||||
|
||||
""" |
||||
General System APIs within Device plugin |
||||
""" |
||||
|
||||
def save_core_config(self, immediate=0): |
||||
if immediate == 0: |
||||
self.core_config_changed = 1 |
||||
return |
||||
|
||||
pool = Pool(size=len(self.core_device_list)) |
||||
|
||||
def m_save_core_config(device): |
||||
ddi_obj = self.core_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]] |
||||
self._invoke_driver_api(ddi_obj, "save_config", []) |
||||
|
||||
output = list() |
||||
for result in pool.imap(m_save_core_config, self.core_device_list): |
||||
output.append(result) |
||||
|
||||
self.core_config_changed = 0 |
||||
return |
||||
|
||||
def save_edge_config(self, immediate=0): |
||||
if immediate == 0: |
||||
self.edge_config_changed = 1 |
||||
return |
||||
|
||||
pool = Pool(size=len(self.edge_device_list)) |
||||
|
||||
def m_save_edge_config(device): |
||||
ddi_obj = self.edge_ddi_list[device[omni_const.OMNI_CFG_DEV_IP]] |
||||
self._invoke_driver_api(ddi_obj, "save_config", []) |
||||
|
||||
output = list() |
||||
for result in pool.imap(m_save_edge_config, self.edge_device_list): |
||||
output.append(result) |
||||
|
||||
self.edge_config_changed = 0 |
||||
return |
||||
|
||||
def save_config(self): |
||||
if self.core_config_changed == 1: |
||||
self.save_core_config(1) |
||||
|
||||
if self.edge_config_changed == 1: |
||||
self.save_edge_config(1) |
||||
|
||||
""" Neutron Core API 2.0 """ |
||||
|
||||
def create_network(self, mech_context): |
||||
ret = False |
||||
if self.cn_edge_config(mech_context): |
||||
if self.cn_core_config(mech_context): |
||||
ret = self.cn_dhcp_config(mech_context) |
||||
return ret |
||||
|
||||
def update_network(self, mech_context): |
||||
self.un_edge_config(mech_context) |
||||
self.un_core_config(mech_context) |
||||
self.un_dhcp_config(mech_context) |
||||
return True |
||||
|
||||
def delete_network(self, mech_context): |
||||
self.dn_dhcp_config(mech_context) |
||||
self.dn_core_config(mech_context) |
||||
self.dn_edge_config(mech_context) |
||||
return True |
||||
|
||||
def update_subnet(self, mech_context): |
||||
return True |
||||
|
||||
def create_subnet(self, mech_context): |
||||
return True |
||||
|
||||
def delete_subnet(self, mech_context): |
||||
return True |
||||
|
||||
def delete_port(self, mech_context): |
||||
return True |
||||
|
||||
def update_port(self, mech_context): |
||||
return True |
||||
|
||||
def create_port(self, mech_context): |
||||
return True |
||||
|
||||
""" |
||||
Wrapper for Core API functional routines |
||||
""" |
||||
def cn_edge_config(self, mech_context): |
||||
ret = True |
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
network_name = network['name'] |
||||
|
||||
def m_cn_edge_config(ddi_obj): |
||||
if self._invoke_driver_api(ddi_obj, "create_network", [vlan_id, network_name]): |
||||
res = self._config_vpa_edge(ddi_obj, vlan_id, omni_const.OMNI_CFG_CREATE) |
||||
else: |
||||
res = False |
||||
return res |
||||
|
||||
pool = Pool(size=len(self.edge_ddi_list.items())) |
||||
output = list() |
||||
|
||||
ddi_list = [item[1] for item in self.edge_ddi_list.items()] |
||||
for result in pool.imap(m_cn_edge_config, ddi_list): |
||||
output.append(result) |
||||
|
||||
if False in output: |
||||
# some error in create network, roll back network creation |
||||
self.delete_network(mech_context) # vad: optimize only for that switch |
||||
self.save_edge_config() |
||||
ret = False |
||||
|
||||
return ret |
||||
|
||||
def cn_core_config(self, mech_context): |
||||
ret = True |
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
network_name = network['name'] |
||||
|
||||
if not self._config_vpa_core(vlan_id, omni_const.OMNI_CFG_CREATE, network_name): |
||||
# some error in vpa creation, roll back network creation |
||||
self.delete_network(mech_context) |
||||
self.save_edge_config() |
||||
ret = False |
||||
else: |
||||
self.save_core_config() |
||||
return ret |
||||
|
||||
def cn_dhcp_config(self, mech_context): |
||||
ret = True |
||||
segments = mech_context.network_segments |
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
|
||||
if self.dhcp_if_inst: |
||||
ret = self.dhcp_if_inst.create_vpa(vlan_id, self.dhcp_service[omni_const.OMNI_CFG_DHCP_SERVER_IF]) |
||||
if not ret: |
||||
# some error in vpa creation for dhcp, roll back network creation |
||||
self.delete_network(mech_context) |
||||
ret = False |
||||
|
||||
self.save_edge_config() |
||||
return ret |
||||
|
||||
def un_edge_config(self, mech_context): |
||||
ret = True |
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
network_name = network['name'] |
||||
|
||||
if network_name == '': |
||||
LOG.error("un_edge_config: update network: network cannot be the empty string!") |
||||
return False |
||||
|
||||
def m_un_edge_config(ddi_obj): |
||||
res = True |
||||
if not self._invoke_driver_api(ddi_obj, "update_network", [vlan_id, network_name]): |
||||
res = False |
||||
if not res: |
||||
LOG.info("update network edge failed") |
||||
return res |
||||
|
||||
output = list() |
||||
pool = Pool(size=len(self.edge_ddi_list.items())) |
||||
ddi_list = [item[1] for item in self.edge_ddi_list.items()] |
||||
|
||||
for result in pool.imap(m_un_edge_config, ddi_list): |
||||
output.append(result) |
||||
if False in output: |
||||
ret = False |
||||
|
||||
self.save_edge_config() |
||||
return ret |
||||
|
||||
def un_core_config(self, mech_context): |
||||
ret = True |
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
network_name = network['name'] |
||||
|
||||
if network_name == '': |
||||
LOG.error("un_core_config: update network: network cannot be the empty string!") |
||||
return False |
||||
|
||||
if not self._config_vpa_core(vlan_id, omni_const.OMNI_CFG_UPDATE, network_name): |
||||
LOG.error("un_core_config: update network core failed") |
||||
ret = False |
||||
else: |
||||
self.save_core_config() |
||||
return ret |
||||
|
||||
def un_dhcp_config(self, mech_context): |
||||
ret = True |
||||
if not self.dhcp_if_inst: |
||||
return ret |
||||
|
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
network_name = network['name'] |
||||
|
||||
if network_name == '': |
||||
LOG.error("un_dhcp_config: network cannot be the empty string!") |
||||
return False |
||||
|
||||
if not self._invoke_driver_api(self.dhcp_if_inst, "update_network", [vlan_id, network_name]): |
||||
LOG.error("un_dhcp_config: update network failed!") |
||||
ret = False |
||||
|
||||
self.save_edge_config() |
||||
return ret |
||||
|
||||
def dn_edge_config(self, mech_context): |
||||
ret = True |
||||
segments = mech_context.network_segments |
||||
|
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
|
||||
def m_dn_edge_config_vlan(ddi_obj): |
||||
self._config_vpa_edge(ddi_obj, vlan_id, omni_const.OMNI_CFG_DELETE) |
||||
self._invoke_driver_api(ddi_obj, "delete_network", [vlan_id]) |
||||
|
||||
pool = Pool(size=len(self.edge_ddi_list.items())) |
||||
output = list() |
||||
ddi_list = [item[1] for item in self.edge_ddi_list.items()] |
||||
for result in pool.imap(m_dn_edge_config_vlan, ddi_list): |
||||
output.append(result) |
||||
|
||||
self.save_edge_config() |
||||
return ret |
||||
|
||||
def dn_core_config(self, mech_context): |
||||
ret = True |
||||
segments = mech_context.network_segments |
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
|
||||
if not self._config_vpa_core(vlan_id, omni_const.OMNI_CFG_DELETE): |
||||
ret = False |
||||
else: |
||||
self.save_core_config() |
||||
return ret |
||||
|
||||
def dn_dhcp_config(self, mech_context): |
||||
segments = mech_context.network_segments |
||||
# currently supports only one segment per network |
||||
segment = segments[0] |
||||
vlan_id = segment['segmentation_id'] |
||||
|
||||
if self.dhcp_if_inst: |
||||
return self.dhcp_if_inst.delete_vpa(vlan_id, self.dhcp_service[omni_const.OMNI_CFG_DHCP_SERVER_IF]) |
||||
return True |
||||
|
||||
""" |
||||
Utility routines related to CONFIG |
||||
""" |
||||
def _get_edge2compute_if(self, dev_ip): |
||||
for device in self.edge_device_list: |
||||
if device[omni_const.OMNI_CFG_DEV_IP] == dev_ip: |
||||
return device[omni_const.OMNI_CFG_DEV_EDGE2COMPUTE_IF] |
||||
|
||||
def _get_driver_type(self, switch_type): |
||||
if switch_type == omni_const.OMNISWITCH_OS6860: |
||||
return omni_const.OMNISWITCH_8XX |
||||
elif switch_type == omni_const.OMNISWITCH_OS6900 or switch_type == omni_const.OMNISWITCH_OS10K: |
||||
return omni_const.OMNISWITCH_7XX |
||||
elif (switch_type == omni_const.OMNISWITCH_OS6850E or |
||||
switch_type == omni_const.OMNISWITCH_OS6855 or |
||||
switch_type == omni_const.OMNISWITCH_OS6450 or |
||||
switch_type == omni_const.OMNISWITCH_OS9000): |
||||
return omni_const.OMNISWITCH_6XX |
||||
|
||||
def _get_switch_access_method(self, switch_access_method): |
||||
return switch_access_method if switch_access_method != "" else omni_const.OMNI_CFG_SWITCH_ACCESS_TELNET |
||||
|
||||
def _invoke_driver_api(self, drvobj, function_name, args): |
||||
# return thread.start_new_thread(getattr(drvobj, function_name), tuple(args)) |
||||
return getattr(drvobj, function_name)(*args) |
||||
|
||||
def omniswitch_8xx(self, device): |
||||
drv_type = self._get_driver_type(device[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
return drv_type == omni_const.OMNISWITCH_8XX |
||||
|
||||
def omniswitch_7xx(self, device): |
||||
drv_type = self._get_driver_type(device[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
return drv_type == omni_const.OMNISWITCH_7XX |
||||
|
||||
def omniswitch_6xx(self, device): |
||||
drv_type = self._get_driver_type(device[omni_const.OMNI_CFG_DEV_TYPE]) |
||||
return drv_type == omni_const.OMNISWITCH_6XX |
||||
|
||||
def device_access_rest(self, device): |
||||
return device[omni_const.OMNI_CFG_DEV_ACCESS_METHOD] == omni_const.OMNI_CFG_SWITCH_ACCESS_REST |
||||
|
||||
def device_access_telnet(self, device): |
||||
return device[omni_const.OMNI_CFG_DEV_ACCESS_METHOD] == omni_const.OMNI_CFG_SWITCH_ACCESS_TELNET |
||||
|
||||
def switch_access_rest(self, device): |
||||
switch_access_method = self._get_switch_access_method(device[omni_const.OMNI_CFG_DEV_ACCESS_METHOD]) |
||||
return switch_access_method == omni_const.OMNI_CFG_SWITCH_ACCESS_REST |
||||
|
||||
def switch_access_telnet(self, device): |
||||
switch_access_method = self._get_switch_access_method(device[omni_const.OMNI_CFG_DEV_ACCESS_METHOD]) |
||||
return switch_access_method == omni_const.OMNI_CFG_SWITCH_ACCESS_TELNET |
||||
|
||||
|
||||
""" Save config thread class """ |
||||
|
||||
|
||||
class SaveConfigThread(threading.Thread): |
||||
plugin_obj = None |
||||
|
||||
def __init__(self, plugin_obj): |
||||
self.plugin_obj = plugin_obj |
||||
threading.Thread.__init__(self) |
||||
self.event = threading.Event() |
||||
|
||||
def run(self): |
||||
if self.plugin_obj is None: |
||||
LOG.info("Plugin Object is Null, SaveConfigThread is terminated!") |
||||
self.stop() |
||||
return |
||||
|
||||
while not self.event.is_set(): |
||||
# print "do something %s" % time.asctime(time.localtime(time.time())) |
||||
# self.event.wait( 1 ) |
||||
self.plugin_obj.save_config() |
||||
# LOG.info("run: %s", time.asctime(time.localtime(time.time()))) |
||||
self.event.wait(self.plugin_obj.switch_save_config_interval) |
||||
|
||||
def stop(self): |
||||
self.event.set() |
@ -0,0 +1,144 @@
|
||||
# Copyright 2014 Alcatel-Lucent Enterprise. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
||||
# except in compliance with the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License |
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
||||
# either express or implied. See the License for the specific language governing permissions |
||||
# and limitations under the License. |
||||
|
||||
|
||||
"""Implentation of Omniswitch ML2 Mechanism driver for ML2 Plugin.""" |
||||
|
||||
|
||||
import logging |
||||
|
||||
from neutron.plugins.ml2 import driver_api |
||||
from oslo_utils import importutils |
||||
|
||||
from networking_ale_omniswitch import config # noqa |
||||
from networking_ale_omniswitch import omniswitch_constants as omni_const |
||||
|
||||
LOG = logging.getLogger(__name__) |
||||
|
||||
|
||||
class OmniswitchMechanismDriver(driver_api.MechanismDriver): |
||||
|
||||
def __init__(self): |
||||
self.omni_plugin_obj = None |
||||
super(OmniswitchMechanismDriver, self).__init__() |
||||
|
||||
def initialize(self): |
||||
self.omniswitch_init() |
||||
LOG.info("Device plug-ins loaded!") |
||||
|
||||
def omniswitch_init(self): |
||||
self.omni_plugin_obj = importutils.import_object(omni_const.OMNI_DEVICE_PLUGIN) |
||||
LOG.info("Device plug-ins loaded!") |
||||
|
||||
def create_network_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def create_network_postcommit(self, mech_context): |
||||
LOG.debug("create_network_postcommit: called") |
||||
network = mech_context.current |
||||
segments = mech_context.network_segments |
||||
segment = segments[0] # currently supports only one segment per network |
||||
network_type = segment['network_type'] |
||||
|
||||
if network_type != 'vlan': |
||||
raise Exception( |
||||
"Omniswitch Mechanism: failed to create network, " |
||||
"only network type vlan is supported") |
||||
|
||||
ret = self.omni_plugin_obj.create_network(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to create network in Omniswitches! %s", network) |
||||
raise Exception( |
||||
"Omniswitch Mechanism: failed to create network in Omniswitches! %s", |
||||
network) |
||||
|
||||
def delete_network_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def delete_network_postcommit(self, mech_context): |
||||
network = mech_context.current |
||||
ret = self.omni_plugin_obj.delete_network(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete network in Omniswitches! %s", network) |
||||
|
||||
def update_network_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def update_network_postcommit(self, mech_context): |
||||
network = mech_context.current |
||||
|
||||
ret = self.omni_plugin_obj.update_network(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to update network in Omniswitches! %s", network) |
||||
raise Exception( |
||||
"Omniswitch Mechanism: failed to update network in Omniswitches! %s", |
||||
network) |
||||
|
||||
def create_port_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def create_port_postcommit(self, mech_context): |
||||
port = mech_context.current |
||||
ret = self.omni_plugin_obj.create_port(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to create port in Omniswitches! %s", port) |
||||
raise Exception( |
||||
"Omniswitch Mechanism: failed to create port in Omniswitches! %s", port) |
||||
|
||||
def delete_port_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def delete_port_postcommit(self, mech_context): |
||||
port = mech_context.current |
||||
|
||||
ret = self.omni_plugin_obj.delete_port(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete port in Omniswitches! %s", port) |
||||
|
||||
def update_port_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def update_port_postcommit(self, mech_context): |
||||
port = mech_context.current |
||||
|
||||
ret = self.omni_plugin_obj.update_port(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete port in Omniswitches! %s", port) |
||||
pass |
||||
|
||||
def create_subnet_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def create_subnet_postcommit(self, mech_context): |
||||
subnet = mech_context.current |
||||
ret = self.omni_plugin_obj.create_subnet(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete subnet in Omniswitches! %s", subnet) |
||||
pass |
||||
|
||||
def delete_subnet_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def delete_subnet_postcommit(self, mech_context): |
||||
subnet = mech_context.current |
||||
ret = self.omni_plugin_obj.delete_subnet(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete subnet in Omniswitches! %s", subnet) |
||||
|
||||
def update_subnet_precommit(self, mech_context): |
||||
pass |
||||
|
||||
def update_subnet_postcommit(self, mech_context): |
||||
subnet = mech_context.current |
||||
ret = self.omni_plugin_obj.update_subnet(mech_context) |
||||
if not ret: |
||||
LOG.error("Omniswitch Mechanism: failed to delete subnet in Omniswitches! %s", subnet) |
@ -0,0 +1,323 @@
|
||||
# Copyright 2014 Alcatel-Lucent Enterprise. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
||||
# except in compliance with the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License |
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
||||
# either express or implied. See the License for the specific language governing permissions |
||||
# and limitations under the License. |
||||
|
||||
import logging |
||||
import threading |
||||
import time |
||||
import urllib2 |
||||
|
||||
from networking_ale_omniswitch.consumer import AOSAPI |
||||
from networking_ale_omniswitch.consumer import AOSConnection |
||||
|
||||
LOG = logging.getLogger(__name__) |
||||
|
||||
|
||||
class OmniSwitchRestfulDriver(object): |
||||
|
||||
"""Name: OmniSwitchRestfulDriver. |
||||
Description: OmniSwitch device driver to communicate with OS6900 and OS10K devices which support |
||||
RESTful interface. |
||||
Details: It is used by OmniSwitchDevicePluginV2 to perform the necessary configuration on the physical |
||||
switches as response to OpenStack networking APIs. This driver is used only for OS6900, OS10K |
||||
and OS6860 devices which support RESTful APIs to configure them. This driver requires the following |
||||
minimum version of AOS SW to be running on these devices... |
||||
OS10K : 732-R01-GA |
||||
OS6900 : 733-R01-GA |
||||
OS6860 : 811-R01-GA |
||||
It uses the "consumer.py" library provided as a reference implementation from the AOS/OmniSwitch |
||||
point of view. No changes is made as part of OmniSwitch plug-in or driver development. For |
||||
latest version of consumer.py, refer "//depot/7.3.3.R01/sw/management/web/consumer/consumer.py". |
||||
For any issues/bugs with the library, please contact AOS 7x WebService module owner |
||||
(Chris Ravanscoft). |
||||
""" |
||||
def __init__(self, ip, platform, login='admin', password='switch', prompt='->'): |
||||
self.switch_type = platform |
||||
self.switch_ip = ip.strip() |
||||
if len(self.switch_ip) == 0: |
||||
LOG.info("Init Error! Must provide a valid IP address!!!") |
||||
return |
||||
|
||||
self.switch_login = login.strip() |
||||
if len(self.switch_login) == 0: |
||||
self.switch_login = 'admin' |
||||
|
||||
self.switch_password = password.strip() |
||||
if len(self.switch_password) == 0: |
||||
self.switch_password = 'switch' |