From 59eb531c7bf8ed26cad45ef6302467cfc06382a2 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Wed, 20 Nov 2019 09:11:42 +0100 Subject: [PATCH] Consume chassis code from layer-ovn The two charms 'ovn-chassis' and 'ovn-dedicated-chassis' are apart from metadata identical. Consume the shared code from layer. Change-Id: Ib133c805151cf66c5316df38c33ea6d20a38fa2b --- .gitreview | 4 ++ .zuul.yaml | 4 ++ README.md | 1 + requirements.txt | 7 ++ src/README.md | 71 ++++++++++++++++++- src/config.yaml | 1 + src/layer.yaml | 8 +++ src/lib/__init__.py | 13 ++++ src/lib/charms/__init__.py | 13 ++++ src/lib/charms/ovn_dedicated_chassis.py | 21 ++++++ src/metadata.yaml | 15 ++++ .../ovn_dedicated_chassis_handlers.py | 10 +++ src/test-requirements.txt | 11 +++ src/tests/bundles/bionic.yaml | 27 +++++++ src/tests/bundles/eoan.yaml | 27 +++++++ src/tests/tests.yaml | 20 ++++++ src/tox.ini | 36 ++++++++++ tox.ini | 4 +- unit_tests/README.md | 1 + unit_tests/__init__.py | 45 ++++++++++++ ...reactive_ovn_dedicated_chassis_handlers.py | 41 +++++++++++ 21 files changed, 376 insertions(+), 4 deletions(-) create mode 100644 .gitreview create mode 100644 .zuul.yaml create mode 120000 README.md create mode 100644 requirements.txt create mode 100644 src/config.yaml create mode 100644 src/layer.yaml create mode 100644 src/lib/__init__.py create mode 100644 src/lib/charms/__init__.py create mode 100644 src/lib/charms/ovn_dedicated_chassis.py create mode 100644 src/metadata.yaml create mode 100644 src/reactive/ovn_dedicated_chassis_handlers.py create mode 100644 src/test-requirements.txt create mode 100644 src/tests/bundles/bionic.yaml create mode 100644 src/tests/bundles/eoan.yaml create mode 100644 src/tests/tests.yaml create mode 100644 src/tox.ini create mode 100644 unit_tests/README.md create mode 100644 unit_tests/__init__.py create mode 100644 unit_tests/test_reactive_ovn_dedicated_chassis_handlers.py diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..b980dea --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=review.opendev.org +port=29418 +project=x/charm-ovn-dedicated-chassis.git diff --git a/.zuul.yaml b/.zuul.yaml new file mode 100644 index 0000000..7cb4023 --- /dev/null +++ b/.zuul.yaml @@ -0,0 +1,4 @@ +- project: + templates: + - openstack-python3-train-jobs + - openstack-cover-jobs diff --git a/README.md b/README.md new file mode 120000 index 0000000..351df1d --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +src/README.md \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..20f335d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +# This file is managed centrally. If you find the need to modify this as a +# one-off, please don't. Intead, consult #openstack-charms and ask about +# requirements management in charms via bot-control. Thank you. +# +# Build requirements +charm-tools>=2.4.4 +simplejson diff --git a/src/README.md b/src/README.md index c4d6486..81a7600 100644 --- a/src/README.md +++ b/src/README.md @@ -1,2 +1,69 @@ -This charm is built from the source of the `charm-ovn-chassis` charm and this -directory is thus empty. +# Overview + +This charm provides the Open Virtual Network (OVN) local controller, Open +vSwitch Database and Switch. + +On successful deployment the unit will be enlisted as a `Chassis` in the OVN +network. + +Open vSwitch bridges for integration, external Layer2 and Layer3 connectivity +is managed by the charm. + +> **Note**: The OVN charms are considered preview charms. + +# Usage + +OVN makes use of Public Key Infrastructure (PKI) to authenticate and authorize +control plane communication. The charm requires a Certificate Authority to be +present in the model as represented by the `certificates` relation. + +There is a [OVN overlay bundle](https://github.com/openstack-charmers/openstack-bundles/blob/master/development/overlays/openstack-base-ovn.yaml) +for use in conjunction with the [OpenStack Base bundle](https://github.com/openstack-charmers/openstack-bundles/blob/master/development/openstack-base-bionic-train/bundle.yaml) +which give an example of how you can automate certificate lifecycle management +with the help from [Vault](https://jaas.ai/vault/). + +## Network Spaces support + +This charm supports the use of Juju Network Spaces. + +By binding the `ovsdb` endpoint you can influence which interface will be used +for communication with the OVN Southbound DB as well as overlay traffic. + + juju deploy ovn-dedicated-chassis --bind "ovsdb=data-space" + +## Port Configuration + +Chassis port configuration is composed of a mapping between physical network +names to bridge names (`ovn-bridge-mappings`) and individual interface to +bridge names (`interface-bridge-mappings`). There must be a match in both +configuration options before the charm will configure bridge and interfaces on +a unit. + +The physical network name can be referenced when the administrator programs the +OVN logical flows, either by talking directly to the Northbound database, or by +interfaceing with a Cloud Management System (CMS). + +Networks for use with external Layer3 connectivity should have mappings on +chassis located in the vicinity of the datacenter border gateways. Having two +or more chassis with mappings for a Layer3 network will have OVN automatically +configure highly available routers with liveness detection provided by the +Bidirectional Forwarding Detection (BFD) protocol. + +Chassis without direct external mapping to a external Layer3 network will +forward traffic through a tunnel to one of the chassis acting as a gateway for +that network. + +> **Note**: It is not necessary nor recommended to add mapping for external + Layer3 networks to all chassis. Doing so will create a scaling problem at + the physical network layer that needs to be resolved with globally shared + Layer2 (does not scale) or tunneling at the top-of-rack switch layer (adds + complexity) and is generally not a recommended configuration. + +Networks for use with external Layer2 connectivity should have mappings present +on all chassis with potential to host the consuming payload. + +# Bugs + +Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-ovn-chassis/+filebug). + +For general questions please refer to the OpenStack [Charm Guide](https://docs.openstack.org/charm-guide/latest/). diff --git a/src/config.yaml b/src/config.yaml new file mode 100644 index 0000000..a985d46 --- /dev/null +++ b/src/config.yaml @@ -0,0 +1 @@ +options: {} diff --git a/src/layer.yaml b/src/layer.yaml new file mode 100644 index 0000000..bcd95ef --- /dev/null +++ b/src/layer.yaml @@ -0,0 +1,8 @@ +includes: + - layer:ovn + - interface:ovsdb +options: + basic: + use_venv: True + include_system_packages: False +repo: https://github.com/openstack/charm-ovn-controller diff --git a/src/lib/__init__.py b/src/lib/__init__.py new file mode 100644 index 0000000..5705e5d --- /dev/null +++ b/src/lib/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Canonical Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/lib/charms/__init__.py b/src/lib/charms/__init__.py new file mode 100644 index 0000000..5705e5d --- /dev/null +++ b/src/lib/charms/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Canonical Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/lib/charms/ovn_dedicated_chassis.py b/src/lib/charms/ovn_dedicated_chassis.py new file mode 100644 index 0000000..568946f --- /dev/null +++ b/src/lib/charms/ovn_dedicated_chassis.py @@ -0,0 +1,21 @@ +# Copyright 2019 Canonical Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import charms.ovn_charm + + +class OVNDedicatedChassisCharm(charms.ovn_charm.BaseOVNChassisCharm): + # OpenvSwitch and OVN is distributed as part of the Ubuntu Cloud Archive + # Pockets get their name from OpenStack releases + release = 'train' + name = 'ovn-dedicated-chassis' diff --git a/src/metadata.yaml b/src/metadata.yaml new file mode 100644 index 0000000..ee69d14 --- /dev/null +++ b/src/metadata.yaml @@ -0,0 +1,15 @@ +name: ovn-dedicated-chassis +summary: Open Virtual Network for Open vSwitch - Chassis +maintainer: OpenStack Charmers +description: | + Subordinate charm that deploys the OVN local controller and Open vSwitch + Database and Switch. +tags: + - networking +series: + - bionic + - eoan +subordinate: false +requires: + ovsdb: + interface: ovsdb diff --git a/src/reactive/ovn_dedicated_chassis_handlers.py b/src/reactive/ovn_dedicated_chassis_handlers.py new file mode 100644 index 0000000..dc6600f --- /dev/null +++ b/src/reactive/ovn_dedicated_chassis_handlers.py @@ -0,0 +1,10 @@ +import charms.reactive as reactive + +from . import ovn_chassis_charm_handlers + + +# NOTE: code shared among the chassis charms can be found in the 'ovn' layer. +@reactive.when_not(ovn_chassis_charm_handlers.OVN_CHASSIS_ENABLE_HANDLERS_FLAG) +def enable_ovn_chassis_handlers(): + reactive.set_flag( + ovn_chassis_charm_handlers.OVN_CHASSIS_ENABLE_HANDLERS_FLAG) diff --git a/src/test-requirements.txt b/src/test-requirements.txt new file mode 100644 index 0000000..3640c8b --- /dev/null +++ b/src/test-requirements.txt @@ -0,0 +1,11 @@ +# This file is managed centrally. If you find the need to modify this as a +# one-off, please don't. Intead, consult #openstack-charms and ask about +# requirements management in charms via bot-control. Thank you. +charm-tools>=2.4.4 +coverage>=3.6 +mock>=1.2 +flake8>=2.2.4,<=2.4.1 +stestr>=2.2.0 +requests>=2.18.4 +git+https://github.com/openstack-charmers/zaza.git#egg=zaza +git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack diff --git a/src/tests/bundles/bionic.yaml b/src/tests/bundles/bionic.yaml new file mode 100644 index 0000000..7f5b723 --- /dev/null +++ b/src/tests/bundles/bionic.yaml @@ -0,0 +1,27 @@ +series: bionic +relations: +- - vault:shared-db + - mysql:shared-db +- - ovn-central:certificates + - vault:certificates +- - ovn-dedicated-chassis:ovsdb + - ovn-central:ovsdb +- - ovn-dedicated-chassis:certificates + - vault:certificates +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + ovn-central: + charm: cs:~openstack-charmers-next/ovn-central + num_units: 3 + options: + source: cloud:bionic-train + ovn-dedicated-chassis: + charm: cs:~openstack-charmers-next/ovn-dedicated-chassis + num_units: 2 + options: + source: cloud:bionic-train diff --git a/src/tests/bundles/eoan.yaml b/src/tests/bundles/eoan.yaml new file mode 100644 index 0000000..88908d0 --- /dev/null +++ b/src/tests/bundles/eoan.yaml @@ -0,0 +1,27 @@ +series: eoan +relations: +- - vault:shared-db + - mysql:shared-db +- - ovn-central:certificates + - vault:certificates +- - ovn-dedicated-chassis:ovsdb + - ovn-central:ovsdb +- - ovn-dedicated-chassis:certificates + - vault:certificates +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + ovn-central: + charm: cs:~openstack-charmers-next/ovn-central + num_units: 3 + options: + source: distro + ovn-dedicated-chassis: + charm: cs:~openstack-charmers-next/ovn-dedicated-chassis + num_units: 2 + options: + source: distro diff --git a/src/tests/tests.yaml b/src/tests/tests.yaml new file mode 100644 index 0000000..f901e53 --- /dev/null +++ b/src/tests/tests.yaml @@ -0,0 +1,20 @@ +charm_name: ovn-dedicated-chassis +gate_bundles: +- eoan +- bionic +smoke_bundles: +- bionic +target_deploy_status: + ovn-central: + workload-status: blocked + workload-status-message: "'certificates' missing" + ovn-dedicated-chassis: + workload-status: blocked + workload-status-message: "'certificates' missing" + vault: + workload-status: blocked + workload-status-message: Vault needs to be initialized +configure: +- zaza.openstack.charm_tests.vault.setup.auto_initialize_no_validation +tests: +- zaza.charm_tests.noop.tests.NoopTest diff --git a/src/tox.ini b/src/tox.ini new file mode 100644 index 0000000..69685b0 --- /dev/null +++ b/src/tox.ini @@ -0,0 +1,36 @@ +[tox] +envlist = pep8 +skipsdist = True + +[testenv] +download = true +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +whitelist_externals = juju +passenv = HOME TERM CS_API_* OS_* AMULET_* +deps = -r{toxinidir}/test-requirements.txt +install_command = + pip install {opts} {packages} + +[testenv:pep8] +basepython = python3 +deps=charm-tools +commands = charm-proof + +[testenv:func-noop] +basepython = python3 +commands = + true + +[testenv:func] +basepython = python3 +commands = + functest-run-suite {posargs} --keep-model + +[testenv:func-smoke] +basepython = python3 +commands = + functest-run-suite {posargs} --keep-model --smoke + +[testenv:venv] +commands = {posargs} diff --git a/tox.ini b/tox.ini index ee3f06d..23750a8 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ # within individual charm repos. [tox] skipsdist = True -envlist = pep8 +envlist = pep8,py3 [testenv] setenv = VIRTUAL_ENV={envdir} @@ -41,7 +41,7 @@ commands = stestr run {posargs} [testenv:pep8] basepython = python3 deps = -r{toxinidir}/test-requirements.txt -commands = flake8 {posargs} src +commands = flake8 {posargs} src unit_tests [testenv:cover] # Technique based heavily upon diff --git a/unit_tests/README.md b/unit_tests/README.md new file mode 100644 index 0000000..96d169d --- /dev/null +++ b/unit_tests/README.md @@ -0,0 +1 @@ +This is not the unit tests you are looking for, take a look at `layer-ovn`. diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py new file mode 100644 index 0000000..5408a9d --- /dev/null +++ b/unit_tests/__init__.py @@ -0,0 +1,45 @@ +# Copyright 2018 Canonical Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +sys.path.append('src') +sys.path.append('src/lib') + +# Mock out charmhelpers so that we can test without it. +import charms_openstack.test_mocks # noqa +charms_openstack.test_mocks.mock_charmhelpers() + +import mock +import charms +charms.leadership = mock.MagicMock() +keystoneauth1 = mock.MagicMock() +neutronclient = mock.MagicMock() +sys.modules['charms.leadership'] = charms.leadership +keystoneauth1 = mock.MagicMock() +novaclient = mock.MagicMock() +neutron_lib = mock.MagicMock() +sys.modules['charms.leadership'] = charms.leadership +sys.modules['keystoneauth1'] = keystoneauth1 +sys.modules['novaclient'] = novaclient +sys.modules['neutronclient'] = neutronclient +sys.modules['neutronclient.v2_0'] = neutronclient.v2_0 +sys.modules['neutron_lib'] = neutron_lib +sys.modules['neutron_lib.constants'] = neutron_lib.constants +import reactive +reactive.ovn_chassis_charm_handlers = mock.MagicMock() +reactive.ovn_chassis_charm_handlers.OVN_CHASSIS_ENABLE_HANDLERS_FLAG = \ + 'MOCKED_FLAG' +sys.modules['reactive.ovn_chassis_charm_handlers'] = \ + reactive.ovn_chassis_charm_handlers diff --git a/unit_tests/test_reactive_ovn_dedicated_chassis_handlers.py b/unit_tests/test_reactive_ovn_dedicated_chassis_handlers.py new file mode 100644 index 0000000..b8ec6c1 --- /dev/null +++ b/unit_tests/test_reactive_ovn_dedicated_chassis_handlers.py @@ -0,0 +1,41 @@ +# Copyright 2019 Canonical Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import reactive.ovn_dedicated_chassis_handlers as handlers + +import charms_openstack.test_utils as test_utils + + +class TestRegisteredHooks(test_utils.TestRegisteredHooks): + + def setUp(self): + super().setUp() + + def test_hooks(self): + hook_set = { + 'when_not': { + 'enable_ovn_chassis_handlers': ('MOCKED_FLAG',), + }, + } + # test that the hooks were registered via the + # reactive.ovn_handlers + self.registered_hooks_test_helper(handlers, hook_set, {}) + + +class TestOvnHandlers(test_utils.PatchHelper): + + def test_enable_ovn_chassis_handlers(self): + self.patch_object(handlers.reactive, 'set_flag') + handlers.enable_ovn_chassis_handlers() + self.set_flag.assert_called_once_with('MOCKED_FLAG')