diff --git a/.travis.yml b/.travis.yml index 7534783..c57a58d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ sudo: true dist: xenial language: python -install: pip install tox-travis +install: + - pip install tox-travis matrix: include: - name: "Python 3.6" @@ -10,5 +11,26 @@ matrix: - name: "Python 3.7" python: 3.7 env: ENV=pep8,py3 + - name: "Functional test" + env: ENV=func-smoke script: - - tox -c tox.ini -e $ENV + - if [ $ENV = 'func-smoke' ]; then + sudo apt update; + sudo apt install -y distro-info; + sudo apt remove -y --purge lxd lxd-client; + sudo snap install lxd; + sudo snap install juju --classic; + sudo sh -c 'echo PATH=/snap/bin:$PATH >> /etc/environment'; + sudo lxd waitready; + sudo lxd init --auto; + sudo usermod -a -G lxd travis; + sudo su travis -c 'juju bootstrap --no-gui localhost'; + echo "export PATH=$PATH;cd $(pwd)" > $HOME/saved_path; + sudo su - travis -c "source $HOME/saved_path; tox -e build"; + sudo su - travis -c "source $HOME/saved_path; tox -c build/builds/ovn-central/tox.ini -e $ENV -- --log DEBUG"; + else + tox -c tox.ini -e $ENV; + fi + - if [ $ENV = 'func-smoke' ]; then + sudo su travis -c 'juju status -m $(juju models --format yaml|grep "^- name:.*zaza"|cut -f2 -d/)'; + fi diff --git a/src/lib/charm/openstack/ovn_central.py b/src/lib/charm/openstack/ovn_central.py index a31054b..aa1a9b5 100644 --- a/src/lib/charm/openstack/ovn_central.py +++ b/src/lib/charm/openstack/ovn_central.py @@ -49,7 +49,7 @@ def ovn_ca_cert(cls): class OVNCentralCharm(charms_openstack.charm.OpenStackCharm): release = 'stein' - name = 'ovn' + name = 'ovn-central' packages = ['ovn-central'] services = ['ovn-central'] required_relations = ['certificates'] diff --git a/src/reactive/ovn_central_handlers.py b/src/reactive/ovn_central_handlers.py index b81a87e..49df1dc 100644 --- a/src/reactive/ovn_central_handlers.py +++ b/src/reactive/ovn_central_handlers.py @@ -46,7 +46,8 @@ def certificates_in_config_tls(): @reactive.when('config.rendered', 'certificates.connected', 'certificates.available', - 'leadership.is_leader') + 'leadership.is_leader', + 'ovsdb-peer.connected',) def announce_leader_ready(): """Announce leader is ready. @@ -57,18 +58,27 @@ def announce_leader_ready(): Signal to our peers that they should render configurations and start their database processes. """ + # although this is done in the interface, explicitly do it in the same + # breath as updating the leader settings as our peers will immediately + # look for it + ovsdb_peer = reactive.endpoint_from_flag('ovsdb-peer.connected') + ovsdb_peer.publish_cluster_local_addr() + # FIXME use the OVSDB cluster and/or server IDs here? leadership.leader_set({'ready': True}) @reactive.when_not('leadership.set.ready') -@reactive.when('charm.installed', 'leadership.is_leader') +@reactive.when('charm.installed', 'leadership.is_leader', + 'ovsdb-peer.connected') def initialize_ovsdbs(): + ovsdb_peer = reactive.endpoint_from_flag('ovsdb-peer.connected') with charm.provide_charm_instance() as ovn_charm: - # this will render the ``/etc/default/ovn-central`` file without - # configuration for the cluster remote addresses which in turn - # leads ``ovn-ctl`` on the path to initializing a new cluster - ovn_charm.render_with_interfaces([]) + # ovsdb_peer at connected state will not provide remote addresses + # for the cluster. this will render the ``/etc/default/ovn-central`` + # file without configuration for the cluster remote addresses which + # in turn leads ``ovn-ctl`` on the path to initializing a new cluster + ovn_charm.render_with_interfaces([ovsdb_peer]) if ovn_charm.enable_services(): # belated enablement of default certificates handler due to the # ``ovsdb-server`` processes must have finished database diff --git a/src/templates/ovn-central b/src/templates/ovn-central index 5e77200..038e2ff 100644 --- a/src/templates/ovn-central +++ b/src/templates/ovn-central @@ -3,7 +3,7 @@ ############################################################################### # [ WARNING ] # Configuration file maintained by Juju. Local changes may be overwritten. -# Configuration managed by neutron-openvswitch charm +# Configuration managed by ovn-central charm ############################################################################### # FORCE_COREFILES: If 'yes' then core files will be enabled. @@ -16,7 +16,7 @@ OVN_CTL_OPTS=" --db-nb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }} --db-nb-cluster-local-port={{ ovsdb_peer.db_nb_cluster_port }} --db-nb-cluster-local-proto=ssl -{%if ovsdb_peer %} +{%if ovsdb_peer and ovsdb_peer.cluster_remote_addrs %} --ovn-nb-db-ssl-key={{ options.ovn_key }} --ovn-nb-db-ssl-cert={{ options.ovn_cert }} --ovn-nb-db-ssl-ca-cert={{ options.ovn_ca_cert }} @@ -28,7 +28,7 @@ OVN_CTL_OPTS=" --db-sb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }} --db-sb-cluster-local-port={{ ovsdb_peer.db_sb_cluster_port }} --db-sb-cluster-local-proto=ssl -{%if ovsdb_peer %} +{%if ovsdb_peer and ovsdb_peer.cluster_remote_addrs %} --ovn-sb-db-ssl-key={{ options.ovn_key }} --ovn-sb-db-ssl-cert={{ options.ovn_cert }} --ovn-sb-db-ssl-ca-cert={{ options.ovn_ca_cert }} diff --git a/src/test-requirements.txt b/src/test-requirements.txt index 3b64d84..5a78c3e 100644 --- a/src/test-requirements.txt +++ b/src/test-requirements.txt @@ -8,4 +8,4 @@ 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+file:///home/frode/Projects/OpenStack/openstack-charmers/zaza-openstack-tests@add-ovn#egg=zaza.openstack +git+https://github.com/openstack-charmers/zaza-openstack-tests.git@add-ovn#egg=zaza.openstack diff --git a/src/tests/bundles/bionic.yaml b/src/tests/bundles/bionic.yaml index b4ac3f6..508ed8b 100644 --- a/src/tests/bundles/bionic.yaml +++ b/src/tests/bundles/bionic.yaml @@ -2,7 +2,7 @@ series: bionic relations: - - vault:shared-db - mysql:shared-db -- - ovn:certificates +- - ovn-central:certificates - vault:certificates applications: mysql: @@ -11,9 +11,9 @@ applications: vault: charm: cs:~openstack-charmers-next/vault num_units: 1 - ovn: + ovn-central: series: bionic - charm: cs:~openstack-charmers-next/ovn + charm: cs:~openstack-charmers-next/ovn-central num_units: 3 options: source: cloud:bionic-stein diff --git a/src/tests/bundles/disco.yaml b/src/tests/bundles/disco.yaml index 9061ecf..90efff6 100644 --- a/src/tests/bundles/disco.yaml +++ b/src/tests/bundles/disco.yaml @@ -2,7 +2,7 @@ series: disco relations: - - vault:shared-db - mysql:shared-db -- - ovn:certificates +- - ovn-central:certificates - vault:certificates applications: mysql: @@ -11,7 +11,7 @@ applications: vault: charm: cs:~openstack-charmers-next/vault num_units: 1 - ovn: + ovn-central: series: disco - charm: cs:~openstack-charmers-next/ovn - num_units: 1 + charm: cs:~openstack-charmers-next/ovn-central + num_units: 3 diff --git a/src/tests/tests.yaml b/src/tests/tests.yaml index 50c34aa..cacf3b5 100644 --- a/src/tests/tests.yaml +++ b/src/tests/tests.yaml @@ -1,11 +1,11 @@ -charm_name: ovn +charm_name: ovn-central gate_bundles: - disco - bionic smoke_bundles: - bionic target_deploy_status: - ovn: + ovn-central: workload-status: blocked workload-status-message: "'certificates' missing" vault: diff --git a/src/tox.ini b/src/tox.ini index ce45106..69685b0 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -3,6 +3,7 @@ envlist = pep8 skipsdist = True [testenv] +download = true setenv = VIRTUAL_ENV={envdir} PYTHONHASHSEED=0 whitelist_externals = juju @@ -24,12 +25,12 @@ commands = [testenv:func] basepython = python3 commands = - functest-run-suite --keep-model + functest-run-suite {posargs} --keep-model [testenv:func-smoke] basepython = python3 commands = - functest-run-suite --keep-model --smoke + functest-run-suite {posargs} --keep-model --smoke [testenv:venv] commands = {posargs} diff --git a/unit_tests/test_lib_charm_openstack_ovn_central.py b/unit_tests/test_lib_charm_openstack_ovn_central.py index 8bff03c..0b81446 100644 --- a/unit_tests/test_lib_charm_openstack_ovn_central.py +++ b/unit_tests/test_lib_charm_openstack_ovn_central.py @@ -132,7 +132,7 @@ class TestOVNCentralCharm(Helper): self.is_flag_set.return_value = True self.target.configure_tls() mocked_open.assert_called_once_with( - '/etc/openvswitch/ovn.crt', 'w') + '/etc/openvswitch/ovn-central.crt', 'w') mocked_file.__enter__().write.assert_called_once_with( 'fakeca\nfakechain') self.target.configure_cert.assert_called_once_with( @@ -145,7 +145,7 @@ class TestOVNCentralCharm(Helper): 'set-ssl', '/etc/openvswitch/key_host', '/etc/openvswitch/cert_host', - '/etc/openvswitch/ovn.crt'), + '/etc/openvswitch/ovn-central.crt'), mock.call('ovs-vsctl', 'set', 'open', @@ -166,7 +166,7 @@ class TestOVNCentralCharm(Helper): 'set-ssl', '/etc/openvswitch/key_host', '/etc/openvswitch/cert_host', - '/etc/openvswitch/ovn.crt'), + '/etc/openvswitch/ovn-central.crt'), mock.call('ovs-vsctl', 'set', 'open', diff --git a/unit_tests/test_reactive_ovn_central_handlers.py b/unit_tests/test_reactive_ovn_central_handlers.py index 120fc93..ce6f50c 100644 --- a/unit_tests/test_reactive_ovn_central_handlers.py +++ b/unit_tests/test_reactive_ovn_central_handlers.py @@ -42,12 +42,14 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): 'announce_leader_ready': ('config.rendered', 'certificates.connected', 'certificates.available', - 'leadership.is_leader',), + 'leadership.is_leader', + 'ovsdb-peer.connected',), 'certificates_in_config_tls': ('config.rendered', 'config.changed',), 'enable_default_certificates': ('charm.installed',), 'initialize_ovsdbs': ('charm.installed', - 'leadership.is_leader',), + 'leadership.is_leader', + 'ovsdb-peer.connected',), 'publish_addr_to_clients': ('ovsdb-peer.available', 'leadership.set.ready', 'certificates.connected', @@ -76,15 +78,22 @@ class TestOvnCentralHandlers(test_utils.PatchHelper): self.provide_charm_instance().__exit__.return_value = None def test_announce_leader_ready(self): + self.patch_object(handlers.reactive, 'endpoint_from_flag') self.patch_object(handlers.leadership, 'leader_set') + ovsdb_peer = mock.MagicMock() + self.endpoint_from_flag.return_value = ovsdb_peer handlers.announce_leader_ready() + ovsdb_peer.publish_cluster_local_addr.assert_called_once_with() self.leader_set.assert_called_once_with({'ready': True}) def test_initialize_ovsdbs(self): + self.patch_object(handlers.reactive, 'endpoint_from_flag') self.patch_object(handlers.charm, 'use_defaults') self.patch_object(handlers.reactive, 'set_flag') + ovsdb_peer = mock.MagicMock() + self.endpoint_from_flag.return_value = ovsdb_peer handlers.initialize_ovsdbs() - self.charm.render_with_interfaces.assert_called_once_with([]) + self.charm.render_with_interfaces.assert_called_once_with([ovsdb_peer]) self.charm.enable_services.assert_called_once_with() self.use_defaults.assert_called_once_with('certificates.available') self.set_flag.assert_called_once_with('config.rendered')