From 1625884690b04902737508e9ebdc21a7745d03a8 Mon Sep 17 00:00:00 2001 From: Sahid Orentino Ferdjaoui Date: Fri, 18 Oct 2019 14:24:31 +0200 Subject: [PATCH] Add train template and train functional tests A train template is added which pulls in sectional placement config from charm-layer-openstack. This requires adding identity-credentials as a required interface for train and above. This patch also updates the smoke test to run train. Closes-Bug: 1850691 Depends-On: https://review.opendev.org/#/c/692426/ Change-Id: Ib3937915c5195b5e031d5056959932849012fc23 Signed-off-by: Sahid Orentino Ferdjaoui --- src/layer.yaml | 1 + .../charm/openstack/nova_cell_controller.py | 13 ++ src/metadata.yaml | 2 + src/reactive/nova_cell_controller_handlers.py | 27 ++- src/templates/train/nova.conf | 22 +++ src/tests/bundles/bionic-train.yaml | 161 ++++++++++++++++++ src/tests/tests.yaml | 3 +- .../test_nova_cell_controller_handlers.py | 31 +++- 8 files changed, 253 insertions(+), 7 deletions(-) create mode 100644 src/templates/train/nova.conf create mode 100644 src/tests/bundles/bionic-train.yaml diff --git a/src/layer.yaml b/src/layer.yaml index e0b15f7..d3a01b1 100644 --- a/src/layer.yaml +++ b/src/layer.yaml @@ -4,6 +4,7 @@ includes: - interface:rabbitmq - interface:nova-compute - interface:nova-cell + - interface:keystone-credentials options: basic: use_venv: True diff --git a/src/lib/charm/openstack/nova_cell_controller.py b/src/lib/charm/openstack/nova_cell_controller.py index 25ba855..7926121 100644 --- a/src/lib/charm/openstack/nova_cell_controller.py +++ b/src/lib/charm/openstack/nova_cell_controller.py @@ -64,6 +64,8 @@ class NovaCellControllerCharm(charms_openstack.charm.HAOpenStackCharm): ('16', 'pike'), ('17', 'queens'), ('18', 'rocky'), + ('19', 'stein'), + ('20', 'train'), ]), } @@ -108,3 +110,14 @@ class NovaCellControllerCharm(charms_openstack.charm.HAOpenStackCharm): required_relations = self.required_relations return super(NovaCellControllerCharm, self).states_to_check( required_relations=required_relations) + + +class NovaCellControllerCharmTrain(NovaCellControllerCharm): + """From train onwards, identity-credentials is a required relation. + As of train, the nova.conf template uses section-placement which + renders config values from identity-credentials.""" + + # This charms support Train and onward + release = 'train' + + required_relations = ['shared-db', 'amqp', 'identity-credentials'] diff --git a/src/metadata.yaml b/src/metadata.yaml index f7cd47a..b222261 100644 --- a/src/metadata.yaml +++ b/src/metadata.yaml @@ -43,6 +43,8 @@ requires: interface: nova-compute nova-cell-compute: interface: nova-cell + identity-credentials: + interface: keystone-credentials peers: cluster: interface: nova-ha diff --git a/src/reactive/nova_cell_controller_handlers.py b/src/reactive/nova_cell_controller_handlers.py index 1c233d9..555bc0f 100644 --- a/src/reactive/nova_cell_controller_handlers.py +++ b/src/reactive/nova_cell_controller_handlers.py @@ -17,6 +17,7 @@ from __future__ import absolute_import import charms.reactive as reactive import charmhelpers.core.hookenv as hookenv +import charmhelpers.contrib.openstack.utils as os_utils import charms_openstack.charm as charm @@ -43,6 +44,15 @@ charm.use_defaults( 'update-status') +@reactive.when('identity-credentials.connected') +def request_credentials(): + keystone_relation = endpoint_from_flag( + 'identity-credentials.connected') + keystone_relation.request_credentials( + 'nova-cell-controller', + project='services') + + # Note that because of the way reactive.when works, (which is to 'find' the # __code__ segment of the decorated function, it's very, very difficult to add # other kinds of decorators here. This rules out adding other things into the @@ -56,9 +66,20 @@ def render_stuff(*args): """ hookenv.log("about to call the render_configs with {}".format(args)) with charm.provide_charm_instance() as nova_cell_controller_charm: - nova_cell_controller_charm.render_with_interfaces(args) - nova_cell_controller_charm.assess_status() - set_flag('config.rendered') + source_config_key = nova_cell_controller_charm.source_config_key + release = os_utils.get_os_codename_install_source( + nova_cell_controller_charm.config[source_config_key]) + auth_endpoint = ( + endpoint_from_flag('identity-credentials.available.auth')) + if ((os_utils.OPENSTACK_RELEASES.index(release) < + os_utils.OPENSTACK_RELEASES.index('train')) or + auth_endpoint): + interfaces = args + if auth_endpoint: + interfaces = (*args, auth_endpoint) + nova_cell_controller_charm.render_with_interfaces(interfaces) + nova_cell_controller_charm.assess_status() + set_flag('config.rendered') @reactive.when_not('shared-db.synced') diff --git a/src/templates/train/nova.conf b/src/templates/train/nova.conf new file mode 100644 index 0000000..b65bfd2 --- /dev/null +++ b/src/templates/train/nova.conf @@ -0,0 +1,22 @@ +# train +############################################################################### +# [ WARNING ] +# Configuration file maintained by Juju. Local changes may be overwritten. +############################################################################### +[DEFAULT] +verbose={{ options.verbose }} +debug={{ options.debug }} +logdir=/var/log/nova +state_path=/var/lib/nova +root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf + +{% include "parts/section-transport-url" %} + +{% include "parts/database" %} + +[conductor] +workers = {{ options.workers }} + +{% include "parts/section-oslo-messaging-rabbit" %} + +{% include "parts/section-placement" %} diff --git a/src/tests/bundles/bionic-train.yaml b/src/tests/bundles/bionic-train.yaml new file mode 100644 index 0000000..661bae1 --- /dev/null +++ b/src/tests/bundles/bionic-train.yaml @@ -0,0 +1,161 @@ +series: bionic +relations: +- - nova-cloud-controller:nova-cell-api + - nova-cell-controller-cell2:nova-cell-compute +- - nova-cloud-controller:shared-db-cell + - mysql-cell2:shared-db +- - nova-cloud-controller:amqp-cell + - rabbitmq-server-nova-cell2:amqp +- - nova-compute-cell2:amqp + - rabbitmq-server-nova-cell2:amqp +- - neutron-gateway:amqp + - rabbitmq-server-neutron:amqp +- - neutron-gateway:amqp-nova + - rabbitmq-server-nova:amqp +- - keystone:shared-db + - mysql:shared-db +- - nova-cloud-controller:identity-service + - keystone:identity-service +- - glance:identity-service + - keystone:identity-service +- - neutron-api:identity-service + - keystone:identity-service +- - neutron-openvswitch:neutron-plugin-api + - neutron-api:neutron-plugin-api +- - neutron-api:shared-db + - mysql:shared-db +- - neutron-api:amqp + - rabbitmq-server-neutron:amqp +- - neutron-gateway:neutron-plugin-api + - neutron-api:neutron-plugin-api +- - glance:shared-db + - mysql:shared-db +- - glance:amqp + - rabbitmq-server-neutron:amqp +- - nova-cloud-controller:image-service + - glance:image-service +- - nova-compute-cell2:image-service + - glance:image-service +- - nova-cell-controller-cell2:cloud-compute + - nova-compute-cell2:cloud-compute +- - nova-cell-controller-cell2:identity-credentials + - keystone:identity-credentials +- - nova-cloud-controller:amqp + - rabbitmq-server-nova:amqp +- - nova-cell-controller-cell2:amqp + - rabbitmq-server-nova-cell2:amqp +- - nova-cloud-controller:quantum-network-service + - neutron-gateway:quantum-network-service +- - nova-compute-cell2:neutron-plugin + - neutron-openvswitch:neutron-plugin +- - neutron-openvswitch:amqp + - rabbitmq-server-neutron:amqp +- - nova-cloud-controller:shared-db + - mysql:shared-db +- - nova-cell-controller-cell2:shared-db + - mysql-cell2:shared-db +- - nova-cloud-controller:neutron-api + - neutron-api:neutron-api +- - nova-compute-cell2:cloud-credentials + - keystone:identity-credentials +- - ntp:juju-info + - nova-compute-cell2:juju-info +- - ntp:juju-info + - neutron-gateway:juju-info +- - placement:identity-service + - keystone:identity-service +- - placement:shared-db + - mysql:shared-db +- - nova-cloud-controller:placement + - placement:placement +applications: + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + admin-password: openstack + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + options: + innodb-buffer-pool-size: 256M + max-connections: 1000 + mysql-cell2: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + options: + innodb-buffer-pool-size: 256M + max-connections: 1000 + neutron-api: + charm: cs:~openstack-charmers-next/neutron-api + num_units: 1 + options: + flat-network-providers: physnet1 + neutron-security-groups: true + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + neutron-gateway: + charm: cs:~openstack-charmers-next/neutron-gateway + num_units: 1 + options: + bridge-mappings: physnet1:br-ex + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + neutron-openvswitch: + charm: cs:~openstack-charmers-next/neutron-openvswitch + num_units: 0 + nova-cloud-controller: + charm: cs:~openstack-charmers-next/nova-cloud-controller + num_units: 1 + options: + network-manager: Neutron + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + debug: true + nova-cell-controller-cell2: + charm: nova-cell-controller + series: bionic + num_units: 1 + options: + openstack-origin: cloud:bionic-train + worker-multiplier: 0.25 + debug: true + cell-name: "cell2" + nova-compute-cell2: + charm: cs:~openstack-charmers-next/nova-compute + num_units: 1 + constraints: mem=4G + options: + config-flags: default_ephemeral_format=ext4 + enable-live-migration: true + enable-resize: true + migration-auth-type: ssh + openstack-origin: cloud:bionic-train + debug: true + ntp: + charm: cs:ntp-24 + num_units: 0 + rabbitmq-server-nova: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + rabbitmq-server-nova-cell2: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + rabbitmq-server-neutron: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + placement: + charm: cs:~openstack-charmers-next/placement + num_units: 1 + constraints: mem=1G + options: + openstack-origin: cloud:bionic-train + debug: true diff --git a/src/tests/tests.yaml b/src/tests/tests.yaml index fe291c8..d5ec1d1 100644 --- a/src/tests/tests.yaml +++ b/src/tests/tests.yaml @@ -8,8 +8,9 @@ configure: - zaza.openstack.charm_tests.nova.setup.create_flavors - zaza.openstack.charm_tests.nova.setup.manage_ssh_key gate_bundles: + - bionic-train - disco-stein - bionic-stein - bionic-rocky smoke_bundles: - - bionic-stein + - bionic-train diff --git a/unit_tests/test_nova_cell_controller_handlers.py b/unit_tests/test_nova_cell_controller_handlers.py index 641ca41..04c2f3e 100644 --- a/unit_tests/test_nova_cell_controller_handlers.py +++ b/unit_tests/test_nova_cell_controller_handlers.py @@ -43,7 +43,9 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): 'send_cell_data': ( 'shared-db.available', 'endpoint.nova-cell-compute.joined', - 'amqp.available',)}, + 'amqp.available',), + 'request_credentials': ( + 'identity-credentials.connected',)}, 'when_not': { 'db_setup': ('shared-db.synced',)} } @@ -54,7 +56,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): class TestRenderStuff(test_utils.PatchHelper): - def bob(self): + def bob(self, release='mitaka'): self.ncc_charm = mock.MagicMock() self.patch_object(handlers.charm, 'provide_charm_instance', new=mock.MagicMock()) @@ -63,9 +65,14 @@ class TestRenderStuff(test_utils.PatchHelper): self.patch_object(handlers, 'set_flag') self.patch_object(handlers.hookenv, 'config') + self.patch_object(handlers.os_utils, 'get_os_codename_install_source') self.mock_nc_ep = mock.MagicMock() self.mock_ncc_ep = mock.MagicMock() self.mock_amqp_ep = mock.MagicMock() + self.mock_cred_conn_ep = mock.MagicMock() + self.mock_cred_avail_ep = None + if release == 'train': + self.mock_cred_avail_ep = 'arg3' self.mock_db_ep = mock.MagicMock() def _endpoint_from_flag(ep): @@ -74,19 +81,37 @@ class TestRenderStuff(test_utils.PatchHelper): 'endpoint.nova-cell-compute.joined': self.mock_ncc_ep, 'endpoint.nova-cell-compute.changed': self.mock_ncc_ep, 'amqp.available': self.mock_amqp_ep, + 'identity-credentials.connected': self.mock_cred_conn_ep, + 'identity-credentials.available.auth': self.mock_cred_avail_ep, 'shared-db.available': self.mock_db_ep} return mocks[ep] self.patch_object(handlers, 'endpoint_from_flag', side_effect=_endpoint_from_flag) - def test_render_stuff(self): + def test_request_credentials(self): self.bob() + handlers.request_credentials() + self.mock_cred_conn_ep.request_credentials.assert_called_with( + 'nova-cell-controller', + project='services') + + def test_render_stuff(self): + self.bob(release='stein') + self.get_os_codename_install_source.return_value = 'stein' handlers.render_stuff('arg1', 'arg2') self.ncc_charm.render_with_interfaces.assert_called_once_with( ('arg1', 'arg2')) self.ncc_charm.assess_status.assert_called_once_with() self.set_flag.assert_called_once_with('config.rendered') + self.bob(release='train') + self.get_os_codename_install_source.return_value = 'train' + handlers.render_stuff('arg1', 'arg2') + self.ncc_charm.render_with_interfaces.assert_called_once_with( + ('arg1', 'arg2', 'arg3')) + self.ncc_charm.assess_status.assert_called_once_with() + self.set_flag.assert_called_once_with('config.rendered') + def test_db_setup(self): self.bob() handlers.db_setup('arg1')