├── .coveragerc ├── .gitignore ├── .gitreview ├── .mailmap ├── .pre-commit-config.yaml ├── .pylintrc ├── .stestr.conf ├── .zuul.yaml ├── CONTRIBUTING.rst ├── HACKING.rst ├── LICENSE ├── README.rst ├── babel-django.cfg ├── babel-djangojs.cfg ├── bgpvpn_dashboard ├── __init__.py ├── api │ ├── __init__.py │ └── bgpvpn.py ├── common │ ├── __init__.py │ └── bgpvpn.py ├── dashboards │ ├── __init__.py │ ├── admin │ │ ├── __init__.py │ │ └── bgpvpn │ │ │ ├── __init__.py │ │ │ ├── forms.py │ │ │ ├── panel.py │ │ │ ├── tables.py │ │ │ ├── tabs.py │ │ │ ├── templates │ │ │ └── bgpvpn │ │ │ │ ├── _create.html │ │ │ │ ├── _detail_overview.html │ │ │ │ └── create.html │ │ │ ├── urls.py │ │ │ ├── views.py │ │ │ └── workflows.py │ └── project │ │ ├── __init__.py │ │ └── bgpvpn │ │ ├── __init__.py │ │ ├── forms.py │ │ ├── network_associations │ │ ├── __init__.py │ │ ├── tables.py │ │ ├── tabs.py │ │ ├── urls.py │ │ └── views.py │ │ ├── panel.py │ │ ├── router_associations │ │ ├── __init__.py │ │ ├── forms.py │ │ ├── tables.py │ │ ├── tabs.py │ │ ├── urls.py │ │ └── views.py │ │ ├── tables.py │ │ ├── tabs.py │ │ ├── templates │ │ └── bgpvpn │ │ │ ├── _associated_networks.html │ │ │ ├── _associated_routers.html │ │ │ ├── _create_network_association.html │ │ │ ├── _detail_overview.html │ │ │ ├── _modify.html │ │ │ ├── create_network_association.html │ │ │ ├── index.html │ │ │ ├── modify.html │ │ │ ├── network_associations │ │ │ └── _detail_overview.html │ │ │ └── router_associations │ │ │ ├── _detail_overview.html │ │ │ ├── _modify.html │ │ │ └── modify.html │ │ ├── urls.py │ │ ├── views.py │ │ └── workflows.py ├── enabled │ ├── _1495_project_bgpvpn_panel.py │ ├── _2360_admin_bgpvpn_panel.py │ └── __init__.py ├── etc │ └── bgpvpn-horizon.conf ├── locale │ ├── en_GB │ │ └── LC_MESSAGES │ │ │ └── django.po │ └── fr │ │ └── LC_MESSAGES │ │ └── django.po └── test │ ├── __init__.py │ ├── admin │ ├── __init__.py │ ├── test_forms.py │ ├── test_tables.py │ └── test_views.py │ ├── api_tests │ ├── __init__.py │ └── test_bgpvpn.py │ ├── helpers.py │ ├── project │ ├── __init__.py │ ├── test_forms.py │ ├── test_tables.py │ └── test_views.py │ ├── settings.py │ ├── test_data │ ├── __init__.py │ ├── bgpvpn_data.py │ └── utils.py │ └── urls.py ├── bindep.txt ├── devstack ├── devstack-gate-bagpipe-rc ├── devstack-gate-rc ├── plugin.sh └── settings ├── doc ├── requirements.txt └── source │ ├── _static │ └── .placeholder │ ├── conf.py │ ├── configuration │ ├── index.rst │ ├── networking-bgpvpn.rst │ ├── policy-sample.rst │ ├── policy.rst │ └── samples │ │ └── networking-bgpvpn.rst │ ├── contributor │ ├── contributing.rst │ ├── future │ │ ├── attributes.rst │ │ └── index.rst │ ├── index.rst │ └── specs.rst │ ├── index.rst │ ├── install │ └── index.rst │ ├── introduction.rst │ ├── samples │ ├── __init__.py │ └── bgpvpn-sample01.py │ └── user │ ├── api.rst │ ├── components-sdn.blockdiag │ ├── drivers │ ├── bagpipe │ │ ├── index.rst │ │ └── overview.blockdiag │ ├── index.rst │ ├── nuage │ │ └── index.rst │ ├── opencontrail │ │ └── index.rst │ └── opendaylight │ │ └── index.rst │ ├── figures │ ├── components_sdn_blockdiag.png │ ├── overview_blockdiag.png │ └── workflows_seqdiag.png │ ├── heat.rst │ ├── horizon.rst │ ├── index.rst │ ├── overview.rst │ ├── usage.rst │ └── workflows.seqdiag ├── etc ├── README.txt ├── neutron │ └── networking_bgpvpn.conf ├── oslo-config-generator │ └── networking-bgpvpn.conf └── oslo-policy-generator │ └── policy.conf ├── networking_bgpvpn ├── __init__.py ├── _i18n.py ├── locale │ └── en_GB │ │ └── LC_MESSAGES │ │ └── networking_bgpvpn.po ├── neutron │ ├── __init__.py │ ├── db │ │ ├── __init__.py │ │ ├── bgpvpn_db.py │ │ ├── head.py │ │ └── migration │ │ │ ├── __init__.py │ │ │ └── alembic_migrations │ │ │ ├── README │ │ │ ├── __init__.py │ │ │ ├── env.py │ │ │ ├── script.py.mako │ │ │ └── versions │ │ │ ├── CONTRACT_HEAD │ │ │ ├── EXPAND_HEAD │ │ │ ├── liberty │ │ │ ├── contract │ │ │ │ └── 180baa4183e0_initial.py │ │ │ └── expand │ │ │ │ ├── 17d9fd4fddee_initial.py │ │ │ │ └── 3600132c6147_add_router_association_table.py │ │ │ ├── newton │ │ │ ├── contract │ │ │ │ └── 23ce05e0a19f_rename_tenant_to_project.py │ │ │ └── expand │ │ │ │ └── 0ab4049986b8_add_indexes_to_tenant_id.py │ │ │ ├── queens │ │ │ └── expand │ │ │ │ ├── 39411aacf9b8_add_vni_to_bgpvpn_table.py │ │ │ │ ├── 4610803bdf0d_router_assoc_add_advertise_extra_routes.py │ │ │ │ ├── 666c706fea3b_bgpvpn_local_pref.py │ │ │ │ └── 9a6664f3b8d4_add_port_association_table.py │ │ │ ├── rocky │ │ │ ├── contract │ │ │ │ └── 9d7f1ae5fa56_add_standard_attributes.py │ │ │ └── expand │ │ │ │ └── 7a9482036ecd_add_standard_attributes.py │ │ │ └── start_networking_bgpvpn.py │ ├── extensions │ │ ├── __init__.py │ │ ├── bgpvpn.py │ │ ├── bgpvpn_routes_control.py │ │ └── bgpvpn_vni.py │ ├── opts.py │ └── services │ │ ├── __init__.py │ │ ├── common │ │ ├── __init__.py │ │ ├── constants.py │ │ └── utils.py │ │ ├── plugin.py │ │ └── service_drivers │ │ ├── __init__.py │ │ ├── bagpipe │ │ ├── __init__.py │ │ ├── bagpipe.py │ │ └── bagpipe_v2.py │ │ └── driver_api.py ├── neutronclient │ ├── __init__.py │ └── neutron │ │ ├── __init__.py │ │ └── v2_0 │ │ ├── __init__.py │ │ └── bgpvpn │ │ ├── __init__.py │ │ └── bgpvpn.py ├── policies │ ├── __init__.py │ ├── bgpvpn.py │ ├── network_association.py │ ├── port_association.py │ └── router_association.py ├── tests │ ├── __init__.py │ ├── functional │ │ ├── __init__.py │ │ ├── db │ │ │ ├── __init__.py │ │ │ └── test_migrations.py │ │ ├── requirements.txt │ │ └── test_placeholder.py │ └── unit │ │ ├── __init__.py │ │ ├── client │ │ ├── __init__.py │ │ └── test_client.py │ │ ├── db │ │ ├── __init__.py │ │ └── test_db.py │ │ ├── extensions │ │ ├── __init__.py │ │ ├── test_bgpvpn.py │ │ ├── test_bgpvpn_rc_base.py │ │ ├── test_bgpvpn_routes_control.py │ │ └── test_bgpvpn_vni.py │ │ └── services │ │ ├── __init__.py │ │ ├── bagpipe │ │ ├── __init__.py │ │ └── test_bagpipe.py │ │ ├── common │ │ ├── __init__.py │ │ └── test_utils.py │ │ └── test_plugin.py └── version.py ├── networking_bgpvpn_heat ├── __init__.py ├── _i18n.py ├── bgpvpnservice.py ├── examples │ ├── bgpvpn_test-00.yaml │ ├── bgpvpn_test-01-admin.yaml │ ├── bgpvpn_test-01-tenant.yaml │ ├── bgpvpn_test-01bis_router-tenant.yaml │ ├── bgpvpn_test-01ter_port-tenant.yaml │ ├── bgpvpn_test-04-admin.yaml │ └── bgpvpn_test-04-tenant.yaml └── locale │ └── en_GB │ └── LC_MESSAGES │ └── networking_bgpvpn_heat.po ├── pyproject.toml ├── releasenotes ├── notes │ ├── .placeholder │ ├── 0_heat-support-ab233de7401aeb36.yaml │ ├── add-vni-to-bgpvpn-31d6eda7ba6d5047.yaml │ ├── bagpipe-driver-improvements-401a7ba59a6f5f45.yaml │ ├── bagpipe-router-compat-b53b6f3799cd23db.yaml │ ├── bagpipe_enable_evpn-ae64f77df89e069b.yaml │ ├── bagpipe_ovo_rpcs-380f7bd52969bef7.yaml │ ├── bgpvpn_service_declaration-6d9ecd2c397e4821.yaml │ ├── deprecate-old-opencontrail-driver-a598892ddf54c724.yaml │ ├── drop-py-2-7-4db5f2b1529bb09c.yaml │ ├── drop-python-3-6-and-3-7-97c0464e7a396023.yaml │ ├── filtering-on-resource-association-2acdbc5b59d1a40a.yaml │ ├── heat_bgpvpn_local_pref-a1cbfde10810b157.yaml │ ├── heat_port_associations-f2d316f3b8c755fe.yaml │ ├── horizon-in-extras-371d572b09437dc4.yaml │ ├── horizon-support-06a7b21286002949.yaml │ ├── mitaka-prelude-1675467c144a91ea.yaml │ ├── odl_router_association-fa2ed7c396531418.yaml │ ├── pre_commit_checks-b902ee19a3654a7b.yaml │ ├── remove_obsolete_drivers-3706e080098a5cb6.yaml │ └── routes-control-api-ext-c0c4020e7370d833.yaml └── source │ ├── 2023.1.rst │ ├── 2023.2.rst │ ├── 2024.1.rst │ ├── 2024.2.rst │ ├── 2025.1.rst │ ├── _static │ └── .placeholder │ ├── _templates │ └── .placeholder │ ├── conf.py │ ├── index.rst │ ├── liberty.rst │ ├── locale │ └── en_GB │ │ └── LC_MESSAGES │ │ └── releasenotes.po │ ├── mitaka.rst │ ├── newton.rst │ ├── ocata.rst │ ├── pike.rst │ ├── queens.rst │ ├── rocky.rst │ ├── stein.rst │ ├── train.rst │ ├── unreleased.rst │ ├── ussuri.rst │ ├── victoria.rst │ ├── wallaby.rst │ ├── xena.rst │ ├── yoga.rst │ └── zed.rst ├── requirements.txt ├── setup.cfg ├── setup.py ├── specs └── bgpvpn.rst ├── test-requirements.txt ├── tools ├── django-manage.py └── generate_config_file_samples.sh └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = networking-bgpvpn 4 | omit = networking-bgpvpn/tests/* 5 | 6 | [report] 7 | ignore_errors = True 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | cover/ 27 | .tox 28 | nosetests.xml 29 | .testrepository 30 | .stestr/ 31 | .venv 32 | bgpvpn_dashboard/test/.secret_key_store 33 | *.lock 34 | 35 | # Translations 36 | *.mo 37 | *.pot 38 | 39 | # Mr Developer 40 | .mr.developer.cfg 41 | .project 42 | .pydevproject 43 | 44 | # Complexity 45 | output/*.html 46 | output/*/index.html 47 | 48 | # Documentation 49 | doc/build 50 | doc/source/_static/config-samples/*.sample 51 | doc/source/_static/*.policy.yaml.sample 52 | etc/**/*.sample 53 | 54 | # pbr generates these 55 | AUTHORS 56 | ChangeLog 57 | 58 | # Files created by releasenotes build 59 | releasenotes/build 60 | 61 | # Editors 62 | *~ 63 | .*.swp 64 | .*sw? 65 | .idea/* 66 | 67 | # dont ignore: 68 | !/.coveragerc 69 | !/.gitignore 70 | !/.gitreview 71 | !/.mailmap 72 | !/.pylintrc 73 | !/.stestr.conf 74 | !/.testr.conf 75 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.opendev.org 3 | port=29418 4 | project=openstack/networking-bgpvpn.git 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | # Format is: 2 | # 3 | # 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | default_language_version: 3 | # force all unspecified python hooks to run python3 4 | python: python3 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.5.0 8 | hooks: 9 | - id: trailing-whitespace 10 | - id: mixed-line-ending 11 | args: ['--fix', 'lf'] 12 | exclude: '.*\.(svg)$' 13 | - id: check-byte-order-marker 14 | - id: check-executables-have-shebangs 15 | - id: check-merge-conflict 16 | - id: debug-statements 17 | - id: check-yaml 18 | - repo: https://github.com/lucas-c/pre-commit-hooks 19 | rev: v1.5.4 20 | hooks: 21 | - id: remove-tabs 22 | exclude: '.*\.(svg)$' 23 | - repo: https://opendev.org/openstack/hacking 24 | rev: 6.1.0 25 | hooks: 26 | - id: hacking 27 | additional_dependencies: ['neutron-lib'] 28 | exclude: '^(doc|releasenotes|tools)/.*$' 29 | - repo: local 30 | hooks: 31 | - id: flake8 32 | name: flake8 33 | additional_dependencies: 34 | - hacking>=6.1.0,<6.2.0 35 | - neutron-lib 36 | language: python 37 | entry: flake8 38 | files: '^.*\.py$' 39 | exclude: '^(doc|releasenotes|tools)/.*$' 40 | # todo(slaweq): enable pylint check once all issues in the current code will 41 | # be solved 42 | # - id: pylint 43 | # name: pylint 44 | # entry: .tox/pep8/bin/pylint 45 | # files: ^networking-bgpvpn/ 46 | # language: system 47 | # types: [python] 48 | # args: ['--rcfile=.pylintrc', '--output-format=colorized'] 49 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | # The format of this file isn't really documented; just use --generate-rcfile 2 | [MASTER] 3 | # Add to the black list. It should be a base name, not a 4 | # path. You may set this option multiple times. 5 | # 6 | ignore=.git,tests 7 | 8 | [MESSAGES CONTROL] 9 | # NOTE(gus): This is a long list. A number of these are important and 10 | # should be re-enabled once the offending code is fixed (or marked 11 | # with a local disable) 12 | disable= 13 | # "F" Fatal errors that prevent further processing 14 | import-error, 15 | # "I" Informational noise 16 | locally-disabled, 17 | # "E" Error for important programming issues (likely bugs) 18 | no-member, 19 | no-method-argument, 20 | no-self-argument, 21 | # "W" Warnings for stylistic problems or minor programming issues 22 | abstract-method, 23 | arguments-differ, 24 | attribute-defined-outside-init, 25 | bad-indentation, 26 | broad-except, 27 | dangerous-default-value, 28 | expression-not-assigned, 29 | fixme, 30 | global-statement, 31 | not-callable, 32 | protected-access, 33 | redefined-builtin, 34 | redefined-outer-name, 35 | super-init-not-called, 36 | unpacking-non-sequence, 37 | unused-argument, 38 | # "C" Coding convention violations 39 | consider-using-f-string, 40 | invalid-name, 41 | len-as-condition, 42 | missing-docstring, 43 | multiple-statements, 44 | superfluous-parens, 45 | # "R" Refactor recommendations 46 | duplicate-code, 47 | inconsistent-return-statements, 48 | no-else-return, 49 | too-few-public-methods, 50 | too-many-ancestors, 51 | too-many-arguments, 52 | too-many-branches, 53 | too-many-instance-attributes, 54 | too-many-lines, 55 | too-many-locals, 56 | too-many-public-methods, 57 | too-many-return-statements, 58 | too-many-statements, 59 | 60 | [BASIC] 61 | # Variable names can be 1 to 31 characters long, with lowercase and underscores 62 | variable-rgx=[a-z_][a-z0-9_]{0,30}$ 63 | 64 | # Argument names can be 2 to 31 characters long, with lowercase and underscores 65 | argument-rgx=[a-z_][a-z0-9_]{1,30}$ 66 | 67 | # Method names should be at least 3 characters long 68 | # and be lowecased with underscores 69 | method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$ 70 | 71 | # Module names matching neutron-* are ok (files in bin/) 72 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$ 73 | 74 | # Don't require docstrings on tests. 75 | no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ 76 | 77 | [FORMAT] 78 | # Maximum number of characters on a single line. 79 | max-line-length=79 80 | 81 | [VARIABLES] 82 | # List of additional names supposed to be defined in builtins. Remember that 83 | # you should avoid to define new builtins when possible. 84 | # _ is used by our localization 85 | additional-builtins=_ 86 | 87 | [IMPORTS] 88 | # Deprecated modules which should not be used, separated by a comma 89 | deprecated-modules= 90 | 91 | [TYPECHECK] 92 | # List of module names for which member attributes should not be checked 93 | ignored-modules= 94 | 95 | [REPORTS] 96 | # Tells whether to display a full report or only the messages 97 | reports=no 98 | -------------------------------------------------------------------------------- /.stestr.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | test_path=${OS_TEST_PATH:-./networking_bgpvpn/tests/unit} 3 | top_dir=./ 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | If you would like to contribute to the development of OpenStack, 2 | you must follow the steps in this page: 3 | 4 | https://docs.openstack.org/infra/manual/developers.html 5 | 6 | Once those steps have been completed, changes to OpenStack 7 | should be submitted for review via the Gerrit tool, following 8 | the workflow documented at: 9 | 10 | https://docs.openstack.org/infra/manual/developers.html#development-workflow 11 | 12 | Pull requests submitted through GitHub will be ignored. 13 | 14 | Bugs should be filed on Launchpad, not GitHub: 15 | 16 | https://bugs.launchpad.net/bgpvpn 17 | -------------------------------------------------------------------------------- /HACKING.rst: -------------------------------------------------------------------------------- 1 | networking-bgpvpn Style Commandments 2 | =============================================== 3 | 4 | Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ 5 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | Team and repository tags 3 | ======================== 4 | 5 | .. image:: https://governance.openstack.org/tc/badges/networking-bgpvpn.svg 6 | :target: https://governance.openstack.org/tc/reference/tags/index.html 7 | 8 | .. Change things from this point on 9 | 10 | =============================================== 11 | BGP-MPLS VPN Extension for OpenStack Networking 12 | =============================================== 13 | 14 | This project provides an API and Framework to interconnect BGP/MPLS VPNs 15 | to Openstack Neutron networks, routers and ports. 16 | 17 | The Border Gateway Protocol and Multi-Protocol Label Switching are widely 18 | used Wide Area Networking technologies. The primary purpose of this project 19 | is to allow attachment of Neutron networks and/or routers to VPNs built in 20 | carrier provided WANs using these standard protocols. An additional purpose 21 | of this project is to enable the use of these technologies within the Neutron 22 | networking environment. 23 | 24 | A vendor-neutral API and data model are provided such that multiple SDN 25 | controllers may be used as backends, while offering the same tenant facing API. 26 | A reference implementation working along with Neutron reference drivers is 27 | also provided. 28 | 29 | * Free software: Apache license 30 | * Source: https://opendev.org/openstack/networking-bgpvpn 31 | * Bugs: https://bugs.launchpad.net/bgpvpn 32 | * Doc: https://docs.openstack.org/networking-bgpvpn/latest/ 33 | * Release notes: https://docs.openstack.org/releasenotes/networking-bgpvpn/ 34 | 35 | =================== 36 | Introduction videos 37 | =================== 38 | 39 | The following videos are filmed presentations of talks given during the 40 | Barcelona OpenStack Summit (Oct' 2016). Although they do not cover the work 41 | done since, they can be a good introduction to the project: 42 | 43 | * https://www.youtube.com/watch?v=kGW5R8mtmRg 44 | * https://www.youtube.com/watch?v=LCDeR7MwTzE 45 | -------------------------------------------------------------------------------- /babel-django.cfg: -------------------------------------------------------------------------------- 1 | [python: **.py] 2 | [django: **/templates/**.html] 3 | -------------------------------------------------------------------------------- /babel-djangojs.cfg: -------------------------------------------------------------------------------- 1 | [javascript: **.js] 2 | [angular: **/static/**.html] 3 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/api/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/common/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/common/bgpvpn.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | import re 16 | 17 | from django.utils.translation import gettext_lazy as _ 18 | 19 | 20 | ROUTE_TARGET_HELP = _("A single BGP Route Target or a " 21 | "comma-separated list of BGP Route Target. Example: " 22 | "64512:1 or 64512:1,64512:2,64512:3") 23 | 24 | RT_FORMAT_ATTRIBUTES = ('route_targets', 'import_targets', 'export_targets') 25 | 26 | 27 | def format_rt(route_targets): 28 | if route_targets: 29 | return re.compile(" *, *").split(route_targets) 30 | else: 31 | return [] 32 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/admin/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/admin/bgpvpn/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/panel.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.utils.translation import gettext_lazy as _ 17 | 18 | import horizon 19 | 20 | 21 | class BGPVPNInterconnections(horizon.Panel): 22 | name = _("BGPVPN Interconnections") 23 | slug = "bgpvpn" 24 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/tabs.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations \ 17 | import tabs as network_tabs 18 | from bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations \ 19 | import tabs as router_tabs 20 | from bgpvpn_dashboard.dashboards.project.bgpvpn import tabs as project_tabs 21 | 22 | 23 | class OverviewTab(project_tabs.OverviewTab): 24 | template_name = "admin/bgpvpn/_detail_overview.html" 25 | 26 | 27 | class BgpvpnDetailsTabs(project_tabs.BgpvpnDetailsTabs): 28 | tabs = (OverviewTab, 29 | network_tabs.NetworkAssociationsTab, 30 | router_tabs.RouterAssociationsTab) 31 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/templates/bgpvpn/_create.html: -------------------------------------------------------------------------------- 1 | {% extends "horizon/common/_modal_form.html" %} 2 | {% load i18n %} 3 | 4 | {% block modal-body %} 5 |
6 |
7 | {% include "horizon/common/_form_fields.html" %} 8 |
9 |
10 |
11 |

{% trans "Description:" %}

12 |

{% trans "Create a new BGP VPN for any project as you need."%}

13 |
14 | {% endblock %} -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/templates/bgpvpn/_detail_overview.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |
4 |
5 |
{% trans "BGPVPN Name" %}
6 |
{{ bgpvpn.name }}
7 |
{% trans "BGPVPN ID" %}
8 |
{{ bgpvpn.id }}
9 |
{% trans "Type" %}
10 |
{{ bgpvpn.type }}
11 |
{% trans "Route Targets" %}
12 |
13 | {% for rt in bgpvpn.route_targets %} 14 | {{ rt }} 15 | {% endfor %} 16 |
17 |
{% trans "Import Targets" %}
18 |
19 | {% for it in bgpvpn.import_targets %} 20 | {{ it }} 21 | {% endfor %} 22 |
23 |
{% trans "Export Targets" %}
24 |
25 | {% for et in bgpvpn.export_targets %} 26 | {{ et }} 27 | {% endfor %} 28 |
29 |
{% trans "Project ID" %}
30 |
{{ bgpvpn.tenant_id }}
31 | {% include "project/bgpvpn/_associated_networks.html" %} 32 | {% include "project/bgpvpn/_associated_routers.html" %} 33 |
34 |
35 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/templates/bgpvpn/create.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Create BGPVPN" %}{% endblock %} 4 | 5 | {% block main %} 6 | {% include "admin/bgpvpn/_create.html" %} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/urls.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import re_path 17 | 18 | import bgpvpn_dashboard.dashboards.admin.bgpvpn.views as bgpvpn_views 19 | 20 | BGPVPN = r'^(?P[^/]+)/%s$' 21 | 22 | urlpatterns = [ 23 | re_path(r'^$', bgpvpn_views.IndexView.as_view(), name='index'), 24 | re_path(r'^create/$', bgpvpn_views.CreateView.as_view(), name='create'), 25 | re_path(BGPVPN % 'edit', bgpvpn_views.EditDataView.as_view(), 26 | name='edit'), 27 | re_path(BGPVPN % 'create-network-association', 28 | bgpvpn_views.CreateNetworkAssociationView.as_view(), 29 | name='create-network-association'), 30 | re_path(BGPVPN % 'create-router-association', 31 | bgpvpn_views.CreateRouterAssociationView.as_view(), 32 | name='create-router-association'), 33 | re_path(r'^(?P[^/]+)/detail/$', 34 | bgpvpn_views.DetailProjectView.as_view(), name='detail'), 35 | ] 36 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/views.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | from django.urls import reverse_lazy 16 | from django.utils.translation import gettext_lazy as _ 17 | 18 | from horizon import exceptions 19 | from horizon import forms 20 | from horizon.utils import memoized 21 | 22 | from openstack_dashboard import api 23 | 24 | import bgpvpn_dashboard.api.bgpvpn as bgpvpn_api 25 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import forms as bgpvpn_forms 26 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import tables as bgpvpn_tables 27 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import tabs as bgpvpn_tabs 28 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import workflows \ 29 | as bgpvpn_workflows 30 | from bgpvpn_dashboard.dashboards.project.bgpvpn import views as project_views 31 | 32 | 33 | class IndexView(project_views.IndexView): 34 | table_class = bgpvpn_tables.BgpvpnTable 35 | 36 | @memoized.memoized_method 37 | def _get_tenant_name(self, id): 38 | try: 39 | return api.keystone.tenant_get(self.request, id).name 40 | except Exception: 41 | msg = _("Unable to retrieve information about the " 42 | "tenant %s") % id 43 | exceptions.handle(self.request, msg) 44 | 45 | def get_data(self): 46 | bgpvpns_list = bgpvpn_api.bgpvpns_list(self.request) 47 | for bgpvpn in bgpvpns_list: 48 | bgpvpn.networks = [api.neutron.network_get( 49 | self.request, id, expand_subnet=False) 50 | for id in bgpvpn.networks] 51 | bgpvpn.routers = [api.neutron.router_get(self.request, id) 52 | for id in bgpvpn.routers] 53 | bgpvpn.tenant_name = self._get_tenant_name(bgpvpn.tenant_id) 54 | return bgpvpns_list 55 | 56 | 57 | class CreateView(forms.ModalFormView): 58 | form_class = bgpvpn_forms.CreateBgpVpn 59 | form_id = "create_bgpvpn_form" 60 | template_name = 'admin/bgpvpn/create.html' 61 | submit_label = _("Create BGPVPN") 62 | success_url = reverse_lazy('horizon:admin:bgpvpn:index') 63 | page_title = _("Create BGPVPN") 64 | submit_url = reverse_lazy("horizon:admin:bgpvpn:create") 65 | 66 | 67 | class EditDataView(project_views.EditDataView): 68 | form_class = bgpvpn_forms.EditDataBgpVpn 69 | submit_url = 'horizon:admin:bgpvpn:edit' 70 | success_url = reverse_lazy('horizon:admin:bgpvpn:index') 71 | 72 | 73 | class CreateNetworkAssociationView(project_views.CreateNetworkAssociationView): 74 | form_class = bgpvpn_forms.CreateNetworkAssociation 75 | submit_url = 'horizon:admin:bgpvpn:create-network-association' 76 | success_url = reverse_lazy('horizon:admin:bgpvpn:index') 77 | 78 | 79 | class CreateRouterAssociationView(project_views.CreateRouterAssociationView): 80 | workflow_class = bgpvpn_workflows.RouterAssociation 81 | failure_url = reverse_lazy("horizon:admin:bgpvpn:index") 82 | 83 | 84 | class DetailProjectView(project_views.DetailProjectView): 85 | tab_group_class = bgpvpn_tabs.BgpvpnDetailsTabs 86 | redirect_url = 'horizon:admin:bgpvpn:index' 87 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/admin/bgpvpn/workflows.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from bgpvpn_dashboard.dashboards.project.bgpvpn import workflows \ 17 | as project_workflows 18 | 19 | 20 | class RouterAssociation(project_workflows.RouterAssociation): 21 | success_url = "horizon:admin:bgpvpn:index" 22 | 23 | def _set_params(self, data, association_type, resource): 24 | params = super()._set_params( 25 | data, association_type, resource) 26 | params['tenant_id'] = data['tenant_id'] 27 | return params 28 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/project/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/project/bgpvpn/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/tables.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | import logging 16 | 17 | from django.urls import reverse 18 | from django.urls import reverse_lazy 19 | from django.utils import safestring 20 | from django.utils.translation import gettext_lazy as _ 21 | from django.utils.translation import ngettext_lazy 22 | 23 | from horizon import exceptions 24 | from horizon import tables 25 | 26 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 27 | 28 | LOG = logging.getLogger(__name__) 29 | 30 | 31 | class DeleteNetworkAssociation(tables.DeleteAction): 32 | 33 | @staticmethod 34 | def action_present(count): 35 | return ngettext_lazy("Delete Network Association", 36 | "Delete Network Associations", 37 | count) 38 | 39 | @staticmethod 40 | def action_past(count): 41 | return ngettext_lazy("Deleted Network Association", 42 | "Deleted Network Associations", 43 | count) 44 | 45 | def delete(self, request, asso_id): 46 | try: 47 | bgpvpn_api.network_association_delete( 48 | request, asso_id, self.table.kwargs['bgpvpn_id']) 49 | except Exception: 50 | msg = _('Failed to delete Network Association %s') % asso_id 51 | LOG.info(msg) 52 | redirect = reverse('horizon:project:bgpvpn:detail') 53 | exceptions.handle(request, msg, redirect=redirect) 54 | 55 | 56 | class CreateNetworkAssociation(tables.LinkAction): 57 | name = "create_network_association" 58 | verbose_name = _("Create Network Association") 59 | url = "horizon:project:bgpvpn:create-network-association" 60 | classes = ("ajax-modal",) 61 | icon = "pencil" 62 | 63 | def get_link_url(self, datum=None): 64 | bgpvpn_id = self.table.kwargs['bgpvpn_id'] 65 | return reverse(self.url, args=(bgpvpn_id,)) 66 | 67 | 68 | class IDColumn(tables.Column): 69 | url = "horizon:project:bgpvpn:network_assos:detail" 70 | 71 | def get_link_url(self, asso): 72 | bgpvpn_id = self.table.kwargs['bgpvpn_id'] 73 | return reverse(self.url, args=(bgpvpn_id, asso.id)) 74 | 75 | 76 | class NetworkColumn(tables.Column): 77 | def get_raw_data(self, asso): 78 | url = reverse('horizon:project:networks:detail', 79 | args=[asso.network_id]) 80 | instance = '{}'.format(url, 81 | asso.network_name or asso.network_id) 82 | return safestring.mark_safe(instance) 83 | 84 | 85 | class NetworkAssociationsTable(tables.DataTable): 86 | id = IDColumn("id", verbose_name=_("Association ID"), 87 | link='horizon:project:bgpvpn:network_assos:detail') 88 | network = NetworkColumn("network_id", verbose_name=_("Network")) 89 | 90 | failure_url = reverse_lazy('horizon:project:bgpvpn:detail') 91 | 92 | class Meta: 93 | name = "network_associations" 94 | verbose_name = _("Network Associations") 95 | table_actions = (CreateNetworkAssociation,) 96 | row_actions = (DeleteNetworkAssociation,) 97 | hidden_title = False 98 | 99 | def get_object_display(self, asso): 100 | return asso.id 101 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/tabs.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import reverse 17 | from django.utils.translation import gettext_lazy as _ 18 | 19 | from horizon import exceptions 20 | from horizon import tabs 21 | from horizon.utils import memoized 22 | 23 | from openstack_dashboard import api 24 | 25 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 26 | 27 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations \ 28 | import tables as network_tables 29 | 30 | 31 | class OverviewTab(tabs.Tab): 32 | name = _("Overview") 33 | slug = "overview" 34 | template_name = "project/bgpvpn/network_associations/_detail_overview.html" 35 | 36 | def get_context_data(self, request): 37 | network_association = self.tab_group.kwargs['network_association'] 38 | network = self.get_network(network_association.network_id) 39 | network_association.network_name = network.get('name') 40 | network_association.network_url = self.get_network_detail_url( 41 | network_association.network_id) 42 | return {'network_association': network_association} 43 | 44 | @memoized.memoized_method 45 | def get_network(self, network_id): 46 | try: 47 | network = api.neutron.network_get(self.request, network_id) 48 | except Exception: 49 | network = {} 50 | msg = _('Unable to retrieve network details.') 51 | exceptions.handle(self.request, msg) 52 | 53 | return network 54 | 55 | @staticmethod 56 | def get_network_detail_url(network_id): 57 | return reverse('horizon:project:networks:detail', args=(network_id,)) 58 | 59 | 60 | class NetworkAssociationsTab(tabs.TableTab): 61 | name = _("Network Associations") 62 | slug = "network_associations_tab" 63 | table_classes = (network_tables.NetworkAssociationsTable,) 64 | template_name = ("horizon/common/_detail_table.html") 65 | preload = False 66 | 67 | def get_network_associations_data(self): 68 | try: 69 | bgpvpn_id = self.tab_group.kwargs['bgpvpn_id'] 70 | network_associations = bgpvpn_api.network_association_list( 71 | self.request, bgpvpn_id) 72 | for network_asso in network_associations: 73 | network = api.neutron.network_get(self.request, 74 | network_asso.network_id) 75 | network_asso.network_name = network.name 76 | except Exception: 77 | network_associations = [] 78 | msg = _('Network associations list can not be retrieved.') 79 | exceptions.handle(self.request, msg) 80 | return network_associations 81 | 82 | 83 | class NetworkAssociationDetailTabs(tabs.TabGroup): 84 | slug = "network_association_details" 85 | tabs = (OverviewTab,) 86 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/urls.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import re_path 17 | 18 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations \ 19 | import views as bgpvpn_network_associations_views 20 | 21 | NETWORK_ASSO = r'^(?P[^/]+)/network_assos/' \ 22 | r'(?P[^/]+)/%s$' 23 | 24 | urlpatterns = [ 25 | re_path(NETWORK_ASSO % 'detail', 26 | bgpvpn_network_associations_views.DetailView.as_view(), 27 | name='detail'), 28 | ] 29 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/network_associations/views.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import reverse 17 | from django.utils.translation import gettext_lazy as _ 18 | from horizon import exceptions 19 | from horizon import tabs 20 | 21 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 22 | 23 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations \ 24 | import tabs as project_tabs 25 | 26 | 27 | class DetailView(tabs.TabView): 28 | tab_group_class = project_tabs.NetworkAssociationDetailTabs 29 | template_name = 'horizon/common/_detail.html' 30 | page_title = "{{ network_association.id }}" 31 | 32 | def get_data(self): 33 | network_association_id = self.kwargs['network_association_id'] 34 | bgpvpn_id = self.kwargs['bgpvpn_id'] 35 | try: 36 | network_association = bgpvpn_api.network_association_get( 37 | self.request, bgpvpn_id, network_association_id) 38 | return network_association 39 | except Exception: 40 | network_association = [] 41 | msg = _('Unable to retrieve network association details.') 42 | exceptions.handle(self.request, msg, 43 | redirect=self.get_redirect_url()) 44 | return network_association 45 | 46 | def get_context_data(self, **kwargs): 47 | context = super().get_context_data(**kwargs) 48 | network_association = self.get_data() 49 | context["url"] = reverse( 50 | "horizon:project:bgpvpn:network_associations_tab", 51 | args=(self.kwargs["bgpvpn_id"], network_association.id)) 52 | return context 53 | 54 | def get_tabs(self, request, *args, **kwargs): 55 | network_association = self.get_data() 56 | return self.tab_group_class( 57 | request, network_association=network_association, **kwargs) 58 | 59 | @staticmethod 60 | def get_redirect_url(): 61 | return reverse('horizon:project:bgpvpn:index') 62 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/panel.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.utils.translation import gettext_lazy as _ 17 | 18 | import horizon 19 | 20 | 21 | class BGPVPNInterconnections(horizon.Panel): 22 | name = _("BGPVPN Interconnections") 23 | slug = "bgpvpn" 24 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/router_associations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/dashboards/project/bgpvpn/router_associations/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/router_associations/forms.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import logging 17 | 18 | from django.utils.translation import gettext_lazy as _ 19 | 20 | from horizon import exceptions 21 | from horizon import forms 22 | 23 | 24 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 25 | 26 | LOG = logging.getLogger(__name__) 27 | 28 | 29 | class UpdateRouterAssociation(forms.SelfHandlingForm): 30 | bgpvpn_id = forms.CharField(widget=forms.HiddenInput()) 31 | router_association_id = forms.CharField( 32 | label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) 33 | router_id = forms.CharField( 34 | label=_("Router"), 35 | widget=forms.TextInput(attrs={'readonly': 'readonly'})) 36 | advertise_extra_routes = forms.BooleanField( 37 | label=_("Advertise Extra Routes"), 38 | initial=True, 39 | required=False, 40 | help_text="Boolean flag controlling whether or not the routes " 41 | "specified in the routes attribute of the router will be " 42 | "advertised to the BGPVPN (default: true).") 43 | 44 | def __init__(self, request, *args, **kwargs): 45 | super().__init__(request, *args, **kwargs) 46 | self.action = 'update' 47 | 48 | def handle(self, request, data): 49 | router_association_id = data['router_association_id'] 50 | bgpvpn_id = data['bgpvpn_id'] 51 | try: 52 | bgpvpn_api.router_association_update( 53 | request, bgpvpn_id, router_association_id, 54 | advertise_extra_routes=data['advertise_extra_routes']) 55 | return True 56 | except exceptions as e: 57 | exceptions.handle( 58 | request, 59 | "Unable to update bgpvpn router association %s:" % str(e)) 60 | return False 61 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/router_associations/tabs.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import reverse 17 | 18 | from django.utils.translation import gettext_lazy as _ 19 | 20 | from horizon import exceptions 21 | from horizon import tabs 22 | from horizon.utils import memoized 23 | 24 | from openstack_dashboard import api 25 | 26 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 27 | 28 | from bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations \ 29 | import tables as router_tables 30 | 31 | 32 | class OverviewTab(tabs.Tab): 33 | name = _("Overview") 34 | slug = "overview" 35 | template_name = "project/bgpvpn/router_associations/_detail_overview.html" 36 | 37 | def get_context_data(self, request): 38 | router_association = self.tab_group.kwargs['router_association'] 39 | router = self.get_router(router_association.router_id) 40 | router_association.router_name = router.get('name') 41 | router_association.router_url = self.get_router_detail_url( 42 | router_association.router_id) 43 | return {'router_association': router_association} 44 | 45 | @memoized.memoized_method 46 | def get_router(self, router_id): 47 | try: 48 | router = api.neutron.router_get(self.request, router_id) 49 | except Exception: 50 | router = {} 51 | msg = _('Unable to retrieve router details.') 52 | exceptions.handle(self.request, msg) 53 | 54 | return router 55 | 56 | @staticmethod 57 | def get_router_detail_url(router_id): 58 | return reverse('horizon:project:routers:detail', args=(router_id,)) 59 | 60 | 61 | class RouterAssociationsTab(tabs.TableTab): 62 | name = _("Router Associations") 63 | slug = "router_associations_tab" 64 | table_classes = (router_tables.RouterAssociationsTable,) 65 | template_name = ("horizon/common/_detail_table.html") 66 | preload = False 67 | 68 | def get_router_associations_data(self): 69 | try: 70 | bgpvpn_id = self.tab_group.kwargs['bgpvpn_id'] 71 | router_associations = bgpvpn_api.router_association_list( 72 | self.request, bgpvpn_id) 73 | for router_asso in router_associations: 74 | router = api.neutron.router_get(self.request, 75 | router_asso.router_id) 76 | router_asso.router_name = router.name 77 | except Exception: 78 | router_associations = [] 79 | msg = _('Router associations list can not be retrieved.') 80 | exceptions.handle(self.request, msg) 81 | return router_associations 82 | 83 | 84 | class RouterAssociationDetailTabs(tabs.TabGroup): 85 | slug = "router_association_details" 86 | tabs = (OverviewTab,) 87 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/router_associations/urls.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import re_path 17 | 18 | import bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations.views \ 19 | as bgpvpn_router_associations_views 20 | 21 | ROUTER_ASSO = r'^(?P[^/]+)/router_assos/' \ 22 | r'(?P[^/]+)/%s$' 23 | 24 | urlpatterns = [ 25 | re_path(ROUTER_ASSO % 'detail', 26 | bgpvpn_router_associations_views.DetailView.as_view(), 27 | name='detail'), 28 | ] 29 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/tables.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.urls import reverse 17 | from django.utils import html 18 | from django.utils.http import urlencode 19 | from django.utils import safestring 20 | from django.utils.translation import gettext_lazy as _ 21 | from horizon import tables 22 | 23 | 24 | class EditInfoBgpVpn(tables.LinkAction): 25 | name = "update_info" 26 | verbose_name = _("Edit BGPVPN") 27 | url = "horizon:project:bgpvpn:edit" 28 | classes = ("ajax-modal",) 29 | icon = "pencil" 30 | 31 | 32 | class CreateNetworkAssociation(tables.LinkAction): 33 | name = "create_network_association" 34 | verbose_name = _("Create Network Association") 35 | url = "horizon:project:bgpvpn:create-network-association" 36 | classes = ("ajax-modal",) 37 | icon = "pencil" 38 | 39 | 40 | class CreateRouterAssociation(tables.LinkAction): 41 | name = "create_router_association" 42 | verbose_name = _("Create Router Association") 43 | url = "horizon:project:bgpvpn:create-router-association" 44 | classes = ("ajax-modal",) 45 | icon = "pencil" 46 | 47 | def get_link_url(self, bgpvpn): 48 | step = 'create_router_association' 49 | base_url = reverse(self.url, args=[bgpvpn.id]) 50 | param = urlencode({"step": step}) 51 | return "?".join([base_url, param]) 52 | 53 | 54 | def get_network_url(network): 55 | url = reverse('horizon:project:networks:detail', args=[network.id]) 56 | instance = '{}'.format(url, html.escape(network.name_or_id)) 57 | return instance 58 | 59 | 60 | def get_router_url(router): 61 | url = reverse('horizon:project:routers:detail', args=[router.id]) 62 | instance = '{}'.format(url, html.escape(router.name_or_id)) 63 | return instance 64 | 65 | 66 | class NetworksColumn(tables.Column): 67 | def get_raw_data(self, bgpvpn): 68 | networks = [get_network_url(network) for network in bgpvpn.networks] 69 | return safestring.mark_safe(', '.join(networks)) 70 | 71 | 72 | class RoutersColumn(tables.Column): 73 | def get_raw_data(self, bgpvpn): 74 | routers = [get_router_url(router) for router in bgpvpn.routers] 75 | return safestring.mark_safe(', '.join(routers)) 76 | 77 | 78 | class BgpvpnTable(tables.DataTable): 79 | name = tables.Column("name_or_id", 80 | verbose_name=_("Name"), 81 | link=("horizon:project:bgpvpn:detail")) 82 | type = tables.Column("type", verbose_name=_("Type")) 83 | networks = NetworksColumn("networks", verbose_name=_("Networks")) 84 | routers = RoutersColumn("routers", verbose_name=_("Routers")) 85 | 86 | class Meta: 87 | name = "bgpvpns" 88 | verbose_name = _("BGPVPN") 89 | row_actions = (EditInfoBgpVpn, 90 | CreateNetworkAssociation, 91 | CreateRouterAssociation) 92 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/tabs.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | import bgpvpn_dashboard.api.bgpvpn as bgpvpn_api 17 | 18 | from django.utils.translation import gettext_lazy as _ 19 | 20 | from horizon import exceptions 21 | from horizon import tabs 22 | 23 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations \ 24 | import tabs as network_tabs 25 | from bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations \ 26 | import tabs as router_tabs 27 | 28 | 29 | class OverviewTab(tabs.Tab): 30 | name = _("Overview") 31 | slug = "overview" 32 | template_name = ("project/bgpvpn/_detail_overview.html") 33 | preload = False 34 | 35 | def _get_data(self): 36 | bgpvpn = {} 37 | bgpvpn_id = None 38 | try: 39 | bgpvpn_id = self.tab_group.kwargs['bgpvpn_id'] 40 | bgpvpn = bgpvpn_api.bgpvpn_get(self.request, bgpvpn_id) 41 | bgpvpn.set_id_as_name_if_empty(length=0) 42 | except Exception: 43 | msg = _('Unable to retrieve details for bgpvpn "%s".') % ( 44 | bgpvpn_id) 45 | exceptions.handle(self.request, msg) 46 | return bgpvpn 47 | 48 | def get_context_data(self, request, **kwargs): 49 | context = super().get_context_data(request, **kwargs) 50 | bgpvpn = self._get_data() 51 | context["bgpvpn"] = bgpvpn 52 | return context 53 | 54 | 55 | class BgpvpnDetailsTabs(tabs.DetailTabsGroup): 56 | slug = "bgpvpn_tabs" 57 | tabs = (OverviewTab, 58 | network_tabs.NetworkAssociationsTab, 59 | router_tabs.RouterAssociationsTab) 60 | sticky = True 61 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/_associated_networks.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |
4 | {% if bgpvpn.networks|length > 1 %} 5 | {% trans "Associated Networks" %} 6 | {% else %} 7 | {% trans "Associated Network" %} 8 | {% endif %} 9 |
10 | {% for network in bgpvpn.networks %} 11 |
12 | {% url 'horizon:project:networks:detail' network as network_url %} 13 | {{ network }} 14 |
15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/_associated_routers.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |
4 | {% if bgpvpn.routers|length > 1 %} 5 | {% trans "Associated Routers" %} 6 | {% else %} 7 | {% trans "Associated Router" %} 8 | {% endif %} 9 |
10 | {% for router in bgpvpn.routers %} 11 |
12 | {% url 'horizon:project:routers:detail' router as router_url %} 13 | {{ router }} 14 |
15 | {% endfor %} -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/_create_network_association.html: -------------------------------------------------------------------------------- 1 | {% extends "horizon/common/_modal_form.html" %} 2 | {% load i18n %} 3 | 4 | {% block modal-body-right %} 5 |

{% trans "Description:" %}

6 |

{% trans "Associate a BGPVPN to a Network" %}

7 | {% endblock %} -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/_detail_overview.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 |
3 |
4 |
{% trans "BGPVPN Name" %}
5 |
{{ bgpvpn.name }}
6 |
{% trans "BGPVPN ID" %}
7 |
{{ bgpvpn.id }}
8 |
{% trans "Type" %}
9 |
{{ bgpvpn.type }}
10 | {% include "project/bgpvpn/_associated_networks.html" %} 11 | {% include "project/bgpvpn/_associated_routers.html" %} 12 |
13 |
14 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/_modify.html: -------------------------------------------------------------------------------- 1 | {% extends "horizon/common/_modal_form.html" %} 2 | {% load i18n %} 3 | 4 | {% block modal-body-right %} 5 |

{% trans "Description:" %}

6 |

{% trans "You may update the editable properties of your BGP VPN here." %}

7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/create_network_association.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Create Network Association" %}{% endblock %} 4 | 5 | {% block main %} 6 | {% include "project/bgpvpn/_create_network_association.html" %} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load i18n %} 3 | {% block title %}{% trans "BGP VPNs" %}{% endblock %} 4 | 5 | {% block main %} 6 | {{ table.render }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/modify.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Update BGPVPN" %}{% endblock %} 4 | 5 | {% block main %} 6 | {% include "project/bgpvpn/_modify.html" %} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/network_associations/_detail_overview.html: -------------------------------------------------------------------------------- 1 | {% load i18n sizeformat %} 2 | 3 |
4 |
5 |
{% trans "Association ID" %}
6 |
{{network_association.id|default:_("None") }}
7 |
{% trans "Network Name" %}
8 |
{{ network_association.network_name|default:_("None") }}
9 |
{% trans "Network ID" %}
10 |
{{ network_association.network_id|default:_("None") }}
11 |
12 |
13 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/router_associations/_detail_overview.html: -------------------------------------------------------------------------------- 1 | {% load i18n sizeformat %} 2 | 3 |
4 |
5 |
{% trans "Association ID" %}
6 |
{{router_association.id|default:_("None") }}
7 |
{% trans "Router Name" %}
8 |
{{ router_association.router_name|default:_("None") }}
9 |
{% trans "Router ID" %}
10 |
{{ router_association.router_id|default:_("None") }}
11 |
{% trans "Advertise Extra Routes" %}
12 |
{{router_association.advertise_extra_routes }}
13 |
14 |
15 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/router_associations/_modify.html: -------------------------------------------------------------------------------- 1 | {% extends "horizon/common/_modal_form.html" %} 2 | {% load i18n %} 3 | 4 | {% block modal-body-right %} 5 |

{% trans "Description:" %}

6 |

{% trans "You may update the editable properties of your BGPVPN Router Association here." %}

7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/templates/bgpvpn/router_associations/modify.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Update BGPVPN Router Association" %}{% endblock %} 4 | 5 | {% block main %} 6 | {% include "project/bgpvpn/_modify.html" %} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/dashboards/project/bgpvpn/urls.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django.conf.urls import include 17 | from django.urls import re_path 18 | 19 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations import \ 20 | urls as network_associations_urls 21 | from bgpvpn_dashboard.dashboards.project.bgpvpn.network_associations import \ 22 | views as network_associations_views 23 | from bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations import \ 24 | urls as router_associations_urls 25 | from bgpvpn_dashboard.dashboards.project.bgpvpn.router_associations import \ 26 | views as router_associations_views 27 | from bgpvpn_dashboard.dashboards.project.bgpvpn import views as bgpvpn_views 28 | 29 | BGPVPN = r'^(?P[^/]+)/%s$' 30 | 31 | urlpatterns = [ 32 | re_path(r'^$', bgpvpn_views.IndexView.as_view(), name='index'), 33 | re_path(BGPVPN % 'edit', bgpvpn_views.EditDataView.as_view(), 34 | name='edit'), 35 | re_path(BGPVPN % 'create-network-association', 36 | bgpvpn_views.CreateNetworkAssociationView.as_view(), 37 | name='create-network-association'), 38 | re_path(BGPVPN % 'create-router-association', 39 | bgpvpn_views.CreateRouterAssociationView.as_view(), 40 | name='create-router-association'), 41 | re_path(r'^(?P[^/]+)/detail/$', 42 | bgpvpn_views.DetailProjectView.as_view(), name='detail'), 43 | re_path(r'^(?P[^/]+)/network_assos/' 44 | r'(?P[^/]+)/' 45 | r'detail\?tab=bgpvpns__network__associations_tab$', 46 | network_associations_views.DetailView.as_view(), 47 | name='network_associations_tab'), 48 | re_path(r'^(?P[^/]+)/router_assos/(?P' 49 | r'[^/]+)/' 50 | r'detail\?tab=bgpvpns__router_associations_tab$', 51 | router_associations_views.DetailView.as_view(), 52 | name='router_associations_tab'), 53 | re_path(r'^(?P[^/]+)/router_assos/(?P' 54 | r'[^/]+)/' 55 | r'update$', 56 | router_associations_views.UpdateRouterAssociationsView.as_view(), 57 | name='update-router-association'), 58 | re_path(r'^network_assos/', 59 | include((network_associations_urls, 'network_assos'))), 60 | re_path(r'^router_assos/', 61 | include((router_associations_urls, 'router_assos'))), 62 | ] 63 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/enabled/_1495_project_bgpvpn_panel.py: -------------------------------------------------------------------------------- 1 | # The slug of the panel to be added to HORIZON_CONFIG. Required. 2 | PANEL = 'BGPVPN Interconnections' 3 | # The slug of the dashboard the PANEL associated with. Required. 4 | PANEL_DASHBOARD = 'project' 5 | # The slug of the panel group the PANEL is associated with. 6 | PANEL_GROUP = 'network' 7 | 8 | # Python panel class of the PANEL to be added. 9 | ADD_PANEL = ('bgpvpn_dashboard.' 10 | 'dashboards.project.bgpvpn.panel.BGPVPNInterconnections') 11 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/enabled/_2360_admin_bgpvpn_panel.py: -------------------------------------------------------------------------------- 1 | # The slug of the panel to be added to HORIZON_CONFIG. Required. 2 | PANEL = 'BGPVPN Interconnections' 3 | # The slug of the dashboard the PANEL associated with. Required. 4 | PANEL_DASHBOARD = 'admin' 5 | # The slug of the panel group the PANEL is associated with. 6 | PANEL_GROUP = 'network' 7 | 8 | # Python panel class of the PANEL to be added. 9 | ADD_PANEL = ('bgpvpn_dashboard.' 10 | 'dashboards.admin.bgpvpn.panel.BGPVPNInterconnections') 11 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/enabled/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/enabled/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/etc/bgpvpn-horizon.conf: -------------------------------------------------------------------------------- 1 | { 2 | "context_is_admin": "role:admin", 3 | "admin_only": "rule:context_is_admin", 4 | "admin_or_owner": "rule:context_is_admin or tenant_id:%(tenant_id)s", 5 | 6 | "create_bgpvpn": "rule:admin_only", 7 | 8 | "get_bgpvpn": "rule:admin_or_owner", 9 | "get_bgpvpn:tenant_id": "rule:admin_only", 10 | "get_bgpvpn:route_targets": "rule:admin_only", 11 | "get_bgpvpn:import_targets": "rule:admin_only", 12 | "get_bgpvpn:export_targets": "rule:admin_only", 13 | "get_bgpvpn:route_distinguishers": "rule:admin_only", 14 | 15 | "update_bgpvpn": "rule:admin_or_owner", 16 | "update_bgpvpn:tenant_id": "rule:admin_only", 17 | "update_bgpvpn:route_targets": "rule:admin_only", 18 | "update_bgpvpn:import_targets": "rule:admin_only", 19 | "update_bgpvpn:export_targets": "rule:admin_only", 20 | "update_bgpvpn:route_distinguishers": "rule:admin_only", 21 | 22 | "delete_bgpvpn": "rule:admin_only", 23 | 24 | "create_bgpvpn_network_association": "rule:admin_or_owner", 25 | "get_bgpvpn_network_association": "rule:admin_or_owner", 26 | "get_bgpvpn_network_association:tenant_id": "rule:admin_only", 27 | "get_bgpvpn_network_associations": "rule:admin_or_owner", 28 | "update_bgpvpn_network_association": "rule:admin_or_owner", 29 | "delete_bgpvpn_network_association": "rule:admin_or_owner", 30 | 31 | "create_bgpvpn_router_association": "rule:admin_or_owner", 32 | "get_bgpvpn_router_association": "rule:admin_or_owner", 33 | "get_bgpvpn_router_association:tenant_id": "rule:admin_only", 34 | "get_bgpvpn_router_associations": "rule:admin_or_owner", 35 | "update_bgpvpn_router_association": "rule:admin_or_owner", 36 | "delete_bgpvpn_router_association": "rule:admin_or_owner", 37 | 38 | "create_bgpvpn_port_association": "rule:admin_or_owner", 39 | "get_bgpvpn_port_association": "rule:admin_or_owner", 40 | "get_bgpvpn_port_association:tenant_id": "rule:admin_only", 41 | "get_bgpvpn_port_associations": "rule:admin_or_owner", 42 | "update_bgpvpn_port_association": "rule:admin_or_owner", 43 | "delete_bgpvpn_port_association": "rule:admin_or_owner" 44 | } 45 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/test/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/admin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/test/admin/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/admin/test_tables.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from django import test 17 | from unittest import mock 18 | 19 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import tables as bgpvpn_tables 20 | 21 | 22 | class TestDeleteBgpvpns(test.TestCase): 23 | @mock.patch.object(bgpvpn_tables, 'bgpvpn_api') 24 | def test_delete(self, mock_bgpvpn_api): 25 | mock_request = mock.Mock() 26 | delete_bgpvpn = bgpvpn_tables.DeleteBgpvpn() 27 | delete_bgpvpn.delete(mock_request, "id") 28 | mock_bgpvpn_api.bgpvpn_delete.assert_called_once_with(mock_request, 29 | "id") 30 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/admin/test_views.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | from unittest import mock 16 | 17 | from collections import namedtuple 18 | 19 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 20 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import tables as bgpvpn_tables 21 | from bgpvpn_dashboard.dashboards.admin.bgpvpn import views as bgpvpn_views 22 | 23 | from openstack_dashboard.test import helpers 24 | 25 | VIEWS = "bgpvpn_dashboard.dashboards.admin.bgpvpn.views" 26 | 27 | 28 | class TestIndexView(helpers.APITestCase): 29 | 30 | def setUp(self): 31 | super().setUp() 32 | mock_request = mock.Mock(horizon={'async_messages': []}) 33 | self.bgpvpn_view = bgpvpn_views.IndexView(request=mock_request) 34 | self.assertEqual(bgpvpn_tables.BgpvpnTable, 35 | self.bgpvpn_view.table_class) 36 | 37 | def _get_mock_bgpvpn(self, prefix): 38 | bgpvpn_info = {} 39 | if prefix: 40 | bgpvpn_info = { 41 | "name": "%s_name" % prefix, 42 | "route_targets": [], 43 | "import_targets": [], 44 | "export_targets": [], 45 | "networks": [], 46 | "routers": [], 47 | "tenant_id": "tenant_id", 48 | "type": "l3" 49 | } 50 | return bgpvpn_api.Bgpvpn(bgpvpn_info) 51 | 52 | @mock.patch.object(bgpvpn_views.api, 'keystone', autospec=True) 53 | def test_get_tenant_name(self, mock_api): 54 | Tenant = namedtuple("Tenant", ["id", "name"]) 55 | tenant = Tenant("tenant_id", "tenant_name") 56 | 57 | mock_api.tenant_get.return_value = tenant 58 | result = self.bgpvpn_view._get_tenant_name("tenant_id") 59 | 60 | mock_api.tenant_get.assert_called_once_with( 61 | self.bgpvpn_view.request, "tenant_id") 62 | self.assertEqual(result, "tenant_name") 63 | 64 | @mock.patch('%s.IndexView._get_tenant_name' % VIEWS, 65 | return_value={"tenant_id": "tenant_name"}) 66 | @mock.patch.object(bgpvpn_views, 'api', autospec=True) 67 | @mock.patch.object(bgpvpn_views, 'bgpvpn_api', autospec=True) 68 | def test_get_data(self, mock_bgpvpn_api, mock_api, mock_get_tenant_name): 69 | bgpvpn_foo = self._get_mock_bgpvpn("foo") 70 | bgpvpn_bar = self._get_mock_bgpvpn("bar") 71 | mock_neutron_client = mock_api.neutron.neutronclient(mock.Mock()) 72 | mock_bgpvpn_api.bgpvpns_list.return_value = [bgpvpn_foo, bgpvpn_bar] 73 | mock_neutron_client.list_networks.return_value = [] 74 | mock_neutron_client.list_routers.return_value = [] 75 | 76 | expected_bgpvpns = [bgpvpn_foo, bgpvpn_bar] 77 | result = self.bgpvpn_view.get_data() 78 | 79 | calls = [mock.call("tenant_id"), mock.call("tenant_id")] 80 | mock_get_tenant_name.assert_has_calls(calls) 81 | self.assertEqual(result, expected_bgpvpns) 82 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/api_tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/test/api_tests/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from openstack_dashboard.test import helpers 17 | 18 | from bgpvpn_dashboard.test.test_data import utils 19 | 20 | 21 | class TestCase(helpers.TestCase): 22 | 23 | def _setup_test_data(self): 24 | super()._setup_test_data() 25 | utils.load_test_data(self) 26 | 27 | 28 | class APITestCase(helpers.APITestCase): 29 | 30 | def _setup_test_data(self): 31 | super()._setup_test_data() 32 | utils.load_test_data(self) 33 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/test/project/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/project/test_forms.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from unittest import mock 17 | 18 | from openstack_dashboard.test import helpers 19 | 20 | from bgpvpn_dashboard.api import bgpvpn as bgpvpn_api 21 | from bgpvpn_dashboard.dashboards.project.bgpvpn import forms as bgpvpn_form 22 | 23 | 24 | class TestEditDataBgpVpn(helpers.APITestCase): 25 | 26 | def setUp(self): 27 | super().setUp() 28 | self.mock_request = mock.MagicMock() 29 | self.bgpvpn_form = bgpvpn_form.EditDataBgpVpn(self.mock_request) 30 | self.bgpvpn_form.action = "update" 31 | 32 | @mock.patch.object(bgpvpn_form, 'bgpvpn_api') 33 | def test_handle(self, mock_bgpvpn_api): 34 | self.bgpvpn_form.request.user.is_superuser = False 35 | test_data = {"bgpvpn_id": "foo-id", 36 | "name": "foo-name", 37 | "type": "l3"} 38 | expected_data = bgpvpn_api.Bgpvpn({"id": "foo-id", 39 | "name": "foo-name", 40 | "type": "l3"}) 41 | mock_bgpvpn_api.bgpvpn_update.return_value = expected_data 42 | result = self.bgpvpn_form.handle(self.mock_request, test_data) 43 | 44 | self.assertEqual(expected_data, result) 45 | mock_bgpvpn_api.bgpvpn_update.assert_called_once_with( 46 | self.mock_request, "foo-id", name="foo-name") 47 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/project/test_tables.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from unittest import mock 17 | 18 | from django import test 19 | from django.utils.translation import gettext_lazy as _ 20 | 21 | from bgpvpn_dashboard.dashboards.project.bgpvpn import tables as bgpvpn_tables 22 | 23 | 24 | class TestFunctionGet(test.TestCase): 25 | 26 | @mock.patch.object(bgpvpn_tables, 'reverse') 27 | def test_get_network_url(self, mock_reverse): 28 | mock_reverse.return_value = 'foo_reverse_url' 29 | mock_network = mock.Mock(id='foo-id', name_or_id="foo") 30 | result = bgpvpn_tables.get_network_url(mock_network) 31 | mock_reverse.assert_called_once_with( 32 | 'horizon:project:networks:detail', args=['foo-id']) 33 | self.assertEqual('foo', result) 34 | 35 | @mock.patch.object(bgpvpn_tables, 'reverse') 36 | def test_get_router_url(self, mock_reverse): 37 | mock_reverse.return_value = 'foo_reverse_url' 38 | mock_network = mock.Mock(id='foo-id', name_or_id="foo") 39 | result = bgpvpn_tables.get_router_url(mock_network) 40 | mock_reverse.assert_called_once_with( 41 | 'horizon:project:routers:detail', args=['foo-id']) 42 | self.assertEqual('foo', result) 43 | 44 | 45 | class TestNetworksColumn(test.TestCase): 46 | 47 | def setUp(self): 48 | super().setUp() 49 | self.nets_column = bgpvpn_tables.NetworksColumn( 50 | "networks", verbose_name=_("Networks")) 51 | 52 | def test_get_raw_data(self): 53 | result_expected = "foo1, " \ 54 | "foo2" 55 | mock_net1 = mock.Mock(id="id1", name_or_id="foo1") 56 | mock_net2 = mock.Mock(id="id2", name_or_id="foo2") 57 | networks = [mock_net1, mock_net2] 58 | mock_bgpvpn = mock.Mock(networks=networks) 59 | result = self.nets_column.get_raw_data(mock_bgpvpn) 60 | 61 | self.assertEqual(result_expected, result) 62 | 63 | 64 | class TestRoutersColumn(test.TestCase): 65 | 66 | def setUp(self): 67 | super().setUp() 68 | self.routers_column = bgpvpn_tables.RoutersColumn( 69 | "routers", verbose_name=_("Routers")) 70 | 71 | def test_get_raw_data(self): 72 | result_expected = "foo1, " \ 73 | "foo2" 74 | mock_router1 = mock.Mock(id="id1", name_or_id="foo1") 75 | mock_router2 = mock.Mock(id="id2", name_or_id="foo2") 76 | routers = [mock_router1, mock_router2] 77 | mock_bgpvpn = mock.Mock(routers=routers) 78 | result = self.routers_column.get_raw_data(mock_bgpvpn) 79 | 80 | self.assertEqual(result_expected, result) 81 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/settings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | # Default to Horizons test settings to avoid any missing keys 15 | from horizon.test.settings import * # noqa 16 | from openstack_dashboard.test.settings import * # noqa 17 | 18 | import bgpvpn_dashboard.enabled 19 | import openstack_dashboard.enabled 20 | 21 | from openstack_dashboard.utils import settings 22 | 23 | 24 | # pop these keys to avoid log warnings about deprecation 25 | # update_dashboards will populate them anyway 26 | HORIZON_CONFIG.pop('dashboards', None) # noqa: F405 27 | HORIZON_CONFIG.pop('default_dashboard', None) # noqa: F405 28 | 29 | 30 | settings.update_dashboards( 31 | [ 32 | bgpvpn_dashboard.enabled, 33 | openstack_dashboard.enabled, 34 | ], 35 | HORIZON_CONFIG, # noqa: F405 36 | INSTALLED_APPS # noqa: F405 37 | ) 38 | 39 | # Ensure any duplicate apps are removed after the update_dashboards call 40 | INSTALLED_APPS = list(set(INSTALLED_APPS)) # noqa: F405 41 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/test_data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/bgpvpn_dashboard/test/test_data/__init__.py -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/test_data/bgpvpn_data.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | 14 | import copy 15 | 16 | from bgpvpn_dashboard.api import bgpvpn 17 | from openstack_dashboard.test.test_data import utils 18 | 19 | 20 | def data(TEST): 21 | TEST.bgpvpns = utils.TestDataContainer() 22 | TEST.api_bgpvpns = utils.TestDataContainer() 23 | TEST.network_associations = utils.TestDataContainer() 24 | TEST.api_network_associations = utils.TestDataContainer() 25 | TEST.router_associations = utils.TestDataContainer() 26 | TEST.api_router_associations = utils.TestDataContainer() 27 | 28 | bgpvpn_dict = {'id': 'b595e758-1877-4aec-92a2-6834d76f1025', 29 | 'tenant_id': '1', 30 | 'name': 'bgpvpn1', 31 | 'route_targets': '64500:1' 32 | } 33 | TEST.api_bgpvpns.add(bgpvpn_dict) 34 | b = bgpvpn.Bgpvpn(copy.deepcopy(bgpvpn_dict)) 35 | TEST.bgpvpns.add(b) 36 | 37 | network_association_dict = { 38 | 'id': '99ef096d-21fb-43a7-9e2a-b3c464abef3a', 39 | 'network_id': '063cf7f3-ded1-4297-bc4c-31eae876cc91', 40 | 'tenant_id': '1'} 41 | TEST.api_network_associations.add(network_association_dict) 42 | na = bgpvpn.NetworkAssociation(copy.deepcopy(network_association_dict)) 43 | TEST.network_associations.add(na) 44 | 45 | router_association_dict = { 46 | 'id': '9736c228-745d-4e78-83a5-d971d9fd8f2c', 47 | 'router_id': '279989f7-54bb-41d9-ba42-0d61f12fda61', 48 | 'tenant_id': '1'} 49 | TEST.api_router_associations.add(router_association_dict) 50 | ra = bgpvpn.RouterAssociation(copy.deepcopy(router_association_dict)) 51 | TEST.router_associations.add(ra) 52 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/test_data/utils.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | from openstack_dashboard.test.test_data import utils 15 | 16 | 17 | def load_test_data(load_onto=None): 18 | from openstack_dashboard.test.test_data import exceptions 19 | from openstack_dashboard.test.test_data import neutron_data 20 | 21 | from bgpvpn_dashboard.test.test_data import bgpvpn_data 22 | 23 | # The order of these loaders matters, some depend on others. 24 | loaders = ( 25 | exceptions.data, 26 | neutron_data.data, 27 | bgpvpn_data.data, 28 | ) 29 | if load_onto: 30 | for data_func in loaders: 31 | data_func(load_onto) 32 | return load_onto 33 | else: 34 | return utils.TestData(*loaders) 35 | -------------------------------------------------------------------------------- /bgpvpn_dashboard/test/urls.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from django.conf import urls 14 | import openstack_dashboard.urls 15 | 16 | urlpatterns = [ 17 | urls.url(r'', urls.include(openstack_dashboard.urls)) 18 | ] 19 | -------------------------------------------------------------------------------- /bindep.txt: -------------------------------------------------------------------------------- 1 | # This is a cross-platform list tracking distribution packages needed for install and tests; 2 | # see https://docs.openstack.org/infra/bindep/ for additional information. 3 | 4 | libpq-dev [platform:dpkg] 5 | mysql-client [platform:dpkg !platform:debian] 6 | mysql-server [platform:dpkg !platform:debian] 7 | mariadb-server [platform:rpm platform:redhat platform:debian] 8 | postgresql [test] 9 | postgresql-client [platform:dpkg test] 10 | postgresql-devel [platform:rpm test] 11 | postgresql-server [platform:rpm test] 12 | -------------------------------------------------------------------------------- /devstack/devstack-gate-bagpipe-rc: -------------------------------------------------------------------------------- 1 | # This file is hooked from https://github.com/openstack-infra/project-config/blob/master/jenkins/jobs/networking-bgpvpn.yaml 2 | 3 | export OVERRIDE_ENABLED_SERVICES=n-api,n-crt,n-cpu,n-cond,n-api-meta,n-sch,placement-api,g-api,neutron-api,neutron-agent,neutron-dhcp,neutron-l3,neutron-metadata-agent,neutron-bagpipe-bgp,key,mysql,rabbit 4 | 5 | if [[ $DEVSTACK_GATE_TEMPEST -eq 1 ]] ; then 6 | export DEVSTACK_GATE_TEMPEST_REGEX="^neutron_tempest_plugin\.bgpvpn" 7 | export OVERRIDE_ENABLED_SERVICES=${OVERRIDE_ENABLED_SERVICES},tempest 8 | fi 9 | 10 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"NETWORKING_BGPVPN_DRIVER=BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe_v2.BaGPipeBGPVPNDriver:default" 11 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin networking-bagpipe https://opendev.org/openstack/networking-bagpipe" 12 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"BAGPIPE_DATAPLANE_DRIVER_IPVPN=ovs" 13 | 14 | # until we do multinode, there is no BGP peer to connect to 15 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"BAGPIPE_BGP_PEERS=-" 16 | 17 | # https://bugs.launchpad.net/devstack/+bug/1567052 18 | # so we need VERBOSE=False until bagpipe-bgp uses rootwrap and is not run with sudo (same for bagpipe-fakerr) 19 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"VERBOSE=False" 20 | 21 | # at least some DB setup things (e.g. for functional tests) require 22 | # helpers from neutron devstack plugin 23 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin neutron https://opendev.org/openstack/neutron" 24 | 25 | # Using the openvswitch firewall driver for security groups is currently 26 | # required to allow BGPVPN/router coexistence in single node or DVR setup 27 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"[[post-config|/etc/neutron/plugins/ml2/ml2_conf.ini]]" 28 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"[securitygroup]" 29 | export DEVSTACK_LOCAL_CONFIG+=$'\n'"firewall_driver = openvswitch" 30 | 31 | -------------------------------------------------------------------------------- /devstack/devstack-gate-rc: -------------------------------------------------------------------------------- 1 | # This file is hooked from https://github.com/openstack-infra/project-config/blob/master/jenkins/jobs/networking-bgpvpn.yaml 2 | 3 | export OVERRIDE_ENABLED_SERVICES=neutron-api,neutron-agent,neutron-dhcp,neutron-l3,key,mysql,rabbit 4 | 5 | -------------------------------------------------------------------------------- /devstack/settings: -------------------------------------------------------------------------------- 1 | NETWORKING_BGPVPN_DIR="$DEST/networking-bgpvpn" 2 | NETWORKING_BGPVPN_CONF="$NEUTRON_CONF_DIR/networking_bgpvpn.conf" 3 | BGPVPN_DASHBOARD_ENABLE="$NETWORKING_BGPVPN_DIR/bgpvpn_dashboard/enabled/*" 4 | 5 | NETWORKING_BGPVPN_DRIVER=${NETWORKING_BGPVPN_DRIVER:-BGPVPN:Dummy:networking_bgpvpn.neutron.services.service_drivers.driver_api.BGPVPNDriverRC:default} 6 | 7 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | # The order of packages is significant, because pip processes them in the order 2 | # of appearance. Changing the order has an impact on the overall integration 3 | # process, which may cause wedges in the gate later. 4 | sphinx>=2.0.0,!=2.1.0 # BSD 5 | openstackdocstheme>=2.2.1 # Apache-2.0 6 | reno>=3.1.0 # Apache-2.0 7 | oslo.config>=5.2.0 # Apache-2.0 8 | oslo.policy>=3.12.0 # Apache-2.0 9 | -------------------------------------------------------------------------------- /doc/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/doc/source/_static/.placeholder -------------------------------------------------------------------------------- /doc/source/configuration/index.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | Configuration Guide 3 | =================== 4 | 5 | Configuration 6 | ------------- 7 | 8 | This section provides a list of all possible options for each 9 | configuration file. 10 | networking-bgpvpn uses the following configuration file. 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | 15 | networking-bgpvpn 16 | 17 | The following is a sample configuration file for networking-bgpvpn. 18 | It is generated from code and reflect the current state of code 19 | in the networking-bgpvpn repository. 20 | 21 | .. toctree:: 22 | :maxdepth: 1 23 | 24 | samples/networking-bgpvpn 25 | 26 | Policy 27 | ------ 28 | 29 | networking-bgpvpn, like most OpenStack projects, uses a policy language to 30 | restrict permissions on REST API actions. 31 | 32 | .. toctree:: 33 | :maxdepth: 1 34 | 35 | Policy Reference 36 | Sample Policy File 37 | -------------------------------------------------------------------------------- /doc/source/configuration/networking-bgpvpn.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | networking-bgpvpn.conf 3 | ====================== 4 | 5 | To use networking-bgpvpn, you need to configure one of valid service providers 6 | for ``BGPVPN`` service in ``service_provider`` of ``[service_providers]`` 7 | group of the neutron server. Note that you can specify multiple providers for 8 | BGPVPN but only one of them can be default. 9 | 10 | * Dummy provider: ``service_provider = BGPVPN:Dummy:networking_bgpvpn.neutron.services.service_drivers.driver_api.BGPVPNDriver:default`` 11 | * BaGPipe provider: ``service_provider = BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe.BaGPipeBGPVPNDriver:default`` 12 | 13 | .. show-options:: 14 | :config-file: etc/oslo-config-generator/networking-bgpvpn.conf 15 | -------------------------------------------------------------------------------- /doc/source/configuration/policy-sample.rst: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Sample networking-bgpvpn Policy File 3 | ==================================== 4 | 5 | The following is a sample networking-bgpvpn policy file for adaptation and use. 6 | 7 | The sample policy can also be viewed in :download:`file form 8 | `. 9 | 10 | .. important:: 11 | 12 | The sample policy file is auto-generated from networking-bgpvpn when this 13 | documentation is built. You must ensure your version of networking-bgpvpn 14 | matches the version of this documentation. 15 | 16 | .. literalinclude:: /_static/networking-bgpvpn.policy.yaml.sample 17 | -------------------------------------------------------------------------------- /doc/source/configuration/policy.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | networking-bgpvpn policies 3 | ========================== 4 | 5 | The following is an overview of all available policies in networking-bgpvpn. 6 | For a sample configuration file, refer to :doc:`/configuration/policy-sample`. 7 | 8 | .. show-policy:: 9 | :config-file: etc/oslo-policy-generator/policy.conf 10 | -------------------------------------------------------------------------------- /doc/source/configuration/samples/networking-bgpvpn.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Sample networking-bgpvpn.conf 3 | ============================= 4 | 5 | This sample configuration can also be viewed in `the raw format 6 | <../../_static/config-samples/networking-bgpvpn.conf.sample>`_. 7 | 8 | .. literalinclude:: 9 | ../../_static/config-samples/networking-bgpvpn.conf.sample 10 | -------------------------------------------------------------------------------- /doc/source/contributor/contributing.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Contributing 3 | ============ 4 | .. include:: ../../../CONTRIBUTING.rst 5 | -------------------------------------------------------------------------------- /doc/source/contributor/future/attributes.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Future attributes 3 | ================= 4 | 5 | Specifications for the following attributes have been defined but not implemented yet: 6 | 7 | .. csv-table:: Future attributes 8 | :header: Attribute Name,Type,Access,Default Value,Validation/Constraint,Description 9 | 10 | technique, string, RW admin only, None, for instance "ipvpn" or "evpn", (optional) selection of the technique used to implement the VPN 11 | auto_aggregate,bool,RW admin only,False,{ True | False },enable prefix aggregation or not (type l3 only) but no support in any driver 12 | admin_state_up,bool,RW admin only,True,{ True | False },interconnection with this BGPVPN is enabled by the admin 13 | 14 | 'auto_aggregate' attribute 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | 17 | The 'auto_aggregate' flag controls whether or not routes should be automatically 18 | aggregated before being advertised outside Neutron. 19 | A backend may or may not support this behavior, and its driver should report 20 | an API error in the latter case. 21 | 22 | 'technique' attribute 23 | ~~~~~~~~~~~~~~~~~~~~~ 24 | 25 | The 'technique' attribute is optional and can be used by the admin to select one 26 | of multiple techniques when more than one is supported by the driver. When no 27 | technique is specified, the driver will use a default value. An API call will 28 | be available to let the API user know about the types supported by the driver 29 | for a said vpn type. 30 | 31 | Currently defined techniques are: 32 | 33 | * for l3: 34 | 35 | * 'ipvpn': this corresponds to RFC4364 36 | * 'evpn-prefix': this corresponds to 37 | draft-ietf-bess-evpn-prefix-advertisement 38 | 39 | * for l2: 40 | 41 | * 'evpn': this corresponds to RFC7432 42 | 43 | API call to list the available techniques, with example answers: 44 | 45 | * GET /bgpvpn/techniques: 46 | 47 | .. code-block:: json 48 | 49 | { "techniques": { 50 | "l3": [ "ipvpn" ], 51 | "l2": [ "evpn" ] 52 | } } 53 | 54 | * GET /bgpvpn/techniques/l3: 55 | 56 | .. code-block:: json 57 | 58 | { "l3": [ "ipvpn"] } 59 | 60 | * GET /bgpvpn/techniques/l2: 61 | 62 | .. code-block:: json 63 | 64 | { "l2": [ "evpn"] } 65 | 66 | 'admin_state_up' attribute 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | This is an admin-only attribute allowing the admin to shutdown connectivity to 70 | and from a BGP VPN and expose this state to the tenant. 71 | -------------------------------------------------------------------------------- /doc/source/contributor/future/index.rst: -------------------------------------------------------------------------------- 1 | To be implemented 2 | ================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | attributes 8 | 9 | 10 | -------------------------------------------------------------------------------- /doc/source/contributor/index.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Contributor Guide 3 | ================= 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | contributing 9 | specs 10 | future/index 11 | -------------------------------------------------------------------------------- /doc/source/contributor/specs.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This work is licensed under a Creative Commons Attribution 3.0 Unported 3 | License. 4 | 5 | http://creativecommons.org/licenses/by/3.0/legalcode 6 | 7 | Specification notes 8 | =================== 9 | 10 | Database design 11 | --------------- 12 | 13 | The implementation will rely on three tables: 14 | 15 | * one for BGPVPN objects 16 | 17 | * one to define the n-n relation ship between BGPVPNs and Networks 18 | 19 | * one to define the n-n relation ship between BGPVPNs and Routers 20 | 21 | 22 | The information stored in these tables will reflect what is exposed on the 23 | API. 24 | 25 | 26 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This work is licensed under a Creative Commons Attribution 3.0 Unported 3 | License. 4 | 5 | http://creativecommons.org/licenses/by/3.0/legalcode 6 | 7 | ============================================= 8 | Neutron BGP VPN Interconnection Documentation 9 | ============================================= 10 | 11 | .. include:: introduction.rst 12 | 13 | .. only:: html 14 | 15 | Contents: 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | user/index 21 | install/index 22 | configuration/index 23 | contributor/index 24 | 25 | .. only:: html 26 | 27 | .. rubric:: Indices and Tables 28 | 29 | * :ref:`genindex` 30 | * :ref:`search` 31 | -------------------------------------------------------------------------------- /doc/source/install/index.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Install and Configuration 3 | ========================= 4 | 5 | Installation 6 | ============ 7 | 8 | The details related to how a package should be installed may depend on your 9 | environment. 10 | 11 | If possible, you should rely on packages provided by your Linux and/or 12 | Openstack distribution. 13 | 14 | If you use ``pip``, follow these steps to install networking-bgpvpn: 15 | 16 | * identify the version of the networking-bgpvpn package that matches 17 | your Openstack version: 18 | 19 | * Liberty: most recent of 3.0.x 20 | * Mitaka: most recent of 4.0.x 21 | * Newton: most recent of 5.0.x 22 | * Ocata: most recent of 6.0.x 23 | * Pike: most recent of 7.0.x 24 | * (see ``_) 25 | 26 | * indicate pip to (a) install precisely this version and (b) take into 27 | account Openstack upper constraints on package versions for dependencies 28 | (example for ocata): 29 | 30 | .. code-block:: console 31 | 32 | $ pip install -c https://releases.openstack.org/constraints/upper/ocata 33 | 34 | Configuration 35 | ============= 36 | 37 | The service plugin is enabled in Neutron, by 38 | adding ``bgpvpn`` to the list 39 | of enabled service plugins in ``neutron.conf`` (typically in ``/etc/neutron/`` 40 | but the location used may depend on your setup or packaging). For instance: 41 | 42 | .. code-block:: ini 43 | 44 | service_plugins = router,bgpvpn 45 | 46 | The BGPVPN driver to use is then specified in the ``networking_bgpvpn.conf`` 47 | file (located by default under ``/etc/neutron/``, but in any case in one of the 48 | directories specified with ``--config-dir`` at neutron startup, which may 49 | differ from ``/etc/neutron`` in your setup): 50 | 51 | .. code-block:: ini 52 | 53 | [service_providers] 54 | service_provider = BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe_v2.BaGPipeBGPVPNDriver:default 55 | #service_provider= BGPVPN:Dummy:networking_bgpvpn.neutron.services.service_drivers.driver_api.BGPVPNDriver:default 56 | 57 | A given driver may require additional packages to work; the driver section 58 | provides detailed installation information for each 59 | specific driver. 60 | 61 | Policy 62 | ====== 63 | 64 | API Policy for the BGPVPN service plugin can be controlled via the standard policy framework. 65 | 66 | When pip is used to install the package, a default policy file is installed at ``/etc/neutron/policy.d/bgpvpn.conf``. 67 | 68 | Database setup 69 | ============== 70 | 71 | The DB tables for networking-bgpvpn are created and upgraded with: 72 | 73 | .. code-block:: console 74 | 75 | neutron-db-manage --config-file /etc/neutron/neutron.conf --subproject networking-bgpvpn upgrade 76 | 77 | Devstack 78 | ======== 79 | 80 | You can easily test the bgpvpn service plugin with devstack, by adding the following line to your local.conf: 81 | 82 | .. code-block:: none 83 | 84 | enable_plugin networking-bgpvpn https://git.openstack.org/openstack/networking-bgpvpn.git 85 | 86 | Or the following if you want a specific branch or version (example for Mitaka): 87 | 88 | .. code-block:: none 89 | 90 | enable_plugin networking-bgpvpn https://git.openstack.org/openstack/networking-bgpvpn.git stable/mitaka 91 | 92 | By default, the service driver will use a dummy driver, that only responds to API calls, and stores data in the database. 93 | If you want to test a fully functional driver with devstack, you can configure the bagpipe driver with its devstack plugin (see :doc:`/user/drivers/bagpipe/index`). 94 | 95 | Detailed information on how to use other drivers is provided in the documentation for each of these drivers. 96 | -------------------------------------------------------------------------------- /doc/source/introduction.rst: -------------------------------------------------------------------------------- 1 | BGP-based IP VPNs networks are widely used in the industry especially for 2 | enterprises. This project aims at supporting inter-connection between L3VPNs 3 | and Neutron resources, i.e. Networks, Routers and Ports. 4 | 5 | A typical use-case is the following: a tenant already having a BGP IP VPN 6 | (a set of external sites) setup outside the datacenter, and they want to be able 7 | to trigger the establishment of connectivity between VMs and these VPN sites. 8 | 9 | Another similar need is when E-VPN is used to provide an Ethernet interconnect 10 | between multiple sites, and inherits the base protocol architecture from 11 | BGP/MPLS IP VPNs. 12 | 13 | This service plugin exposes an API to interconnect OpenStack Neutron ports, 14 | typically VMs, via the Networks and Routers they are connected to, with 15 | a IP VPN as defined by [RFC4364]_ (BGP/MPLS IP Virtual Private Networks) or 16 | with an E-VPN [RFC7432]_. 17 | 18 | .. rubric:: Introduction videos: 19 | 20 | The following videos are filmed presentations of talks given during the 21 | Barcelona OpenStack Summit (Oct' 2016). Although they do not cover the work 22 | done since, they can be a good introduction to the project: 23 | 24 | * https://www.youtube.com/watch?v=kGW5R8mtmRg 25 | * https://www.youtube.com/watch?v=LCDeR7MwTzE 26 | -------------------------------------------------------------------------------- /doc/source/samples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/doc/source/samples/__init__.py -------------------------------------------------------------------------------- /doc/source/user/api.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This work is licensed under a Creative Commons Attribution 3.0 Unported 3 | License. 4 | 5 | http://creativecommons.org/licenses/by/3.0/legalcode 6 | 7 | === 8 | API 9 | === 10 | 11 | This API is documented in the `Neutron API Reference `_. 12 | 13 | ADMIN 14 | ===== 15 | 16 | Configuration 17 | ============= 18 | 19 | On VXLAN VNI 20 | ------------ 21 | 22 | .. note:: This feature is under development in the Queens release 23 | 24 | VXLAN is one option among others that could be used for BGP E-VPNs. 25 | When VXLAN is used on a hardware platform the use of a locally-assigned id 26 | may not be always possible which introduces the need to configure a 27 | globally-assigned VXLAN VNI. 28 | 29 | The optional ``vni`` attribute is an admin-only parameter and allows the 30 | admin to enforce the use of a chosen globally-assigned VXLAN VNI for the 31 | said BGPVPN. 32 | 33 | The default when no VNI is specified and the VXLAN encapsulation is used, is 34 | to let the backend choose the VNI in advertised routes, and use the VNI in 35 | received routes for transmitted traffic. The backend will conform to 36 | E-VPN overlay specs. 37 | 38 | If the ``vni`` attribute is set for a BGPVPN, the following is enforced: 39 | 40 | * the routes announced by the backend will advertise the specified VNI (this 41 | relates to traffic sent from this BGP VPN to a Network or Router) 42 | 43 | * for the routes received by the backend for this BGPVPN, and that carry a 44 | different VNI that the VNI specified for the BGPVPN the behavior may 45 | depend on the backend, with the recommended behavior being to 46 | liberally accept such routes. 47 | 48 | If a backend does not support the approach recommended above of liberally 49 | accepting routes with a different VNI, the check can be implemented as follows: 50 | 51 | * when a route is imported, for each BGPVPN associated to the Network or 52 | Router and having a VNI defined: 53 | 54 | * the set of Route Targets of the route is intersected with the import_rts of 55 | the BGPVPN 56 | 57 | * if this intersection is non-empty the ``vni`` of the BGPVPN is retained 58 | 59 | * the route is used to establish connectivity to the destination in the 60 | forwarding plane only if the advertised VNI is equal to all retained 61 | VNIs in the previous step 62 | 63 | The above check is applied similarly for a Router associated to multiple BGP 64 | VPN. 65 | 66 | The backend is expected to provide troubleshooting information for the cases 67 | when a route ends up not being used because the VNI check failed. 68 | 69 | Valid range for the ``vni`` attribute is [1, 2\ :sup:`24`\ -1]. 70 | -------------------------------------------------------------------------------- /doc/source/user/components-sdn.blockdiag: -------------------------------------------------------------------------------- 1 | blockdiag components-sdn { 2 | span_width = 64; 3 | node_height = 100; 4 | shadow_style=none; 5 | 6 | default_shape = roundedbox; 7 | 8 | group bgpvpn { 9 | label="BGPVPN service plugin"; 10 | color=red; 11 | 12 | api[label="BGPVPN API"]; 13 | db[shape=flowchart.database,label="DB"]; 14 | driver; 15 | } 16 | 17 | group backend_g { 18 | label="Backend"; 19 | color=orange; 20 | 21 | comment[label="can be e.g.\nan 'SDN' solution...",shape=note,color=orange,style=none]; 22 | 23 | backend[label="...",shape=box,stacked,color=none]; 24 | vswitches[stacked,label="vswitches\nand/or routers"]; 25 | bgpspeakers[stacked,label="MP-BGP Speakers"]; 26 | } 27 | 28 | group routers { 29 | color=lightgrey; 30 | shape=line; 31 | style=dashed; 32 | 33 | bgppeers[label="BGP Peers",stacked,color=green]; 34 | mplsrouters[label="MPLS routers"]; 35 | bgppeers -- mplsrouters[style=dotted,folded]; 36 | } 37 | 38 | admin_or_tenant [shape=actor,label="admin, tenant"]; 39 | admin_or_tenant -> api[color=blue]; 40 | 41 | api -> driver ; 42 | api -> db[folded]; 43 | driver -> db[folded]; 44 | driver -> backend; 45 | backend <-> bgpspeakers; 46 | bgpspeakers <-> bgppeers[color=green,label="MP-BGP",textcolor=green]; 47 | backend -> vswitches[folded]; 48 | 49 | vswitches <-> mplsrouters[label="MPLS\nor ..",folded]; 50 | } 51 | -------------------------------------------------------------------------------- /doc/source/user/drivers/bagpipe/overview.blockdiag: -------------------------------------------------------------------------------- 1 | blockdiag components-bagpipe { 2 | span_width = 64; 3 | node_height = 100; 4 | 5 | shadow_style=none; 6 | default_shape = roundedbox; 7 | 8 | group bgpvpn { 9 | label="BGPVPN service plugin"; 10 | color=red; 11 | 12 | api[label="BGPVPN API"]; 13 | db[shape=flowchart.database,label="Neutron DB"]; 14 | driver[label="bagpipe driver"]; 15 | 16 | api -> driver ; 17 | api -> db[folded]; 18 | driver -> db[folded]; 19 | } 20 | 21 | group backend_g { 22 | label="bagpipe backend"; 23 | color=orange; 24 | 25 | comment[label="on each compute\nnode ... : ",shape=note,color=orange,style=none]; 26 | 27 | backend[label="OpenVSwitch Agent\n+ BGPVPN extension",color=grey,textcolor=darkorange]; 28 | vswitch[label="OVS br-int/br-tun",color=lightgrey]; 29 | mplsvswitch[label="OVS br-mpls",color="darkorange"]; 30 | bgpspeaker[label="bagpipe-bgp",color="darkorange"]; 31 | 32 | backend -> bgpspeaker; 33 | backend -> vswitch[folded]; 34 | vswitch <-> mplsvswitch[label="packets"]; 35 | bgpspeaker -> mplsvswitch[folded]; 36 | } 37 | 38 | group routers { 39 | color=lightgrey; 40 | shape=line; 41 | style=dashed; 42 | 43 | bgppeers[label="BGP Peers",stacked,color=green]; 44 | mplsrouters[label="MPLS routers"]; 45 | 46 | bgppeers -- mplsrouters[style=dotted,folded]; 47 | } 48 | 49 | admin_or_tenant [shape=actor,label="admin, tenant"]; 50 | admin_or_tenant -> api[color=blue]; 51 | 52 | driver <-> backend [label="RPCs"]; 53 | 54 | bgpspeaker <-> bgppeers[color=green,label="MP-BGP",textcolor=green]; 55 | 56 | mplsvswitch <-> mplsrouters[label="MPLS\nor ..",folded]; 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /doc/source/user/drivers/nuage/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This work is licensed under a Creative Commons Attribution 3.0 Unported 3 | License. 4 | 5 | http://creativecommons.org/licenses/by/3.0/legalcode 6 | 7 | ===================== 8 | Nuage Networks driver 9 | ===================== 10 | 11 | The Nuage Network driver works jointly with 12 | `Nuage Networks VSP `__. 13 | 14 | A pre-requisite for the nuage BGPVPN driver is that the Nuage-specific 15 | installation and configuration steps have been applied; in particular the 16 | installation of the ``nuage_neutron`` package. Please refer to Nuage Networks 17 | documentation. 18 | 19 | The driver will be enabled, by specifying in ``/etc/neutron/networking_bgpvpn.conf``: 20 | 21 | .. code-block:: ini 22 | 23 | [service_providers] 24 | service_provider = BGPVPN:Nuage:nuage_neutron.bgpvpn.services.service_drivers.driver.NuageBGPVPNDriver:default 25 | -------------------------------------------------------------------------------- /doc/source/user/drivers/opendaylight/index.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | OpenDaylight driver 3 | =================== 4 | 5 | The **OpenDaylight** driver for the BGPVPN service plugin is designed to work 6 | jointly with the `OpenDaylight SDN controller `__. 7 | 8 | OpenDaylight driver requires `networking-odl plugin`_ which comes with its own 9 | devstack scripts. Details on how to configure devstack for OpenDaylight 10 | plugin can be found at `networking-odl/devstack`_. 11 | 12 | .. note:: 13 | 14 | The legacy BGPVPN *v1 driver* for ODL that was hosted in 15 | ``networking-bgpvpn`` tree (``networking_bgpvpn.neutron.services.service_drivers.opendaylight.odl.OpenDaylightBgpvpnDriver``) 16 | has been deprecated in Rocky OpenStack release, and removed in Stein 17 | OpenStack release. The documentation below refers to the newer *v2 driver* 18 | in the ``networking-odl`` project. 19 | 20 | * add the following to local.conf to enable networking-odl plugin: 21 | 22 | .. code-block:: none 23 | 24 | enable_plugin networking-odl http://opendev.org/openstack/networking-odl 25 | 26 | * add the following to local.conf to enable ODL Driver for BGPVPN service Plugin: 27 | 28 | .. code-block:: ini 29 | 30 | NETWORKING_BGPVPN_DRIVER="BGPVPN:OpenDaylight:networking_odl.bgpvpn.odl_v2.OpenDaylightBgpvpnDriver:default" 31 | 32 | * Run stack.sh: 33 | 34 | .. code-block:: console 35 | 36 | ./stack.sh 37 | 38 | .. _networking-odl plugin : https://launchpad.net/networking-odl 39 | .. _networking-odl/devstack : https://github.com/openstack/networking-odl/tree/master/devstack 40 | -------------------------------------------------------------------------------- /doc/source/user/figures/components_sdn_blockdiag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/doc/source/user/figures/components_sdn_blockdiag.png -------------------------------------------------------------------------------- /doc/source/user/figures/overview_blockdiag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/doc/source/user/figures/overview_blockdiag.png -------------------------------------------------------------------------------- /doc/source/user/figures/workflows_seqdiag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/doc/source/user/figures/workflows_seqdiag.png -------------------------------------------------------------------------------- /doc/source/user/horizon.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Horizon 3 | ======== 4 | 5 | General information 6 | =================== 7 | 8 | Networking-bgpvpn contains the bgpvpn_dashboard plugin for Horizon. 9 | It adds a BGPVPN Interconnections panel in the admin section. Admin users can 10 | handle BGPVPNs resources through this panel. 11 | The operations possible for admin users are: 12 | 13 | * listing BGPVPN 14 | * creating a BGPVPN 15 | * editing a BGPVPN 16 | * associating or disassociating a BGPVPN to network(s) 17 | * associating or disassociating a BGPVPN to router(s) 18 | * deleting a BGPVPN 19 | 20 | For non admin users the plugin adds a BGPVPN Interconnections panel in the Project 21 | section under the Network subsection. 22 | The operations possible for non admin users are: 23 | 24 | * listing BGPVPN (display only name, type, networks and routers associations) 25 | * editing a BGPVPN (only the name) 26 | * associating or disassociating a BGPVPN to network(s) 27 | * associating or disassociating a BGPVPN to router(s) 28 | 29 | Installation and Configuration 30 | ============================== 31 | 32 | Devstack will automatically configure Horizon to enable the Horizon plugin. 33 | 34 | For others deployments we assume that Horizon and networking-bgpvpn are already 35 | installed. Their installation folders are respectively and 36 | . 37 | 38 | 39 | Copy configuration file: 40 | 41 | .. code-block:: shell 42 | 43 | cp /bgpvpn_dashboard/enabled/_[0-9]*.py /openstack_dashboard/local/enabled/ 44 | 45 | Configure the policy file for BGPVPN dashboard in OpenStack Dashboard ``local_settings.py``. 46 | ```` is a directory which contains configurations for 47 | BGPVPN dashboard and the location varies across distributions or deployments. 48 | ```` can be found with: ``dirname $(python -c 'import bgpvpn_dashboard as _; print _.__file__')`` 49 | 50 | .. code-block:: python 51 | 52 | POLICY_FILES[' networking-bgpvpn'] = '/bgpvpn_dashboard/etc/bgpvpn-horizon.conf' 53 | 54 | .. note:: 55 | 56 | If you do not configure ``POLICY_FILES`` in your ``local_settings.py``, 57 | you also need to define the default ``POLICY_FILES`` in 58 | ``local_settings.py``. If you use the example ``local_settings.py`` file 59 | from horizon, what you need is to uncomment ``POLICY_FILES`` (which contains 60 | the default values). 61 | 62 | Restart the web server hosting Horizon. 63 | 64 | The BGPVPN Interconnections panels will now be in your Horizon dashboard. 65 | -------------------------------------------------------------------------------- /doc/source/user/index.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | User Documentation 3 | ================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | overview 9 | drivers/index 10 | usage 11 | horizon 12 | heat 13 | api 14 | -------------------------------------------------------------------------------- /doc/source/user/workflows.seqdiag: -------------------------------------------------------------------------------- 1 | diagram { 2 | span_width = 40; 3 | 4 | os-admin [label="Openstack Admin",color="lightgray"]; 5 | tenant [label="Openstack Tenant X",color="lightblue"]; 6 | api [label="Neutron BGPVPN API",color="red"]; 7 | driver [label="BGPVPN Driver for\nbackend Foo",color="red"]; 8 | backend [label="BGPVPN Backend Foo\n",color="orange"]; 9 | bgppeers [label="BGP Peers",color="green"]; 10 | 11 | backend --> bgppeers[label="BGP peerings",color=green]; 12 | backend <-- bgppeers[rightnote="BGP sessions live in parallel\nto BGPVPN service plugin",color=green]; 13 | 14 | os-admin -> api [label="POST: create a BGP VPN\nresource corresponding to a\nBGP VPN",color=blue]; 15 | api -> driver [leftnote="persist resource"]; 16 | driver --> backend [label="(driver-backend exchanges\nvarying bw. backends)"]; 17 | driver <-- backend; 18 | api <-- driver; 19 | os-admin <-- api [label="BGPVPN Y",color=blue]; 20 | os-admin -> api [label="UPDATE: set tenant X as\nowner of BGPVPN Y",color=blue]; 21 | api -> driver; 22 | driver --> backend [label="(?)"]; 23 | driver <-- backend; 24 | api <-- driver; 25 | os-admin <-- api; 26 | 27 | tenant -> api [label="GET:Learns that it\nowns BGPVPN Y",color=blue]; 28 | api -> driver; 29 | driver --> backend [label="(?)"]; 30 | driver <-- backend; 31 | api <-- driver; 32 | tenant <-- api; 33 | tenant -> api [label="UPDATE:Associate BGPVPN Y to\nnetwork Z",color=blue]; 34 | 35 | api -> driver; 36 | driver -> backend [rightnote="now ready to interconnect\nNetwork Z and BGPVPN Y"]; 37 | driver <-- backend; 38 | backend -> bgppeers[label="MP-BGP VPNv4 routes\ntoward Network Z exported\nto BGP VPN Y",color=green]; 39 | backend <-- bgppeers[label="MP-BGP VPNv4 routes\nfrom BGP VPN Y prefixes", 40 | leftnote="forwarding plane setup\n(e.g. MPLS/GRE)",color=green]; 41 | api <-- driver; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /etc/README.txt: -------------------------------------------------------------------------------- 1 | To generate the sample networking-bgpvpn configuration files and 2 | the sample policy file, run the following commands respectively 3 | from the top level of the networking-bgpvpn directory: 4 | 5 | tox -e genconfig 6 | tox -e genpolicy 7 | 8 | If a 'tox' environment is unavailable, then you can run 9 | the following commands respectively 10 | instead to generate the configuration files: 11 | 12 | oslo-config-generator --config-file etc/oslo-config-generator/networking-bgpvpn.conf 13 | oslopolicy-sample-generator --config-file=etc/oslo-policy-generator/policy.conf 14 | -------------------------------------------------------------------------------- /etc/neutron/networking_bgpvpn.conf: -------------------------------------------------------------------------------- 1 | [service_providers] 2 | # both cannot be default, please choose: 3 | service_provider=BGPVPN:Dummy:networking_bgpvpn.neutron.services.service_drivers.driver_api.BGPVPNDriver:default 4 | #service_provider=BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe.BaGPipeBGPVPNDriver:default 5 | 6 | 7 | -------------------------------------------------------------------------------- /etc/oslo-config-generator/networking-bgpvpn.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/neutron/networking-bgpvpn.conf.sample 3 | wrap_width = 79 4 | 5 | namespace = networking-bgpvpn.service_provider 6 | -------------------------------------------------------------------------------- /etc/oslo-policy-generator/policy.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/policy.yaml.sample 3 | namespace = networking-bgpvpn 4 | -------------------------------------------------------------------------------- /networking_bgpvpn/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import pbr.version 14 | 15 | 16 | __version__ = pbr.version.VersionInfo( 17 | 'networking_bgpvpn').version_string() 18 | -------------------------------------------------------------------------------- /networking_bgpvpn/_i18n.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import oslo_i18n 14 | 15 | DOMAIN = "networking_bgpvpn" 16 | 17 | _translators = oslo_i18n.TranslatorFactory(domain=DOMAIN) 18 | 19 | # The primary translation function using the well-known name "_" 20 | _ = _translators.primary 21 | 22 | # The contextual translation function using the name "_C" 23 | # requires oslo.i18n >=2.1.0 24 | _C = _translators.contextual_form 25 | 26 | # The plural translation function using the name "_P" 27 | # requires oslo.i18n >=2.1.0 28 | _P = _translators.plural_form 29 | 30 | # Translators for log levels. 31 | # 32 | # The abbreviated names are meant to reflect the usual use of a short 33 | # name like '_'. The "L" is for "log" and the other letter comes from 34 | # the level. 35 | _LI = _translators.log_info 36 | _LW = _translators.log_warning 37 | _LE = _translators.log_error 38 | _LC = _translators.log_critical 39 | 40 | 41 | def get_available_languages(): 42 | return oslo_i18n.get_available_languages(DOMAIN) 43 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/db/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/head.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | from neutron.db.migration.models import head 14 | 15 | # pylint: disable=unused-import 16 | import networking_bgpvpn.neutron.db.bgpvpn_db # noqa 17 | 18 | 19 | def get_metadata(): 20 | return head.model_base.BASEV2.metadata 21 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/db/migration/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/db/migration/alembic_migrations/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/env.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | from logging import config as logging_config 16 | 17 | from alembic import context 18 | from neutron_lib.db import model_base 19 | from oslo_config import cfg 20 | from oslo_db.sqlalchemy import session 21 | import sqlalchemy as sa 22 | from sqlalchemy import event 23 | 24 | 25 | MYSQL_ENGINE = None 26 | BGPVPN_VERSION_TABLE = 'alembic_version_bgpvpn' 27 | config = context.config 28 | neutron_config = config.neutron_config 29 | logging_config.fileConfig(config.config_file_name) 30 | target_metadata = model_base.BASEV2.metadata 31 | 32 | 33 | def set_mysql_engine(): 34 | try: 35 | mysql_engine = neutron_config.command.mysql_engine 36 | except cfg.NoSuchOptError: 37 | mysql_engine = None 38 | 39 | global MYSQL_ENGINE 40 | MYSQL_ENGINE = (mysql_engine or 41 | model_base.BASEV2.__table_args__['mysql_engine']) 42 | 43 | 44 | def run_migrations_offline(): 45 | set_mysql_engine() 46 | 47 | kwargs = {} 48 | if neutron_config.database.connection: 49 | kwargs['url'] = neutron_config.database.connection 50 | else: 51 | kwargs['dialect_name'] = neutron_config.database.engine 52 | kwargs['version_table'] = BGPVPN_VERSION_TABLE 53 | context.configure(**kwargs) 54 | 55 | with context.begin_transaction(): 56 | context.run_migrations() 57 | 58 | 59 | @event.listens_for(sa.Table, 'after_parent_attach') 60 | def set_storage_engine(target, parent): 61 | if MYSQL_ENGINE: 62 | target.kwargs['mysql_engine'] = MYSQL_ENGINE 63 | 64 | 65 | def run_migrations_online(): 66 | set_mysql_engine() 67 | engine = session.create_engine(neutron_config.database.connection) 68 | 69 | connection = engine.connect() 70 | context.configure( 71 | connection=connection, 72 | target_metadata=target_metadata, 73 | version_table=BGPVPN_VERSION_TABLE 74 | ) 75 | try: 76 | with context.begin_transaction(): 77 | context.run_migrations() 78 | finally: 79 | connection.close() 80 | engine.dispose() 81 | 82 | 83 | if context.is_offline_mode(): 84 | run_migrations_offline() 85 | else: 86 | run_migrations_online() 87 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | # Copyright ${create_date.year} 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """${message} 17 | 18 | Revision ID: ${up_revision} 19 | Revises: ${down_revision} 20 | Create Date: ${create_date} 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = ${repr(up_revision)} 26 | down_revision = ${repr(down_revision)} 27 | % if branch_labels: 28 | branch_labels = ${repr(branch_labels)} 29 | % endif 30 | 31 | from alembic import op 32 | import sqlalchemy as sa 33 | ${imports if imports else ""} 34 | 35 | 36 | def upgrade(): 37 | ${upgrades if upgrades else "pass"} 38 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/CONTRACT_HEAD: -------------------------------------------------------------------------------- 1 | 9d7f1ae5fa56 2 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD: -------------------------------------------------------------------------------- 1 | 7a9482036ecd 2 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/liberty/contract/180baa4183e0_initial.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Orange 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """contract initial 17 | Revision ID: 180baa4183e0 18 | Revises: start_networking_bgpvpn 19 | Create Date: 2015-10-01 17:35:11.000000 20 | """ 21 | 22 | from neutron.db.migration import cli 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = '180baa4183e0' 26 | down_revision = 'start_networking_bgpvpn' 27 | branch_labels = (cli.CONTRACT_BRANCH,) 28 | 29 | 30 | def upgrade(): 31 | pass 32 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/liberty/expand/17d9fd4fddee_initial.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Orange 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """expand initial 17 | Revision ID: 17d9fd4fddee 18 | Revises: start_networking_bgpvpn 19 | Create Date: 2015-10-01 17:35:11.000000 20 | """ 21 | 22 | from alembic import op 23 | import sqlalchemy as sa 24 | 25 | from neutron.db.migration import cli 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '17d9fd4fddee' 29 | down_revision = 'start_networking_bgpvpn' 30 | branch_labels = (cli.EXPAND_BRANCH,) 31 | 32 | vpn_types = sa.Enum("l2", "l3", name="vpn_types") 33 | 34 | 35 | def upgrade(): 36 | op.create_table( 37 | 'bgpvpns', 38 | sa.Column('name', sa.String(255), nullable=True), 39 | sa.Column('id', sa.String(length=36), nullable=False), 40 | sa.Column('tenant_id', sa.String(length=255), nullable=True), 41 | sa.Column('type', vpn_types, nullable=False), 42 | sa.Column('route_targets', sa.String(255), nullable=False), 43 | sa.Column('import_targets', sa.String(255), nullable=True), 44 | sa.Column('export_targets', sa.String(255), nullable=True), 45 | sa.Column('route_distinguishers', sa.String(255), nullable=True), 46 | sa.PrimaryKeyConstraint('id'), 47 | ) 48 | op.create_table( 49 | 'bgpvpn_network_associations', 50 | sa.Column('id', sa.String(length=36), nullable=False), 51 | sa.Column('tenant_id', sa.String(length=255), nullable=False), 52 | sa.Column('bgpvpn_id', sa.String(36), nullable=False), 53 | sa.Column('network_id', sa.String(36), nullable=False), 54 | sa.ForeignKeyConstraint(['network_id'], ['networks.id'], 55 | ondelete='CASCADE'), 56 | sa.ForeignKeyConstraint(['bgpvpn_id'], ['bgpvpns.id'], 57 | ondelete='CASCADE'), 58 | sa.PrimaryKeyConstraint('id'), 59 | sa.UniqueConstraint('bgpvpn_id', 'network_id') 60 | ) 61 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/liberty/expand/3600132c6147_add_router_association_table.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Alcatel-Lucent 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """Add router association table 17 | 18 | Revision ID: 3600132c6147 19 | Revises: 17d9fd4fddee 20 | Create Date: 2015-11-16 15:48:31.343859 21 | 22 | """ 23 | 24 | from alembic import op 25 | import sqlalchemy as sa 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '3600132c6147' 29 | down_revision = '17d9fd4fddee' 30 | 31 | 32 | def upgrade(): 33 | op.create_table( 34 | 'bgpvpn_router_associations', 35 | sa.Column('id', sa.String(length=36), nullable=False), 36 | sa.Column('tenant_id', sa.String(length=255), nullable=False), 37 | sa.Column('bgpvpn_id', sa.String(36), nullable=False), 38 | sa.Column('router_id', sa.String(36), nullable=False), 39 | sa.ForeignKeyConstraint(['router_id'], ['routers.id'], 40 | ondelete='CASCADE'), 41 | sa.ForeignKeyConstraint(['bgpvpn_id'], ['bgpvpns.id'], 42 | ondelete='CASCADE'), 43 | sa.PrimaryKeyConstraint('id'), 44 | sa.UniqueConstraint('bgpvpn_id', 'router_id') 45 | ) 46 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/newton/contract/23ce05e0a19f_rename_tenant_to_project.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Intel Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | from sqlalchemy.engine import reflection 19 | 20 | 21 | """rename tenant to project 22 | 23 | Revision ID: 010308b06b49 24 | 25 | Create Date: 2016-06-29 19:42:17.862721 26 | 27 | """ 28 | 29 | # revision identifiers, used by Alembic. 30 | revision = '23ce05e0a19f' 31 | down_revision = '180baa4183e0' 32 | depends_on = ('0ab4049986b8',) 33 | 34 | 35 | _INSPECTOR = None 36 | 37 | 38 | def get_inspector(): 39 | """Reuse inspector""" 40 | 41 | global _INSPECTOR 42 | 43 | if _INSPECTOR: 44 | return _INSPECTOR 45 | 46 | else: 47 | bind = op.get_bind() 48 | _INSPECTOR = reflection.Inspector.from_engine(bind) 49 | 50 | return _INSPECTOR 51 | 52 | 53 | def get_tables(): 54 | """Returns hardcoded list of tables which have ``tenant_id`` column. 55 | 56 | The list is hard-coded to match the state of the schema when this upgrade 57 | script is run. 58 | """ 59 | 60 | tables = [ 61 | 'bgpvpn_router_associations', 62 | 'bgpvpns', 63 | 'bgpvpn_network_associations', 64 | ] 65 | 66 | return tables 67 | 68 | 69 | def get_columns(table): 70 | """Returns list of columns for given table.""" 71 | inspector = get_inspector() 72 | return inspector.get_columns(table) 73 | 74 | 75 | def get_data(): 76 | """Returns combined list of tuples: [(table, column)]. 77 | 78 | The list is built from tables with a tenant_id column. 79 | """ 80 | 81 | output = [] 82 | tables = get_tables() 83 | for table in tables: 84 | columns = get_columns(table) 85 | 86 | for column in columns: 87 | if column['name'] == 'tenant_id': 88 | output.append((table, column)) 89 | 90 | return output 91 | 92 | 93 | def alter_column(table, column): 94 | old_name = 'tenant_id' 95 | new_name = 'project_id' 96 | 97 | op.alter_column( 98 | table_name=table, 99 | column_name=old_name, 100 | new_column_name=new_name, 101 | existing_type=column['type'], 102 | existing_nullable=column['nullable'] 103 | ) 104 | 105 | 106 | def recreate_index(index, table_name): 107 | old_name = index['name'] 108 | new_name = old_name.replace('tenant', 'project') 109 | 110 | op.drop_index(op.f(old_name), table_name) 111 | op.create_index(new_name, table_name, ['project_id']) 112 | 113 | 114 | def upgrade(): 115 | inspector = get_inspector() 116 | 117 | data = get_data() 118 | for table, column in data: 119 | alter_column(table, column) 120 | 121 | indexes = inspector.get_indexes(table) 122 | for index in indexes: 123 | if 'tenant_id' in index['name']: 124 | recreate_index(index, table) 125 | 126 | 127 | def contract_creation_exceptions(): 128 | """Special migration for the blueprint to support Keystone V3. 129 | 130 | We drop all tenant_id columns and create project_id columns instead. 131 | """ 132 | 133 | return { 134 | sa.Column: ['.'.join([table, 'project_id']) for table in get_tables()], 135 | sa.Index: get_tables() 136 | } 137 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/newton/expand/0ab4049986b8_add_indexes_to_tenant_id.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | # 13 | 14 | """add indexes to tenant_id 15 | 16 | Revision ID: 0ab4049986b8 17 | Create Date: 2016-07-22 14:19:04.888614 18 | 19 | """ 20 | 21 | from alembic import op 22 | 23 | # revision identifiers, used by Alembic. 24 | revision = '0ab4049986b8' 25 | down_revision = '3600132c6147' 26 | 27 | 28 | def upgrade(): 29 | for table in [ 30 | 'bgpvpns', 31 | 'bgpvpn_network_associations', 32 | 'bgpvpn_router_associations', 33 | ]: 34 | op.create_index(op.f('ix_%s_tenant_id' % table), 35 | table, ['tenant_id'], unique=False) 36 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/queens/expand/39411aacf9b8_add_vni_to_bgpvpn_table.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Ericsson India Global Services Pvt Ltd. All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | 17 | from alembic import op 18 | import sqlalchemy as sa 19 | 20 | """add vni to bgpvpn table 21 | 22 | Revision ID: 39411aacf9b8 23 | Revises: 9a6664f3b8d4 24 | Create Date: 2017-09-19 17:37:11.359338 25 | 26 | """ 27 | 28 | # revision identifiers, used by Alembic. 29 | revision = '39411aacf9b8' 30 | down_revision = '9a6664f3b8d4' 31 | 32 | 33 | def upgrade(): 34 | op.add_column('bgpvpns', sa.Column('vni', sa.Integer)) 35 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/queens/expand/4610803bdf0d_router_assoc_add_advertise_extra_routes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | 19 | """Add 'extra-routes' to router association table 20 | 21 | Revision ID: 4610803bdf0d 22 | Revises: 9a6664f3b8d4 23 | Create Date: 2017-06-26 17:39:11.086696 24 | 25 | """ 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '4610803bdf0d' 29 | down_revision = '39411aacf9b8' 30 | 31 | 32 | def upgrade(): 33 | op.add_column('bgpvpn_router_associations', 34 | sa.Column('advertise_extra_routes', 35 | sa.Boolean(), nullable=False, 36 | server_default=sa.true())) 37 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/queens/expand/666c706fea3b_bgpvpn_local_pref.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | 19 | """ Add local_pref to bgpvpns table 20 | 21 | Revision ID: 666c706fea3b 22 | Revises: 39411aacf9b8 23 | Create Date: 2018-01-18 15:40:05.723129 24 | 25 | """ 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '666c706fea3b' 29 | down_revision = '4610803bdf0d' 30 | 31 | 32 | def upgrade(): 33 | op.add_column('bgpvpns', sa.Column('local_pref', 34 | sa.BigInteger, 35 | nullable=True)) 36 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/queens/expand/9a6664f3b8d4_add_port_association_table.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | 19 | """Add tables for port associations 20 | 21 | Revision ID: 9a6664f3b8d4 22 | Revises: 0ab4049986b8 23 | Create Date: 2017-06-26 17:34:14.411603 24 | 25 | """ 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '9a6664f3b8d4' 29 | down_revision = '0ab4049986b8' 30 | 31 | 32 | def upgrade(): 33 | op.create_table( 34 | 'bgpvpn_port_associations', 35 | sa.Column('id', sa.String(length=36), nullable=False), 36 | sa.PrimaryKeyConstraint('id'), 37 | sa.Column('project_id', sa.String(length=255), 38 | index=True, nullable=False), 39 | sa.Column('bgpvpn_id', sa.String(36), nullable=False), 40 | sa.ForeignKeyConstraint(['bgpvpn_id'], ['bgpvpns.id'], 41 | ondelete='CASCADE'), 42 | sa.Column('port_id', sa.String(36), nullable=False), 43 | sa.ForeignKeyConstraint(['port_id'], ['ports.id'], 44 | ondelete='CASCADE'), 45 | sa.Column('advertise_fixed_ips', sa.Boolean(), 46 | server_default=sa.sql.true(), nullable=False), 47 | sa.UniqueConstraint('bgpvpn_id', 'port_id') 48 | ) 49 | 50 | op.create_table( 51 | 'bgpvpn_port_association_routes', 52 | sa.Column('id', sa.String(length=36), nullable=False), 53 | sa.PrimaryKeyConstraint('id'), 54 | sa.Column('port_association_id', sa.String(length=36), nullable=False), 55 | sa.ForeignKeyConstraint(['port_association_id'], 56 | ['bgpvpn_port_associations.id'], 57 | ondelete='CASCADE'), 58 | sa.Column('type', sa.Enum("prefix", "bgpvpn", 59 | name="bgpvpn_port_association_route_type"), 60 | nullable=False), 61 | sa.Column('local_pref', sa.BigInteger(), 62 | autoincrement=False, nullable=True), 63 | # an IPv6 prefix can be up to 49 chars (IPv4-mapped IPv6 string 64 | # representation: up to 45 chars, plus 4 chars for "/128" which is the 65 | # highest/longest possible mask) 66 | sa.Column('prefix', sa.String(49), nullable=True), 67 | sa.Column('bgpvpn_id', sa.String(length=36), nullable=True), 68 | sa.ForeignKeyConstraint(['bgpvpn_id'], 69 | ['bgpvpns.id'], 70 | ondelete='CASCADE') 71 | # NOTE(tmorin): it would be nice to add some CheckConstraint so that 72 | # prefix and bgpvpn_id are enforced as NULL unless relevant for the 73 | # type, and non-NULL when relevant for the type 74 | ) 75 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/rocky/contract/9d7f1ae5fa56_add_standard_attributes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 OpenStack Fundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | 19 | """Add standard FK and constraints, and defs for existing objects 20 | 21 | Revision ID: 9d7f1ae5fa56 22 | Revises: 23ce05e0a19f 23 | Create Date: 2018-04-19 12:44:54.352253 24 | 25 | """ 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '9d7f1ae5fa56' 29 | down_revision = '23ce05e0a19f' 30 | depends_on = ('7a9482036ecd',) 31 | 32 | 33 | # adapted from b12a3ef66e62_add_standardattr_to_qos_policies.py 34 | 35 | standardattrs = sa.Table( 36 | 'standardattributes', sa.MetaData(), 37 | sa.Column('id', sa.BigInteger(), primary_key=True, autoincrement=True), 38 | sa.Column('resource_type', sa.String(length=255), nullable=False), 39 | sa.Column('description', sa.String(length=255), nullable=True)) 40 | 41 | 42 | def upgrade(): 43 | for table in ('bgpvpns', 'bgpvpn_network_associations', 44 | 'bgpvpn_router_associations', 'bgpvpn_port_associations'): 45 | upgrade_table(table) 46 | 47 | 48 | def upgrade_table(table): 49 | table_model = sa.Table( 50 | table, sa.MetaData(), 51 | sa.Column('id', sa.String(length=36), nullable=False), 52 | sa.Column('standard_attr_id', sa.BigInteger(), nullable=True)) 53 | 54 | generate_records_for_existing(table, table_model) 55 | # add the constraint now that everything is populated on that table 56 | op.alter_column(table, 'standard_attr_id', nullable=False, 57 | existing_type=sa.BigInteger(), existing_nullable=True, 58 | existing_server_default=False) 59 | op.create_unique_constraint( 60 | constraint_name='uniq_%s0standard_attr_id' % table, 61 | table_name=table, columns=['standard_attr_id']) 62 | op.create_foreign_key( 63 | constraint_name=None, source_table=table, 64 | referent_table='standardattributes', 65 | local_cols=['standard_attr_id'], remote_cols=['id'], 66 | ondelete='CASCADE') 67 | 68 | 69 | def generate_records_for_existing(table, table_model): 70 | session = sa.orm.Session(bind=op.get_bind()) 71 | values = [] 72 | with session.begin(): 73 | for row in session.query(table_model): 74 | # NOTE(kevinbenton): without this disabled, pylint complains 75 | # about a missing 'dml' argument. 76 | # pylint: disable=no-value-for-parameter 77 | res = session.execute( 78 | standardattrs.insert().values(resource_type=table) 79 | ) 80 | session.execute( 81 | table_model.update().values( 82 | standard_attr_id=res.inserted_primary_key[0]).where( 83 | table_model.c.id == row[0]) 84 | ) 85 | # this commit is necessary to allow further operations 86 | session.commit() 87 | return values 88 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/rocky/expand/7a9482036ecd_add_standard_attributes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 OpenStack Fundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | from alembic import op 17 | import sqlalchemy as sa 18 | 19 | """Add standard attributes 20 | 21 | Revision ID: 7a9482036ecd 22 | Revises: 666c706fea3b 23 | Create Date: 2018-04-04 10:12:40.399032 24 | 25 | """ 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '7a9482036ecd' 29 | down_revision = '666c706fea3b' 30 | 31 | 32 | def upgrade(): 33 | for table in ('bgpvpns', 'bgpvpn_network_associations', 34 | 'bgpvpn_router_associations', 'bgpvpn_port_associations'): 35 | op.add_column(table, sa.Column('standard_attr_id', sa.BigInteger(), 36 | nullable=True)) 37 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/db/migration/alembic_migrations/versions/start_networking_bgpvpn.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """start networking_bgpvpn chain 17 | Revision ID: start_networking_bgpvpn 18 | Revises: None 19 | Create Date: 2015-10-01 18:04:17.265514 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = 'start_networking_bgpvpn' 24 | down_revision = None 25 | 26 | 27 | def upgrade(): 28 | pass 29 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/extensions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/extensions/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/extensions/bgpvpn_vni.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Ericsson India Global Services Pvt Ltd. All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | 17 | from neutron_lib.api.definitions import bgpvpn_vni 18 | from neutron_lib.api import extensions 19 | 20 | 21 | class Bgpvpn_vni(extensions.APIExtensionDescriptor): 22 | """Extension class supporting vni. 23 | 24 | This class is used by neutron's extension framework to make 25 | metadata about the vni attribute in bgpvpn available to 26 | external applications. 27 | 28 | With admin rights one will be able to create and read the values. 29 | """ 30 | 31 | api_definition = bgpvpn_vni 32 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/opts.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from neutron.conf.services import provider_configuration 14 | from oslo_config import cfg 15 | 16 | 17 | def list_service_provider(): 18 | return [ 19 | ('service_providers', provider_configuration.serviceprovider_opts), 20 | ] 21 | 22 | 23 | _dummy_bgpvpn_provider = ':'.join([ 24 | 'BGPVPN', 'Dummy', 25 | 'networking_bgpvpn.neutron.services.service_drivers.driver_api.' 26 | 'BGPVPNDriver', 27 | 'default' 28 | ]) 29 | 30 | 31 | # Set reasonable example for BGPVPN as a default value 32 | def set_service_provider_default(): 33 | cfg.set_defaults(provider_configuration.serviceprovider_opts, 34 | service_provider=[_dummy_bgpvpn_provider]) 35 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/services/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/services/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/services/common/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/services/common/constants.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 OpenStack Foundation 2 | # Copyright (c) 2015 Hewlett-Packard Development Company, L.P. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from neutron_lib.api.definitions import bgpvpn 17 | 18 | BGPVPN_RES = bgpvpn.BGPVPN_RES 19 | BGPVPN_L3 = bgpvpn.BGPVPN_L3 20 | BGPVPN_L2 = bgpvpn.BGPVPN_L2 21 | BGPVPN_TYPES = bgpvpn.BGPVPN_TYPES 22 | UINT32_REGEX = bgpvpn.UINT32_REGEX 23 | UINT16_REGEX = bgpvpn.UINT16_REGEX 24 | UINT8_REGEX = bgpvpn.UINT8_REGEX 25 | IP4_REGEX = bgpvpn.IP4_REGEX 26 | RTRD_REGEX = bgpvpn.RTRD_REGEX 27 | -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/services/service_drivers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/services/service_drivers/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutron/services/service_drivers/bagpipe/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutron/services/service_drivers/bagpipe/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutronclient/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutronclient/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutronclient/neutron/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutronclient/neutron/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutronclient/neutron/v2_0/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutronclient/neutron/v2_0/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/neutronclient/neutron/v2_0/bgpvpn/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/neutronclient/neutron/v2_0/bgpvpn/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/policies/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import itertools 14 | 15 | from networking_bgpvpn.policies import bgpvpn 16 | from networking_bgpvpn.policies import network_association 17 | from networking_bgpvpn.policies import port_association 18 | from networking_bgpvpn.policies import router_association 19 | 20 | 21 | def list_rules(): 22 | return itertools.chain( 23 | bgpvpn.list_rules(), 24 | network_association.list_rules(), 25 | router_association.list_rules(), 26 | port_association.list_rules(), 27 | ) 28 | -------------------------------------------------------------------------------- /networking_bgpvpn/policies/network_association.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from neutron_lib import policy as base 14 | from oslo_policy import policy 15 | 16 | 17 | rules = [ 18 | policy.DocumentedRuleDefault( 19 | 'create_bgpvpn_network_association', 20 | base.RULE_ADMIN_OR_OWNER, 21 | 'Create a network association', 22 | [ 23 | { 24 | 'method': 'POST', 25 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/network_associations', 26 | }, 27 | ] 28 | ), 29 | # TODO(amotoki): PUT operation is not defined in the API ref. Drop it? 30 | policy.DocumentedRuleDefault( 31 | 'update_bgpvpn_network_association', 32 | base.RULE_ADMIN_OR_OWNER, 33 | 'Update a network association', 34 | [ 35 | { 36 | 'method': 'PUT', 37 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 38 | 'network_associations/{network_association_id}'), 39 | }, 40 | ] 41 | ), 42 | policy.DocumentedRuleDefault( 43 | 'delete_bgpvpn_network_association', 44 | base.RULE_ADMIN_OR_OWNER, 45 | 'Delete a network association', 46 | [ 47 | { 48 | 'method': 'DELETE', 49 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 50 | 'network_associations/{network_association_id}'), 51 | }, 52 | ] 53 | ), 54 | policy.DocumentedRuleDefault( 55 | 'get_bgpvpn_network_association', 56 | base.RULE_ADMIN_OR_OWNER, 57 | 'Get network associations', 58 | [ 59 | { 60 | 'method': 'GET', 61 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/network_associations', 62 | }, 63 | { 64 | 'method': 'GET', 65 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 66 | 'network_associations/{network_association_id}'), 67 | }, 68 | ] 69 | ), 70 | policy.DocumentedRuleDefault( 71 | 'get_bgpvpn_network_association:tenant_id', 72 | base.RULE_ADMIN_ONLY, 73 | 'Get ``tenant_id`` attributes of network associations', 74 | [ 75 | { 76 | 'method': 'GET', 77 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/network_associations', 78 | }, 79 | { 80 | 'method': 'GET', 81 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 82 | 'network_associations/{network_association_id}'), 83 | }, 84 | ] 85 | ), 86 | ] 87 | 88 | 89 | def list_rules(): 90 | return rules 91 | -------------------------------------------------------------------------------- /networking_bgpvpn/policies/port_association.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from neutron_lib import policy as base 14 | from oslo_policy import policy 15 | 16 | 17 | rules = [ 18 | policy.DocumentedRuleDefault( 19 | 'create_bgpvpn_port_association', 20 | base.RULE_ADMIN_OR_OWNER, 21 | 'Create a port association', 22 | [ 23 | { 24 | 'method': 'POST', 25 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations', 26 | }, 27 | ] 28 | ), 29 | policy.DocumentedRuleDefault( 30 | 'update_bgpvpn_port_association', 31 | base.RULE_ADMIN_OR_OWNER, 32 | 'Update a port association', 33 | [ 34 | { 35 | 'method': 'PUT', 36 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 37 | 'port_associations/{port_association_id}'), 38 | }, 39 | ] 40 | ), 41 | policy.DocumentedRuleDefault( 42 | 'delete_bgpvpn_port_association', 43 | base.RULE_ADMIN_OR_OWNER, 44 | 'Delete a port association', 45 | [ 46 | { 47 | 'method': 'DELETE', 48 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 49 | 'port_associations/{port_association_id}'), 50 | }, 51 | ] 52 | ), 53 | policy.DocumentedRuleDefault( 54 | 'get_bgpvpn_port_association', 55 | base.RULE_ADMIN_OR_OWNER, 56 | 'Get port associations', 57 | [ 58 | { 59 | 'method': 'GET', 60 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations', 61 | }, 62 | { 63 | 'method': 'GET', 64 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 65 | 'port_associations/{port_association_id}'), 66 | }, 67 | ] 68 | ), 69 | policy.DocumentedRuleDefault( 70 | 'get_bgpvpn_port_association:tenant_id', 71 | base.RULE_ADMIN_ONLY, 72 | 'Get ``tenant_id`` attributes of port associations', 73 | [ 74 | { 75 | 'method': 'GET', 76 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations', 77 | }, 78 | { 79 | 'method': 'GET', 80 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 81 | 'port_associations/{port_association_id}'), 82 | }, 83 | ] 84 | ), 85 | ] 86 | 87 | 88 | def list_rules(): 89 | return rules 90 | -------------------------------------------------------------------------------- /networking_bgpvpn/policies/router_association.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from neutron_lib import policy as base 14 | from oslo_policy import policy 15 | 16 | 17 | rules = [ 18 | policy.DocumentedRuleDefault( 19 | 'create_bgpvpn_router_association', 20 | base.RULE_ADMIN_OR_OWNER, 21 | 'Create a router association', 22 | [ 23 | { 24 | 'method': 'POST', 25 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/router_associations', 26 | }, 27 | ] 28 | ), 29 | policy.DocumentedRuleDefault( 30 | 'update_bgpvpn_router_association', 31 | base.RULE_ADMIN_OR_OWNER, 32 | 'Update a router association', 33 | [ 34 | { 35 | 'method': 'PUT', 36 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 37 | 'router_associations/{router_association_id}'), 38 | }, 39 | ] 40 | ), 41 | policy.DocumentedRuleDefault( 42 | 'delete_bgpvpn_router_association', 43 | base.RULE_ADMIN_OR_OWNER, 44 | 'Delete a router association', 45 | [ 46 | { 47 | 'method': 'DELETE', 48 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 49 | 'router_associations/{router_association_id}'), 50 | }, 51 | ] 52 | ), 53 | policy.DocumentedRuleDefault( 54 | 'get_bgpvpn_router_association', 55 | base.RULE_ADMIN_OR_OWNER, 56 | 'Get router associations', 57 | [ 58 | { 59 | 'method': 'GET', 60 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/router_associations', 61 | }, 62 | { 63 | 'method': 'GET', 64 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 65 | 'router_associations/{router_association_id}'), 66 | }, 67 | ] 68 | ), 69 | policy.DocumentedRuleDefault( 70 | 'get_bgpvpn_router_association:tenant_id', 71 | base.RULE_ADMIN_ONLY, 72 | 'Get ``tenant_id`` attributes of router associations', 73 | [ 74 | { 75 | 'method': 'GET', 76 | 'path': '/bgpvpn/bgpvpns/{bgpvpn_id}/router_associations', 77 | }, 78 | { 79 | 'method': 'GET', 80 | 'path': ('/bgpvpn/bgpvpns/{bgpvpn_id}/' 81 | 'router_associations/{router_association_id}'), 82 | }, 83 | ] 84 | ), 85 | ] 86 | 87 | 88 | def list_rules(): 89 | return rules 90 | -------------------------------------------------------------------------------- /networking_bgpvpn/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/functional/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/functional/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/functional/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/functional/db/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/functional/db/test_migrations.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from oslo_config import cfg 14 | 15 | from neutron.db.migration.alembic_migrations import external 16 | from neutron.db.migration import cli as migration 17 | from neutron.tests.functional.db import test_migrations 18 | from neutron.tests.unit import testlib_api 19 | 20 | from networking_bgpvpn.neutron.db import head 21 | 22 | 23 | # Tables from other repos that we depend on but do not manage. 24 | IGNORED_TABLES_MATCH = ( 25 | 'ml2_route_target_allocations', 26 | '_bagpipe_', 27 | ) 28 | 29 | # EXTERNAL_TABLES should contain all names of tables that are not related to 30 | # current repo. 31 | EXTERNAL_TABLES = set(external.TABLES) 32 | VERSION_TABLE = 'alembic_version_bgpvpn' 33 | 34 | 35 | class TestModelsMigrationsBGPVPN(test_migrations.TestModelsMigrations, 36 | testlib_api.MySQLTestCaseMixin, 37 | testlib_api.SqlTestCaseLight): 38 | 39 | def db_sync(self, engine): 40 | cfg.CONF.set_override( 41 | 'connection', 42 | engine.url.render_as_string(hide_password=False), 43 | group='database') 44 | for conf in migration.get_alembic_configs(): 45 | self.alembic_config = conf 46 | self.alembic_config.neutron_config = cfg.CONF 47 | migration.do_alembic_command(conf, 'upgrade', 'heads') 48 | 49 | def get_metadata(self): 50 | return head.get_metadata() 51 | 52 | def include_object(self, object_, name, type_, reflected, compare_to): 53 | if (type_ == "table" and ( 54 | name.startswith("alembic") or 55 | name == VERSION_TABLE or 56 | name in EXTERNAL_TABLES or 57 | any([match in name for match in IGNORED_TABLES_MATCH]) 58 | )): 59 | return False 60 | if type_ == 'index' and reflected and name.startswith("idx_autoinc_"): 61 | return False 62 | return True 63 | -------------------------------------------------------------------------------- /networking_bgpvpn/tests/functional/requirements.txt: -------------------------------------------------------------------------------- 1 | # Additional requirements for functional tests 2 | 3 | # The order of packages is significant, because pip processes them in the order 4 | # of appearance. Changing the order has an impact on the overall integration 5 | # process, which may cause wedges in the gate later. 6 | -------------------------------------------------------------------------------- /networking_bgpvpn/tests/functional/test_placeholder.py: -------------------------------------------------------------------------------- 1 | from neutron.tests import base 2 | 3 | 4 | class PlaceholderTest(base.BaseTestCase): 5 | 6 | def test_noop(self): 7 | pass 8 | -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/client/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/client/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/client/test_client.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015 Orange. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from unittest import mock 17 | 18 | from neutron.tests.unit.extensions import base as test_extensions_base 19 | 20 | from neutronclient.v2_0 import client 21 | 22 | 23 | BGPVPN_ID = "uuid-bgpvpn-foo" 24 | NET_ASSOC_ID = "uuid-netassoc-bar" 25 | 26 | ASSOCS_PATH = "/bgpvpn/bgpvpns/%s/network_associations" % BGPVPN_ID 27 | ASSOC_PATH = "/bgpvpn/bgpvpns/%s/network_associations/%%s" % BGPVPN_ID 28 | 29 | 30 | class BgpvpnClientTestCase(test_extensions_base.ExtensionTestCase): 31 | 32 | def setUp(self): 33 | super().setUp() 34 | 35 | self.client = client.Client() 36 | self.client.list_ext = mock.Mock() 37 | self.client.create_ext = mock.Mock() 38 | self.client.show_ext = mock.Mock() 39 | self.client.update_ext = mock.Mock() 40 | self.client.delete_ext = mock.Mock() 41 | 42 | def test_api_url_list(self): 43 | self.client.list_network_associations(BGPVPN_ID) 44 | self.client.list_ext.assert_called_once_with(mock.ANY, ASSOCS_PATH, 45 | mock.ANY) 46 | 47 | def test_api_url_create(self): 48 | self.client.create_network_association(BGPVPN_ID, {}) 49 | self.client.create_ext.assert_called_once_with(ASSOCS_PATH, mock.ANY) 50 | 51 | def test_api_url_show(self): 52 | self.client.show_network_association(NET_ASSOC_ID, BGPVPN_ID) 53 | self.client.show_ext.assert_called_once_with(ASSOC_PATH, 54 | NET_ASSOC_ID) 55 | 56 | def test_api_url_update(self): 57 | self.client.update_network_association(NET_ASSOC_ID, BGPVPN_ID, {}) 58 | self.client.update_ext.assert_called_once_with(ASSOC_PATH, 59 | NET_ASSOC_ID, 60 | mock.ANY) 61 | 62 | def test_api_url_delete(self): 63 | self.client.delete_network_association(NET_ASSOC_ID, BGPVPN_ID) 64 | self.client.delete_ext.assert_called_once_with(ASSOC_PATH, 65 | NET_ASSOC_ID) 66 | -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/db/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/extensions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/extensions/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/services/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/services/bagpipe/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/services/bagpipe/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/services/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn/tests/unit/services/common/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn/tests/unit/services/common/test_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Juniper Networks, Inc. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from neutron.tests import base 17 | 18 | from networking_bgpvpn.neutron.services.common.utils import filter_resource 19 | 20 | 21 | class TestFilterResource(base.BaseTestCase): 22 | _fake_resource_string = { 23 | 'fake_attribute': 'fake_value1', 24 | } 25 | _fake_resource_list = { 26 | 'fake_attribute': ['fake_value1', 'fake_value2', 'fake_value3'], 27 | } 28 | 29 | def test_filter_resource_succeeds_with_one_value(self): 30 | filters = { 31 | 'fake_attribute': 'fake_value1', 32 | } 33 | self.assertTrue(filter_resource(self._fake_resource_string, filters)) 34 | self.assertTrue(filter_resource(self._fake_resource_list, filters)) 35 | 36 | def test_filter_resource_fails_with_one_value(self): 37 | filters = { 38 | 'fake_attribute': 'wrong_fake_value1', 39 | } 40 | self.assertFalse(filter_resource(self._fake_resource_string, filters)) 41 | self.assertFalse(filter_resource(self._fake_resource_list, filters)) 42 | 43 | def test_filter_resource_succeeds_with_list_of_values(self): 44 | filters = { 45 | 'fake_attribute': ['fake_value1'], 46 | } 47 | self.assertTrue(filter_resource(self._fake_resource_string, filters)) 48 | filters = { 49 | 'fake_attribute': ['fake_value1', 'fake_value2'], 50 | } 51 | self.assertTrue(filter_resource(self._fake_resource_list, filters)) 52 | 53 | def test_filter_resource_fails_with_list_of_values(self): 54 | filters = { 55 | 'fake_attribute': ['wrong_fake_value1'], 56 | } 57 | self.assertFalse(filter_resource(self._fake_resource_string, filters)) 58 | filters = { 59 | 'fake_attribute': ['wrong_fake_value1', 'fake_value2'], 60 | } 61 | self.assertFalse(filter_resource(self._fake_resource_list, filters)) 62 | -------------------------------------------------------------------------------- /networking_bgpvpn/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2011 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | import pbr.version 16 | 17 | # DNM: just test state of master 18 | version_info = pbr.version.VersionInfo('networking-bgpvpn') 19 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/networking_bgpvpn_heat/__init__.py -------------------------------------------------------------------------------- /networking_bgpvpn_heat/_i18n.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import oslo_i18n 14 | 15 | DOMAIN = "networking_bgpvpn_heat" 16 | 17 | _translators = oslo_i18n.TranslatorFactory(domain=DOMAIN) 18 | 19 | # The primary translation function using the well-known name "_" 20 | _ = _translators.primary 21 | 22 | # The contextual translation function using the name "_C" 23 | # requires oslo.i18n >=2.1.0 24 | _C = _translators.contextual_form 25 | 26 | # The plural translation function using the name "_P" 27 | # requires oslo.i18n >=2.1.0 28 | _P = _translators.plural_form 29 | 30 | 31 | def get_available_languages(): 32 | return oslo_i18n.get_available_languages(DOMAIN) 33 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-00.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (admin) 2 | heat_template_version: '2013-05-23' 3 | 4 | resources: 5 | 6 | BGPVPN1: 7 | type: OS::Neutron::BGPVPN 8 | properties: 9 | import_targets: [ "100:1001"] 10 | export_targets: [ "100:1002"] 11 | route_targets: [ "100:1000" ] 12 | name: "default VPN" 13 | 14 | Net1: 15 | type: OS::Neutron::Net 16 | 17 | SubNet1: 18 | type: OS::Neutron::Subnet 19 | properties: 20 | network: { get_resource: Net1 } 21 | cidr: 192.168.10.0/24 22 | 23 | BGPVPN_NET_assoc1: 24 | type: OS::Neutron::BGPVPN-NET-ASSOCIATION 25 | properties: 26 | bgpvpn_id: { get_resource: BGPVPN1 } 27 | network_id: { get_resource: Net1 } 28 | 29 | 30 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-01-admin.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (admin) 2 | heat_template_version: '2013-05-23' 3 | 4 | resources: 5 | BGPVPN1: 6 | type: OS::Neutron::BGPVPN 7 | properties: 8 | import_targets: [ "100:1001"] 9 | export_targets: [ "100:1002"] 10 | route_targets: [ "100:1000" ] 11 | name: "default_vpn" 12 | 13 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-01-tenant.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (tenant) 2 | heat_template_version: '2013-05-23' 3 | 4 | parameters: 5 | bgpvpn: 6 | type: string 7 | description: id of BGPVPN to bind the network to 8 | 9 | resources: 10 | Net1: 11 | type: OS::Neutron::Net 12 | 13 | SubNet1: 14 | type: OS::Neutron::Subnet 15 | properties: 16 | network: { get_resource: Net1 } 17 | cidr: 192.168.10.0/24 18 | 19 | BGPVPN_NET_assoc1: 20 | type: OS::Neutron::BGPVPN-NET-ASSOCIATION 21 | properties: 22 | bgpvpn_id: { get_param: bgpvpn } 23 | network_id: { get_resource: Net1 } 24 | 25 | 26 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-01bis_router-tenant.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (tenant) 2 | heat_template_version: '2013-05-23' 3 | 4 | parameters: 5 | bgpvpn: 6 | type: string 7 | description: id of BGPVPN to bind the network to 8 | 9 | resources: 10 | Net1: 11 | type: OS::Neutron::Net 12 | 13 | SubNet1: 14 | type: OS::Neutron::Subnet 15 | properties: 16 | network: { get_resource: Net1 } 17 | cidr: 192.168.10.0/24 18 | 19 | Router1: 20 | type: OS::Neutron::Router 21 | 22 | router_interface1: 23 | type: OS::Neutron::RouterInterface 24 | properties: 25 | router_id: { get_resource: Router1 } 26 | subnet_id: { get_resource: SubNet1 } 27 | 28 | BGPVPN_router_assoc1: 29 | type: OS::Neutron::BGPVPN-ROUTER-ASSOCIATION 30 | properties: 31 | bgpvpn_id: { get_param: bgpvpn } 32 | router_id: { get_resource: Router1 } 33 | 34 | 35 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-01ter_port-tenant.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (tenant) 2 | heat_template_version: '2013-05-23' 3 | 4 | parameters: 5 | bgpvpn: 6 | type: string 7 | description: id of BGPVPN to bind the network to 8 | 9 | bgpvpn_bis: 10 | type: string 11 | description: id of BGPVPN from which to readvertise a route 12 | 13 | resources: 14 | Net1: 15 | type: OS::Neutron::Net 16 | 17 | SubNet1: 18 | type: OS::Neutron::Subnet 19 | properties: 20 | network: { get_resource: Net1 } 21 | cidr: 192.168.10.0/24 22 | Port1: 23 | type: OS::Neutron::Port 24 | properties: 25 | network: { get_resource: Net1 } 26 | 27 | Port2: 28 | type: OS::Neutron::Port 29 | properties: 30 | network: { get_resource: Net1 } 31 | 32 | BGPVPN_port_assoc1: 33 | type: OS::Neutron::BGPVPN-PORT-ASSOCIATION 34 | properties: 35 | bgpvpn_id: { get_param: bgpvpn } 36 | port_id: { get_resource: Port1 } 37 | 38 | BGPVPN_port_assoc2: 39 | type: OS::Neutron::BGPVPN-PORT-ASSOCIATION 40 | properties: 41 | bgpvpn_id: { get_param: bgpvpn } 42 | port_id: { get_resource: Port2 } 43 | advertise_fixed_ips: false 44 | routes: 45 | - type: prefix 46 | prefix: 1.1.1.1/32 47 | local_pref: 42 48 | - type: bgpvpn 49 | bgpvpn_id: { get_param: bgpvpn_bis } 50 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-04-admin.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (admin) 2 | heat_template_version: '2013-05-23' 3 | 4 | resources: 5 | BGPVPN1: 6 | type: OS::Neutron::BGPVPN 7 | properties: 8 | import_targets: [ "100:1001"] 9 | export_targets: [ "100:1002"] 10 | route_targets: [ "100:1000" ] 11 | name: "default_vpn" 12 | tenant_id: "demo" 13 | 14 | 15 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/examples/bgpvpn_test-04-tenant.yaml: -------------------------------------------------------------------------------- 1 | description: BGPVPN networking example (tenant) 2 | heat_template_version: '2013-05-23' 3 | 4 | resources: 5 | Net1: 6 | type: OS::Neutron::Net 7 | 8 | SubNet1: 9 | type: OS::Neutron::Subnet 10 | properties: 11 | network: { get_resource: Net1 } 12 | cidr: 192.168.10.0/24 13 | 14 | BGPVPN_NET_assoc1: 15 | type: OS::Neutron::BGPVPN-NET-ASSOCIATION 16 | properties: 17 | bgpvpn_id: "default_vpn" 18 | network_id: { get_resource: Net1 } 19 | 20 | Net2: 21 | type: OS::Neutron::Net 22 | 23 | SubNet2: 24 | type: OS::Neutron::Subnet 25 | properties: 26 | network: { get_resource: Net2 } 27 | cidr: 192.168.10.0/24 28 | 29 | Router: 30 | type: OS::Neutron::Router 31 | 32 | router_interface: 33 | type: OS::Neutron::RouterInterface 34 | properties: 35 | router_id: { get_resource: Router } 36 | subnet_id: { get_resource: SubNet2 } 37 | 38 | BGPVPN_router_assoc1: 39 | type: OS::Neutron::BGPVPN-ROUTER-ASSOCIATION 40 | properties: 41 | bgpvpn_id: "default_vpn" 42 | router_id: { get_resource: Router } 43 | 44 | Net3: 45 | type: OS::Neutron::Net 46 | 47 | SubNet3: 48 | type: OS::Neutron::Subnet 49 | properties: 50 | network: { get_resource: Net3 } 51 | cidr: 192.168.10.0/24 52 | Port: 53 | type: OS::Neutron::Port 54 | properties: 55 | network: { get_resource: Net3 } 56 | BGPVPN_port_assoc1: 57 | type: OS::Neutron::BGPVPN-PORT-ASSOCIATION 58 | properties: 59 | bgpvpn_id: "default_vpn" 60 | port_id: { get_resource: Port } 61 | 62 | 63 | -------------------------------------------------------------------------------- /networking_bgpvpn_heat/locale/en_GB/LC_MESSAGES/networking_bgpvpn_heat.po: -------------------------------------------------------------------------------- 1 | # Andi Chandler , 2017. #zanata 2 | # Andi Chandler , 2019. #zanata 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: networking-bgpvpn VERSION\n" 6 | "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" 7 | "POT-Creation-Date: 2019-12-05 06:33+0000\n" 8 | "MIME-Version: 1.0\n" 9 | "Content-Type: text/plain; charset=UTF-8\n" 10 | "Content-Transfer-Encoding: 8bit\n" 11 | "PO-Revision-Date: 2019-12-21 02:47+0000\n" 12 | "Last-Translator: Andi Chandler \n" 13 | "Language-Team: English (United Kingdom)\n" 14 | "Language: en_GB\n" 15 | "X-Generator: Zanata 4.3.3\n" 16 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 17 | 18 | msgid "All attributes." 19 | msgstr "All attributes." 20 | 21 | msgid "BGP VPN type selection between L3VPN (l3) and EVPN (l2), default:l3" 22 | msgstr "BGP VPN type selection between L3VPN (l3) and EVPN (l2), default:l3" 23 | 24 | msgid "" 25 | "BGPVPN from which to readvertise routes(any route carrying an RT among " 26 | "route_targets or import_targets of this BGPVPN, will be readvertised)." 27 | msgstr "" 28 | "BGPVPN from which to readvertise routes(any route carrying an RT among " 29 | "route_targets or import_targets of this BGPVPN, will be readvertised)." 30 | 31 | msgid "" 32 | "Default value of the BGP LOCAL_PREF for the route advertisement to this " 33 | "BGPVPN." 34 | msgstr "" 35 | "Default value of the BGP LOCAL_PREF for the route advertisement to this " 36 | "BGPVPN." 37 | 38 | msgid "" 39 | "Defines routes to advertise into the BGPVPN, and for which this port will be " 40 | "the nexthop" 41 | msgstr "" 42 | "Defines routes to advertise into the BGPVPN, and for which this port will be " 43 | "the nexthop" 44 | 45 | msgid "Description for the bgpvpn." 46 | msgstr "Description for the BGPVPN." 47 | 48 | msgid "List of RDs that will be used to advertize BGPVPN routes." 49 | msgstr "List of RDs that will be used to advertise BGPVPN routes." 50 | 51 | msgid "List of additional Route Targets to export to." 52 | msgstr "List of additional Route Targets to export to." 53 | 54 | msgid "List of additional Route Targets to import from." 55 | msgstr "List of additional Route Targets to import from." 56 | 57 | msgid "Name for the bgpvpn." 58 | msgstr "Name for the BGPVPN." 59 | 60 | msgid "Network which shall be associated with the BGPVPN." 61 | msgstr "Network which shall be associated with the BGPVPN." 62 | 63 | msgid "Port which shall be associated with the BGPVPN." 64 | msgstr "Port which shall be associated with the BGPVPN." 65 | 66 | msgid "Prefix to readvertise." 67 | msgstr "Prefix to readvertise." 68 | 69 | msgid "Route Targets list to import/export for this BGPVPN." 70 | msgstr "Route Targets list to import/export for this BGPVPN." 71 | 72 | msgid "Router which shall be associated with the BGPVPN." 73 | msgstr "Router which shall be associated with the BGPVPN." 74 | 75 | msgid "Status of bgpvpn." 76 | msgstr "Status of BGPVPN." 77 | 78 | msgid "Tenant this bgpvpn belongs to (name or id)." 79 | msgstr "Tenant this BGPVPN belongs to (name or id)." 80 | 81 | msgid "Type of the route." 82 | msgstr "Type of the route." 83 | 84 | msgid "Value of the BGP LOCAL_PREF for the routes." 85 | msgstr "Value of the BGP LOCAL_PREF for the routes." 86 | 87 | msgid "name or ID of the BGPVPN." 88 | msgstr "name or ID of the BGPVPN." 89 | 90 | msgid "" 91 | "whether or not the fixed IPs of he port will be advertised into the BGPVPN." 92 | msgstr "" 93 | "whether or not the fixed IPs of he port will be advertised into the BGPVPN." 94 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["pbr>=5.7.0", "setuptools>=64.0.0", "wheel"] 3 | build-backend = "pbr.build" 4 | 5 | -------------------------------------------------------------------------------- /releasenotes/notes/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/releasenotes/notes/.placeholder -------------------------------------------------------------------------------- /releasenotes/notes/0_heat-support-ab233de7401aeb36.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - Heat support for the whole BGPVPN Interconnection API 4 | -------------------------------------------------------------------------------- /releasenotes/notes/add-vni-to-bgpvpn-31d6eda7ba6d5047.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add ``vni`` optional attribute to ``bgpvpn`` resource to control the VXLAN 5 | VNI when VXLAN encapsulation is used. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/bagpipe-driver-improvements-401a7ba59a6f5f45.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - BaGPipe driver improvement for a clean integration in the Neutron OpenVSwitch agent (see Bug `1492021 `_). 4 | Instead of requiring to use a modified OVS agent, we now provide an extension that is loaded 5 | into the unmodified OVS agent. 6 | fixes: 7 | - with BaGPipe driver, the OVS agent does not lose BGPVPN flows on restart (Bug `1531459 `_) 8 | -------------------------------------------------------------------------------- /releasenotes/notes/bagpipe-router-compat-b53b6f3799cd23db.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | The ovs/bagpipe driver now let you use both a Neutron 4 | router and a BGPVPN association simultaneously on a 5 | given Port. 6 | features: 7 | - The bagpipe driver now let happily coexist a BGPVPN 8 | association and a Neutron router. Traffic that does 9 | not match any VPN route will be handled by the Neutron 10 | router. This evolution depends on corresponding evolutions 11 | in networking-bagpipe and bagpipe-bgp. 12 | (`see bug 1627645 `_) 13 | 14 | -------------------------------------------------------------------------------- /releasenotes/notes/bagpipe_enable_evpn-ae64f77df89e069b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | BGPVPNs of type L2 are now supported with Neutron ML2 reference 5 | drivers (OVS and linuxbridge). 6 | -------------------------------------------------------------------------------- /releasenotes/notes/bagpipe_ovo_rpcs-380f7bd52969bef7.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The BGPVPN reference driver `bagpipe`, for use with Neutron linuxbridge 5 | or OVS reference drivers, has adopted OVO-based RPCs. A v2 driver is provided 6 | to avoid the production of old-style RPCs. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/bgpvpn_service_declaration-6d9ecd2c397e4821.yaml: -------------------------------------------------------------------------------- 1 | features: 2 | - | 3 | The BGPVPN Interconnection API can now be enabled by adding ``bgpvpn`` to 4 | ``service_plugins`` in ``neutron.conf``, instead of the verbose 5 | ``networking_bgpvpn.neutron.services.plugin.BGPVPNPlugin``. 6 | 7 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-old-opencontrail-driver-a598892ddf54c724.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The first OpenContrail Driver was not developed with production ready in 5 | mind, it was more a proof of concept. We do not recommend to use it in 6 | production. Instead a production ready driver is available in the 7 | OpenContrail monolithic Neutron core plugin tree. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-py-2-7-4db5f2b1529bb09c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Python 2.7 support has been dropped. Last release of networking-bgpvpn 5 | to support Python 2.7 is OpenStack Train. The minimum version 6 | of Python now supported by networking-bgpvpn is Python 3.6. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-python-3-6-and-3-7-97c0464e7a396023.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Python 3.6 & 3.7 support has been dropped. The minimum version of Python now 5 | supported is Python 3.8. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/filtering-on-resource-association-2acdbc5b59d1a40a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - The API now supports filtering BGPVPN resources based 4 | on the networks or routers they are associated with. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/heat_bgpvpn_local_pref-a1cbfde10810b157.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The the 'local_pref' attribute of a Heat BGPVPN resource 5 | can now be controlled in a Heat template. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/heat_port_associations-f2d316f3b8c755fe.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The Heat plugin for the BGPVPN interconnection API extension now supports 5 | BGPVPN Port Association resources. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/horizon-in-extras-371d572b09437dc4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Horizon is now an optional dependency of networking-bgpvpn 5 | as the GUI support is optional. This means horizon will not be 6 | installed automatically. The horizon dependency is now declared 7 | in ``extras`` section in ``setup.cfg``. If you would like to enable 8 | the GUI support, you can install the dependencies using 9 | ``python -m pip install networking-bgpvpn[horizon]`` 10 | (or ``.[horizon]`` in case you install it from the source code). 11 | -------------------------------------------------------------------------------- /releasenotes/notes/horizon-support-06a7b21286002949.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | New Horizon panels for BGPVPN resources, allowing you to create a 4 | bgpvpn and to associate related resources such as a network or a 5 | router. 6 | features: 7 | - | 8 | Horizon: 9 | * a view of all the existing BGPVPNs. 10 | * ability to view details of a BGPVPN. 11 | * ability to create, update and delete BGPVPN resources for an 12 | admin user. 13 | * ability to update BGPVPN resources for a tenant user. 14 | (with restrictions, compared to what an admin user can change) 15 | * abiity to associate/disassociate BGPVPN to/from networks and 16 | routers (for both tenant and admin users) 17 | 18 | -------------------------------------------------------------------------------- /releasenotes/notes/mitaka-prelude-1675467c144a91ea.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | Mitaka release is a short-cycle release to compensate for the 4 | delayed Liberty release and get the project in sync 5 | with Openstack release cycles 6 | -------------------------------------------------------------------------------- /releasenotes/notes/odl_router_association-fa2ed7c396531418.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - OpenDaylight driver now supports Router associations 4 | -------------------------------------------------------------------------------- /releasenotes/notes/pre_commit_checks-b902ee19a3654a7b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - Pre-commit hooks were added in the driver framework, and then leveraged in BaGPipe and OpenDaylight drivers 4 | 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove_obsolete_drivers-3706e080098a5cb6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The obsolete in-tree drivers for OpenContrail and OpenDaylight have been 5 | removed, in favor of the out-of-tree drivers provided by these projects. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/routes-control-api-ext-c0c4020e7370d833.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The `bgpvpn-routes-control` API extension is introduced, allowing control 5 | of BGPVPN routing with a finer grain, including API-defined static routes 6 | pointing to Neutron ports, or BGPVPN route leaking via Neutron ports. 7 | -------------------------------------------------------------------------------- /releasenotes/source/2023.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/2023.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2023.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2023.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2025.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2025.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2025.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/releasenotes/source/_static/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/_templates/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/networking-bgpvpn/1044a82287af01f3f627a233370aaf03fd85830d/releasenotes/source/_templates/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/index.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Networking-bgpvpn Release Notes 3 | ================================ 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | unreleased 9 | 2025.1 10 | 2024.2 11 | 2024.1 12 | 2023.2 13 | 2023.1 14 | zed 15 | yoga 16 | xena 17 | wallaby 18 | victoria 19 | ussuri 20 | train 21 | stein 22 | rocky 23 | queens 24 | pike 25 | ocata 26 | newton 27 | mitaka 28 | liberty 29 | -------------------------------------------------------------------------------- /releasenotes/source/liberty.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Liberty Series Release Notes 3 | ============================== 4 | 5 | .. release-notes:: 6 | :branch: origin/stable/liberty 7 | -------------------------------------------------------------------------------- /releasenotes/source/mitaka.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Mitaka Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/mitaka 7 | -------------------------------------------------------------------------------- /releasenotes/source/newton.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Newton Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/newton 7 | -------------------------------------------------------------------------------- /releasenotes/source/ocata.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Ocata Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: origin/stable/ocata 7 | -------------------------------------------------------------------------------- /releasenotes/source/pike.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Pike Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/pike 7 | -------------------------------------------------------------------------------- /releasenotes/source/queens.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Queens Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/queens 7 | -------------------------------------------------------------------------------- /releasenotes/source/rocky.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Rocky Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/rocky 7 | -------------------------------------------------------------------------------- /releasenotes/source/stein.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Stein Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/stein 7 | -------------------------------------------------------------------------------- /releasenotes/source/train.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Train Series Release Notes 3 | ========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/train 7 | -------------------------------------------------------------------------------- /releasenotes/source/unreleased.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Current Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | -------------------------------------------------------------------------------- /releasenotes/source/ussuri.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Ussuri Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/ussuri 7 | -------------------------------------------------------------------------------- /releasenotes/source/victoria.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Victoria Series Release Notes 3 | ============================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/victoria 7 | -------------------------------------------------------------------------------- /releasenotes/source/wallaby.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Wallaby Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/wallaby 7 | -------------------------------------------------------------------------------- /releasenotes/source/xena.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Xena Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/xena 7 | -------------------------------------------------------------------------------- /releasenotes/source/yoga.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Yoga Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/yoga 7 | -------------------------------------------------------------------------------- /releasenotes/source/zed.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | Zed Series Release Notes 3 | ======================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/zed 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Requirements lower bounds listed here are our best effort to keep them up to 2 | # date but we do not test them so no guarantee of having them all correct. If 3 | # you find any incorrect lower bounds, let us know or propose a fix. 4 | 5 | pbr>=4.0.0 # Apache-2.0 6 | oslo.config>=5.2.0 # Apache-2.0 7 | oslo.db>=4.37.0 # Apache-2.0 8 | oslo.i18n>=3.15.3 # Apache-2.0 9 | oslo.log>=3.36.0 # Apache-2.0 10 | oslo.utils>=3.33.0 # Apache-2.0 11 | neutron-lib>=1.30.0 # Apache-2.0 12 | debtcollector>=1.19.0 # Apache-2.0 13 | 14 | # OpenStack CI will install the following projects from git 15 | # if they are in the required-projects list for a job: 16 | neutron>=23.0.0.0b2 # Apache-2.0 17 | 18 | # The comment below indicates this project repo is current with neutron-lib 19 | # and should receive neutron-lib consumption patches as they are released 20 | # in neutron-lib. It also implies the project will stay current with TC 21 | # and infra initiatives ensuring consumption patches can land. 22 | # neutron-lib-current 23 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = networking-bgpvpn 3 | summary = API and Framework to interconnect bgpvpn to neutron networks 4 | description_file = 5 | README.rst 6 | author = OpenStack 7 | author_email = openstack-discuss@lists.openstack.org 8 | home_page = https://docs.openstack.org/networking-bgpvpn/latest/ 9 | python_requires = >=3.9 10 | classifier = 11 | Environment :: OpenStack 12 | Intended Audience :: Information Technology 13 | Intended Audience :: System Administrators 14 | License :: OSI Approved :: Apache Software License 15 | Operating System :: POSIX :: Linux 16 | Programming Language :: Python 17 | Programming Language :: Python :: Implementation :: CPython 18 | Programming Language :: Python :: 3 :: Only 19 | Programming Language :: Python :: 3 20 | Programming Language :: Python :: 3.9 21 | Programming Language :: Python :: 3.10 22 | Programming Language :: Python :: 3.11 23 | Programming Language :: Python :: 3.12 24 | 25 | [files] 26 | packages = 27 | networking_bgpvpn 28 | networking_bgpvpn_heat 29 | bgpvpn_dashboard 30 | data_files = 31 | etc/neutron = 32 | etc/neutron/networking_bgpvpn.conf 33 | 34 | [extras] 35 | # Dependencies for optional drivers/features. 36 | # To install them, specify networking-bgpvpn[] 37 | # e.g. "networking-bgpvpn[horizon]" 38 | # For tox testing, we have these in test-requirements.txt too 39 | # as tox extras installation does not honor constraints file. 40 | bagpipe = 41 | networking-bagpipe>=12.0.0 # Apache-2.0 42 | horizon = 43 | horizon>=17.1.0 # Apache-2.0 44 | 45 | [entry_points] 46 | neutronclient.extension= 47 | bgpvpn = networking_bgpvpn.neutronclient.neutron.v2_0.bgpvpn.bgpvpn 48 | neutron.db.alembic_migrations= 49 | networking-bgpvpn = networking_bgpvpn.neutron.db.migration:alembic_migrations 50 | heat.constraints = 51 | neutron.bgpvpn = networking_bgpvpn_heat.bgpvpnservice:BGPVPNConstraint 52 | neutron.service_plugins = 53 | bgpvpn = networking_bgpvpn.neutron.services.plugin:BGPVPNPlugin 54 | oslo.config.opts = 55 | networking-bgpvpn.service_provider = networking_bgpvpn.neutron.opts:list_service_provider 56 | oslo.config.opts.defaults = 57 | networking-bgpvpn.service_provider = networking_bgpvpn.neutron.opts:set_service_provider_default 58 | oslo.policy.policies = 59 | networking-bgpvpn = networking_bgpvpn.policies:list_rules 60 | neutron.policies = 61 | networking-bgpvpn = networking_bgpvpn.policies:list_rules 62 | 63 | [openstack_translations] 64 | django_modules = bgpvpn_dashboard 65 | python_modules = networking_bgpvpn networking_bgpvpn_heat 66 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import setuptools 17 | 18 | setuptools.setup( 19 | setup_requires=['pbr>=2.0.0'], 20 | pbr=True) 21 | -------------------------------------------------------------------------------- /specs/bgpvpn.rst: -------------------------------------------------------------------------------- 1 | This is a work in progress to implement the specs currently discussed at: 2 | https://review.openstack.org/#/c/177740/ 3 | 4 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | hacking>=6.1.0,<6.2.0 # Apache-2.0 2 | 3 | coverage!=4.4,>=4.0 # Apache-2.0 4 | python-subunit>=1.0.0 # Apache-2.0/BSD 5 | psycopg2>=2.8.5 # LGPL/ZPL 6 | PyMySQL>=0.7.6 # MIT License 7 | WebOb>=1.8.2 # MIT 8 | oslotest>=3.2.0 # Apache-2.0 9 | pytest>=5.3.5 # MIT 10 | stestr>=1.0.0 # Apache-2.0 11 | testresources>=2.0.0 # Apache-2.0/BSD 12 | testscenarios>=0.4 # Apache-2.0/BSD 13 | testtools>=2.2.0 # MIT 14 | tempest>=17.1.0 # Apache-2.0 15 | isort==4.3.21 # MIT 16 | 17 | # OpenStack CI will install the following projects from git 18 | # if they are in the required-projects list for a job. 19 | # Installation by 'extras' in tox.ini does not honor upper-constraints, 20 | # so we specify the same here to ensure upper-constraints. 21 | networking-bagpipe>=12.0.0.0 # Apache-2.0 22 | horizon>=17.1.0 # Apache-2.0 23 | 24 | # This is necessary as pecan dropped this dependency 25 | # see https://review.opendev.org/c/openstack/neutron/+/848706 26 | WebTest>=2.0.27 # MIT 27 | -------------------------------------------------------------------------------- /tools/django-manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | import os 16 | import sys 17 | 18 | from django.core.management import execute_from_command_line 19 | 20 | if __name__ == "__main__": 21 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", 22 | "bgpvpn_dashboard.test.settings") 23 | execute_from_command_line(sys.argv) 24 | -------------------------------------------------------------------------------- /tools/generate_config_file_samples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | set -e 16 | 17 | GEN_CMD=oslo-config-generator 18 | 19 | if ! type "$GEN_CMD" > /dev/null; then 20 | echo "ERROR: $GEN_CMD not installed on the system." 21 | exit 1 22 | fi 23 | 24 | for file in `ls etc/oslo-config-generator/*`; do 25 | $GEN_CMD --config-file=$file 26 | done 27 | 28 | set -x 29 | --------------------------------------------------------------------------------