From b5418e5912ea6007d4ddedd43c6fcd2957bfb4f6 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Mon, 17 Apr 2017 19:27:38 +0200 Subject: [PATCH] Retire repo This repo was created by accident, use deb-python-os-net-config instead. Needed-By: I1ac1a06931c8b6dd7c2e73620a0302c29e605f03 Change-Id: I81894aea69b9d09b0977039623c26781093a397a --- .coveragerc | 7 - .gitignore | 51 - .gitreview | 4 - .mailmap | 3 - .testr.conf | 7 - CONTRIBUTING.rst | 16 - HACKING.rst | 4 - LICENSE | 175 ---- MANIFEST.in | 6 - README.rst | 111 -- README.txt | 13 + babel.cfg | 1 - doc/source/conf.py | 75 -- doc/source/contributing.rst | 4 - doc/source/index.rst | 24 - doc/source/installation.rst | 12 - doc/source/readme.rst | 1 - doc/source/usage.rst | 7 - etc/os-net-config/samples/bond.json | 19 - etc/os-net-config/samples/bond.yaml | 17 - etc/os-net-config/samples/bond_mapped.yaml | 23 - etc/os-net-config/samples/bridge_dhcp.json | 17 - etc/os-net-config/samples/bridge_dhcp.yaml | 11 - etc/os-net-config/samples/bridge_vlan.json | 25 - etc/os-net-config/samples/bridge_vlan.yaml | 19 - etc/os-net-config/samples/ib_interface.json | 26 - etc/os-net-config/samples/ib_interface.yaml | 18 - etc/os-net-config/samples/interface.json | 26 - etc/os-net-config/samples/interface.yaml | 18 - etc/os-net-config/samples/ivs.json | 37 - etc/os-net-config/samples/ivs.yaml | 24 - etc/os-net-config/samples/linux_bond.yaml | 13 - etc/os-net-config/samples/linux_bridge.yaml | 9 - etc/os-net-config/samples/mapping.yaml | 12 - etc/os-net-config/samples/nfvswitch.json | 38 - etc/os-net-config/samples/nfvswitch.yaml | 25 - etc/os-net-config/samples/ovs_patch_port.json | 37 - etc/os-net-config/samples/ovs_patch_port.yaml | 23 - etc/os-net-config/samples/team.json | 13 - etc/os-net-config/samples/team.yaml | 18 - os_net_config/__init__.py | 233 ----- os_net_config/cli.py | 201 ---- os_net_config/impl_eni.py | 241 ----- os_net_config/impl_ifcfg.py | 835 --------------- os_net_config/impl_iproute.py | 21 - os_net_config/objects.py | 875 ---------------- os_net_config/tests/__init__.py | 0 os_net_config/tests/base.py | 70 -- os_net_config/tests/test_cli.py | 166 --- os_net_config/tests/test_impl_eni.py | 297 ------ os_net_config/tests/test_impl_ifcfg.py | 976 ------------------ os_net_config/tests/test_objects.py | 819 --------------- os_net_config/tests/test_os_net_config.py | 30 - os_net_config/tests/test_utils.py | 51 - os_net_config/utils.py | 120 --- os_net_config/version.py | 19 - requirements.txt | 10 - setup.cfg | 54 - setup.py | 22 - test-requirements.txt | 13 - tox.ini | 34 - 61 files changed, 13 insertions(+), 6063 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 .mailmap delete mode 100644 .testr.conf delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 MANIFEST.in delete mode 100644 README.rst create mode 100644 README.txt delete mode 100644 babel.cfg delete mode 100755 doc/source/conf.py delete mode 100644 doc/source/contributing.rst delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/installation.rst delete mode 100644 doc/source/readme.rst delete mode 100644 doc/source/usage.rst delete mode 100644 etc/os-net-config/samples/bond.json delete mode 100644 etc/os-net-config/samples/bond.yaml delete mode 100644 etc/os-net-config/samples/bond_mapped.yaml delete mode 100644 etc/os-net-config/samples/bridge_dhcp.json delete mode 100644 etc/os-net-config/samples/bridge_dhcp.yaml delete mode 100644 etc/os-net-config/samples/bridge_vlan.json delete mode 100644 etc/os-net-config/samples/bridge_vlan.yaml delete mode 100644 etc/os-net-config/samples/ib_interface.json delete mode 100644 etc/os-net-config/samples/ib_interface.yaml delete mode 100644 etc/os-net-config/samples/interface.json delete mode 100644 etc/os-net-config/samples/interface.yaml delete mode 100644 etc/os-net-config/samples/ivs.json delete mode 100644 etc/os-net-config/samples/ivs.yaml delete mode 100644 etc/os-net-config/samples/linux_bond.yaml delete mode 100644 etc/os-net-config/samples/linux_bridge.yaml delete mode 100644 etc/os-net-config/samples/mapping.yaml delete mode 100644 etc/os-net-config/samples/nfvswitch.json delete mode 100644 etc/os-net-config/samples/nfvswitch.yaml delete mode 100644 etc/os-net-config/samples/ovs_patch_port.json delete mode 100644 etc/os-net-config/samples/ovs_patch_port.yaml delete mode 100644 etc/os-net-config/samples/team.json delete mode 100644 etc/os-net-config/samples/team.yaml delete mode 100644 os_net_config/__init__.py delete mode 100644 os_net_config/cli.py delete mode 100644 os_net_config/impl_eni.py delete mode 100644 os_net_config/impl_ifcfg.py delete mode 100644 os_net_config/impl_iproute.py delete mode 100644 os_net_config/objects.py delete mode 100644 os_net_config/tests/__init__.py delete mode 100644 os_net_config/tests/base.py delete mode 100644 os_net_config/tests/test_cli.py delete mode 100644 os_net_config/tests/test_impl_eni.py delete mode 100644 os_net_config/tests/test_impl_ifcfg.py delete mode 100644 os_net_config/tests/test_objects.py delete mode 100644 os_net_config/tests/test_os_net_config.py delete mode 100644 os_net_config/tests/test_utils.py delete mode 100644 os_net_config/utils.py delete mode 100644 os_net_config/version.py delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100755 setup.py delete mode 100644 test-requirements.txt delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 96a0e8d..0000000 --- a/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = os_net_config -omit = os_net_config/tests/*,os_net_config/openstack/* - -[report] -ignore_errors = True diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1399c98..0000000 --- a/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg -*.egg-info -dist -build -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 - -# 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 \ No newline at end of file diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 88e4f4f..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/os-net-config.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index cc92f17..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# \ No newline at end of file diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index fb62267..0000000 --- a/.testr.conf +++ /dev/null @@ -1,7 +0,0 @@ -[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 \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index e94f240..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/os-net-config \ No newline at end of file diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 6c0e75c..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ -os-net-config Style Commandments -=============================================== - -Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 67db858..0000000 --- a/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 90f8a7a..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include AUTHORS -include ChangeLog -exclude .gitignore -exclude .gitreview - -global-exclude *.pyc \ No newline at end of file diff --git a/README.rst b/README.rst deleted file mode 100644 index 54b6080..0000000 --- a/README.rst +++ /dev/null @@ -1,111 +0,0 @@ -=============================== -os-net-config -=============================== - -host network configuration tool - -An implementation of the 'network configuration' spec @ -https://review.openstack.org/#/c/97859/. -The intention is for this code to be moved under the tripleo project in due course. - -* Free software: Apache license -* Documentation: http://docs.openstack.org/developer/os-net-config -* Source: http://git.openstack.org/cgit/openstack/os-net-config -* Bugs: http://bugs.launchpad.net/os-net-config - -Features --------- - -The core aim of this project is to allow fine grained (but extendable) -configuration of the networking parameters for a network host. The -project consists of: - - * A CLI (os-net-config) which provides configuration via a YAML or JSON - file formats. By default os-net-config uses a YAML config file located - at /etc/os-net-config/config.yaml. This can be customized via the - --config-file CLI option. - - * A python library which provides configuration via an object model. - -YAML Config Examples --------------------- - * Configure an OVS bridge with a single attached interface (port) - -.. code-block:: yaml - - network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - ovs_extra: - - br-set-external-id br-ctlplane bridge-id br-ctlplane - members: - - - type: interface - name: em1 - -.. - - - * Configure an OVS bridge on top of an OVS bond - -.. code-block:: yaml - - network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: ovs_bond - name: bond1 - members: - - - type: interface - name: em1 - - - type: interface - name: em2 - -.. - - * Configure a tagged VLAN interface on top of an OVS bridge - -.. code-block:: yaml - - network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: interface - name: em1 - - - type: vlan - vlan_id: 16 - addresses: - - - ip_netmask: 192.0.2.1/24 - -.. - -Provider Configuration ----------------------- -Providers are use to apply (implement) the desired configuration on the -host system. By default 3 providers are implemented: - - * Ifcfg: persistent network config format stored in - /etc/sysconfig/network-scripts - - * ENI: persistent network config format stored in /etc/network/interfaces - - * iproute2: non-persistent provider which implements the config using - iproute2, vconfig, etc... (implementation in progress) - -When using bin/os-net-config the provider is automatically selected based on -the host systems perferred persistent network type (ifcfg or ENI). This can -be customized via the --provider CLI option. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e73551f --- /dev/null +++ b/README.txt @@ -0,0 +1,13 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +Use instead the project deb-python-os-net-config at +http://git.openstack.org/cgit/openstack/deb-python-os-net-config . + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index efceab8..0000000 --- a/babel.cfg +++ /dev/null @@ -1 +0,0 @@ -[python: **.py] diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index 4bbfbc1..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - #'sphinx.ext.intersphinx', - 'oslosphinx' -] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'os-net-config' -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} \ No newline at end of file diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst deleted file mode 100644 index ed77c12..0000000 --- a/doc/source/contributing.rst +++ /dev/null @@ -1,4 +0,0 @@ -============ -Contributing -============ -.. include:: ../../CONTRIBUTING.rst \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 77009e5..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. os-net-config 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 os-net-config's documentation! -======================================================== - -Contents: - -.. toctree:: - :maxdepth: 2 - - readme - installation - usage - contributing - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/source/installation.rst b/doc/source/installation.rst deleted file mode 100644 index f2213c3..0000000 --- a/doc/source/installation.rst +++ /dev/null @@ -1,12 +0,0 @@ -============ -Installation -============ - -At the command line:: - - $ pip install os-net-config - -Or, if you have virtualenvwrapper installed:: - - $ mkvirtualenv os-net-config - $ pip install os-net-config \ No newline at end of file diff --git a/doc/source/readme.rst b/doc/source/readme.rst deleted file mode 100644 index 38ba804..0000000 --- a/doc/source/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../README.rst \ No newline at end of file diff --git a/doc/source/usage.rst b/doc/source/usage.rst deleted file mode 100644 index 6585240..0000000 --- a/doc/source/usage.rst +++ /dev/null @@ -1,7 +0,0 @@ -======== -Usage -======== - -To use os-net-config in a project:: - - import os_net_config \ No newline at end of file diff --git a/etc/os-net-config/samples/bond.json b/etc/os-net-config/samples/bond.json deleted file mode 100644 index b21b2d9..0000000 --- a/etc/os-net-config/samples/bond.json +++ /dev/null @@ -1,19 +0,0 @@ -{ "network_config": [ - { - "type": "ovs_bridge", - "name": "br-ctlplane", - "use_dhcp": "true", - "members": [ - { - "type": "ovs_bond", - "name": "bond1", - "use_dhcp": "true", - "members": [ - { "type": "interface", "name": "em1" }, - { "type": "interface", "name": "em2" } - ] - } - ] - } - ] -} diff --git a/etc/os-net-config/samples/bond.yaml b/etc/os-net-config/samples/bond.yaml deleted file mode 100644 index 7b8b4ec..0000000 --- a/etc/os-net-config/samples/bond.yaml +++ /dev/null @@ -1,17 +0,0 @@ -network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: ovs_bond - name: bond1 - use_dhcp: true - members: - - - type: interface - name: em1 - - - type: interface - name: em2 diff --git a/etc/os-net-config/samples/bond_mapped.yaml b/etc/os-net-config/samples/bond_mapped.yaml deleted file mode 100644 index 9a118c9..0000000 --- a/etc/os-net-config/samples/bond_mapped.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Example showing use of the optional nicN abstraction -# for device naming, which defaults to an ordered -# translation to biodev names based on which interfaces -# are active on the system. -# Optionally the default mapping may be overriden by -# a mapping file via the -m option. -network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: ovs_bond - name: bond1 - use_dhcp: true - members: - - - type: interface - name: nic1 - - - type: interface - name: nic2 diff --git a/etc/os-net-config/samples/bridge_dhcp.json b/etc/os-net-config/samples/bridge_dhcp.json deleted file mode 100644 index 76d5408..0000000 --- a/etc/os-net-config/samples/bridge_dhcp.json +++ /dev/null @@ -1,17 +0,0 @@ -{ "network_config": [ - { - "type": "ovs_bridge", - "name": "br-ctlplane", - "ovs_extra": [ - "br-set-external-id br-ctlplane bridge-id br-ctlplane" - ], - "use_dhcp": "true", - "members": [ - { - "type": "interface", - "name": "em1" - } - ] - } - ] -} diff --git a/etc/os-net-config/samples/bridge_dhcp.yaml b/etc/os-net-config/samples/bridge_dhcp.yaml deleted file mode 100644 index a6ac593..0000000 --- a/etc/os-net-config/samples/bridge_dhcp.yaml +++ /dev/null @@ -1,11 +0,0 @@ -network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - ovs_extra: - - br-set-external-id br-ctlplane bridge-id br-ctlplane - members: - - - type: interface - name: em1 diff --git a/etc/os-net-config/samples/bridge_vlan.json b/etc/os-net-config/samples/bridge_vlan.json deleted file mode 100644 index 244c89a..0000000 --- a/etc/os-net-config/samples/bridge_vlan.json +++ /dev/null @@ -1,25 +0,0 @@ -{ "network_config": [ - { - "type": "ovs_bridge", - "name": "br-ctlplane", - "use_dhcp": "true", - "members": [ - { - "type": "interface", - "name": "em1" - }, - { - "type": "vlan", - "vlan_id": 16, - "addresses": [{ - "ip_netmask": "192.0.2.1/24" - }] - } - ], - "routes": [{ - "next_hop": "192.0.2.1", - "ip_netmask": "192.0.2.1/24" - }] - } - ] -} diff --git a/etc/os-net-config/samples/bridge_vlan.yaml b/etc/os-net-config/samples/bridge_vlan.yaml deleted file mode 100644 index fdf9041..0000000 --- a/etc/os-net-config/samples/bridge_vlan.yaml +++ /dev/null @@ -1,19 +0,0 @@ -network_config: - - - type: ovs_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: interface - name: em1 - - - type: vlan - vlan_id: 16 - addresses: - - - ip_netmask: 192.0.2.1/24 - routes: - - - next_hop: 192.0.2.1 - ip_netmask: 192.0.2.1/24 diff --git a/etc/os-net-config/samples/ib_interface.json b/etc/os-net-config/samples/ib_interface.json deleted file mode 100644 index 4e42867..0000000 --- a/etc/os-net-config/samples/ib_interface.json +++ /dev/null @@ -1,26 +0,0 @@ -{"network_config": [ - { - "type": "ib_interface", - "name": "ib0", - "use_dhcp": false, - "addresses": [ - { - "ip_netmask": "192.0.2.1/24" - } - ], - "routes": [ - { - "ip_netmask": "0.0.0.0/0", - "next_hop": "192.0.2.254", - "default": "true" - } - ] - }, - { - "type": "ib_interface", - "name": "ib1", - "use_dhcp": true, - "defroute": no - } - ] -} diff --git a/etc/os-net-config/samples/ib_interface.yaml b/etc/os-net-config/samples/ib_interface.yaml deleted file mode 100644 index f930471..0000000 --- a/etc/os-net-config/samples/ib_interface.yaml +++ /dev/null @@ -1,18 +0,0 @@ -network_config: - - - type: ib_interface - name: ib0 - use_dhcp: false - addresses: - - - ip_netmask: 192.0.2.1/24 - routes: - - - ip_netmask: 0.0.0.0/0 - next_hop: 192.0.2.254 - default: true - - - type: interface - name: ib1 - use_dhcp: true - defroute: no \ No newline at end of file diff --git a/etc/os-net-config/samples/interface.json b/etc/os-net-config/samples/interface.json deleted file mode 100644 index 8a942b5..0000000 --- a/etc/os-net-config/samples/interface.json +++ /dev/null @@ -1,26 +0,0 @@ -{"network_config": [ - { - "type": "interface", - "name": "em1", - "use_dhcp": false, - "addresses": [ - { - "ip_netmask": "192.0.2.1/24" - } - ], - "routes": [ - { - "ip_netmask": "0.0.0.0/0", - "next_hop": "192.0.2.254", - "default": "true" - } - ] - }, - { - "type": "interface", - "name": "em2", - "use_dhcp": true, - "defroute": no - } - ] -} diff --git a/etc/os-net-config/samples/interface.yaml b/etc/os-net-config/samples/interface.yaml deleted file mode 100644 index 4f76e07..0000000 --- a/etc/os-net-config/samples/interface.yaml +++ /dev/null @@ -1,18 +0,0 @@ -network_config: - - - type: interface - name: em1 - use_dhcp: false - addresses: - - - ip_netmask: 192.0.2.1/24 - routes: - - - ip_netmask: 0.0.0.0/0 - next_hop: 192.0.2.254 - default: true - - - type: interface - name: em2 - use_dhcp: true - defroute: no \ No newline at end of file diff --git a/etc/os-net-config/samples/ivs.json b/etc/os-net-config/samples/ivs.json deleted file mode 100644 index 746e1c0..0000000 --- a/etc/os-net-config/samples/ivs.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "network_config": [ - { - "type": "ivs_bridge", - "members": [ - { - "type": "interface", - "name": "nic2", - }, - { - "type": "interface", - "name": "nic3" - }, - { - "type": "ivs_interface", - "name": "api", - "addresses": [ - { - "ip_netmask": "172.16.2.7/24" - } - ], - "vlan_id": 201 - }, - { - "type": "ivs_interface", - "name": "storage", - "addresses": [ - { - "ip_netmask": "172.16.1.6/24" - } - ], - "vlan_id": 202 - } - ] - } - ] -} diff --git a/etc/os-net-config/samples/ivs.yaml b/etc/os-net-config/samples/ivs.yaml deleted file mode 100644 index 9813316..0000000 --- a/etc/os-net-config/samples/ivs.yaml +++ /dev/null @@ -1,24 +0,0 @@ -network_config: - - - type: ivs_bridge - members: - - - type: interface - name: nic2 - - - type: interface - name: nic3 - - - type: ivs_interface - name: api - vlan_id: 201 - addresses: - - - ip_netmask: 172.16.2.7/24 - - - type: ivs_interface - name: storage - vlan_id: 202 - addresses: - - - ip_netmask: 172.16.1.6/24 diff --git a/etc/os-net-config/samples/linux_bond.yaml b/etc/os-net-config/samples/linux_bond.yaml deleted file mode 100644 index 566c747..0000000 --- a/etc/os-net-config/samples/linux_bond.yaml +++ /dev/null @@ -1,13 +0,0 @@ -network_config: - - - type: linux_bond - name: bond1 - use_dhcp: true - bonding_options: "mode=active-backup" - members: - - - type: interface - name: em1 - - - type: interface - name: em2 diff --git a/etc/os-net-config/samples/linux_bridge.yaml b/etc/os-net-config/samples/linux_bridge.yaml deleted file mode 100644 index 051f6f3..0000000 --- a/etc/os-net-config/samples/linux_bridge.yaml +++ /dev/null @@ -1,9 +0,0 @@ -network_config: - - - type: linux_bridge - name: br-ctlplane - use_dhcp: true - members: - - - type: interface - name: em1 diff --git a/etc/os-net-config/samples/mapping.yaml b/etc/os-net-config/samples/mapping.yaml deleted file mode 100644 index a832dc9..0000000 --- a/etc/os-net-config/samples/mapping.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# This can be used with the -m option to override the -# default mapping of the nicN aliases in configs -# The mapping can specify either a device name or a mac address -# If --persist-mapping is specified, we write the device aliases -# config instead of the system names, e.g we actually configure -# nic1 intead of em3. This is probably best used with --cleanup -# to remove the stale configs e.g for em3 -interface_mapping: - nic1: em3 - nic2: em1 - nic3: 12:34:56:de:f0:12 - nic4: 12:34:56:78:9a:bc diff --git a/etc/os-net-config/samples/nfvswitch.json b/etc/os-net-config/samples/nfvswitch.json deleted file mode 100644 index 2d8af8a..0000000 --- a/etc/os-net-config/samples/nfvswitch.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "network_config": [ - { - "type": "nfvswitch_bridge", - "cpus": "2,3,4,5", - "members": [ - { - "type": "interface", - "name": "nic2", - }, - { - "type": "interface", - "name": "nic3" - }, - { - "type": "nfvswitch_internal", - "name": "api", - "addresses": [ - { - "ip_netmask": "172.16.2.7/24" - } - ], - "vlan_id": 201 - }, - { - "type": "nfvswitch_internal", - "name": "storage", - "addresses": [ - { - "ip_netmask": "172.16.1.6/24" - } - ], - "vlan_id": 202 - } - ] - } - ] -} diff --git a/etc/os-net-config/samples/nfvswitch.yaml b/etc/os-net-config/samples/nfvswitch.yaml deleted file mode 100644 index 5af3f70..0000000 --- a/etc/os-net-config/samples/nfvswitch.yaml +++ /dev/null @@ -1,25 +0,0 @@ -network_config: - - - type: nfvswitch_bridge - cpus: "2,3,4,5" - members: - - - type: interface - name: nic2 - - - type: interface - name: nic3 - - - type: nfvswitch_internal - name: api - vlan_id: 201 - addresses: - - - ip_netmask: 172.16.2.7/24 - - - type: nfvswitch_internal - name: storage - vlan_id: 202 - addresses: - - - ip_netmask: 172.16.1.6/24 \ No newline at end of file diff --git a/etc/os-net-config/samples/ovs_patch_port.json b/etc/os-net-config/samples/ovs_patch_port.json deleted file mode 100644 index d457371..0000000 --- a/etc/os-net-config/samples/ovs_patch_port.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "network_config": [ - { - "name": "br-ctlplane", - "type": "ovs_bridge", - "members": [ - { - "mtu": 1500, - "primary": "true", - "name": "eth1", - "type": "interface" - } - ], - "ovs_extra": [ - "br-set-external-id br-ctlplane bridge-id br-ctlplane" - ], - "mtu": 1500, - "addresses": [ - { - "ip_netmask": "192.0.2.1/24" - } - ] - }, - { - "name": "br_pub-patch", - "type": "ovs_patch_port", - "bridge_name": "br-ctlplane", - "peer": "br-ctlplane-patch" - }, - { - "name": "br-ctlplane-patch", - "type": "ovs_patch_port", - "bridge_name": "br_pub", - "peer": "br_pub-patch" - } - ] -} diff --git a/etc/os-net-config/samples/ovs_patch_port.yaml b/etc/os-net-config/samples/ovs_patch_port.yaml deleted file mode 100644 index 91858be..0000000 --- a/etc/os-net-config/samples/ovs_patch_port.yaml +++ /dev/null @@ -1,23 +0,0 @@ -network_config: - - - type: ovs_bridge - name: br-ctlplane - mtu: 1500 - members: - - - type: interface - name: eth1 - # force the MAC address of the bridge to this interface - primary: true - mtu: 1500 - ovs_extra: "br-set-external-id br-ctlplane bridge-id br-ctlplane" - - - type: ovs_patch_port - name: br_pub-patch - bridge_name: br-ctlplane - peer: br-ctlplane-patch - - - type: ovs_patch_port - name: br-ctlplane-patch - bridge_name: br_pub - peer: br_pub-patch diff --git a/etc/os-net-config/samples/team.json b/etc/os-net-config/samples/team.json deleted file mode 100644 index 4524b3c..0000000 --- a/etc/os-net-config/samples/team.json +++ /dev/null @@ -1,13 +0,0 @@ -{ "network_config": [ - { - "type": "team", - "name": "team1", - "use_dhcp": true, - "bonding_options": "{\"runner\": {\"name\": \"activebackup\"}}", - "members": [ - { "type": "interface", "name": "em1", "primary": true }, - { "type": "interface", "name": "em2" } - ] - } - ] -} diff --git a/etc/os-net-config/samples/team.yaml b/etc/os-net-config/samples/team.yaml deleted file mode 100644 index 3770de0..0000000 --- a/etc/os-net-config/samples/team.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Config for bonding with teamd. Bonding options are provided as a JSON -# string. The following runners are available in teamd: broadcast, -# roundrobin, activebackup, loadbalance, and lacp. -# Please see the teamd.conf(5) man page for more information. -network_config: - - - type: team - name: team1 - use_dhcp: true - bonding_options: '{"runner": {"name": "activebackup"}}' - members: - - - type: interface - name: em1 - primary: true - - - type: interface - name: em2 diff --git a/os_net_config/__init__.py b/os_net_config/__init__.py deleted file mode 100644 index 2aafc23..0000000 --- a/os_net_config/__init__.py +++ /dev/null @@ -1,233 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import os - -from oslo_concurrency import processutils - -from os_net_config import objects -from os_net_config import utils - - -logger = logging.getLogger(__name__) - - -class NotImplemented(Exception): - pass - - -class NetConfig(object): - """Common network config methods class.""" - - def __init__(self, noop=False, root_dir=''): - self.noop = noop - self.log_prefix = "NOOP: " if noop else "" - self.root_dir = root_dir - - def add_object(self, obj): - """Convenience method to add any type of object to the network config. - - See objects.py. - - :param obj: The object to add. - """ - if isinstance(obj, objects.Interface): - self.add_interface(obj) - elif isinstance(obj, objects.Vlan): - self.add_vlan(obj) - elif isinstance(obj, objects.IvsInterface): - self.add_ivs_interface(obj) - elif isinstance(obj, objects.NfvswitchInternal): - self.add_nfvswitch_internal(obj) - elif isinstance(obj, objects.OvsBridge): - self.add_bridge(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.LinuxBridge): - self.add_linux_bridge(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.IvsBridge): - self.add_ivs_bridge(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.NfvswitchBridge): - self.add_nfvswitch_bridge(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.OvsBond): - self.add_bond(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.LinuxBond): - self.add_linux_bond(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.LinuxTeam): - self.add_linux_team(obj) - for member in obj.members: - self.add_object(member) - elif isinstance(obj, objects.OvsTunnel): - self.add_ovs_tunnel(obj) - elif isinstance(obj, objects.OvsPatchPort): - self.add_ovs_patch_port(obj) - elif isinstance(obj, objects.IbInterface): - self.add_ib_interface(obj) - - def add_interface(self, interface): - """Add an Interface object to the net config object. - - :param interface: The Interface object to add. - """ - raise NotImplemented("add_interface is not implemented.") - - def add_vlan(self, vlan): - """Add a Vlan object to the net config object. - - :param vlan: The vlan object to add. - """ - raise NotImplemented("add_vlan is not implemented.") - - def add_bridge(self, bridge): - """Add an OvsBridge object to the net config object. - - :param bridge: The OvsBridge object to add. - """ - raise NotImplemented("add_bridge is not implemented.") - - def add_linux_bridge(self, bridge): - """Add a LinuxBridge object to the net config object. - - :param bridge: The LinuxBridge object to add. - """ - raise NotImplemented("add_linux_bridge is not implemented.") - - def add_ivs_bridge(self, bridge): - """Add a IvsBridge object to the net config object. - - :param bridge: The IvsBridge object to add. - """ - raise NotImplemented("add_ivs_bridge is not implemented.") - - def add_nfvswitch_bridge(self, bridge): - """Add a NfvswitchBridge object to the net config object. - - :param bridge: The NfvswitchBridge object to add. - """ - raise NotImplemented("add_nfvswitch_bridge is not implemented.") - - def add_bond(self, bond): - """Add an OvsBond object to the net config object. - - :param bond: The OvsBond object to add. - """ - raise NotImplemented("add_bond is not implemented.") - - def add_linux_bond(self, bond): - """Add a LinuxBond object to the net config object. - - :param bond: The LinuxBond object to add. - """ - raise NotImplemented("add_linux_bond is not implemented.") - - def add_linux_team(self, team): - """Add a LinuxTeam object to the net config object. - - :param team: The LinuxTeam object to add. - """ - raise NotImplemented("add_linux_team is not implemented.") - - def add_ovs_tunnel(self, tunnel): - """Add a OvsTunnel object to the net config object. - - :param tunnel: The OvsTunnel object to add. - """ - raise NotImplemented("add_ovs_tunnel is not implemented.") - - def add_ovs_patch_port(self, ovs_patch_port): - """Add a OvsPatchPort object to the net config object. - - :param ovs_patch_port: The OvsPatchPort object to add. - """ - raise NotImplemented("add_ovs_patch_port is not implemented.") - - def add_ib_interface(self, ib_interface): - """Add an InfiniBand Interface object to the net config object. - - :param interface: The InfiniBand Interface object to add. - """ - raise NotImplemented("add_ib_interface is not implemented.") - - def apply(self, cleanup=False): - """Apply the network configuration. - - :param cleanup: A boolean which indicates whether any undefined - (existing but not present in the object model) interfaces - should be disabled and deleted. - :returns: a dict of the format: filename/data which contains info - for each file that was changed (or would be changed if in --noop - mode). - """ - raise NotImplemented("apply is not implemented.") - - def execute(self, msg, cmd, *args, **kwargs): - """Print a message and run a command. - - Print a message and run a command with processutils - in noop mode, this just prints a message. - """ - logger.info('%s%s' % (self.log_prefix, msg)) - if not self.noop: - processutils.execute(cmd, *args, **kwargs) - - def write_config(self, filename, data, msg=None): - msg = msg or "Writing config %s" % filename - logger.info('%s%s' % (self.log_prefix, msg)) - if not self.noop: - utils.write_config(filename, data) - - def remove_config(self, filename, msg=None): - msg = msg or "Removing config %s" % filename - logger.info('%s%s' % (self.log_prefix, msg)) - if not self.noop: - os.remove(filename) - - def ifdown(self, interface, iftype='interface'): - msg = 'running ifdown on %s: %s' % (iftype, interface) - self.execute(msg, '/sbin/ifdown', interface, check_exit_code=False) - - def ifup(self, interface, iftype='interface'): - msg = 'running ifup on %s: %s' % (iftype, interface) - self.execute(msg, '/sbin/ifup', interface) - - def ifrename(self, oldname, newname): - msg = 'renaming %s to %s: ' % (oldname, newname) - # ifdown isn't enough when renaming, we need the link down - for name in (oldname, newname): - if utils._is_active_nic(name): - self.execute(msg, '/sbin/ip', - 'link', 'set', 'dev', name, 'down') - self.execute(msg, '/sbin/ip', - 'link', 'set', 'dev', name, 'link', 'down') - self.execute(msg, '/sbin/ip', - 'link', 'set', 'dev', oldname, 'name', newname) - self.execute(msg, '/sbin/ip', - 'link', 'set', 'dev', newname, 'up') - - def ovs_appctl(self, action, *parameters): - msg = 'Running ovs-appctl %s %s' % (action, parameters) - self.execute(msg, '/bin/ovs-appctl', action, *parameters) diff --git a/os_net_config/cli.py b/os_net_config/cli.py deleted file mode 100644 index c0ac5c4..0000000 --- a/os_net_config/cli.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import argparse -import logging -import os -import sys -import yaml - -from os_net_config import impl_eni -from os_net_config import impl_ifcfg -from os_net_config import impl_iproute -from os_net_config import objects -from os_net_config import version - - -logger = logging.getLogger(__name__) - - -def parse_opts(argv): - parser = argparse.ArgumentParser( - description='Configure host network interfaces using a JSON' - ' config file format.') - parser.add_argument('-c', '--config-file', metavar='CONFIG_FILE', - help="""path to the configuration file.""", - default='/etc/os-net-config/config.yaml') - parser.add_argument('-m', '--mapping-file', metavar='MAPPING_FILE', - help="""path to the interface mapping file.""", - default='/etc/os-net-config/mapping.yaml') - parser.add_argument('-p', '--provider', metavar='PROVIDER', - help="""The provider to use.""" - """One of: ifcfg, eni, iproute.""", - default=None) - parser.add_argument('-r', '--root-dir', metavar='ROOT_DIR', - help="""The root directory of the filesystem.""", - default='') - parser.add_argument('--detailed-exit-codes', - action='store_true', - help="""Enable detailed exit codes. """ - """If enabled an exit code of '2' means """ - """that files were modified.""" - """Disabled by default.""", - default=False) - parser.add_argument( - '-d', '--debug', - dest="debug", - action='store_true', - help="Print debugging output.", - required=False) - parser.add_argument( - '-v', '--verbose', - dest="verbose", - action='store_true', - help="Print verbose output.", - required=False) - - parser.add_argument('--version', action='version', - version=version.version_info.version_string()) - parser.add_argument( - '--noop', - dest="noop", - action='store_true', - help="Return the configuration commands, without applying them.", - required=False) - - parser.add_argument( - '--no-activate', - dest="no_activate", - action='store_true', - help="Install the configuration but don't start/stop interfaces.", - required=False) - - parser.add_argument( - '--cleanup', - dest="cleanup", - action='store_true', - help="Cleanup unconfigured interfaces.", - required=False) - - parser.add_argument( - '--persist-mapping', - dest="persist_mapping", - action='store_true', - help="Make aliases defined in the mapping file permanent " - "(WARNING, permanently renames nics).", - required=False) - - opts = parser.parse_args(argv[1:]) - - return opts - - -def configure_logger(verbose=False, debug=False): - LOG_FORMAT = '[%(asctime)s] [%(levelname)s] %(message)s' - DATE_FORMAT = '%Y/%m/%d %I:%M:%S %p' - log_level = logging.WARN - - if debug: - log_level = logging.DEBUG - elif verbose: - log_level = logging.INFO - - logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT, - level=log_level) - - -def main(argv=sys.argv): - opts = parse_opts(argv) - configure_logger(opts.verbose, opts.debug) - logger.info('Using config file at: %s' % opts.config_file) - if opts.mapping_file: - logger.info('Using mapping file at: %s' % opts.mapping_file) - iface_array = [] - - provider = None - if opts.provider: - if opts.provider == 'ifcfg': - provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, - root_dir=opts.root_dir) - elif opts.provider == 'eni': - provider = impl_eni.ENINetConfig(noop=opts.noop, - root_dir=opts.root_dir) - elif opts.provider == 'iproute': - provider = impl_iproute.IPRouteNetConfig(noop=opts.noop, - root_dir=opts.root_dir) - else: - logger.error('Invalid provider specified.') - return 1 - else: - if os.path.exists('%s/etc/sysconfig/network-scripts/' % opts.root_dir): - provider = impl_ifcfg.IfcfgNetConfig(noop=opts.noop, - root_dir=opts.root_dir) - elif os.path.exists('%s/etc/network/' % opts.root_dir): - provider = impl_eni.ENINetConfig(noop=opts.noop, - root_dir=opts.root_dir) - else: - logger.error('Unable to set provider for this operating system.') - return 1 - - # Read config file containing network configs to apply - if os.path.exists(opts.config_file): - with open(opts.config_file) as cf: - iface_array = yaml.load(cf.read()).get("network_config") - logger.debug('network_config JSON: %s' % str(iface_array)) - else: - logger.error('No config file exists at: %s' % opts.config_file) - return 1 - - if not isinstance(iface_array, list): - logger.error('No interfaces defined in config: %s' % opts.config_file) - return 1 - - # Read the interface mapping file, if it exists - # This allows you to override the default network naming abstraction - # mappings by specifying a specific nicN->name or nicN->MAC mapping - if os.path.exists(opts.mapping_file): - with open(opts.mapping_file) as cf: - iface_map = yaml.load(cf.read()) - iface_mapping = iface_map.get("interface_mapping") - logger.debug('interface_mapping JSON: %s' % str(iface_mapping)) - persist_mapping = opts.persist_mapping - logger.debug('persist_mapping: %s' % persist_mapping) - else: - iface_mapping = None - persist_mapping = False - - for iface_json in iface_array: - iface_json.update({'nic_mapping': iface_mapping}) - iface_json.update({'persist_mapping': persist_mapping}) - obj = objects.object_from_json(iface_json) - provider.add_object(obj) - files_changed = provider.apply(cleanup=opts.cleanup, - activate=not opts.no_activate) - if opts.noop: - for location, data in files_changed.iteritems(): - print("File: %s\n" % location) - print(data) - print("----") - - if opts.detailed_exit_codes and len(files_changed) > 0: - return 2 - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/os_net_config/impl_eni.py b/os_net_config/impl_eni.py deleted file mode 100644 index ae60099..0000000 --- a/os_net_config/impl_eni.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- Coding: utf-8 -*- - -# Copyright 2014-2015 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import netaddr -import os_net_config -from os_net_config import objects -from os_net_config import utils - - -logger = logging.getLogger(__name__) - - -# TODO(?): should move to interfaces.d -def _network_config_path(prefix=''): - return prefix + "/etc/network/interfaces" - - -class ENINetConfig(os_net_config.NetConfig): - """Debian/Ubuntu implementation for network config - - Configure iface/bridge/routes using debian/ubuntu - /etc/network/interfaces format. - """ - - def __init__(self, noop=False, root_dir=''): - super(ENINetConfig, self).__init__(noop, root_dir) - self.interfaces = {} - self.routes = {} - self.bridges = {} - logger.info('ENI net config provider created.') - - def _add_common(self, interface, static_addr=None, ip_version=4): - - ovs_extra = [] - data = "" - address_data = "" - if static_addr: - address_data += " address %s\n" % static_addr.ip - if ip_version == 6: - address_data += " netmask %s\n" % static_addr.prefixlen - else: - address_data += " netmask %s\n" % static_addr.netmask - else: - v4_addresses = interface.v4_addresses() - if v4_addresses: - for v4_address in v4_addresses: - data += self._add_common(interface, v4_address) - - v6_addresses = interface.v6_addresses() - if v6_addresses: - for v6_address in v6_addresses: - data += self._add_common(interface, v6_address, 6) - - if data: - return data - - if isinstance(interface, objects.Vlan): - _iface = "iface vlan%i " % interface.vlan_id - else: - _iface = "iface %s " % interface.name - if static_addr and static_addr.version == 6: - _iface += "inet6 " - else: - _iface += "inet " - if interface.use_dhcp: - _iface += "dhcp\n" - elif interface.addresses: - _iface += "static\n" - else: - _iface += "manual\n" - if isinstance(interface, objects.OvsBridge): - data += "auto %s\n" % interface.name - data += "allow-ovs %s\n" % interface.name - data += _iface - data += address_data - data += " ovs_type OVSBridge\n" - if interface.members: - data += " ovs_ports" - for i in interface.members: - data += " %s" % i.name - data += "\n" - for mem in interface.members: - if isinstance(mem, objects.Interface): - data += " pre-up ip addr flush dev %s\n" % mem.name - if interface.primary_interface_name: - mac = utils.interface_mac(interface.primary_interface_name) - ovs_extra.append("set bridge %s other-config:hwaddr=%s" % - (interface.name, mac)) - ovs_extra.extend(interface.ovs_extra) - elif interface.ovs_port: - if isinstance(interface, objects.Vlan): - data += "auto vlan%i\n" % interface.vlan_id - data += "allow-%s vlan%i\n" % (interface.bridge_name, - interface.vlan_id) - data += _iface - data += address_data - data += " ovs_bridge %s\n" % interface.bridge_name - data += " ovs_type OVSIntPort\n" - data += " ovs_options tag=%s\n" % interface.vlan_id - - else: - data += "auto %s\n" % interface.name - data += "allow-%s %s\n" % (interface.bridge_name, - interface.name) - data += _iface - data += address_data - data += " ovs_bridge %s\n" % interface.bridge_name - data += " ovs_type OVSPort\n" - elif isinstance(interface, objects.Vlan): - data += "auto vlan%i\n" % interface.vlan_id - data += _iface - data += address_data - data += " vlan-raw-device %s\n" % interface.device - else: - data += "auto %s\n" % interface.name - data += _iface - data += address_data - if interface.mtu: - data += " mtu %i\n" % interface.mtu - - if interface.hwaddr: - raise NotImplemented("hwaddr is not implemented.") - - if ovs_extra: - data += " ovs_extra %s\n" % " -- ".join(ovs_extra) - - return data - - def add_interface(self, interface): - """Add an Interface object to the net config object. - - :param interface: The Interface object to add. - """ - logger.info('adding interface: %s' % interface.name) - data = self._add_common(interface) - logger.debug('interface data: %s' % data) - self.interfaces[interface.name] = data - if interface.routes: - self._add_routes(interface.name, interface.routes) - - def add_bridge(self, bridge): - """Add an OvsBridge object to the net config object. - - :param bridge: The OvsBridge object to add. - """ - logger.info('adding bridge: %s' % bridge.name) - data = self._add_common(bridge) - logger.debug('bridge data: %s' % data) - self.bridges[bridge.name] = data - if bridge.routes: - self._add_routes(bridge.name, bridge.routes) - - def add_vlan(self, vlan): - """Add a Vlan object to the net config object. - - :param vlan: The vlan object to add. - """ - logger.info('adding vlan: %s' % vlan.name) - data = self._add_common(vlan) - logger.debug('vlan data: %s' % data) - self.interfaces[vlan.name] = data - if vlan.routes: - self._add_routes(vlan.name, vlan.routes) - - def _add_routes(self, interface_name, routes=[]): - logger.info('adding custom route for interface: %s' % interface_name) - data = "" - for route in routes: - if route.default and not route.ip_netmask: - rt = netaddr.IPNetwork("0.0.0.0/0") - else: - rt = netaddr.IPNetwork(route.ip_netmask) - data += "up route add -net %s netmask %s gw %s\n" % ( - str(rt.ip), str(rt.netmask), route.next_hop) - data += "down route del -net %s netmask %s gw %s\n" % ( - str(rt.ip), str(rt.netmask), route.next_hop) - self.routes[interface_name] = data - logger.debug('route data: %s' % self.routes[interface_name]) - - def apply(self, cleanup=False, activate=True): - """Apply the network configuration. - - :param cleanup: A boolean which indicates whether any undefined - (existing but not present in the object model) interface - should be disabled and deleted. - :param activate: A boolean which indicates if the config should - be activated by stopping/starting interfaces - :returns: a dict of the format: filename/data which contains info - for each file that was changed (or would be changed if in --noop - mode). - Note the noop mode is set via the constructor noop boolean - """ - new_config = "" - - # write out bridges first. This ensures that an ifup -a - # on reboot brings them up first - for bridge_name, bridge_data in self.bridges.iteritems(): - route_data = self.routes.get(bridge_name) - bridge_data += (route_data or '') - new_config += bridge_data - - for interface_name, iface_data in self.interfaces.iteritems(): - route_data = self.routes.get(interface_name) - iface_data += (route_data or '') - new_config += iface_data - - if utils.diff(_network_config_path(self.root_dir), new_config): - if activate: - for interface in self.interfaces.keys(): - self.ifdown(interface) - - for bridge in self.bridges.keys(): - self.ifdown(bridge, iftype='bridge') - - self.write_config(_network_config_path(self.root_dir), new_config) - - if activate: - for bridge in self.bridges.keys(): - self.ifup(bridge, iftype='bridge') - - for interface in self.interfaces.keys(): - self.ifup(interface) - else: - logger.info('No interface changes are required.') - - return {_network_config_path(self.root_dir): new_config} diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py deleted file mode 100644 index d49b57b..0000000 --- a/os_net_config/impl_ifcfg.py +++ /dev/null @@ -1,835 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import glob -import logging -import re - -import os_net_config -from os_net_config import objects -from os_net_config import utils - - -logger = logging.getLogger(__name__) - - -def ifcfg_config_path(name): - return "/etc/sysconfig/network-scripts/ifcfg-%s" % name - - -# NOTE(dprince): added here for testability -def bridge_config_path(name): - return ifcfg_config_path(name) - - -def ivs_config_path(): - return "/etc/sysconfig/ivs" - - -def nfvswitch_config_path(): - return "/etc/sysconfig/nfvswitch" - - -def route_config_path(name): - return "/etc/sysconfig/network-scripts/route-%s" % name - - -def route6_config_path(name): - return "/etc/sysconfig/network-scripts/route6-%s" % name - - -def cleanup_pattern(): - return "/etc/sysconfig/network-scripts/ifcfg-*" - - -class IfcfgNetConfig(os_net_config.NetConfig): - """Configure network interfaces using the ifcfg format.""" - - def __init__(self, noop=False, root_dir=''): - super(IfcfgNetConfig, self).__init__(noop, root_dir) - self.interface_data = {} - self.ivsinterface_data = {} - self.nfvswitch_intiface_data = {} - self.nfvswitch_cpus = None - self.vlan_data = {} - self.route_data = {} - self.route6_data = {} - self.bridge_data = {} - self.linuxbridge_data = {} - self.linuxbond_data = {} - self.ib_interface_data = {} - self.linuxteam_data = {} - self.member_names = {} - self.renamed_interfaces = {} - self.bond_primary_ifaces = {} - logger.info('Ifcfg net config provider created.') - - def child_members(self, name): - children = set() - try: - for member in self.member_names[name]: - children.add(member) - children.update(self.child_members(member)) - except KeyError: - pass - return children - - def _add_common(self, base_opt): - - ovs_extra = [] - - data = "# This file is autogenerated by os-net-config\n" - data += "DEVICE=%s\n" % base_opt.name - data += "ONBOOT=yes\n" - data += "HOTPLUG=no\n" - data += "NM_CONTROLLED=no\n" - if not base_opt.dns_servers and not base_opt.use_dhcp: - data += "PEERDNS=no\n" - if isinstance(base_opt, objects.Vlan): - if not base_opt.ovs_port: - # vlans on OVS bridges are internal ports (no device, etc) - data += "VLAN=yes\n" - if base_opt.device: - data += "PHYSDEV=%s\n" % base_opt.device - else: - if base_opt.linux_bond_name: - data += "PHYSDEV=%s\n" % base_opt.linux_bond_name - elif isinstance(base_opt, objects.IvsInterface): - data += "TYPE=IVSIntPort\n" - elif isinstance(base_opt, objects.NfvswitchInternal): - data += "TYPE=NFVSWITCHIntPort\n" - elif isinstance(base_opt, objects.IbInterface): - data += "TYPE=Infiniband\n" - elif re.match('\w+\.\d+$', base_opt.name): - data += "VLAN=yes\n" - if base_opt.linux_bond_name: - data += "MASTER=%s\n" % base_opt.linux_bond_name - data += "SLAVE=yes\n" - if base_opt.linux_team_name: - data += "TEAM_MASTER=%s\n" % base_opt.linux_team_name - if base_opt.primary: - data += "TEAM_PORT_CONFIG='{\"prio\": 100}'\n" - if base_opt.ivs_bridge_name: - data += "DEVICETYPE=ivs\n" - data += "IVS_BRIDGE=%s\n" % base_opt.ivs_bridge_name - if base_opt.nfvswitch_bridge_name: - data += "DEVICETYPE=nfvswitch\n" - data += "NFVSWITCH_BRIDGE=%s\n" % base_opt.nfvswitch_bridge_name - if base_opt.ovs_port: - if not isinstance(base_opt, objects.LinuxTeam): - data += "DEVICETYPE=ovs\n" - if base_opt.bridge_name: - if isinstance(base_opt, objects.Vlan): - data += "TYPE=OVSIntPort\n" - data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name - data += "OVS_OPTIONS=\"tag=%s\"\n" % base_opt.vlan_id - else: - data += "TYPE=OVSPort\n" - data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name - if base_opt.linux_bridge_name: - data += "BRIDGE=%s\n" % base_opt.linux_bridge_name - if isinstance(base_opt, objects.OvsBridge): - data += "DEVICETYPE=ovs\n" - data += "TYPE=OVSBridge\n" - if base_opt.use_dhcp: - data += "OVSBOOTPROTO=dhcp\n" - if base_opt.members: - members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members - if base_opt.use_dhcp: - data += ("OVSDHCPINTERFACES=\"%s\"\n" % " ".join(members)) - if base_opt.primary_interface_name: - mac = utils.interface_mac(base_opt.primary_interface_name) - ovs_extra.append("set bridge %s other-config:hwaddr=%s" % - (base_opt.name, mac)) - if base_opt.ovs_options: - data += "OVS_OPTIONS=\"%s\"\n" % base_opt.ovs_options - ovs_extra.extend(base_opt.ovs_extra) - elif isinstance(base_opt, objects.OvsBond): - if base_opt.primary_interface_name: - primary_name = base_opt.primary_interface_name - self.bond_primary_ifaces[base_opt.name] = primary_name - data += "DEVICETYPE=ovs\n" - data += "TYPE=OVSBond\n" - if base_opt.use_dhcp: - data += "OVSBOOTPROTO=dhcp\n" - if base_opt.members: - members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members - data += ("BOND_IFACES=\"%s\"\n" % " ".join(members)) - if base_opt.ovs_options: - data += "OVS_OPTIONS=\"%s\"\n" % base_opt.ovs_options - ovs_extra.extend(base_opt.ovs_extra) - elif isinstance(base_opt, objects.LinuxBridge): - data += "TYPE=Bridge\n" - data += "DELAY=0\n" - if base_opt.use_dhcp: - data += "BOOTPROTO=dhcp\n" - if base_opt.members: - members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members - if base_opt.primary_interface_name: - primary_name = base_opt.primary_interface_name - primary_mac = utils.interface_mac(primary_name) - data += "MACADDR=\"%s\"\n" % primary_mac - elif isinstance(base_opt, objects.LinuxBond): - if base_opt.primary_interface_name: - primary_name = base_opt.primary_interface_name - primary_mac = utils.interface_mac(primary_name) - data += "MACADDR=\"%s\"\n" % primary_mac - if base_opt.use_dhcp: - data += "BOOTPROTO=dhcp\n" - if base_opt.members: - members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members - if base_opt.bonding_options: - data += "BONDING_OPTS=\"%s\"\n" % base_opt.bonding_options - elif isinstance(base_opt, objects.LinuxTeam): - if base_opt.primary_interface_name: - primary_name = base_opt.primary_interface_name - primary_mac = utils.interface_mac(primary_name) - data += "MACADDR=\"%s\"\n" % primary_mac - if base_opt.use_dhcp: - data += "BOOTPROTO=dhcp\n" - if base_opt.members: - members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members - data += "DEVICETYPE=Team\n" - if base_opt.bonding_options: - data += "TEAM_CONFIG='%s'\n" % base_opt.bonding_options - elif isinstance(base_opt, objects.OvsTunnel): - ovs_extra.extend(base_opt.ovs_extra) - data += "DEVICETYPE=ovs\n" - data += "TYPE=OVSTunnel\n" - data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name - data += "OVS_TUNNEL_TYPE=%s\n" % base_opt.tunnel_type - data += "OVS_TUNNEL_OPTIONS=\"%s\"\n" % \ - ' '.join(base_opt.ovs_options) - elif isinstance(base_opt, objects.OvsPatchPort): - ovs_extra.extend(base_opt.ovs_extra) - data += "DEVICETYPE=ovs\n" - data += "TYPE=OVSPatchPort\n" - data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name - data += "OVS_PATCH_PEER=%s\n" % base_opt.peer - else: - if base_opt.use_dhcp: - data += "BOOTPROTO=dhcp\n" - elif not base_opt.addresses: - data += "BOOTPROTO=none\n" - - if base_opt.mtu: - data += "MTU=%i\n" % base_opt.mtu - if base_opt.use_dhcpv6 or base_opt.v6_addresses(): - data += "IPV6INIT=yes\n" - if base_opt.mtu: - data += "IPV6_MTU=%i\n" % base_opt.mtu - if base_opt.use_dhcpv6: - data += "DHCPV6C=yes\n" - elif base_opt.addresses: - v4_addresses = base_opt.v4_addresses() - if v4_addresses: - data += "BOOTPROTO=static\n" - for i, address in enumerate(v4_addresses): - num = '%s' % i if i else '' - data += "IPADDR%s=%s\n" % (num, address.ip) - data += "NETMASK%s=%s\n" % (num, address.netmask) - - v6_addresses = base_opt.v6_addresses() - if v6_addresses: - first_v6 = v6_addresses[0] - data += "IPV6_AUTOCONF=no\n" - data += "IPV6ADDR=%s\n" % first_v6.ip_netmask - if len(v6_addresses) > 1: - secondaries_v6 = " ".join(map(lambda a: a.ip_netmask, - v6_addresses[1:])) - data += "IPV6ADDR_SECONDARIES=\"%s\"\n" % secondaries_v6 - - if base_opt.hwaddr: - data += "HWADDR=%s\n" % base_opt.hwaddr - if ovs_extra: - data += "OVS_EXTRA=\"%s\"\n" % " -- ".join(ovs_extra) - if not base_opt.defroute: - data += "DEFROUTE=no\n" - if base_opt.dhclient_args: - data += "DHCLIENTARGS=%s\n" % base_opt.dhclient_args - if base_opt.dns_servers: - data += "DNS1=%s\n" % base_opt.dns_servers[0] - if len(base_opt.dns_servers) == 2: - data += "DNS2=%s\n" % base_opt.dns_servers[1] - elif len(base_opt.dns_servers) > 2: - logger.warning('ifcfg format supports a max of 2 dns servers.') - return data - - def _add_routes(self, interface_name, routes=[]): - logger.info('adding custom route for interface: %s' % interface_name) - data = "" - first_line = "" - data6 = "" - first_line6 = "" - for route in routes: - if ":" not in route.next_hop: - # Route is an IPv4 route - if route.default: - first_line = "default via %s dev %s\n" % (route.next_hop, - interface_name) - else: - data += "%s via %s dev %s\n" % (route.ip_netmask, - route.next_hop, - interface_name) - else: - # Route is an IPv6 route - if route.default: - first_line6 = "default via %s dev %s\n" % (route.next_hop, - interface_name) - else: - data6 += "%s via %s dev %s\n" % (route.ip_netmask, - route.next_hop, - interface_name) - self.route_data[interface_name] = first_line + data - self.route6_data[interface_name] = first_line6 + data6 - logger.debug('route data: %s' % self.route_data[interface_name]) - logger.debug('ipv6 route data: %s' % self.route6_data[interface_name]) - - def add_interface(self, interface): - """Add an Interface object to the net config object. - - :param interface: The Interface object to add. - """ - logger.info('adding interface: %s' % interface.name) - data = self._add_common(interface) - logger.debug('interface data: %s' % data) - self.interface_data[interface.name] = data - if interface.routes: - self._add_routes(interface.name, interface.routes) - - if interface.renamed: - logger.info("Interface %s being renamed to %s" - % (interface.hwname, interface.name)) - self.renamed_interfaces[interface.hwname] = interface.name - - def add_vlan(self, vlan): - """Add a Vlan object to the net config object. - - :param vlan: The vlan object to add. - """ - logger.info('adding vlan: %s' % vlan.name) - data = self._add_common(vlan) - logger.debug('vlan data: %s' % data) - self.vlan_data[vlan.name] = data - if vlan.routes: - self._add_routes(vlan.name, vlan.routes) - - def add_ivs_interface(self, ivs_interface): - """Add a ivs_interface object to the net config object. - - :param ivs_interface: The ivs_interface object to add. - """ - logger.info('adding ivs_interface: %s' % ivs_interface.name) - data = self._add_common(ivs_interface) - logger.debug('ivs_interface data: %s' % data) - self.ivsinterface_data[ivs_interface.name] = data - if ivs_interface.routes: - self._add_routes(ivs_interface.name, ivs_interface.routes) - - def add_nfvswitch_internal(self, nfvswitch_internal): - """Add a nfvswitch_internal interface object to the net config object. - - :param nfvswitch_internal: The nfvswitch_internal object to add. - """ - iface_name = nfvswitch_internal.name - logger.info('adding nfvswitch_internal interface: %s' % iface_name) - data = self._add_common(nfvswitch_internal) - logger.debug('nfvswitch_internal interface data: %s' % data) - self.nfvswitch_intiface_data[iface_name] = data - if nfvswitch_internal.routes: - self._add_routes(iface_name, nfvswitch_internal.routes) - - def add_bridge(self, bridge): - """Add an OvsBridge object to the net config object. - - :param bridge: The OvsBridge object to add. - """ - logger.info('adding bridge: %s' % bridge.name) - data = self._add_common(bridge) - logger.debug('bridge data: %s' % data) - self.bridge_data[bridge.name] = data - if bridge.routes: - self._add_routes(bridge.name, bridge.routes) - - def add_linux_bridge(self, bridge): - """Add a LinuxBridge object to the net config object. - - :param bridge: The LinuxBridge object to add. - """ - logger.info('adding linux bridge: %s' % bridge.name) - data = self._add_common(bridge) - logger.debug('bridge data: %s' % data) - self.linuxbridge_data[bridge.name] = data - if bridge.routes: - self._add_routes(bridge.name, bridge.routes) - - def add_ivs_bridge(self, bridge): - """Add a IvsBridge object to the net config object. - - IVS can only support one virtual switch per node, - using "ivs" as its name. As long as the ivs service - is running, the ivs virtual switch will be there. - It is impossible to add multiple ivs virtual switches - per node. - :param bridge: The IvsBridge object to add. - """ - pass - - def add_nfvswitch_bridge(self, bridge): - """Add a NFVSwitchBridge object to the net config object. - - NFVSwitch can only support one virtual switch per node, - using "nfvswitch" as its name. As long as the nfvswitch service - is running, the nfvswitch virtual switch will be available. - :param bridge: The NfvswitchBridge object to add. - """ - self.nfvswitch_cpus = bridge.cpus - - def add_bond(self, bond): - """Add an OvsBond object to the net config object. - - :param bond: The OvsBond object to add. - """ - logger.info('adding bond: %s' % bond.name) - data = self._add_common(bond) - logger.debug('bond data: %s' % data) - self.interface_data[bond.name] = data - if bond.routes: - self._add_routes(bond.name, bond.routes) - - def add_linux_bond(self, bond): - """Add a LinuxBond object to the net config object. - - :param bond: The LinuxBond object to add. - """ - logger.info('adding linux bond: %s' % bond.name) - data = self._add_common(bond) - logger.debug('bond data: %s' % data) - self.linuxbond_data[bond.name] = data - if bond.routes: - self._add_routes(bond.name, bond.routes) - - def add_linux_team(self, team): - """Add a LinuxTeam object to the net config object. - - :param team: The LinuxTeam object to add. - """ - logger.info('adding linux team: %s' % team.name) - data = self._add_common(team) - logger.debug('team data: %s' % data) - self.linuxteam_data[team.name] = data - if team.routes: - self._add_routes(team.name, team.routes) - - def add_ovs_tunnel(self, tunnel): - """Add a OvsTunnel object to the net config object. - - :param tunnel: The OvsTunnel object to add. - """ - logger.info('adding ovs tunnel: %s' % tunnel.name) - data = self._add_common(tunnel) - logger.debug('ovs tunnel data: %s' % data) - self.interface_data[tunnel.name] = data - - def add_ovs_patch_port(self, ovs_patch_port): - """Add a OvsPatchPort object to the net config object. - - :param ovs_patch_port: The OvsPatchPort object to add. - """ - logger.info('adding ovs patch port: %s' % ovs_patch_port.name) - data = self._add_common(ovs_patch_port) - logger.debug('ovs patch port data: %s' % data) - self.interface_data[ovs_patch_port.name] = data - - def add_ib_interface(self, ib_interface): - """Add an InfiniBand interface object to the net config object. - - :param ib_interface: The InfiniBand interface object to add. - """ - logger.info('adding ib_interface: %s' % ib_interface.name) - data = self._add_common(ib_interface) - logger.debug('ib_interface data: %s' % data) - self.ib_interface_data[ib_interface.name] = data - if ib_interface.routes: - self._add_routes(ib_interface.name, ib_interface.routes) - - if ib_interface.renamed: - logger.info("InfiniBand interface %s being renamed to %s" - % (ib_interface.hwname, ib_interface.name)) - self.renamed_interfaces[ib_interface.hwname] = ib_interface.name - - def generate_ivs_config(self, ivs_uplinks, ivs_interfaces): - """Generate configuration content for ivs.""" - - intfs = [] - for intf in ivs_uplinks: - intfs.append(' -u ') - intfs.append(intf) - uplink_str = ''.join(intfs) - - intfs = [] - for intf in ivs_interfaces: - intfs.append(' --internal-port=') - intfs.append(intf) - intf_str = ''.join(intfs) - - data = ("DAEMON_ARGS=\"--hitless --certificate /etc/ivs " - "--inband-vlan 4092%s%s\"" - % (uplink_str, intf_str)) - return data - - def generate_nfvswitch_config(self, nfvswitch_ifaces, - nfvswitch_internal_ifaces): - """Generate configuration content for nfvswitch.""" - - cpu_str = "" - if self.nfvswitch_cpus: - cpu_str = " -c " + self.nfvswitch_cpus - - ifaces = [] - for iface in nfvswitch_ifaces: - ifaces.append(' -u ') - ifaces.append(iface) - iface_str = ''.join(ifaces) - - ifaces = [] - for iface in nfvswitch_internal_ifaces: - ifaces.append(' -m ') - ifaces.append(iface) - internal_str = ''.join(ifaces) - - data = ("SETUP_ARGS=\"%s%s%s\"" % (cpu_str, iface_str, internal_str)) - return data - - def apply(self, cleanup=False, activate=True): - """Apply the network configuration. - - :param cleanup: A boolean which indicates whether any undefined - (existing but not present in the object model) interface - should be disabled and deleted. - :param activate: A boolean which indicates if the config should - be activated by stopping/starting interfaces - NOTE: if cleanup is specified we will deactivate interfaces even - if activate is false - :returns: a dict of the format: filename/data which contains info - for each file that was changed (or would be changed if in --noop - mode). - Note the noop mode is set via the constructor noop boolean - """ - logger.info('applying network configs...') - restart_interfaces = [] - restart_vlans = [] - restart_bridges = [] - restart_linux_bonds = [] - restart_linux_teams = [] - update_files = {} - all_file_names = [] - ivs_uplinks = [] # ivs physical uplinks - ivs_interfaces = [] # ivs internal ports - nfvswitch_interfaces = [] # nfvswitch physical interfaces - nfvswitch_internal_ifaces = [] # nfvswitch internal/management ports - - for interface_name, iface_data in self.interface_data.iteritems(): - route_data = self.route_data.get(interface_name, '') - route6_data = self.route6_data.get(interface_name, '') - interface_path = self.root_dir + ifcfg_config_path(interface_name) - route_path = self.root_dir + route_config_path(interface_name) - route6_path = self.root_dir + route6_config_path(interface_name) - all_file_names.append(interface_path) - all_file_names.append(route_path) - all_file_names.append(route6_path) - if "IVS_BRIDGE" in iface_data: - ivs_uplinks.append(interface_name) - if "NFVSWITCH_BRIDGE" in iface_data: - nfvswitch_interfaces.append(interface_name) - all_file_names.append(route6_path) - if (utils.diff(interface_path, iface_data) or - utils.diff(route_path, route_data) or - utils.diff(route6_path, route6_data)): - restart_interfaces.append(interface_name) - restart_interfaces.extend(self.child_members(interface_name)) - update_files[interface_path] = iface_data - update_files[route_path] = route_data - update_files[route6_path] = route6_data - else: - logger.info('No changes required for interface: %s' % - interface_name) - - for interface_name, iface_data in self.ivsinterface_data.iteritems(): - route_data = self.route_data.get(interface_name, '') - route6_data = self.route6_data.get(interface_name, '') - interface_path = self.root_dir + ifcfg_config_path(interface_name) - route_path = self.root_dir + route_config_path(interface_name) - route6_path = self.root_dir + route6_config_path(interface_name) - all_file_names.append(interface_path) - all_file_names.append(route_path) - all_file_names.append(route6_path) - ivs_interfaces.append(interface_name) - if (utils.diff(interface_path, iface_data) or - utils.diff(route_path, route_data)): - restart_interfaces.append(interface_name) - restart_interfaces.extend(self.child_members(interface_name)) - update_files[interface_path] = iface_data - update_files[route_path] = route_data - update_files[route6_path] = route6_data - else: - logger.info('No changes required for ivs interface: %s' % - interface_name) - - for iface_name, iface_data in self.nfvswitch_intiface_data.iteritems(): - route_data = self.route_data.get(iface_name, '') - route6_data = self.route6_data.get(iface_name, '') - iface_path = self.root_dir + ifcfg_config_path(iface_name) - route_path = self.root_dir + route_config_path(iface_name) - route6_path = self.root_dir + route6_config_path(iface_name) - all_file_names.append(iface_path) - all_file_names.append(route_path) - all_file_names.append(route6_path) - nfvswitch_internal_ifaces.append(iface_name) - if (utils.diff(iface_path, iface_data) or - utils.diff(route_path, route_data)): - restart_interfaces.append(iface_name) - restart_interfaces.extend(self.child_members(iface_name)) - update_files[iface_path] = iface_data - update_files[route_path] = route_data - update_files[route6_path] = route6_data - else: - logger.info('No changes required for nfvswitch interface: %s' % - iface_name) - - for vlan_name, vlan_data in self.vlan_data.iteritems(): - route_data = self.route_data.get(vlan_name, '') - route6_data = self.route6_data.get(vlan_name, '') - vlan_path = self.root_dir + ifcfg_config_path(vlan_name) - vlan_route_path = self.root_dir + route_config_path(vlan_name) - vlan_route6_path = self.root_dir + route6_config_path(vlan_name) - all_file_names.append(vlan_path) - all_file_names.append(vlan_route_path) - all_file_names.append(vlan_route6_path) - if (utils.diff(vlan_path, vlan_data) or - utils.diff(vlan_route_path, route_data)): - restart_vlans.append(vlan_name) - restart_vlans.extend(self.child_members(vlan_name)) - update_files[vlan_path] = vlan_data - update_files[vlan_route_path] = route_data - update_files[vlan_route6_path] = route6_data - else: - logger.info('No changes required for vlan interface: %s' % - vlan_name) - - for bridge_name, bridge_data in self.bridge_data.iteritems(): - route_data = self.route_data.get(bridge_name, '') - route6_data = self.route6_data.get(bridge_name, '') - bridge_path = self.root_dir + bridge_config_path(bridge_name) - br_route_path = self.root_dir + route_config_path(bridge_name) - br_route6_path = self.root_dir + route6_config_path(bridge_name) - all_file_names.append(bridge_path) - all_file_names.append(br_route_path) - all_file_names.append(br_route6_path) - if (utils.diff(bridge_path, bridge_data) or - utils.diff(br_route_path, route_data) or - utils.diff(br_route6_path, route6_data)): - restart_bridges.append(bridge_name) - restart_interfaces.extend(self.child_members(bridge_name)) - update_files[bridge_path] = bridge_data - update_files[br_route_path] = route_data - update_files[br_route6_path] = route6_data - else: - logger.info('No changes required for bridge: %s' % bridge_name) - - for bridge_name, bridge_data in self.linuxbridge_data.iteritems(): - route_data = self.route_data.get(bridge_name, '') - route6_data = self.route6_data.get(bridge_name, '') - bridge_path = self.root_dir + bridge_config_path(bridge_name) - br_route_path = self.root_dir + route_config_path(bridge_name) - br_route6_path = self.root_dir + route6_config_path(bridge_name) - all_file_names.append(bridge_path) - all_file_names.append(br_route_path) - all_file_names.append(br_route6_path) - if (utils.diff(bridge_path, bridge_data) or - utils.diff(br_route_path, route_data) or - utils.diff(br_route6_path, route6_data)): - restart_bridges.append(bridge_name) - restart_interfaces.extend(self.child_members(bridge_name)) - update_files[bridge_path] = bridge_data - update_files[br_route_path] = route_data - update_files[br_route6_path] = route6_data - else: - logger.info('No changes required for bridge: %s' % bridge_name) - - for team_name, team_data in self.linuxteam_data.iteritems(): - route_data = self.route_data.get(team_name, '') - route6_data = self.route6_data.get(team_name, '') - team_path = self.root_dir + bridge_config_path(team_name) - team_route_path = self.root_dir + route_config_path(team_name) - team_route6_path = self.root_dir + route6_config_path(team_name) - all_file_names.append(team_path) - all_file_names.append(team_route_path) - all_file_names.append(team_route6_path) - if (utils.diff(team_path, team_data) or - utils.diff(team_route_path, route_data) or - utils.diff(team_route6_path, route6_data)): - restart_linux_teams.append(team_name) - restart_interfaces.extend(self.child_members(team_name)) - update_files[team_path] = team_data - update_files[team_route_path] = route_data - update_files[team_route6_path] = route6_data - else: - logger.info('No changes required for linux team: %s' % - team_name) - - for bond_name, bond_data in self.linuxbond_data.iteritems(): - route_data = self.route_data.get(bond_name, '') - route6_data = self.route6_data.get(bond_name, '') - bond_path = self.root_dir + bridge_config_path(bond_name) - bond_route_path = self.root_dir + route_config_path(bond_name) - bond_route6_path = self.root_dir + route6_config_path(bond_name) - all_file_names.append(bond_path) - all_file_names.append(bond_route_path) - all_file_names.append(bond_route6_path) - if (utils.diff(bond_path, bond_data) or - utils.diff(bond_route_path, route_data) or - utils.diff(bond_route6_path, route6_data)): - restart_linux_bonds.append(bond_name) - restart_interfaces.extend(self.child_members(bond_name)) - update_files[bond_path] = bond_data - update_files[bond_route_path] = route_data - update_files[bond_route6_path] = route6_data - else: - logger.info('No changes required for linux bond: %s' % - bond_name) - - # Infiniband interfaces are handled similarly to Ethernet interfaces - for interface_name, iface_data in self.ib_interface_data.iteritems(): - route_data = self.route_data.get(interface_name, '') - route6_data = self.route6_data.get(interface_name, '') - interface_path = self.root_dir + ifcfg_config_path(interface_name) - route_path = self.root_dir + route_config_path(interface_name) - route6_path = self.root_dir + route6_config_path(interface_name) - all_file_names.append(interface_path) - all_file_names.append(route_path) - all_file_names.append(route6_path) - # TODO(dsneddon) determine if InfiniBand can be used with IVS - if "IVS_BRIDGE" in iface_data: - ivs_uplinks.append(interface_name) - all_file_names.append(route6_path) - if (utils.diff(interface_path, iface_data) or - utils.diff(route_path, route_data) or - utils.diff(route6_path, route6_data)): - restart_interfaces.append(interface_name) - restart_interfaces.extend(self.child_members(interface_name)) - update_files[interface_path] = iface_data - update_files[route_path] = route_data - update_files[route6_path] = route6_data - else: - logger.info('No changes required for InfiniBand iface: %s' % - interface_name) - - if cleanup: - for ifcfg_file in glob.iglob(cleanup_pattern()): - if ifcfg_file not in all_file_names: - interface_name = ifcfg_file[len(cleanup_pattern()) - 1:] - if interface_name != 'lo': - logger.info('cleaning up interface: %s' - % interface_name) - self.ifdown(interface_name) - self.remove_config(ifcfg_file) - - if activate: - for vlan in restart_vlans: - self.ifdown(vlan) - - for interface in restart_interfaces: - self.ifdown(interface) - - for linux_bond in restart_linux_bonds: - self.ifdown(linux_bond) - - for linux_team in restart_linux_teams: - self.ifdown(linux_team) - - for bridge in restart_bridges: - self.ifdown(bridge, iftype='bridge') - - for oldname, newname in self.renamed_interfaces.iteritems(): - self.ifrename(oldname, newname) - - for location, data in update_files.iteritems(): - self.write_config(location, data) - - if ivs_uplinks or ivs_interfaces: - location = ivs_config_path() - data = self.generate_ivs_config(ivs_uplinks, ivs_interfaces) - self.write_config(location, data) - - if nfvswitch_interfaces or nfvswitch_internal_ifaces: - location = nfvswitch_config_path() - data = self.generate_nfvswitch_config(nfvswitch_interfaces, - nfvswitch_internal_ifaces) - self.write_config(location, data) - - if activate: - for linux_team in restart_linux_teams: - self.ifup(linux_team) - - for bridge in restart_bridges: - self.ifup(bridge, iftype='bridge') - - for interface in restart_interfaces: - self.ifup(interface) - - for linux_bond in restart_linux_bonds: - self.ifup(linux_bond) - - for bond in self.bond_primary_ifaces: - self.ovs_appctl('bond/set-active-slave', bond, - self.bond_primary_ifaces[bond]) - - if ivs_uplinks or ivs_interfaces: - logger.info("Attach to ivs with " - "uplinks: %s, " - "interfaces: %s" % - (ivs_uplinks, ivs_interfaces)) - for ivs_uplink in ivs_uplinks: - self.ifup(ivs_uplink) - for ivs_interface in ivs_interfaces: - self.ifup(ivs_interface) - msg = "Restart ivs" - self.execute(msg, '/usr/bin/systemctl', - 'restart', 'ivs') - - if nfvswitch_interfaces or nfvswitch_internal_ifaces: - logger.info("Attach to nfvswitch with " - "interfaces: %s, " - "internal interfaces: %s" % - (nfvswitch_interfaces, nfvswitch_internal_ifaces)) - for nfvswitch_interface in nfvswitch_interfaces: - self.ifup(nfvswitch_interface) - for nfvswitch_internal in nfvswitch_internal_ifaces: - self.ifup(nfvswitch_internal) - msg = "Restart nfvswitch" - self.execute(msg, '/usr/bin/systemctl', - 'restart', 'nfvswitch') - - for vlan in restart_vlans: - self.ifup(vlan) - - return update_files diff --git a/os_net_config/impl_iproute.py b/os_net_config/impl_iproute.py deleted file mode 100644 index ddc6a7b..0000000 --- a/os_net_config/impl_iproute.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os_net_config - - -class IprouteNetConfig(os_net_config.NetConfig): - """Configure network interfaces using iproute2.""" diff --git a/os_net_config/objects.py b/os_net_config/objects.py deleted file mode 100644 index 4a15d05..0000000 --- a/os_net_config/objects.py +++ /dev/null @@ -1,875 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import netaddr -from oslo_utils import strutils - -from os_net_config import utils - - -logger = logging.getLogger(__name__) - -_NUMBERED_NICS = None - - -class InvalidConfigException(ValueError): - pass - - -def object_from_json(json): - obj_type = json.get("type") - if obj_type == "interface": - return Interface.from_json(json) - elif obj_type == "vlan": - return Vlan.from_json(json) - elif obj_type == "ovs_bridge": - return OvsBridge.from_json(json) - elif obj_type == "ovs_bond": - return OvsBond.from_json(json) - elif obj_type == "linux_bond": - return LinuxBond.from_json(json) - elif obj_type == "team": - return LinuxTeam.from_json(json) - elif obj_type == "linux_bridge": - return LinuxBridge.from_json(json) - elif obj_type == "ivs_bridge": - return IvsBridge.from_json(json) - elif obj_type == "ivs_interface": - return IvsInterface.from_json(json) - elif obj_type == "nfvswitch_bridge": - return NfvswitchBridge.from_json(json) - elif obj_type == "nfvswitch_internal": - return NfvswitchInternal.from_json(json) - elif obj_type == "ovs_tunnel": - return OvsTunnel.from_json(json) - elif obj_type == "ovs_patch_port": - return OvsPatchPort.from_json(json) - elif obj_type == "ib_interface": - return IbInterface.from_json(json) - - -def _get_required_field(json, name, object_name): - field = json.get(name) - if not field: - msg = '%s JSON objects require \'%s\' to be configured.' \ - % (object_name, name) - raise InvalidConfigException(msg) - return field - - -def _numbered_nics(nic_mapping=None): - mapping = nic_mapping or {} - global _NUMBERED_NICS - if _NUMBERED_NICS: - return _NUMBERED_NICS - _NUMBERED_NICS = {} - count = 0 - active_nics = utils.ordered_active_nics() - for nic in active_nics: - count += 1 - nic_alias = "nic%i" % count - nic_mapped = mapping.get(nic_alias, nic) - - # The mapping is either invalid, or specifies a mac - if nic_mapped not in active_nics: - for active in active_nics: - try: - active_mac = utils.interface_mac(active) - except IOError: - continue - if nic_mapped == active_mac: - logger.debug("%s matches device %s" % (nic_mapped, active)) - nic_mapped = active - break - else: - # The mapping can't specify a non-active or non-existent nic - logger.warning('interface %s is not in an active nic (%s)' - % (nic_mapped, ', '.join(active_nics))) - continue - - # Duplicate mappings are not allowed - if nic_mapped in _NUMBERED_NICS.values(): - msg = ('interface %s already mapped, ' - 'check mapping file for duplicates' - % nic_mapped) - raise InvalidConfigException(msg) - - _NUMBERED_NICS[nic_alias] = nic_mapped - logger.info("%s mapped to: %s" % (nic_alias, nic_mapped)) - if not _NUMBERED_NICS: - logger.warning('No active nics found.') - return _NUMBERED_NICS - - -class Route(object): - """Base class for network routes.""" - - def __init__(self, next_hop, ip_netmask="", default=False): - self.next_hop = next_hop - self.ip_netmask = ip_netmask - self.default = default - - @staticmethod - def from_json(json): - next_hop = _get_required_field(json, 'next_hop', 'Route') - ip_netmask = json.get('ip_netmask', "") - default = strutils.bool_from_string(str(json.get('default', False))) - return Route(next_hop, ip_netmask, default) - - -class Address(object): - """Base class for network addresses.""" - - def __init__(self, ip_netmask): - self.ip_netmask = ip_netmask - ip_nw = netaddr.IPNetwork(self.ip_netmask) - self.ip = str(ip_nw.ip) - self.netmask = str(ip_nw.netmask) - self.prefixlen = ip_nw.prefixlen - self.version = ip_nw.version - - @staticmethod - def from_json(json): - ip_netmask = _get_required_field(json, 'ip_netmask', 'Address') - return Address(ip_netmask) - - -class _BaseOpts(object): - """Base abstraction for logical port options.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - numbered_nic_names = _numbered_nics(nic_mapping) - self.hwaddr = None - self.hwname = None - self.renamed = False - if name in numbered_nic_names: - if persist_mapping: - self.name = name - self.hwname = numbered_nic_names[name] - self.hwaddr = utils.interface_mac(self.hwname) - self.renamed = True - else: - self.name = numbered_nic_names[name] - else: - self.name = name - - self.mtu = mtu - self.use_dhcp = use_dhcp - self.use_dhcpv6 = use_dhcpv6 - self.addresses = addresses - self.routes = routes - self.primary = primary - self.defroute = defroute - self.dhclient_args = dhclient_args - self.dns_servers = dns_servers - self.bridge_name = None # internal - self.linux_bridge_name = None # internal - self.ivs_bridge_name = None # internal - self.nfvswitch_bridge_name = None # internal - self.linux_bond_name = None # internal - self.linux_team_name = None # internal - self.ovs_port = False # internal - self.primary_interface_name = None # internal - - def v4_addresses(self): - v4_addresses = [] - for addr in self.addresses: - if addr.version == 4: - v4_addresses.append(addr) - - return v4_addresses - - def v6_addresses(self): - v6_addresses = [] - for addr in self.addresses: - if addr.version == 6: - v6_addresses.append(addr) - - return v6_addresses - - @staticmethod - def base_opts_from_json(json, include_primary=True): - use_dhcp = strutils.bool_from_string(str(json.get('use_dhcp', False))) - use_dhcpv6 = strutils.bool_from_string(str(json.get('use_dhcpv6', - False))) - defroute = strutils.bool_from_string(str(json.get('defroute', - True))) - mtu = json.get('mtu', None) - dhclient_args = json.get('dhclient_args') - dns_servers = json.get('dns_servers') - primary = strutils.bool_from_string(str(json.get('primary', False))) - addresses = [] - routes = [] - - # addresses - addresses_json = json.get('addresses') - if addresses_json: - if isinstance(addresses_json, list): - for address in addresses_json: - addresses.append(Address.from_json(address)) - else: - msg = 'Addresses must be a list.' - raise InvalidConfigException(msg) - - # routes - routes_json = json.get('routes') - if routes_json: - if isinstance(routes_json, list): - for route in routes_json: - routes.append(Route.from_json(route)) - else: - msg = 'Routes must be a list.' - raise InvalidConfigException(msg) - - nic_mapping = json.get('nic_mapping') - persist_mapping = json.get('persist_mapping') - - if include_primary: - return (use_dhcp, use_dhcpv6, addresses, routes, mtu, primary, - nic_mapping, persist_mapping, defroute, dhclient_args, - dns_servers) - else: - return (use_dhcp, use_dhcpv6, addresses, routes, mtu, - nic_mapping, persist_mapping, defroute, dhclient_args, - dns_servers) - - -class Interface(_BaseOpts): - """Base class for network interfaces.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - super(Interface, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'Interface') - opts = _BaseOpts.base_opts_from_json(json) - return Interface(name, *opts) - - -class Vlan(_BaseOpts): - """Base class for VLANs. - - NOTE: the name parameter must be formated w/ vlan where - matches the vlan ID being used. Example: vlan5 - """ - - def __init__(self, device, vlan_id, use_dhcp=False, use_dhcpv6=False, - addresses=None, routes=None, mtu=None, primary=False, - nic_mapping=None, persist_mapping=False, defroute=True, - dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - name = 'vlan%i' % vlan_id - super(Vlan, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) - self.vlan_id = int(vlan_id) - - numbered_nic_names = _numbered_nics(nic_mapping) - if device in numbered_nic_names: - self.device = numbered_nic_names[device] - else: - self.device = device - - @staticmethod - def from_json(json): - # A vlan on an OVS bridge won't require a device (OVS Int Port) - device = json.get('device') - vlan_id = _get_required_field(json, 'vlan_id', 'Vlan') - opts = _BaseOpts.base_opts_from_json(json) - return Vlan(device, vlan_id, *opts) - - -class IvsInterface(_BaseOpts): - """Base class for ivs interfaces.""" - - def __init__(self, vlan_id, name='ivs', use_dhcp=False, use_dhcpv6=False, - addresses=None, routes=None, mtu=1500, primary=False, - nic_mapping=None, persist_mapping=False, defroute=True, - dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - name_vlan = '%s%i' % (name, vlan_id) - super(IvsInterface, self).__init__(name_vlan, use_dhcp, use_dhcpv6, - addresses, routes, mtu, primary, - nic_mapping, persist_mapping, - defroute, dhclient_args, - dns_servers) - self.vlan_id = int(vlan_id) - - @staticmethod - def from_json(json): - name = json.get('name') - vlan_id = _get_required_field(json, 'vlan_id', 'IvsInterface') - opts = _BaseOpts.base_opts_from_json(json) - return IvsInterface(vlan_id, name, *opts) - - -class NfvswitchInternal(_BaseOpts): - """Base class for nfvswitch internal interfaces.""" - - def __init__(self, vlan_id, name='nfvswitch', use_dhcp=False, - use_dhcpv6=False, addresses=None, routes=None, mtu=1500, - primary=False, nic_mapping=None, persist_mapping=False, - defroute=True, dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - name_vlan = '%s%i' % (name, vlan_id) - super(NfvswitchInternal, self).__init__(name_vlan, use_dhcp, - use_dhcpv6, addresses, routes, - mtu, primary, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - self.vlan_id = int(vlan_id) - - @staticmethod - def from_json(json): - name = json.get('name') - vlan_id = _get_required_field(json, 'vlan_id', 'NfvswitchInternal') - opts = _BaseOpts.base_opts_from_json(json) - return NfvswitchInternal(vlan_id, name, *opts) - - -class OvsBridge(_BaseOpts): - """Base class for OVS bridges.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, members=None, ovs_options=None, - ovs_extra=None, nic_mapping=None, persist_mapping=False, - defroute=True, dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - ovs_extra = ovs_extra or [] - dns_servers = dns_servers or [] - super(OvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, False, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - self.members = members - self.ovs_options = ovs_options - self.ovs_extra = ovs_extra - for member in self.members: - member.bridge_name = name - if not isinstance(member, OvsTunnel): - member.ovs_port = True - if member.primary: - if self.primary_interface_name: - msg = 'Only one primary interface allowed per bridge.' - raise InvalidConfigException(msg) - if member.primary_interface_name: - self.primary_interface_name = member.primary_interface_name - else: - self.primary_interface_name = member.name - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'OvsBridge') - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - ovs_options = json.get('ovs_options') - ovs_extra = json.get('ovs_extra', []) - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return OvsBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, ovs_options=ovs_options, - ovs_extra=ovs_extra, nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, dns_servers=dns_servers) - - -class LinuxBridge(_BaseOpts): - """Base class for Linux bridges.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, members=None, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - dns_servers = dns_servers or [] - super(LinuxBridge, self).__init__(name, use_dhcp, use_dhcpv6, - addresses, routes, mtu, False, - nic_mapping, persist_mapping, - defroute, dhclient_args, dns_servers) - self.members = members - for member in self.members: - member.linux_bridge_name = name - member.ovs_port = False - if member.primary: - if self.primary_interface_name: - msg = 'Only one primary interface allowed per bridge.' - raise InvalidConfigException(msg) - if member.primary_interface_name: - self.primary_interface_name = member.primary_interface_name - else: - self.primary_interface_name = member.name - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'LinuxBridge') - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return LinuxBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, - dns_servers=dns_servers) - - -class IvsBridge(_BaseOpts): - """Base class for IVS bridges. - - Indigo Virtual Switch (IVS) is a virtual switch for Linux. - It is compatible with the KVM hypervisor and leveraging the - Open vSwitch kernel module for packet forwarding. There are - three major differences between IVS and OVS: - 1. Each node can have at most one ivs, no name required. - 2. Bond is not allowed to attach to an ivs. It is the SDN - controller's job to dynamically form bonds on ivs. - 3. IP address can only be statically assigned. - """ - - def __init__(self, name='ivs', use_dhcp=False, use_dhcpv6=False, - addresses=None, routes=None, mtu=1500, members=None, - nic_mapping=None, persist_mapping=False, defroute=True, - dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - dns_servers = dns_servers or [] - super(IvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, - addresses, routes, mtu, False, - nic_mapping, persist_mapping, - defroute, dhclient_args, dns_servers) - self.members = members - for member in self.members: - if isinstance(member, OvsBond) or isinstance(member, LinuxBond): - msg = 'IVS does not support bond interfaces.' - raise InvalidConfigException(msg) - member.ivs_bridge_name = name - member.ovs_port = False - self.primary_interface_name = None # ivs doesn't use primary intf - - @staticmethod - def from_json(json): - name = 'ivs' - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return IvsBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, - dns_servers=dns_servers) - - -class NfvswitchBridge(_BaseOpts): - """Base class for NFVSwitch bridges. - - NFVSwitch is a virtual switch for Linux. - It is compatible with the KVM hypervisor and uses DPDK for packet - forwarding. - """ - - def __init__(self, name='nfvswitch', use_dhcp=False, use_dhcpv6=False, - addresses=None, routes=None, mtu=1500, members=None, - nic_mapping=None, persist_mapping=False, defroute=True, - dhclient_args=None, dns_servers=None, cpus=""): - addresses = addresses or [] - routes = routes or [] - members = members or [] - dns_servers = dns_servers or [] - super(NfvswitchBridge, self).__init__(name, use_dhcp, use_dhcpv6, - addresses, routes, mtu, False, - nic_mapping, persist_mapping, - defroute, dhclient_args, - dns_servers) - self.cpus = cpus - self.members = members - for member in self.members: - if isinstance(member, OvsBond) or isinstance(member, LinuxBond): - msg = 'NFVSwitch does not support bond interfaces.' - raise InvalidConfigException(msg) - member.nfvswitch_bridge_name = name - member.ovs_port = False - self.primary_interface_name = None - - @staticmethod - def from_json(json): - name = 'nfvswitch' - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - - # members - members = [] - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - cpus = '' - cpus_json = json.get('cpus') - if cpus_json: - if isinstance(cpus_json, basestring): - cpus = cpus_json - else: - msg = '"cpus" must be a string of numbers separated by commas.' - raise InvalidConfigException(msg) - else: - msg = 'Config "cpus" is mandatory.' - raise InvalidConfigException(msg) - - return NfvswitchBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, nic_mapping=nic_mapping, - persist_mapping=persist_mapping, - defroute=defroute, dhclient_args=dhclient_args, - dns_servers=dns_servers, cpus=cpus) - - -class LinuxTeam(_BaseOpts): - """Base class for Linux bonds using teamd.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, members=None, - bonding_options=None, nic_mapping=None, persist_mapping=False, - defroute=True, dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - dns_servers = dns_servers or [] - super(LinuxTeam, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - self.members = members - self.bonding_options = bonding_options - for member in self.members: - member.linux_team_name = name - if member.primary: - if self.primary_interface_name: - msg = 'Only one primary interface allowed per team.' - raise InvalidConfigException(msg) - if member.primary_interface_name: - self.primary_interface_name = member.primary_interface_name - else: - self.primary_interface_name = member.name - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'LinuxTeam') - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - bonding_options = json.get('bonding_options') - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return LinuxTeam(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, bonding_options=bonding_options, - nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, dns_servers=dns_servers) - - -class LinuxBond(_BaseOpts): - """Base class for Linux bonds.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, members=None, - bonding_options=None, nic_mapping=None, persist_mapping=False, - defroute=True, dhclient_args=None, dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - dns_servers = dns_servers or [] - super(LinuxBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - self.members = members - self.bonding_options = bonding_options - for member in self.members: - member.linux_bond_name = name - if member.primary: - if self.primary_interface_name: - msg = 'Only one primary interface allowed per bond.' - raise InvalidConfigException(msg) - if member.primary_interface_name: - self.primary_interface_name = member.primary_interface_name - else: - self.primary_interface_name = member.name - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'LinuxBond') - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - bonding_options = json.get('bonding_options') - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return LinuxBond(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, bonding_options=bonding_options, - nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, dns_servers=dns_servers) - - -class OvsBond(_BaseOpts): - """Base class for OVS bonds.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, members=None, - ovs_options=None, ovs_extra=None, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None): - addresses = addresses or [] - routes = routes or [] - members = members or [] - ovs_extra = ovs_extra or [] - dns_servers = dns_servers or [] - super(OvsBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) - self.members = members - self.ovs_options = ovs_options - self.ovs_extra = ovs_extra - for member in self.members: - if member.primary: - if self.primary_interface_name: - msg = 'Only one primary interface allowed per bond.' - raise InvalidConfigException(msg) - if member.primary_interface_name: - self.primary_interface_name = member.primary_interface_name - else: - self.primary_interface_name = member.name - if not self.primary_interface_name: - bond_members = list(self.members) - bond_members.sort(key=lambda x: x.name) - self.primary_interface_name = bond_members[0].name - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'OvsBond') - (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping, - persist_mapping, defroute, dhclient_args, - dns_servers) = _BaseOpts.base_opts_from_json( - json, include_primary=False) - ovs_options = json.get('ovs_options') - ovs_extra = json.get('ovs_extra', []) - members = [] - - # members - members_json = json.get('members') - if members_json: - if isinstance(members_json, list): - for member in members_json: - members.append(object_from_json(member)) - else: - msg = 'Members must be a list.' - raise InvalidConfigException(msg) - - return OvsBond(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6, - addresses=addresses, routes=routes, mtu=mtu, - members=members, ovs_options=ovs_options, - ovs_extra=ovs_extra, nic_mapping=nic_mapping, - persist_mapping=persist_mapping, defroute=defroute, - dhclient_args=dhclient_args, dns_servers=dns_servers) - - -class OvsTunnel(_BaseOpts): - """Base class for OVS Tunnels.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None, tunnel_type=None, ovs_options=None, - ovs_extra=None): - addresses = addresses or [] - routes = routes or [] - ovs_extra = ovs_extra or [] - dns_servers = dns_servers or [] - super(OvsTunnel, self).__init__(name, use_dhcp, use_dhcpv6, addresses, - routes, mtu, primary, nic_mapping, - persist_mapping, defroute, - dhclient_args, dns_servers) - self.tunnel_type = tunnel_type - self.ovs_options = ovs_options or [] - self.ovs_extra = ovs_extra or [] - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'OvsTunnel') - tunnel_type = _get_required_field(json, 'tunnel_type', 'OvsTunnel') - ovs_options = json.get('ovs_options', []) - ovs_options = ['options:%s' % opt for opt in ovs_options] - ovs_extra = json.get('ovs_extra', []) - opts = _BaseOpts.base_opts_from_json(json) - return OvsTunnel(name, *opts, tunnel_type=tunnel_type, - ovs_options=ovs_options, ovs_extra=ovs_extra) - - -class OvsPatchPort(_BaseOpts): - """Base class for OVS Patch Ports.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None, bridge_name=None, peer=None, - ovs_options=None, ovs_extra=None): - addresses = addresses or [] - routes = routes or [] - ovs_extra = ovs_extra or [] - dns_servers = dns_servers or [] - super(OvsPatchPort, self).__init__(name, use_dhcp, use_dhcpv6, - addresses, routes, mtu, primary, - nic_mapping, persist_mapping, - defroute, dhclient_args, - dns_servers) - self.bridge_name = bridge_name - self.peer = peer - self.ovs_options = ovs_options or [] - self.ovs_extra = ovs_extra or [] - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'OvsPatchPort') - bridge_name = _get_required_field(json, 'bridge_name', 'OvsPatchPort') - peer = _get_required_field(json, 'peer', 'OvsPatchPort') - ovs_options = json.get('ovs_options', []) - ovs_options = ['options:%s' % opt for opt in ovs_options] - ovs_extra = json.get('ovs_extra', []) - opts = _BaseOpts.base_opts_from_json(json) - return OvsPatchPort(name, *opts, bridge_name=bridge_name, peer=peer, - ovs_options=ovs_options, ovs_extra=ovs_extra) - - -class IbInterface(_BaseOpts): - """Base class for InfiniBand network interfaces.""" - - def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None, - routes=None, mtu=None, primary=False, nic_mapping=None, - persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None): - addresses = addresses or [] - routes = routes or [] - dns_servers = dns_servers or [] - super(IbInterface, self).__init__(name, use_dhcp, use_dhcpv6, - addresses, routes, mtu, primary, - nic_mapping, persist_mapping, - defroute, dhclient_args, dns_servers) - - @staticmethod - def from_json(json): - name = _get_required_field(json, 'name', 'IbInterface') - opts = _BaseOpts.base_opts_from_json(json) - return IbInterface(name, *opts) diff --git a/os_net_config/tests/__init__.py b/os_net_config/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/os_net_config/tests/base.py b/os_net_config/tests/base.py deleted file mode 100644 index d5adc66..0000000 --- a/os_net_config/tests/base.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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 fixtures -import stubout -import testtools - -from os_net_config import objects - -_TRUE_VALUES = ('True', 'true', '1', 'yes') - - -class TestCase(testtools.TestCase): - - """Test case base class for all unit tests.""" - stub_numbered_nics = True - - def setUp(self): - """Run before each test method to initialize test environment.""" - - super(TestCase, self).setUp() - self.stubs = stubout.StubOutForTesting() - self.stubbed_numbered_nics = {} - - def dummy_numbered_nics(nic_mapping=None): - return self.stubbed_numbered_nics - if self.stub_numbered_nics: - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) - try: - test_timeout = int(test_timeout) - except ValueError: - # If timeout value is invalid do not set a timeout. - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) - - self.useFixture(fixtures.NestedTempfile()) - self.useFixture(fixtures.TempHomeDir()) - - if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - self.log_fixture = self.useFixture(fixtures.FakeLogger()) - - def tearDown(self): - self.stubs.UnsetAll() - self.stubs.SmartUnsetAll() - super(TestCase, self).tearDown() diff --git a/os_net_config/tests/test_cli.py b/os_net_config/tests/test_cli.py deleted file mode 100644 index e598dcb..0000000 --- a/os_net_config/tests/test_cli.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os.path -import sys - -import os_net_config -from os_net_config import cli -from os_net_config import impl_ifcfg -from os_net_config.tests import base -import six - - -REALPATH = os.path.dirname(os.path.realpath(__file__)) -SAMPLE_BASE = os.path.join(REALPATH, '../../', 'etc', - 'os-net-config', 'samples') - - -class TestCli(base.TestCase): - - def run_cli(self, argstr, exitcodes=(0,)): - orig = sys.stdout - orig_stderr = sys.stderr - - sys.stdout = six.StringIO() - sys.stderr = six.StringIO() - ret = cli.main(argstr.split()) - self.assertIn(ret, exitcodes) - - stdout = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - stderr = sys.stderr.getvalue() - sys.stderr.close() - sys.stderr = orig_stderr - return (stdout, stderr) - - def test_bond_noop_output(self): - bond_yaml = os.path.join(SAMPLE_BASE, 'bond.yaml') - bond_json = os.path.join(SAMPLE_BASE, 'bond.json') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s' % bond_yaml) - self.assertEqual('', stderr) - stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s' % bond_json) - self.assertEqual('', stderr) - sanity_devices = ['DEVICE=br-ctlplane', - 'DEVICE=em2', - 'DEVICE=em1', - 'DEVICE=bond1', - 'DEVICETYPE=ovs'] - for dev in sanity_devices: - self.assertIn(dev, stdout_yaml) - self.assertEqual(stdout_yaml, stdout_json) - - def test_bridge_noop_output(self): - bridge_yaml = os.path.join(SAMPLE_BASE, 'bridge_dhcp.yaml') - bridge_json = os.path.join(SAMPLE_BASE, 'bridge_dhcp.json') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=eni --noop -c %s' % - bridge_yaml) - self.assertEqual('', stderr) - stdout_json, stderr = self.run_cli('ARG0 --provider=eni --noop -c %s' % - bridge_json) - self.assertEqual('', stderr) - sanity_devices = ['iface br-ctlplane inet dhcp', - 'iface em1', - 'ovs_type OVSBridge'] - for dev in sanity_devices: - self.assertIn(dev, stdout_yaml) - self.assertEqual(stdout_yaml, stdout_json) - - def test_vlan_noop_output(self): - vlan_yaml = os.path.join(SAMPLE_BASE, 'bridge_vlan.yaml') - vlan_json = os.path.join(SAMPLE_BASE, 'bridge_vlan.json') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop -c %s' - % vlan_yaml) - self.assertEqual('', stderr) - stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop -c %s' - % vlan_json) - self.assertEqual('', stderr) - sanity_devices = ['DEVICE=br-ctlplane', - 'DEVICE=em1', - 'DEVICE=vlan16', - 'DEVICETYPE=ovs'] - for dev in sanity_devices: - self.assertIn(dev, stdout_yaml) - self.assertEqual(stdout_yaml, stdout_json) - - def test_interface_noop_output(self): - interface_yaml = os.path.join(SAMPLE_BASE, 'interface.yaml') - interface_json = os.path.join(SAMPLE_BASE, 'interface.json') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop -c %s' - % interface_yaml) - self.assertEqual('', stderr) - stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop -c %s' - % interface_json) - self.assertEqual('', stderr) - sanity_devices = ['DEVICE=em1', - 'BOOTPROTO=static', - 'IPADDR=192.0.2.1'] - for dev in sanity_devices: - self.assertIn(dev, stdout_yaml) - self.assertEqual(stdout_yaml, stdout_json) - - def test_bridge_noop_rootfs(self): - for provider in ('ifcfg', 'eni'): - bond_yaml = os.path.join(SAMPLE_BASE, 'bridge_dhcp.yaml') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=%s --noop ' - '--root-dir=/rootfs ' - '-c %s' % (provider, bond_yaml)) - self.assertEqual('', stderr) - self.assertIn('File: /rootfs/', stdout_yaml) - - def test_interface_noop_detailed_exit_codes(self): - interface_yaml = os.path.join(SAMPLE_BASE, 'interface.yaml') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s --detailed-exit-codes' - % interface_yaml, exitcodes=(2,)) - - def test_interface_noop_detailed_exit_codes_no_changes(self): - interface_yaml = os.path.join(SAMPLE_BASE, 'interface.yaml') - - class TestImpl(os_net_config.NetConfig): - - def add_interface(self, interface): - pass - - def apply(self, cleanup=False, activate=True): - # this fake implementation returns no changes - return {} - - self.stubs.Set(impl_ifcfg, 'IfcfgNetConfig', TestImpl) - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s --detailed-exit-codes' - % interface_yaml, exitcodes=(0,)) - - def test_nfvswitch_noop_output(self): - nfvswitch_yaml = os.path.join(SAMPLE_BASE, 'nfvswitch.yaml') - nfvswitch_json = os.path.join(SAMPLE_BASE, 'nfvswitch.json') - stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s' % nfvswitch_yaml) - self.assertEqual('', stderr) - stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop ' - '-c %s' % nfvswitch_json) - self.assertEqual('', stderr) - sanity_devices = ['DEVICE=nic2', - 'DEVICE=nic3', - 'DEVICE=api201', - 'DEVICE=storage202', - 'DEVICETYPE=nfvswitch'] - for dev in sanity_devices: - self.assertIn(dev, stdout_yaml) - self.assertEqual(stdout_yaml, stdout_json) diff --git a/os_net_config/tests/test_impl_eni.py b/os_net_config/tests/test_impl_eni.py deleted file mode 100644 index 7f909ff..0000000 --- a/os_net_config/tests/test_impl_eni.py +++ /dev/null @@ -1,297 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import tempfile - -from oslo_concurrency import processutils - -from os_net_config import impl_eni -from os_net_config import objects -from os_net_config.tests import base -from os_net_config import utils - -_AUTO = "auto eth0\n" - -_v4_IFACE_NO_IP = _AUTO + "iface eth0 inet manual\n" - -_V4_IFACE_STATIC_IP = _AUTO + """iface eth0 inet static - address 192.168.1.2 - netmask 255.255.255.0 -""" - -_V4_IFACE_STATIC_IP_MULTIPLE = (_V4_IFACE_STATIC_IP + _AUTO + - """iface eth0 inet static - address 10.0.0.2 - netmask 255.0.0.0 -""") - -_V6_IFACE_STATIC_IP = _AUTO + """iface eth0 inet6 static - address fe80::2677:3ff:fe7d:4c - netmask 128 -""" - -_V6_IFACE_STATIC_IP_MULTIPLE = (_V6_IFACE_STATIC_IP + _AUTO + - """iface eth0 inet6 static - address 2001:abcd::2 - netmask 64 -""") - -_IFACE_DHCP = _AUTO + "iface eth0 inet dhcp\n" - -_OVS_PORT_BASE = _AUTO + "allow-br0 eth0\n" - -_OVS_PORT_IFACE = _OVS_PORT_BASE + """iface eth0 inet manual - ovs_bridge br0 - ovs_type OVSPort -""" - -_OVS_BRIDGE_DHCP = """auto br0 -allow-ovs br0 -iface br0 inet dhcp - ovs_type OVSBridge - ovs_ports eth0 - pre-up ip addr flush dev eth0 -""" - -_OVS_BRIDGE_DHCP_PRIMARY_INTERFACE = _OVS_BRIDGE_DHCP + \ - " ovs_extra set bridge br0 other-config:hwaddr=a1:b2:c3:d4:e5\n" - - -_OVS_BRIDGE_DHCP_OVS_EXTRA = _OVS_BRIDGE_DHCP + \ - " ovs_extra set bridge br0 other-config:hwaddr=a1:b2:c3:d4:e5" + \ - " -- br-set-external-id br-ctlplane bridge-id br-ctlplane\n" - - -_VLAN_NO_IP = """auto vlan5 -iface vlan5 inet manual - vlan-raw-device eth0 -""" - -_VLAN_OVS_PORT = """auto vlan5 -allow-br0 vlan5 -iface vlan5 inet manual - ovs_bridge br0 - ovs_type OVSIntPort - ovs_options tag=5 -""" - -_RTS = """up route add -net 172.19.0.0 netmask 255.255.255.0 gw 192.168.1.1 -down route del -net 172.19.0.0 netmask 255.255.255.0 gw 192.168.1.1 -""" - - -class TestENINetConfig(base.TestCase): - - def setUp(self): - super(TestENINetConfig, self).setUp() - - self.provider = impl_eni.ENINetConfig() - self.if_name = 'eth0' - - def tearDown(self): - super(TestENINetConfig, self).tearDown() - - def get_interface_config(self, name="eth0"): - return self.provider.interfaces[name] - - def get_route_config(self): - return self.provider.routes[self.if_name] - - def _default_interface(self, addr=[], rts=[]): - return objects.Interface(self.if_name, addresses=addr, routes=rts) - - def test_interface_no_ip(self): - interface = self._default_interface() - self.provider.add_interface(interface) - self.assertEqual(_v4_IFACE_NO_IP, self.get_interface_config()) - - def test_add_interface_with_v4(self): - v4_addr = objects.Address('192.168.1.2/24') - interface = self._default_interface([v4_addr]) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFACE_STATIC_IP, self.get_interface_config()) - - def test_add_interface_with_v4_multiple(self): - v4_addresses = [objects.Address('192.168.1.2/24'), - objects.Address('10.0.0.2/8')] - interface = self._default_interface(v4_addresses) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFACE_STATIC_IP_MULTIPLE, - self.get_interface_config()) - - def test_add_interface_with_v6(self): - v6_addr = objects.Address('fe80::2677:3ff:fe7d:4c') - interface = self._default_interface([v6_addr]) - self.provider.add_interface(interface) - self.assertEqual(_V6_IFACE_STATIC_IP, self.get_interface_config()) - - def test_add_interface_with_v6_multiple(self): - v6_addresses = [objects.Address('fe80::2677:3ff:fe7d:4c'), - objects.Address('2001:abcd::2/64')] - interface = self._default_interface(v6_addresses) - self.provider.add_interface(interface) - self.assertEqual(_V6_IFACE_STATIC_IP_MULTIPLE, - self.get_interface_config()) - - def test_add_interface_dhcp(self): - interface = self._default_interface() - interface.use_dhcp = True - self.provider.add_interface(interface) - self.assertEqual(_IFACE_DHCP, self.get_interface_config()) - - def test_add_interface_with_both_v4_and_v6(self): - v4_addr = objects.Address('192.168.1.2/24') - v6_addr = objects.Address('fe80::2677:3ff:fe7d:4c') - interface = self._default_interface([v4_addr, v6_addr]) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFACE_STATIC_IP + _V6_IFACE_STATIC_IP, - self.get_interface_config()) - - def test_add_ovs_port_interface(self): - interface = self._default_interface() - interface.ovs_port = True - interface.bridge_name = 'br0' - self.provider.add_interface(interface) - self.assertEqual(_OVS_PORT_IFACE, self.get_interface_config()) - - def test_network_with_routes(self): - route1 = objects.Route('192.168.1.1', '172.19.0.0/24') - v4_addr = objects.Address('192.168.1.2/24') - interface = self._default_interface([v4_addr], [route1]) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFACE_STATIC_IP, self.get_interface_config()) - self.assertEqual(_RTS, self.get_route_config()) - - def test_network_ovs_bridge_with_dhcp(self): - interface = self._default_interface() - bridge = objects.OvsBridge('br0', use_dhcp=True, - members=[interface]) - self.provider.add_bridge(bridge) - self.provider.add_interface(interface) - self.assertEqual(_OVS_PORT_IFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP, self.provider.bridges['br0']) - - def test_network_ovs_bridge_with_dhcp_and_primary_interface(self): - - def test_interface_mac(name): - return "a1:b2:c3:d4:e5" - self.stubs.Set(utils, 'interface_mac', test_interface_mac) - - interface = objects.Interface(self.if_name, primary=True) - bridge = objects.OvsBridge('br0', use_dhcp=True, - members=[interface]) - self.provider.add_bridge(bridge) - self.provider.add_interface(interface) - self.assertEqual(_OVS_PORT_IFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP_PRIMARY_INTERFACE, - self.provider.bridges['br0']) - - def test_network_ovs_bridge_with_dhcp_and_primary_with_ovs_extra(self): - - def test_interface_mac(name): - return "a1:b2:c3:d4:e5" - self.stubs.Set(utils, 'interface_mac', test_interface_mac) - - interface = objects.Interface(self.if_name, primary=True) - ovs_extra = "br-set-external-id br-ctlplane bridge-id br-ctlplane" - bridge = objects.OvsBridge('br0', use_dhcp=True, - members=[interface], - ovs_extra=[ovs_extra]) - self.provider.add_bridge(bridge) - self.provider.add_interface(interface) - self.assertEqual(_OVS_PORT_IFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP_OVS_EXTRA, - self.provider.bridges['br0']) - - def test_vlan(self): - vlan = objects.Vlan('eth0', 5) - self.provider.add_vlan(vlan) - self.assertEqual(_VLAN_NO_IP, self.get_interface_config('vlan5')) - - def test_vlan_mtu_1500(self): - vlan = objects.Vlan('eth0', 5, mtu=1500) - self.provider.add_vlan(vlan) - expected = _VLAN_NO_IP + ' mtu 1500\n' - self.assertEqual(expected, self.get_interface_config('vlan5')) - - def test_vlan_ovs_bridge_int_port(self): - vlan = objects.Vlan('eth0', 5) - bridge = objects.OvsBridge('br0', use_dhcp=True, - members=[vlan]) - self.provider.add_bridge(bridge) - self.provider.add_vlan(vlan) - self.assertEqual(_VLAN_OVS_PORT, self.get_interface_config('vlan5')) - - -class TestENINetConfigApply(base.TestCase): - - def setUp(self): - super(TestENINetConfigApply, self).setUp() - self.temp_config_file = tempfile.NamedTemporaryFile() - self.ifup_interface_names = [] - - def test_config_path(prefix): - return self.temp_config_file.name - self.stubs.Set(impl_eni, '_network_config_path', test_config_path) - - def test_execute(*args, **kwargs): - if args[0] == '/sbin/ifup': - self.ifup_interface_names.append(args[1]) - pass - - self.stubs.Set(processutils, 'execute', test_execute) - - self.provider = impl_eni.ENINetConfig() - - def tearDown(self): - self.temp_config_file.close() - super(TestENINetConfigApply, self).tearDown() - - def test_network_apply(self): - route = objects.Route('192.168.1.1', '172.19.0.0/24') - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('eth0', addresses=[v4_addr], - routes=[route]) - self.provider.add_interface(interface) - - self.provider.apply() - iface_data = utils.get_file_data(self.temp_config_file.name) - self.assertEqual((_V4_IFACE_STATIC_IP + _RTS), iface_data) - self.assertIn('eth0', self.ifup_interface_names) - - def test_apply_noactivate(self): - route = objects.Route('192.168.1.1', '172.19.0.0/24') - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('eth0', addresses=[v4_addr], - routes=[route]) - self.provider.add_interface(interface) - - self.provider.apply(activate=False) - iface_data = utils.get_file_data(self.temp_config_file.name) - self.assertEqual((_V4_IFACE_STATIC_IP + _RTS), iface_data) - self.assertEqual([], self.ifup_interface_names) - - def test_dhcp_ovs_bridge_network_apply(self): - interface = objects.Interface('eth0') - bridge = objects.OvsBridge('br0', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply() - iface_data = utils.get_file_data(self.temp_config_file.name) - self.assertEqual((_OVS_BRIDGE_DHCP + _OVS_PORT_IFACE), iface_data) - self.assertIn('eth0', self.ifup_interface_names) - self.assertIn('br0', self.ifup_interface_names) diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py deleted file mode 100644 index 467db65..0000000 --- a/os_net_config/tests/test_impl_ifcfg.py +++ /dev/null @@ -1,976 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os.path -import tempfile - -from oslo_concurrency import processutils - -from os_net_config import impl_ifcfg -from os_net_config import objects -from os_net_config.tests import base -from os_net_config import utils - - -_BASE_IFCFG = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -""" - -_NO_IP = _BASE_IFCFG + "BOOTPROTO=none\n" - -_V4_IFCFG = _BASE_IFCFG + """BOOTPROTO=static -IPADDR=192.168.1.2 -NETMASK=255.255.255.0 -""" - -_V4_V6_IFCFG = _BASE_IFCFG + """IPV6INIT=yes -BOOTPROTO=static -IPADDR=192.168.1.2 -NETMASK=255.255.255.0 -IPV6_AUTOCONF=no -IPV6ADDR=2001:abc:a::/64 -""" - -_IFCFG_VLAN = """# This file is autogenerated by os-net-config -DEVICE=em1.120 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -VLAN=yes -BOOTPROTO=none -""" - -_V4_IFCFG_MAPPED = _V4_IFCFG.replace('em1', 'nic1') + "HWADDR=a1:b2:c3:d4:e5\n" - - -_BASE_IB_IFCFG = """# This file is autogenerated by os-net-config -DEVICE=ib0 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -TYPE=Infiniband -""" - -_V4_IB_IFCFG = _BASE_IB_IFCFG + """BOOTPROTO=static -IPADDR=192.168.1.2 -NETMASK=255.255.255.0 -""" - -_V4_IFCFG_MULTIPLE = _V4_IFCFG + """IPADDR1=192.168.1.3 -NETMASK1=255.255.255.255 -IPADDR2=10.0.0.2 -NETMASK2=255.0.0.0 -""" - -_IB_V4_IFCFG_MULTIPLE = _V4_IB_IFCFG + """IPADDR1=192.168.1.3 -NETMASK1=255.255.255.255 -IPADDR2=10.0.0.2 -NETMASK2=255.0.0.0 -""" - -_V6_IFCFG = _BASE_IFCFG + """IPV6INIT=yes -IPV6_AUTOCONF=no -IPV6ADDR=2001:abc:a::/64 -""" - -_V6_IFCFG_MULTIPLE = (_V6_IFCFG + "IPV6ADDR_SECONDARIES=\"2001:abc:b::1/64 " + - "2001:abc:c::2/96\"\n") - -_OVS_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\nBOOTPROTO=none\n" - -_OVS_IFCFG_TUNNEL = """# This file is autogenerated by os-net-config -DEVICE=tun0 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -DEVICETYPE=ovs -TYPE=OVSTunnel -OVS_BRIDGE=br-ctlplane -OVS_TUNNEL_TYPE=gre -OVS_TUNNEL_OPTIONS="options:remote_ip=192.168.1.1" -""" - - -_OVS_BRIDGE_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\n" - -_LINUX_BRIDGE_IFCFG = _BASE_IFCFG + "BRIDGE=br-ctlplane\nBOOTPROTO=none\n" - -_ROUTES = """default via 192.168.1.1 dev em1 -172.19.0.0/24 via 192.168.1.1 dev em1 -""" - -_ROUTES_V6 = """default via 2001:db8::1 dev em1 -2001:db8:dead:beef:cafe::/56 via fd00:fd00:2000::1 dev em1 -""" - - -_OVS_INTERFACE = _BASE_IFCFG + """DEVICETYPE=ovs -TYPE=OVSPort -OVS_BRIDGE=br-ctlplane -BOOTPROTO=none -""" - -_OVS_BRIDGE_DHCP = """# This file is autogenerated by os-net-config -DEVICE=br-ctlplane -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -DEVICETYPE=ovs -TYPE=OVSBridge -OVSBOOTPROTO=dhcp -OVSDHCPINTERFACES="em1" -""" - -_LINUX_BRIDGE_DHCP = """# This file is autogenerated by os-net-config -DEVICE=br-ctlplane -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -TYPE=Bridge -DELAY=0 -BOOTPROTO=dhcp -""" - -_OVS_BRIDGE_STATIC = """# This file is autogenerated by os-net-config -DEVICE=br-ctlplane -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -DEVICETYPE=ovs -TYPE=OVSBridge -BOOTPROTO=static -IPADDR=192.168.1.2 -NETMASK=255.255.255.0 -""" - -_LINUX_BRIDGE_STATIC = """# This file is autogenerated by os-net-config -DEVICE=br-ctlplane -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -TYPE=Bridge -DELAY=0 -BOOTPROTO=static -IPADDR=192.168.1.2 -NETMASK=255.255.255.0 -""" - -_OVS_BRIDGE_DHCP_PRIMARY_INTERFACE = _OVS_BRIDGE_DHCP + \ - "OVS_EXTRA=\"set bridge br-ctlplane other-config:hwaddr=a1:b2:c3:d4:e5\"\n" - - -_OVS_BRIDGE_DHCP_OVS_EXTRA = _OVS_BRIDGE_DHCP + \ - "OVS_EXTRA=\"set bridge br-ctlplane other-config:hwaddr=a1:b2:c3:d4:e5" + \ - " -- br-set-external-id br-ctlplane bridge-id br-ctlplane\"\n" - - -_BASE_VLAN = """# This file is autogenerated by os-net-config -DEVICE=vlan5 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -VLAN=yes -PHYSDEV=em1 -""" - -# vlans on an OVS bridge do not set VLAN=yes or PHYSDEV -_BASE_VLAN_OVS = """# This file is autogenerated by os-net-config -DEVICE=vlan5 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -""" - -_VLAN_NO_IP = _BASE_VLAN + "BOOTPROTO=none\n" - - -_VLAN_OVS = _BASE_VLAN_OVS + "DEVICETYPE=ovs\nBOOTPROTO=none\n" - - -_VLAN_OVS_BRIDGE = _BASE_VLAN_OVS + """DEVICETYPE=ovs -TYPE=OVSIntPort -OVS_BRIDGE=br-ctlplane -OVS_OPTIONS="tag=5" -BOOTPROTO=none -""" - -_VLAN_LINUX_BRIDGE = _BASE_VLAN_OVS + """VLAN=yes -PHYSDEV=em1 -BRIDGE=br-ctlplane -BOOTPROTO=none -""" - -_OVS_BOND_DHCP = """# This file is autogenerated by os-net-config -DEVICE=bond0 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -DEVICETYPE=ovs -TYPE=OVSBond -OVSBOOTPROTO=dhcp -BOND_IFACES="em1 em2" -""" - -_LINUX_BOND_DHCP = """# This file is autogenerated by os-net-config -DEVICE=bond0 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -BOOTPROTO=dhcp -""" - - -_LINUX_TEAM_DHCP = """# This file is autogenerated by os-net-config -DEVICE=team0 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -BOOTPROTO=dhcp -DEVICETYPE=Team -""" - - -_LINUX_BOND_INTERFACE = _BASE_IFCFG + """MASTER=bond0 -SLAVE=yes -BOOTPROTO=none -""" - -_LINUX_TEAM_INTERFACE = _BASE_IFCFG + """TEAM_MASTER=team0 -BOOTPROTO=none -""" - -_IVS_UPLINK = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -DEVICETYPE=ivs -IVS_BRIDGE=ivs -BOOTPROTO=none -""" - -_IVS_INTERFACE = """# This file is autogenerated by os-net-config -DEVICE=storage5 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -TYPE=IVSIntPort -DEVICETYPE=ivs -IVS_BRIDGE=ivs -MTU=1500 -BOOTPROTO=static -IPADDR=172.16.2.7 -NETMASK=255.255.255.0 -""" - -_IVS_CONFIG = ('DAEMON_ARGS=\"--hitless --certificate /etc/ivs ' - '--inband-vlan 4092 -u em1 --internal-port=storage5\"') - -_NFVSWITCH_INTERFACE = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -DEVICETYPE=nfvswitch -NFVSWITCH_BRIDGE=nfvswitch -BOOTPROTO=none -""" - -_NFVSWITCH_INTERNAL = """# This file is autogenerated by os-net-config -DEVICE=storage5 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -TYPE=NFVSWITCHIntPort -DEVICETYPE=nfvswitch -NFVSWITCH_BRIDGE=nfvswitch -MTU=1500 -BOOTPROTO=static -IPADDR=172.16.2.7 -NETMASK=255.255.255.0 -""" - -_NFVSWITCH_CONFIG = ('SETUP_ARGS=\" -c 2,3,4,5 -u em1 -m storage5\"') - -_OVS_IFCFG_PATCH_PORT = """# This file is autogenerated by os-net-config -DEVICE=br-pub-patch -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -DEVICETYPE=ovs -TYPE=OVSPatchPort -OVS_BRIDGE=br-ex -OVS_PATCH_PEER=br-ex-patch -""" - -_LINUX_TEAM_PRIMARY_IFACE = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -TEAM_MASTER=team1 -TEAM_PORT_CONFIG='{"prio": 100}' -BOOTPROTO=none -""" - - -class TestIfcfgNetConfig(base.TestCase): - - def setUp(self): - super(TestIfcfgNetConfig, self).setUp() - - self.provider = impl_ifcfg.IfcfgNetConfig() - - def tearDown(self): - super(TestIfcfgNetConfig, self).tearDown() - - def get_interface_config(self, name='em1'): - return self.provider.interface_data[name] - - def get_vlan_config(self, name='vlan1'): - return self.provider.vlan_data[name] - - def get_linux_bond_config(self, name='bond0'): - return self.provider.linuxbond_data[name] - - def get_linux_team_config(self, name='team0'): - return self.provider.linuxteam_data[name] - - def get_route_config(self, name='em1'): - return self.provider.route_data.get(name, '') - - def get_route6_config(self, name='em1'): - return self.provider.route6_data.get(name, '') - - def test_add_base_interface(self): - interface = objects.Interface('em1') - self.provider.add_interface(interface) - self.assertEqual(_NO_IP, self.get_interface_config()) - - def test_add_base_interface_vlan(self): - interface = objects.Interface('em1.120') - self.provider.add_interface(interface) - self.assertEqual(_IFCFG_VLAN, self.get_interface_config('em1.120')) - - def test_add_ovs_interface(self): - interface = objects.Interface('em1') - interface.ovs_port = True - self.provider.add_interface(interface) - self.assertEqual(_OVS_IFCFG, self.get_interface_config()) - - def test_add_ovs_tunnel(self): - interface = objects.OvsTunnel('tun0') - interface.type = 'ovs_tunnel' - interface.tunnel_type = 'gre' - interface.ovs_options = ['options:remote_ip=192.168.1.1'] - interface.bridge_name = 'br-ctlplane' - self.provider.add_interface(interface) - self.assertEqual(_OVS_IFCFG_TUNNEL, self.get_interface_config('tun0')) - - def test_add_ovs_patch_port(self): - patch_port = objects.OvsPatchPort("br-pub-patch") - patch_port.type = 'ovs_patch_port' - patch_port.bridge_name = 'br-ex' - patch_port.peer = 'br-ex-patch' - self.provider.add_interface(patch_port) - self.assertEqual(_OVS_IFCFG_PATCH_PORT, - self.get_interface_config('br-pub-patch')) - - def test_add_interface_with_v4(self): - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('em1', addresses=[v4_addr]) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFCFG, self.get_interface_config()) - self.assertEqual('', self.get_route_config()) - - def test_add_interface_with_v4_multiple(self): - addresses = [objects.Address('192.168.1.2/24'), - objects.Address('192.168.1.3/32'), - objects.Address('10.0.0.2/8')] - interface = objects.Interface('em1', addresses=addresses) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFCFG_MULTIPLE, self.get_interface_config()) - self.assertEqual('', self.get_route_config()) - - def test_add_interface_map_persisted(self): - def test_interface_mac(name): - macs = {'em1': 'a1:b2:c3:d4:e5'} - return macs[name] - self.stubs.Set(utils, 'interface_mac', test_interface_mac) - - nic_mapping = {'nic1': 'em1'} - self.stubbed_numbered_nics = nic_mapping - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('nic1', addresses=[v4_addr], - nic_mapping=nic_mapping, - persist_mapping=True) - self.assertEqual('a1:b2:c3:d4:e5', interface.hwaddr) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFCFG_MAPPED, self.get_interface_config('nic1')) - self.assertEqual('', self.get_route_config('nic1')) - - def test_add_interface_with_v6(self): - v6_addr = objects.Address('2001:abc:a::/64') - interface = objects.Interface('em1', addresses=[v6_addr]) - self.provider.add_interface(interface) - self.assertEqual(_V6_IFCFG, self.get_interface_config()) - - def test_add_interface_with_v6_multiple(self): - addresses = [objects.Address('2001:abc:a::/64'), - objects.Address('2001:abc:b::1/64'), - objects.Address('2001:abc:c::2/96')] - interface = objects.Interface('em1', addresses=addresses) - self.provider.add_interface(interface) - self.assertEqual(_V6_IFCFG_MULTIPLE, self.get_interface_config()) - - def test_network_with_routes(self): - route1 = objects.Route('192.168.1.1', default=True) - route2 = objects.Route('192.168.1.1', '172.19.0.0/24') - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('em1', addresses=[v4_addr], - routes=[route1, route2]) - self.provider.add_interface(interface) - self.assertEqual(_V4_IFCFG, self.get_interface_config()) - self.assertEqual(_ROUTES, self.get_route_config()) - - def test_network_with_ipv6_routes(self): - route1 = objects.Route('192.168.1.1', default=True) - route2 = objects.Route('192.168.1.1', '172.19.0.0/24') - route3 = objects.Route('2001:db8::1', default=True) - route4 = objects.Route('fd00:fd00:2000::1', - '2001:db8:dead:beef:cafe::/56') - v4_addr = objects.Address('192.168.1.2/24') - v6_addr = objects.Address('2001:abc:a::/64') - interface = objects.Interface('em1', addresses=[v4_addr, v6_addr], - routes=[route1, route2, route3, route4]) - self.provider.add_interface(interface) - self.assertEqual(_V4_V6_IFCFG, self.get_interface_config()) - self.assertEqual(_ROUTES_V6, self.get_route6_config()) - - def test_network_ovs_bridge_with_dhcp(self): - interface = objects.Interface('em1') - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.assertEqual(_OVS_INTERFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP, - self.provider.bridge_data['br-ctlplane']) - - def test_network_linux_bridge_with_dhcp(self): - interface = objects.Interface('em1') - bridge = objects.LinuxBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_linux_bridge(bridge) - self.provider.add_interface(interface) - self.assertEqual(_LINUX_BRIDGE_IFCFG, self.get_interface_config()) - self.assertEqual(_LINUX_BRIDGE_DHCP, - self.provider.linuxbridge_data['br-ctlplane']) - - def test_network_ovs_bridge_static(self): - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('em1') - bridge = objects.OvsBridge('br-ctlplane', members=[interface], - addresses=[v4_addr]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.assertEqual(_OVS_INTERFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_STATIC, - self.provider.bridge_data['br-ctlplane']) - - def test_network_ovs_bridge_with_tunnel(self): - interface = objects.OvsTunnel('tun0') - interface.type = 'ovs_tunnel' - interface.tunnel_type = 'gre' - interface.ovs_options = ['options:remote_ip=192.168.1.1'] - interface.bridge_name = 'br-ctlplane' - self.provider.add_interface(interface) - v4_addr = objects.Address('192.168.1.2/24') - bridge = objects.OvsBridge('br-ctlplane', members=[interface], - addresses=[v4_addr]) - self.provider.add_bridge(bridge) - self.provider.add_interface(interface) - self.assertEqual(_OVS_IFCFG_TUNNEL, self.get_interface_config('tun0')) - self.assertEqual(_OVS_BRIDGE_STATIC, - self.provider.bridge_data['br-ctlplane']) - - def test_network_linux_bridge_static(self): - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('em1') - bridge = objects.LinuxBridge('br-ctlplane', members=[interface], - addresses=[v4_addr]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.assertEqual(_LINUX_BRIDGE_IFCFG, self.get_interface_config()) - self.assertEqual(_LINUX_BRIDGE_STATIC, - self.provider.bridge_data['br-ctlplane']) - - def test_network_ovs_bridge_with_dhcp_primary_interface(self): - def test_interface_mac(name): - return "a1:b2:c3:d4:e5" - self.stubs.Set(utils, 'interface_mac', test_interface_mac) - - interface = objects.Interface('em1', primary=True) - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.assertEqual(_OVS_INTERFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP_PRIMARY_INTERFACE, - self.provider.bridge_data['br-ctlplane']) - - def test_network_ovs_bridge_with_dhcp_primary_interface_with_extra(self): - def test_interface_mac(name): - return "a1:b2:c3:d4:e5" - self.stubs.Set(utils, 'interface_mac', test_interface_mac) - - interface = objects.Interface('em1', primary=True) - ovs_extra = "br-set-external-id br-ctlplane bridge-id br-ctlplane" - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface], - ovs_extra=[ovs_extra]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.assertEqual(_OVS_INTERFACE, self.get_interface_config()) - self.assertEqual(_OVS_BRIDGE_DHCP_OVS_EXTRA, - self.provider.bridge_data['br-ctlplane']) - - def test_network_ivs_with_uplink_and_interface(self): - interface = objects.Interface('em1') - v4_addr = objects.Address('172.16.2.7/24') - ivs_interface = objects.IvsInterface(vlan_id=5, - name='storage', - addresses=[v4_addr]) - bridge = objects.IvsBridge(members=[interface, ivs_interface]) - self.provider.add_interface(interface) - self.provider.add_ivs_interface(ivs_interface) - self.provider.add_bridge(bridge) - self.assertEqual(_IVS_UPLINK, self.get_interface_config()) - self.assertEqual(_IVS_INTERFACE, - self.provider.ivsinterface_data[ivs_interface.name]) - data = self.provider.generate_ivs_config(['em1'], ['storage5']) - self.assertEqual(_IVS_CONFIG, data) - - def test_network_nfvswitch_with_interfaces_and_internal_interfaces(self): - interface = objects.Interface('em1') - v4_addr = objects.Address('172.16.2.7/24') - nfvswitch_internal = objects.NfvswitchInternal(vlan_id=5, - name='storage', - addresses=[v4_addr]) - iface_name = nfvswitch_internal.name - bridge = objects.NfvswitchBridge(members=[interface, - nfvswitch_internal], - cpus="2,3,4,5") - self.provider.add_interface(interface) - self.provider.add_nfvswitch_internal(nfvswitch_internal) - self.provider.add_nfvswitch_bridge(bridge) - self.assertEqual(_NFVSWITCH_INTERFACE, self.get_interface_config()) - self.assertEqual(_NFVSWITCH_INTERNAL, - self.provider.nfvswitch_intiface_data[iface_name]) - data = self.provider.generate_nfvswitch_config(['em1'], ['storage5']) - self.assertEqual(_NFVSWITCH_CONFIG, data) - - def test_add_ib_interface_with_v4_multiple(self): - addresses = [objects.Address('192.168.1.2/24'), - objects.Address('192.168.1.3/32'), - objects.Address('10.0.0.2/8')] - ib_interface = objects.IbInterface('ib0', addresses=addresses) - self.provider.add_interface(ib_interface) - self.assertEqual(_IB_V4_IFCFG_MULTIPLE, - self.get_interface_config('ib0')) - self.assertEqual('', self.get_route_config()) - - def test_add_vlan(self): - vlan = objects.Vlan('em1', 5) - self.provider.add_vlan(vlan) - self.assertEqual(_VLAN_NO_IP, self.get_vlan_config('vlan5')) - - def test_add_vlan_ovs(self): - vlan = objects.Vlan('em1', 5) - vlan.ovs_port = True - self.provider.add_vlan(vlan) - self.assertEqual(_VLAN_OVS, self.get_vlan_config('vlan5')) - - def test_add_vlan_mtu_1500(self): - vlan = objects.Vlan('em1', 5, mtu=1500) - self.provider.add_vlan(vlan) - expected = _VLAN_NO_IP + 'MTU=1500\n' - self.assertEqual(expected, self.get_vlan_config('vlan5')) - - def test_add_ovs_bridge_with_vlan(self): - vlan = objects.Vlan('em1', 5) - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[vlan]) - self.provider.add_vlan(vlan) - self.provider.add_bridge(bridge) - self.assertEqual(_VLAN_OVS_BRIDGE, self.get_vlan_config('vlan5')) - - def test_add_linux_bridge_with_vlan(self): - vlan = objects.Vlan('em1', 5) - bridge = objects.LinuxBridge('br-ctlplane', use_dhcp=True, - members=[vlan]) - self.provider.add_vlan(vlan) - self.provider.add_bridge(bridge) - self.assertEqual(_VLAN_LINUX_BRIDGE, self.get_vlan_config('vlan5')) - - def test_ovs_bond(self): - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2') - bond = objects.OvsBond('bond0', use_dhcp=True, - members=[interface1, interface2]) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.provider.add_bond(bond) - self.assertEqual(_NO_IP, self.get_interface_config('em1')) - - em2_config = """# This file is autogenerated by os-net-config -DEVICE=em2 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -BOOTPROTO=none -""" - self.assertEqual(em2_config, self.get_interface_config('em2')) - self.assertEqual(_OVS_BOND_DHCP, - self.get_interface_config('bond0')) - - def test_linux_bond(self): - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2') - bond = objects.LinuxBond('bond0', use_dhcp=True, - members=[interface1, interface2]) - self.provider.add_linux_bond(bond) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.assertEqual(_LINUX_BOND_DHCP, - self.get_linux_bond_config('bond0')) - self.assertEqual(_LINUX_BOND_INTERFACE, - self.get_interface_config('em1')) - - def test_linux_team(self): - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2') - team = objects.LinuxTeam('team0', use_dhcp=True, - members=[interface1, interface2]) - self.provider.add_linux_team(team) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.assertEqual(_LINUX_TEAM_DHCP, - self.get_linux_team_config('team0')) - self.assertEqual(_LINUX_TEAM_INTERFACE, - self.get_interface_config('em1')) - - def test_interface_defroute(self): - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2', defroute=False) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - em1_config = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -BOOTPROTO=none -""" - em2_config = """# This file is autogenerated by os-net-config -DEVICE=em2 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -BOOTPROTO=none -DEFROUTE=no -""" - self.assertEqual(em1_config, self.get_interface_config('em1')) - self.assertEqual(em2_config, self.get_interface_config('em2')) - - def test_interface_dhclient_opts(self): - interface1 = objects.Interface('em1', dhclient_args='--foobar') - self.provider.add_interface(interface1) - em1_config = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -PEERDNS=no -BOOTPROTO=none -DHCLIENTARGS=--foobar -""" - self.assertEqual(em1_config, self.get_interface_config('em1')) - - def test_interface_single_dns_server(self): - interface1 = objects.Interface('em1', dns_servers=['1.2.3.4']) - self.provider.add_interface(interface1) - em1_config = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -BOOTPROTO=none -DNS1=1.2.3.4 -""" - self.assertEqual(em1_config, self.get_interface_config('em1')) - - def test_interface_dns_servers(self): - interface1 = objects.Interface('em1', dns_servers=['1.2.3.4', - '5.6.7.8']) - self.provider.add_interface(interface1) - em1_config = """# This file is autogenerated by os-net-config -DEVICE=em1 -ONBOOT=yes -HOTPLUG=no -NM_CONTROLLED=no -BOOTPROTO=none -DNS1=1.2.3.4 -DNS2=5.6.7.8 -""" - self.assertEqual(em1_config, self.get_interface_config('em1')) - - -class TestIfcfgNetConfigApply(base.TestCase): - - def setUp(self): - super(TestIfcfgNetConfigApply, self).setUp() - self.temp_ifcfg_file = tempfile.NamedTemporaryFile() - self.temp_route_file = tempfile.NamedTemporaryFile() - self.temp_route6_file = tempfile.NamedTemporaryFile() - self.temp_bridge_file = tempfile.NamedTemporaryFile() - self.temp_cleanup_file = tempfile.NamedTemporaryFile(delete=False) - self.ifup_interface_names = [] - self.ovs_appctl_cmds = [] - - def test_ifcfg_path(name): - return self.temp_ifcfg_file.name - self.stubs.Set(impl_ifcfg, 'ifcfg_config_path', test_ifcfg_path) - - def test_routes_path(name): - return self.temp_route_file.name - self.stubs.Set(impl_ifcfg, 'route_config_path', test_routes_path) - - def test_routes6_path(name): - return self.temp_route6_file.name - self.stubs.Set(impl_ifcfg, 'route6_config_path', test_routes6_path) - - def test_bridge_path(name): - return self.temp_bridge_file.name - self.stubs.Set(impl_ifcfg, 'bridge_config_path', test_bridge_path) - - def test_cleanup_pattern(): - return self.temp_cleanup_file.name - self.stubs.Set(impl_ifcfg, 'cleanup_pattern', test_cleanup_pattern) - - def test_execute(*args, **kwargs): - if args[0] == '/sbin/ifup': - self.ifup_interface_names.append(args[1]) - elif args[0] == '/bin/ovs-appctl': - self.ovs_appctl_cmds.append(' '.join(args)) - pass - self.stubs.Set(processutils, 'execute', test_execute) - - self.provider = impl_ifcfg.IfcfgNetConfig() - - def tearDown(self): - self.temp_ifcfg_file.close() - self.temp_route_file.close() - self.temp_route6_file.close() - self.temp_bridge_file.close() - if os.path.exists(self.temp_cleanup_file.name): - self.temp_cleanup_file.close() - super(TestIfcfgNetConfigApply, self).tearDown() - - def test_network_apply(self): - route1 = objects.Route('192.168.1.1', default=True) - route2 = objects.Route('192.168.1.1', '172.19.0.0/24') - v4_addr = objects.Address('192.168.1.2/24') - interface = objects.Interface('em1', addresses=[v4_addr], - routes=[route1, route2]) - self.provider.add_interface(interface) - - self.provider.apply() - - ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name) - self.assertEqual(_V4_IFCFG, ifcfg_data) - route_data = utils.get_file_data(self.temp_route_file.name) - self.assertEqual(_ROUTES, route_data) - - def test_dhcp_ovs_bridge_network_apply(self): - interface = objects.Interface('em1') - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply() - - ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name) - self.assertEqual(_OVS_INTERFACE, ifcfg_data) - bridge_data = utils.get_file_data(self.temp_bridge_file.name) - self.assertEqual(_OVS_BRIDGE_DHCP, bridge_data) - route_data = utils.get_file_data(self.temp_route_file.name) - self.assertEqual("", route_data) - - def test_apply_noactivate(self): - interface = objects.Interface('em1') - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply(activate=False) - self.assertEqual([], self.ifup_interface_names) - - def test_bond_active_slave(self): - # setup and apply a bond - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2', primary=True) - bond = objects.OvsBond('bond1', use_dhcp=True, - members=[interface1, interface2]) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.provider.add_bond(bond) - self.provider.apply() - ovs_appctl_cmds = '/bin/ovs-appctl bond/set-active-slave bond1 em2' - self.assertIn(ovs_appctl_cmds, self.ovs_appctl_cmds) - - def test_bond_active_ordering(self): - # setup and apply a bond - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2') - bond = objects.OvsBond('bond1', use_dhcp=True, - members=[interface1, interface2]) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.provider.add_bond(bond) - self.provider.apply() - ovs_appctl_cmds = '/bin/ovs-appctl bond/set-active-slave bond1 em1' - self.assertIn(ovs_appctl_cmds, self.ovs_appctl_cmds) - - def test_restart_children_on_change(self): - # setup and apply a bridge - interface = objects.Interface('em1') - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply() - self.assertIn('em1', self.ifup_interface_names) - self.assertIn('br-ctlplane', self.ifup_interface_names) - - # changing the bridge should restart the interface too - self.ifup_interface_names = [] - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=False, - members=[interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply() - self.assertIn('em1', self.ifup_interface_names) - - # test infiniband interfaces act as proper bridge members - ib_interface = objects.IbInterface('ib0') - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[ib_interface]) - self.provider.add_interface(ib_interface) - self.provider.add_bridge(bridge) - self.provider.apply() - self.assertIn('ib0', self.ifup_interface_names) - self.assertIn('br-ctlplane', self.ifup_interface_names) - - # changing the bridge should restart the interface too - self.ifup_interface_names = [] - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=False, - members=[ib_interface]) - self.provider.add_interface(interface) - self.provider.add_bridge(bridge) - self.provider.apply() - self.assertIn('ib0', self.ifup_interface_names) - - # setup and apply a bond on a bridge - self.ifup_interface_names = [] - interface1 = objects.Interface('em1') - interface2 = objects.Interface('em2') - bond = objects.OvsBond('bond0', - members=[interface1, interface2]) - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True, - members=[bond]) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.provider.add_bond(bond) - self.provider.add_bridge(bridge) - self.provider.apply() - - # changing the bridge should restart everything - self.ifup_interface_names = [] - bridge = objects.OvsBridge('br-ctlplane', use_dhcp=False, - members=[bond]) - self.provider.add_interface(interface1) - self.provider.add_interface(interface2) - self.provider.add_bond(bond) - self.provider.add_bridge(bridge) - self.provider.apply() - self.assertIn('br-ctlplane', self.ifup_interface_names) - self.assertIn('bond0', self.ifup_interface_names) - self.assertIn('em1', self.ifup_interface_names) - self.assertIn('em2', self.ifup_interface_names) - - def test_restart_interface_counts(self): - interface = objects.Interface('em1') - self.provider.add_interface(interface) - interface2 = objects.Interface('em2') - self.provider.add_interface(interface2) - self.provider.apply() - self.assertEqual(1, self.ifup_interface_names.count("em1")) - self.assertEqual(1, self.ifup_interface_names.count("em2")) - - def test_vlan_apply(self): - vlan = objects.Vlan('em1', 5) - self.provider.add_vlan(vlan) - self.provider.apply() - - ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name) - self.assertEqual(_VLAN_NO_IP, ifcfg_data) - - def test_cleanup(self): - self.provider.apply(cleanup=True) - self.assertTrue(not os.path.exists(self.temp_cleanup_file.name)) - - def test_cleanup_not_loopback(self): - tmp_lo_file = '%s-lo' % self.temp_cleanup_file.name - utils.write_config(tmp_lo_file, 'foo') - - def test_cleanup_pattern(): - return '%s-*' % self.temp_cleanup_file.name - self.stubs.Set(impl_ifcfg, 'cleanup_pattern', test_cleanup_pattern) - - self.provider.apply(cleanup=True) - self.assertTrue(os.path.exists(tmp_lo_file)) - os.remove(tmp_lo_file) diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py deleted file mode 100644 index bbff1f3..0000000 --- a/os_net_config/tests/test_objects.py +++ /dev/null @@ -1,819 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import six - -from os_net_config import objects -from os_net_config.tests import base -from os_net_config import utils - - -class TestRoute(base.TestCase): - - def test_from_json(self): - data = '{"next_hop": "172.19.0.1", "ip_netmask": "172.19.0.0/24"}' - route = objects.Route.from_json(json.loads(data)) - self.assertEqual("172.19.0.1", route.next_hop) - self.assertEqual("172.19.0.0/24", route.ip_netmask) - self.assertFalse(route.default) - - def test_from_json_default_route(self): - data = '{"next_hop": "172.19.0.1", "ip_netmask": "172.19.0.0/24", ' \ - '"default": true}' - route = objects.Route.from_json(json.loads(data)) - self.assertEqual("172.19.0.1", route.next_hop) - self.assertEqual("172.19.0.0/24", route.ip_netmask) - self.assertTrue(route.default) - - data = '{"next_hop": "172.19.0.1", "ip_netmask": "172.19.0.0/24", ' \ - '"default": "true"}' - route = objects.Route.from_json(json.loads(data)) - self.assertEqual("172.19.0.1", route.next_hop) - self.assertEqual("172.19.0.0/24", route.ip_netmask) - self.assertTrue(route.default) - - -class TestAddress(base.TestCase): - - def test_ipv4_address(self): - address = objects.Address('192.168.1.1/24') - self.assertEqual("192.168.1.1", address.ip) - self.assertEqual("255.255.255.0", address.netmask) - self.assertEqual(4, address.version) - - def test_ipv6_address(self): - address = objects.Address('2001:abc:a::/64') - self.assertEqual("2001:abc:a::", address.ip) - self.assertEqual("ffff:ffff:ffff:ffff::", address.netmask) - self.assertEqual(6, address.version) - - def test_from_json(self): - data = '{"ip_netmask": "192.0.2.5/24"}' - address = objects.Address.from_json(json.loads(data)) - self.assertEqual("192.0.2.5", address.ip) - self.assertEqual("255.255.255.0", address.netmask) - self.assertEqual(4, address.version) - - def test_from_json_invalid(self): - self.assertRaises(objects.InvalidConfigException, - objects.Address.from_json, - {}) - data = '{"ip_netmask": false}' - json_data = json.loads(data) - self.assertRaises(objects.InvalidConfigException, - objects.Address.from_json, - json_data) - - -class TestInterface(base.TestCase): - - def test_interface_addresses(self): - v4_addr = objects.Address('192.168.1.1/24') - v6_addr = objects.Address('2001:abc:a::/64') - interface = objects.Interface('foo', addresses=[v4_addr, v6_addr]) - self.assertEqual("192.168.1.1", interface.v4_addresses()[0].ip) - self.assertEqual("2001:abc:a::", interface.v6_addresses()[0].ip) - - def test_from_json_dhcp(self): - data = '{"type": "interface", "name": "em1", "use_dhcp": true}' - interface = objects.object_from_json(json.loads(data)) - self.assertEqual("em1", interface.name) - self.assertTrue(interface.use_dhcp) - - def test_from_json_defroute(self): - data = '{"type": "interface", "name": "em1", "use_dhcp": true}' - interface1 = objects.object_from_json(json.loads(data)) - data = """{ -"type": "interface", -"name": "em1", -"use_dhcp": true, -"defroute": false -} -""" - interface2 = objects.object_from_json(json.loads(data)) - self.assertTrue(interface1.defroute) - self.assertFalse(interface2.defroute) - - def test_from_json_dhclient_args(self): - data = """{ -"type": "interface", -"name": "em1", -"use_dhcp": true, -"dhclient_args": "--foobar" -} -""" - interface1 = objects.object_from_json(json.loads(data)) - self.assertEqual("--foobar", interface1.dhclient_args) - - def test_from_json_dns_servers(self): - data = """{ -"type": "interface", -"name": "em1", -"use_dhcp": true, -"dns_servers": ["1.2.3.4"] -} -""" - interface1 = objects.object_from_json(json.loads(data)) - self.assertEqual(["1.2.3.4"], interface1.dns_servers) - - def test_from_json_dhcp_nic1(self): - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em3"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = '{"type": "interface", "name": "nic1", "use_dhcp": true}' - interface = objects.object_from_json(json.loads(data)) - self.assertEqual("em3", interface.name) - self.assertTrue(interface.use_dhcp) - - def test_from_json_with_addresses(self): - data = """{ -"type": "interface", -"name": "em1", -"use_dhcp": false, -"mtu": 1501, -"addresses": [{ - "ip_netmask": "192.0.2.1/24" -}], -"routes": [{ - "next_hop": "192.0.2.1", - "ip_netmask": "192.0.2.1/24" -}] -} -""" - interface = objects.object_from_json(json.loads(data)) - self.assertEqual("em1", interface.name) - self.assertFalse(interface.use_dhcp) - self.assertFalse(interface.use_dhcpv6) - self.assertEqual(1501, interface.mtu) - address1 = interface.v4_addresses()[0] - self.assertEqual("192.0.2.1", address1.ip) - self.assertEqual("255.255.255.0", address1.netmask) - route1 = interface.routes[0] - self.assertEqual("192.0.2.1", route1.next_hop) - self.assertEqual("192.0.2.1/24", route1.ip_netmask) - - -class TestVlan(base.TestCase): - - def test_from_json_dhcp(self): - data = '{"type": "vlan", "device": "em1", "vlan_id": 16,' \ - '"use_dhcp": true}' - vlan = objects.object_from_json(json.loads(data)) - self.assertEqual("em1", vlan.device) - self.assertEqual(16, vlan.vlan_id) - self.assertTrue(vlan.use_dhcp) - - def test_from_json_dhcp_nic1(self): - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em4"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = '{"type": "vlan", "device": "nic1", "vlan_id": 16,' \ - '"use_dhcp": true}' - vlan = objects.object_from_json(json.loads(data)) - self.assertEqual("em4", vlan.device) - self.assertEqual(16, vlan.vlan_id) - self.assertTrue(vlan.use_dhcp) - - -class TestBridge(base.TestCase): - - def test_from_json_dhcp(self): - data = """{ -"type": "ovs_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [{ - "type": "interface", - "name": "em1" -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - self.assertTrue(interface1.ovs_port) - self.assertEqual("br-foo", interface1.bridge_name) - - def test_from_json_dhcp_with_nic1(self): - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em5"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = """{ -"type": "ovs_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [{ - "type": "interface", - "name": "nic1" -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em5", interface1.name) - self.assertTrue(interface1.ovs_port) - self.assertEqual("br-foo", interface1.bridge_name) - - def test_from_json_primary_interface(self): - data = """{ -"type": "ovs_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "em1", - "primary": "true" - }, - { - "type": "interface", - "name": "em2" - }] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - self.assertEqual("em1", bridge.primary_interface_name) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - self.assertTrue(interface1.ovs_port) - self.assertTrue(interface1.primary) - self.assertEqual("br-foo", interface1.bridge_name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - self.assertTrue(interface2.ovs_port) - self.assertEqual("br-foo", interface2.bridge_name) - - -class TestLinuxBridge(base.TestCase): - - def test_from_json_dhcp(self): - data = """{ -"type": "linux_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [{ - "type": "interface", - "name": "em1" -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - self.assertFalse(interface1.ovs_port) - self.assertEqual("br-foo", interface1.linux_bridge_name) - - def test_from_json_dhcp_with_nic1(self): - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em5"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = """{ -"type": "linux_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [{ - "type": "interface", - "name": "nic1" -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em5", interface1.name) - self.assertFalse(interface1.ovs_port) - self.assertEqual("br-foo", interface1.linux_bridge_name) - - def test_from_json_primary_interface(self): - data = """{ -"type": "linux_bridge", -"name": "br-foo", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "em1", - "primary": "true" - }, - { - "type": "interface", - "name": "em2" - }] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - self.assertTrue(bridge.use_dhcp) - self.assertEqual("em1", bridge.primary_interface_name) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - self.assertFalse(interface1.ovs_port) - self.assertTrue(interface1.primary) - self.assertEqual("br-foo", interface1.linux_bridge_name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - self.assertFalse(interface2.ovs_port) - self.assertEqual("br-foo", interface2.linux_bridge_name) - - -class TestIvsBridge(base.TestCase): - - def test_interface_from_json(self): - data = """{ -"type": "ivs_bridge", -"members": [{ - "type": "interface", - "name": "nic2" -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("ivs", bridge.name) - interface1 = bridge.members[0] - self.assertEqual("nic2", interface1.name) - self.assertEqual(False, interface1.ovs_port) - self.assertEqual("ivs", interface1.ivs_bridge_name) - - def test_ivs_interface_from_json(self): - data = """{ -"type": "ivs_bridge", -"members": [{ - "type": "ivs_interface", - "name": "storage", - "vlan_id": 202 -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("ivs", bridge.name) - interface1 = bridge.members[0] - self.assertEqual("storage202", interface1.name) - self.assertEqual(False, interface1.ovs_port) - self.assertEqual("ivs", interface1.ivs_bridge_name) - - def test_bond_interface_from_json(self): - data = """{ -"type": "ivs_bridge", -"members": [{ - "type": "linux_bond", - "name": "bond1", - "members": [ - {"type": "interface", "name": "nic2"}, - {"type": "interface", "name": "nic3"} - ] -}] -} -""" - err = self.assertRaises(objects.InvalidConfigException, - objects.IvsBridge.from_json, - json.loads(data)) - expected = 'IVS does not support bond interfaces.' - self.assertIn(expected, err) - - -class TestNfvswitchBridge(base.TestCase): - - def test_from_json(self): - data = """{ -"type": "nfvswitch_bridge", -"cpus": "2,3,4,5", -"members": [ - {"type": "interface", "name": "nic2"} - ] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("nfvswitch", bridge.name) - self.assertEqual("2,3,4,5", bridge.cpus) - interface1 = bridge.members[0] - self.assertEqual("nic2", interface1.name) - self.assertEqual(False, interface1.ovs_port) - self.assertEqual("nfvswitch", interface1.nfvswitch_bridge_name) - - -class TestNfvswitchInterface(base.TestCase): - - def test_interface_from_json(self): - data = """{ -"type": "nfvswitch_bridge", -"cpus": "2,3,4,5", -"members": [ - {"type": "interface","name": "nic1"}, - {"type": "interface","name": "nic2"} - ] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("nfvswitch", bridge.name) - self.assertEqual("2,3,4,5", bridge.cpus) - interface1 = bridge.members[0] - self.assertEqual("nic1", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("nic2", interface2.name) - self.assertEqual(False, interface2.ovs_port) - self.assertEqual("nfvswitch", interface1.nfvswitch_bridge_name) - - def test_nfvswitch_internal_from_json(self): - data = """{ -"type": "nfvswitch_bridge", -"cpus": "2,3,4,5", -"members": [ - {"type": "nfvswitch_internal", "name": "storage", "vlan_id": 202}, - {"type": "nfvswitch_internal", "name": "api", "vlan_id": 201} - ] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("nfvswitch", bridge.name) - self.assertEqual("2,3,4,5", bridge.cpus) - interface1 = bridge.members[0] - self.assertEqual("storage202", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("api201", interface2.name) - self.assertEqual(False, interface1.ovs_port) - self.assertEqual("nfvswitch", interface1.nfvswitch_bridge_name) - - def test_bond_interface_from_json(self): - data = """{ -"type": "nfvswitch_bridge", -"cpus": "2,3,4,5", -"members": [{ - "type": "linux_bond", "name": "bond1", "members": - [{"type": "interface", "name": "nic2"}, - {"type": "interface", "name": "nic3"}] - } - ] -} -""" - err = self.assertRaises(objects.InvalidConfigException, - objects.NfvswitchBridge.from_json, - json.loads(data)) - expected = 'NFVSwitch does not support bond interfaces.' - self.assertIn(expected, err) - - -class TestBond(base.TestCase): - - def test_from_json_dhcp(self): - data = """{ -"type": "ovs_bond", -"name": "bond1", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "em1" - }, - { - "type": "interface", - "name": "em2" - } -] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("bond1", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - - def test_from_json_dhcp_with_nic1_nic2(self): - - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em1", "nic2": "em2"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = """{ -"type": "ovs_bond", -"name": "bond1", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "nic1" - }, - { - "type": "interface", - "name": "nic2" - } -] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("bond1", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - - -class TestLinuxTeam(base.TestCase): - - def test_from_json_dhcp(self): - data = """{ -"type": "team", -"name": "team1", -"use_dhcp": true, -"members": [ - { "type": "interface", "name": "em1", "primary": true }, - { "type": "interface", "name": "em2" } -] -} -""" - team = objects.object_from_json(json.loads(data)) - self.assertEqual("team1", team.name) - self.assertTrue(team.use_dhcp) - interface1 = team.members[0] - self.assertEqual("em1", interface1.name) - interface2 = team.members[1] - self.assertEqual("em2", interface2.name) - - -class TestLinuxBond(base.TestCase): - - def test_from_json_dhcp(self): - data = """{ -"type": "linux_bond", -"name": "bond1", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "em1" - }, - { - "type": "interface", - "name": "em2" - } -] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("bond1", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - - def test_from_json_dhcp_with_nic1_nic2(self): - - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "em1", "nic2": "em2"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = """{ -"type": "ovs_bond", -"name": "bond1", -"use_dhcp": true, -"members": [ - { - "type": "interface", - "name": "nic1" - }, - { - "type": "interface", - "name": "nic2" - } -] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("bond1", bridge.name) - self.assertTrue(bridge.use_dhcp) - interface1 = bridge.members[0] - self.assertEqual("em1", interface1.name) - interface2 = bridge.members[1] - self.assertEqual("em2", interface2.name) - - -class TestOvsTunnel(base.TestCase): - - def test_from_json(self): - data = """{ -"type": "ovs_bridge", -"name": "br-foo", -"members": [{ - "type": "ovs_tunnel", - "name": "tun0", - "tunnel_type": "gre", - "ovs_options": [ - "remote_ip=192.168.1.1" - ], - "ovs_extra": [ - "ovs extra" - ] -}] -} -""" - bridge = objects.object_from_json(json.loads(data)) - self.assertEqual("br-foo", bridge.name) - tun0 = bridge.members[0] - self.assertEqual("tun0", tun0.name) - self.assertFalse(tun0.ovs_port) - self.assertEqual("br-foo", tun0.bridge_name) - self.assertEqual("gre", tun0.tunnel_type) - self.assertEqual( - ["options:remote_ip=192.168.1.1"], - tun0.ovs_options) - self.assertEqual( - ["ovs extra"], - tun0.ovs_extra) - - -class TestOvsPatchPort(base.TestCase): - - def test_from_json(self): - data = """{ -"type": "ovs_patch_port", -"name": "br-pub-patch", -"bridge_name": "br-ex", -"peer": "br-ex-patch" -} -""" - patch_port = objects.object_from_json(json.loads(data)) - self.assertEqual("br-pub-patch", patch_port.name) - self.assertEqual("br-ex", patch_port.bridge_name) - self.assertEqual("br-ex-patch", patch_port.peer) - - -class TestIbInterface(base.TestCase): - - def test_ib_interface_addresses(self): - v4_addr = objects.Address('192.168.1.1/24') - v6_addr = objects.Address('2001:abc:a::/64') - ib_interface = objects.IbInterface('foo', addresses=[v4_addr, v6_addr]) - self.assertEqual("192.168.1.1", ib_interface.v4_addresses()[0].ip) - self.assertEqual("2001:abc:a::", ib_interface.v6_addresses()[0].ip) - - def test_from_json_dhcp(self): - data = '{"type": "ib_interface", "name": "ib0", "use_dhcp": true}' - ib_interface = objects.object_from_json(json.loads(data)) - self.assertEqual("ib0", ib_interface.name) - self.assertTrue(ib_interface.use_dhcp) - - def test_from_json_defroute(self): - data = '{"type": "ib_interface", "name": "ib0", "use_dhcp": true}' - ib_interface1 = objects.object_from_json(json.loads(data)) - data = """{ -"type": "ib_interface", -"name": "ib0", -"use_dhcp": true, -"defroute": false -} -""" - ib_interface2 = objects.object_from_json(json.loads(data)) - self.assertTrue(ib_interface1.defroute) - self.assertFalse(ib_interface2.defroute) - - def test_from_json_dhclient_args(self): - data = """{ -"type": "ib_interface", -"name": "ib0", -"use_dhcp": true, -"dhclient_args": "--foobar" -} -""" - ib_interface1 = objects.object_from_json(json.loads(data)) - self.assertEqual("--foobar", ib_interface1.dhclient_args) - - def test_from_json_dns_servers(self): - data = """{ -"type": "ib_interface", -"name": "ib0", -"use_dhcp": true, -"dns_servers": ["1.2.3.4"] -} -""" - ib_interface1 = objects.object_from_json(json.loads(data)) - self.assertEqual(["1.2.3.4"], ib_interface1.dns_servers) - - def test_from_json_dhcp_nic1(self): - def dummy_numbered_nics(nic_mapping=None): - return {"nic1": "ib0"} - self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics) - - data = '{"type": "ib_interface", "name": "nic1", "use_dhcp": true}' - ib_interface = objects.object_from_json(json.loads(data)) - self.assertEqual("ib0", ib_interface.name) - self.assertTrue(ib_interface.use_dhcp) - - def test_from_json_with_addresses(self): - data = """{ -"type": "ib_interface", -"name": "ib0", -"use_dhcp": false, -"mtu": 1501, -"addresses": [{ - "ip_netmask": "192.0.2.1/24" -}], -"routes": [{ - "next_hop": "192.0.2.1", - "ip_netmask": "192.0.2.1/24" -}] -} -""" - ib_interface = objects.object_from_json(json.loads(data)) - self.assertEqual("ib0", ib_interface.name) - self.assertFalse(ib_interface.use_dhcp) - self.assertFalse(ib_interface.use_dhcpv6) - self.assertEqual(1501, ib_interface.mtu) - address1 = ib_interface.v4_addresses()[0] - self.assertEqual("192.0.2.1", address1.ip) - self.assertEqual("255.255.255.0", address1.netmask) - route1 = ib_interface.routes[0] - self.assertEqual("192.0.2.1", route1.next_hop) - self.assertEqual("192.0.2.1/24", route1.ip_netmask) - - -class TestNumberedNicsMapping(base.TestCase): - - # We want to test the function, not the dummy.. - stub_numbered_nics = False - - def tearDown(self): - super(TestNumberedNicsMapping, self).tearDown() - objects._NUMBERED_NICS = None - - def _stub_active_nics(self, nics): - def dummy_ordered_active_nics(): - return nics - self.stubs.Set(utils, 'ordered_active_nics', dummy_ordered_active_nics) - - def test_numbered_nics_default(self): - self._stub_active_nics(['em1', 'em2']) - expected = {'nic1': 'em1', 'nic2': 'em2'} - self.assertEqual(expected, objects._numbered_nics()) - - def test_numbered_nics_mapped(self): - self._stub_active_nics(['em1', 'em2']) - mapping = {'nic1': 'em2', 'nic2': 'em1'} - expected = {'nic1': 'em2', 'nic2': 'em1'} - self.assertEqual(expected, objects._numbered_nics(nic_mapping=mapping)) - - def test_numbered_nics_mapped_partial(self): - self._stub_active_nics(['em1', 'em2', 'em3', 'em4']) - mapping = {'nic1': 'em2', 'nic2': 'em1'} - expected = {'nic1': 'em2', 'nic2': 'em1', 'nic3': 'em3', 'nic4': 'em4'} - self.assertEqual(expected, objects._numbered_nics(nic_mapping=mapping)) - - def test_numbered_nics_map_error_notactive(self): - self._stub_active_nics(['em1', 'em2']) - mapping = {'nic1': 'em3', 'nic2': 'em1'} - expected = {'nic2': 'em1'} - self.assertEqual(expected, objects._numbered_nics(nic_mapping=mapping)) - - def test_numbered_nics_map_error_duplicate(self): - self._stub_active_nics(['em1', 'em2']) - mapping = {'nic1': 'em1', 'nic2': 'em1'} - err = self.assertRaises(objects.InvalidConfigException, - objects._numbered_nics, nic_mapping=mapping) - expected = 'em1 already mapped, check mapping file for duplicates' - self.assertIn(expected, six.text_type(err)) - - def test_numbered_nics_map_mac(self): - def dummy_interface_mac(name): - mac_map = {'em1': '12:34:56:78:9a:bc', - 'em2': '12:34:56:de:f0:12'} - return mac_map[name] - self.stubs.Set(utils, 'interface_mac', dummy_interface_mac) - self._stub_active_nics(['em1', 'em2']) - mapping = {'nic1': '12:34:56:de:f0:12', 'nic2': '12:34:56:78:9a:bc'} - expected = {'nic1': 'em2', 'nic2': 'em1'} - self.assertEqual(expected, objects._numbered_nics(nic_mapping=mapping)) - - def test_numbered_nics_no_active(self): - self._stub_active_nics([]) - expected = {} - # This only emits a warning, so it should still work - self.assertEqual(expected, objects._numbered_nics()) diff --git a/os_net_config/tests/test_os_net_config.py b/os_net_config/tests/test_os_net_config.py deleted file mode 100644 index ad45baa..0000000 --- a/os_net_config/tests/test_os_net_config.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -test_os_net_config ----------------------------------- - -Tests for `os_net_config` module. -""" - -from os_net_config.tests import base - - -class TestOs_net_config(base.TestCase): - - def test_something(self): - pass diff --git a/os_net_config/tests/test_utils.py b/os_net_config/tests/test_utils.py deleted file mode 100644 index b6531a6..0000000 --- a/os_net_config/tests/test_utils.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os.path -import shutil -import tempfile - -from os_net_config.tests import base -from os_net_config import utils - - -class TestUtils(base.TestCase): - - def test_ordered_active_nics(self): - - tmpdir = tempfile.mkdtemp() - self.stubs.Set(utils, '_SYS_CLASS_NET', tmpdir) - - def test_is_active_nic(interface_name): - return True - self.stubs.Set(utils, '_is_active_nic', test_is_active_nic) - - for nic in ['a1', 'em1', 'em2', 'eth2', 'z1', - 'enp8s0', 'enp10s0', 'enp1s0f0']: - with open(os.path.join(tmpdir, nic), 'w') as f: - f.write(nic) - - nics = utils.ordered_active_nics() - self.assertEqual('em1', nics[0]) - self.assertEqual('em2', nics[1]) - self.assertEqual('eth2', nics[2]) - self.assertEqual('a1', nics[3]) - self.assertEqual('enp1s0f0', nics[4]) - self.assertEqual('enp8s0', nics[5]) - self.assertEqual('enp10s0', nics[6]) - self.assertEqual('z1', nics[7]) - - shutil.rmtree(tmpdir) diff --git a/os_net_config/utils.py b/os_net_config/utils.py deleted file mode 100644 index 83aae63..0000000 --- a/os_net_config/utils.py +++ /dev/null @@ -1,120 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import glob -import logging -import os -import re - - -logger = logging.getLogger(__name__) -_SYS_CLASS_NET = '/sys/class/net' - - -def write_config(filename, data): - with open(filename, 'w') as f: - f.write(str(data)) - - -def get_file_data(filename): - if not os.path.exists(filename): - return '' - - try: - with open(filename, 'r') as f: - return f.read() - except IOError: - logger.error("Error reading file: %s" % filename) - return '' - - -def interface_mac(name): - try: # If the iface is part of a Linux bond, the real MAC is only here. - with open('/sys/class/net/%s/bonding_slave/perm_hwaddr' % name, - 'r') as f: - return f.read().rstrip() - except IOError: - pass # Iface is not part of a bond, continue - - try: - with open('/sys/class/net/%s/address' % name, 'r') as f: - return f.read().rstrip() - except IOError: - logger.error("Unable to read mac address: %s" % name) - raise - - -def _is_active_nic(interface_name): - try: - if interface_name == 'lo': - return False - - device_dir = _SYS_CLASS_NET + '/%s/device' % interface_name - has_device_dir = os.path.isdir(device_dir) - - operstate = None - with open(_SYS_CLASS_NET + '/%s/operstate' % interface_name, 'r') as f: - operstate = f.read().rstrip().lower() - - address = None - with open(_SYS_CLASS_NET + '/%s/address' % interface_name, 'r') as f: - address = f.read().rstrip() - - if has_device_dir and operstate == 'up' and address: - return True - else: - return False - except IOError: - return False - - -def _natural_sort_key(s): - nsre = re.compile('([0-9]+)') - return [int(text) if text.isdigit() else text - for text in re.split(nsre, s)] - - -def ordered_active_nics(): - embedded_nics = [] - nics = [] - logger.debug("Finding active nics") - for name in glob.iglob(_SYS_CLASS_NET + '/*'): - nic = name[(len(_SYS_CLASS_NET) + 1):] - if _is_active_nic(nic): - if nic.startswith('em') or nic.startswith('eth') or \ - nic.startswith('eno'): - logger.debug("%s is an embedded active nic" % nic) - embedded_nics.append(nic) - else: - logger.debug("%s is an active nic" % nic) - nics.append(nic) - else: - logger.debug("%s is not an active nic" % nic) - # NOTE: we could just natural sort all active devices, - # but this ensures em, eno, and eth are ordered first - # (more backwards compatible) - active_nics = (sorted(embedded_nics, key=_natural_sort_key) + - sorted(nics, key=_natural_sort_key)) - logger.debug("Active nics are %s" % active_nics) - return active_nics - - -def diff(filename, data): - file_data = get_file_data(filename) - logger.debug("Diff file data:\n%s" % file_data) - logger.debug("Diff data:\n%s" % data) - # convert to string as JSON may have unicode in it - return not file_data == data diff --git a/os_net_config/version.py b/os_net_config/version.py deleted file mode 100644 index 2af627c..0000000 --- a/os_net_config/version.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pbr.version - -version_info = pbr.version.VersionInfo('os-net-config') diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index cc08a28..0000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -pbr>=0.6,!=0.7,<1.0 -anyjson>=0.3.3 -Babel>=0.9.6 -six>=1.6.0 -eventlet>=0.13.0 -iso8601>=0.1.9 -netaddr>=0.7.6 -oslo.concurrency>=1.4.1 # Apache-2.0 -oslo.utils>=1.2.0 # Apache-2.0 -PyYAML>=3.1.0 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8e69787..0000000 --- a/setup.cfg +++ /dev/null @@ -1,54 +0,0 @@ -[metadata] -name = os-net-config -summary = OpenStack network configuration -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://git.openstack.org/cgit/openstack/os-net-config -classifier = - Environment :: OpenStack - Intended Audience :: Developers - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: OS Independent - Programming Language :: Python - -[files] -packages = - os_net_config - -[global] -setup-hooks = - pbr.hooks.setup_hook - -[entry_points] -console_scripts = - os-net-config = os_net_config.cli:main - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[compile_catalog] -directory = os_net_config/locale -domain = os-net-config - -[update_catalog] -domain = os-net-config -output_dir = os_net_config/locale -input_file = os_net_config/locale/os-net-config.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = os_net_config/locale/os-net-config.pot - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 diff --git a/setup.py b/setup.py deleted file mode 100755 index 70c2b3f..0000000 --- a/setup.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -setuptools.setup( - setup_requires=['pbr'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index a0f2371..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -hacking>=0.10.2,<0.11 # Apache-2.0 - -coverage>=3.6 -discover -fixtures>=0.3.14 -python-subunit -sphinx>=1.1.2 -oslosphinx -testrepository>=0.0.17 -testscenarios>=0.4,<0.5 -testtools>=0.9.32 -mock>=1.0 -mox>=0.5.3 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 5b6ac5d..0000000 --- a/tox.ini +++ /dev/null @@ -1,34 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py27,py33,pypy,pep8 -skipsdist = True - -[testenv] -usedevelop = True -install_command = pip install -U {opts} {packages} -setenv = - VIRTUAL_ENV={envdir} -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --slowest --testr-args='{posargs}' - -[testenv:pep8] -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = python setup.py testr --coverage --testr-args='{posargs}' - -[testenv:docs] -commands = python setup.py build_sphinx - -[flake8] -# H803 skipped on purpose per list discussion. -# E123, E125 skipped as they are invalid PEP-8. - -show-source = True -ignore = E123,E125,H803 -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build