Browse Source

Initial code base for networking-ale-omniswitch ml2 driver

Change-Id: I267eadffb49e4455287c71129372ca725ff9b352
changes/06/211006/1
Vadivel Poonathan 7 years ago
parent
commit
216eb0d3c8
  1. 7
      .coveragerc
  2. 54
      .gitignore
  3. 3
      .mailmap
  4. 7
      .testr.conf
  5. 17
      CONTRIBUTING.rst
  6. 4
      HACKING.rst
  7. 176
      LICENSE
  8. 6
      MANIFEST.in
  9. 16
      README.rst
  10. 2
      babel.cfg
  11. 75
      doc/source/conf.py
  12. 4
      doc/source/contributing.rst
  13. 25
      doc/source/index.rst
  14. 12
      doc/source/installation.rst
  15. 1
      doc/source/readme.rst
  16. 7
      doc/source/usage.rst
  17. 91
      etc/neutron/plugins/ml2/ml2_conf_ale_omniswitch.ini
  18. 19
      networking_ale_omniswitch/__init__.py
  19. 25
      networking_ale_omniswitch/config.py
  20. 1225
      networking_ale_omniswitch/consumer.py
  21. 76
      networking_ale_omniswitch/omniswitch_constants.py
  22. 587
      networking_ale_omniswitch/omniswitch_device_plugin.py
  23. 144
      networking_ale_omniswitch/omniswitch_mechanism_driver.py
  24. 323
      networking_ale_omniswitch/omniswitch_restful_driver.py
  25. 217
      networking_ale_omniswitch/omniswitch_telnet_driver.py
  26. 0
      networking_ale_omniswitch/tests/__init__.py
  27. 23
      networking_ale_omniswitch/tests/base.py
  28. 28
      networking_ale_omniswitch/tests/test_networking_ale_omniswitch.py
  29. 0
      networking_ale_omniswitch/tests/unit/__init__.py
  30. 92
      networking_ale_omniswitch/tests/unit/omniswitch_restful_driver_test.py
  31. 54
      networking_ale_omniswitch/tests/unit/omniswitch_telnet_driver_test.py
  32. 528
      networking_ale_omniswitch/tests/unit/test_omniswitch_device_plugin.py
  33. 111
      networking_ale_omniswitch/tests/unit/test_omniswitch_restful_driver.py
  34. 187
      networking_ale_omniswitch/tests/unit/test_omniswitch_telnet_driver.py
  35. 27
      omniswitch_setup
  36. 6
      openstack-common.conf
  37. 8
      requirements.txt
  38. 59
      setup.cfg
  39. 29
      setup.py
  40. 16
      test-requirements.txt
  41. 37
      tox.ini

7
.coveragerc

@ -0,0 +1,7 @@
[run]
branch = True
source = networking_ale_omniswitch
omit = networking_ale_omniswitch/openstack/*
[report]
ignore-errors = True

54
.gitignore vendored

@ -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?

3
.mailmap

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

7
.testr.conf

@ -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

17
CONTRIBUTING.rst

@ -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

4
HACKING.rst

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

176
LICENSE

@ -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.

6
MANIFEST.in

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

16
README.rst

@ -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

2
babel.cfg

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

75
doc/source/conf.py

@ -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}

4
doc/source/contributing.rst

@ -0,0 +1,4 @@
============
Contributing
============
.. include:: ../../CONTRIBUTING.rst

25
doc/source/index.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`

12
doc/source/installation.rst

@ -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

1
doc/source/readme.rst

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

7
doc/source/usage.rst

@ -0,0 +1,7 @@
========
Usage
========
To use networking-ale-omniswitch in a project::
import networking_ale_omniswitch

91
etc/neutron/plugins/ml2/ml2_conf_ale_omniswitch.ini

@ -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

19
networking_ale_omniswitch/__init__.py

@ -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()

25
networking_ale_omniswitch/config.py

@ -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")

1225
networking_ale_omniswitch/consumer.py

File diff suppressed because it is too large Load Diff

76
networking_ale_omniswitch/omniswitch_constants.py

@ -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

587
networking_ale_omniswitch/omniswitch_device_plugin.py

@ -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()

144
networking_ale_omniswitch/omniswitch_mechanism_driver.py

@ -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)

323
networking_ale_omniswitch/omniswitch_restful_driver.py

@ -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'