From 34d1008d9e00f4bd97af1f04f143f37383647462 Mon Sep 17 00:00:00 2001 From: Ionut Balutoiu Date: Thu, 25 Feb 2021 16:51:22 +0200 Subject: [PATCH] Add initial charm code --- .gitignore | 7 + .stestr.conf | 3 + README.md | 27 ++- actions.yaml | 4 + build-requirements.txt | 1 + config.yaml | 40 ++++ metadata.yaml | 30 +++ requirements.txt | 3 + src/charm.py | 104 +++++++++ src/interface_manila_plugin.py | 69 ++++++ templates/queens/manila.conf | 26 +++ test-requirements.txt | 8 + tests/bundles/bionic-ussuri.yaml | 189 +++++++++++++++ tests/bundles/focal-ussuri.yaml | 220 ++++++++++++++++++ tests/bundles/focal-victoria.yaml | 220 ++++++++++++++++++ tests/bundles/groovy-victoria.yaml | 220 ++++++++++++++++++ .../overlays/local-charm-overlay.yaml.j2 | 7 + tests/tests.yaml | 27 +++ tox.ini | 121 ++++++++++ 19 files changed, 1324 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .stestr.conf create mode 100644 actions.yaml create mode 100644 build-requirements.txt create mode 100644 config.yaml create mode 100644 metadata.yaml create mode 100644 requirements.txt create mode 100755 src/charm.py create mode 100644 src/interface_manila_plugin.py create mode 100644 templates/queens/manila.conf create mode 100644 test-requirements.txt create mode 100644 tests/bundles/bionic-ussuri.yaml create mode 100644 tests/bundles/focal-ussuri.yaml create mode 100644 tests/bundles/focal-victoria.yaml create mode 100644 tests/bundles/groovy-victoria.yaml create mode 100644 tests/bundles/overlays/local-charm-overlay.yaml.j2 create mode 100644 tests/tests.yaml create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc37341 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.tox +**/*.swp +__pycache__ +.stestr +build +manila-netapp.charm +.vscode diff --git a/.stestr.conf b/.stestr.conf new file mode 100644 index 0000000..5fcccac --- /dev/null +++ b/.stestr.conf @@ -0,0 +1,3 @@ +[DEFAULT] +test_path=./unit_tests +top_dir=./ diff --git a/README.md b/README.md index 2096181..c6383d6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ -# charm-manila-netapp -Juju charm to use NetApp storage as Manila backend +# manila-netapp + +## Description + +TODO: Describe your charm in a few paragraphs of Markdown + +## Usage + +TODO: Provide high-level usage, such as required config or relations + + +## Developing + +Create and activate a virtualenv with the development requirements: + + virtualenv -p python3 venv + source venv/bin/activate + pip install -r requirements-dev.txt + +## Testing + +The Python operator framework includes a very nice harness for testing +operator behaviour without full deployment. Just `run_tests`: + + ./run_tests diff --git a/actions.yaml b/actions.yaml new file mode 100644 index 0000000..e3eaf22 --- /dev/null +++ b/actions.yaml @@ -0,0 +1,4 @@ +pause: + description: Pause services. +resume: + description: Resume services. diff --git a/build-requirements.txt b/build-requirements.txt new file mode 100644 index 0000000..8b826e4 --- /dev/null +++ b/build-requirements.txt @@ -0,0 +1 @@ +charmcraft diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..da638c1 --- /dev/null +++ b/config.yaml @@ -0,0 +1,40 @@ +options: + share-backend-name: + type: string + default: netapp-ontap + description: | + The name given to the backend. This is used to generate the backend + configuration section. If two different configurations of the same + backend type are needed, then this config option can be used to separate + them in the backend configuration. + driver-handles-share-servers: + type: boolean + description: | + Whether the Manila driver should manage the Vservers within the + NetApp ONTAP cluster. + default: True + root-volume-aggregate-name: + type: string + description: | + Name of aggregate to create Vserver root volumes on. This option only + applies when the option 'driver-handles-share-servers' is set to True. + vserver-name: + type: string + description: | + The name of the Vserver already configured within the NetApp ONTAP + cluster. This option is used only when 'driver-handles-share-servers' is + set to False. + management-address: + type: string + description: | + The management address (IP or hostname) for the NetApp ONTAP cluster. + admin-name: + type: string + default: admin + description: | + Administrative user account name used to access the storage system. + admin-password: + type: string + description: | + Password for the administrative user account specified in the + 'admin-name' option. diff --git a/metadata.yaml b/metadata.yaml new file mode 100644 index 0000000..197bd30 --- /dev/null +++ b/metadata.yaml @@ -0,0 +1,30 @@ +name: manila-netapp +summary: NetApp ONTAP backend configuration for Manila. +maintainer: OpenStack Charmers +description: | + The Manila share file system service provides a set of services for management + of shared file systems in a multi-tenant cloud environment. The service + resembles OpenStack block-based storage management from the OpenStack Block + Storage service project. With the Shared File Systems service, you can create + a remote file system, mount the file system on your instances, and then read + and write data from your instances to and from your file system. + + This charm configures a Manila backend using the NetApp Clustered Data + ONTAP driver. +tags: + - openstack + - storage + - file-servers +series: + - bionic + - focal + - groovy +subordinate: true +provides: + manila-plugin: + interface: manila-plugin + scope: container +requires: + juju-info: + interface: juju-info + scope: container diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4fbd852 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +ops +git+https://github.com/openstack-charmers/ops-openstack#egg=ops_openstack +git+https://github.com/juju/charm-helpers.git#egg=charmhelpers diff --git a/src/charm.py b/src/charm.py new file mode 100755 index 0000000..182c674 --- /dev/null +++ b/src/charm.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import logging +import os + +from ops.main import main +import ops.model + +import ops_openstack.adapters +import ops_openstack.core + +import charmhelpers.core.templating as ch_templating +import charmhelpers.contrib.openstack.templating as os_templating + +import interface_manila_plugin + + +logger = logging.getLogger(__name__) + + +class ManilaPluginAdapter(ops_openstack.adapters.OpenStackOperRelationAdapter): + + def __init__(self, relation): + super(ManilaPluginAdapter, self).__init__(relation) + + +class ManilaNetappAdapters(ops_openstack.adapters.OpenStackRelationAdapters): + + relation_adapters = { + 'options': ops_openstack.adapters.ConfigurationAdapter, + 'manila-plugin': ManilaPluginAdapter, + } + + +class ManilaNetappCharm(ops_openstack.core.OSBaseCharm): + + REQUIRED_RELATIONS = ['manila-plugin'] + + release = 'default' + + def __init__(self, framework): + super().__init__(framework) + logging.info("Using {} class".format(self.release)) + self.manila_plugin = interface_manila_plugin.ManilaPluginProvides( + self, + 'manila-plugin') + self.options = ops_openstack.adapters.ConfigurationAdapter( + self) + self.adapters = ManilaNetappAdapters( + [self.manila_plugin], + self, + self.options) + self.framework.observe( + self.on.config_changed, + self.send_config) + self.framework.observe( + self.manila_plugin.on.manila_plugin_ready, + self.send_config) + + def send_config(self, event): + if not self.custom_status_check(): + return + if self.options.driver_handles_share_servers: + if not self.manila_plugin.authentication_data: + logging.warning( + "Manila plugin authentication_data is required when " + "'driver-handles-share-servers' config is enabled.") + event.defer() + return + rendered_configs = ch_templating.render( + source=os.path.basename(interface_manila_plugin.MANILA_CONF), + template_loader=os_templating.get_loader( + 'templates/', self.release), + target=None, + context=self.adapters) + self.manila_plugin.send_backend_config( + self.options.share_backend_name, rendered_configs) + self.state.is_started = True + self.update_status() + + def custom_status_check(self): + required_configs = [ + 'share-backend-name', + 'management-address', + 'admin-name', + 'admin-password'] + if self.options.driver_handles_share_servers: + required_configs.append('root-volume-aggregate-name') + else: + required_configs.append('vserver-name') + missing_configs = [] + for config in required_configs: + if not self.model.config.get(config): + missing_configs.append(config) + if len(missing_configs) > 0: + msg = 'Missing configs: {}'.format(missing_configs) + logger.warning(msg) + self.unit.status = ops.model.BlockedStatus(msg) + return False + return True + + +if __name__ == '__main__': + main(ManilaNetappCharm) diff --git a/src/interface_manila_plugin.py b/src/interface_manila_plugin.py new file mode 100644 index 0000000..ce434ff --- /dev/null +++ b/src/interface_manila_plugin.py @@ -0,0 +1,69 @@ +import logging +import json + +from ops.framework import ( + StoredState, + EventBase, + ObjectEvents, + EventSource, + Object +) + +MANILA_DIR = '/etc/manila/' +MANILA_CONF = MANILA_DIR + 'manila.conf' + + +logger = logging.getLogger(__name__) + + +class ManilaPluginReadyEvent(EventBase): + pass + + +class ManilaPluginEvents(ObjectEvents): + manila_plugin_ready = EventSource(ManilaPluginReadyEvent) + + +class ManilaPluginProvides(Object): + + on = ManilaPluginEvents() + state = StoredState() + + def __init__(self, charm, relation_name): + super().__init__(charm, relation_name) + self.this_unit = self.model.unit + self.relation_name = relation_name + self.state.set_default( + authentication_data={}) + self.framework.observe( + charm.on[relation_name].relation_changed, + self.on_changed) + + def on_changed(self, event): + logging.info("relation manila-plugin on_changed") + rel_data = event.relation.data.get(event.unit) + if not rel_data: + return + auth_data = rel_data.get('_authentication_data') + if auth_data: + logger.info("relation manila-plugin is ready") + self.state.authentication_data = json.loads(auth_data).get("data") + self.on.manila_plugin_ready.emit() + + def send_backend_config(self, share_backend_name, rendered_configs): + logging.info("Sending manila backend config") + # This seems to be the relation variables format expected by the + # remote reactive Manila charm. + self.manila_plugin_rel.data[self.this_unit][ + '_name'] = share_backend_name + self.manila_plugin_rel.data[self.this_unit][ + "_configuration_data"] = json.dumps( + {"data": {MANILA_CONF: rendered_configs}}) + + @property + def authentication_data(self): + return self.state.authentication_data + + @property + def manila_plugin_rel(self): + return self.model.get_relation(self.relation_name) diff --git a/templates/queens/manila.conf b/templates/queens/manila.conf new file mode 100644 index 0000000..88491d4 --- /dev/null +++ b/templates/queens/manila.conf @@ -0,0 +1,26 @@ + +[{{ options.share_backend_name }}] +share_backend_name = {{ options.share_backend_name }} +share_driver = manila.share.drivers.netapp.common.NetAppDriver +driver_handles_share_servers = {{ options.driver_handles_share_servers }} +{%- if options.driver_handles_share_servers %} +netapp_root_volume_aggregate = {{ options.root_volume_aggregate_name }} +{%- else %} +netapp_vserver = {{ options.vserver_name }} +{%- endif %} +netapp_storage_family = ontap_cluster +netapp_server_hostname = {{ options.management_address }} +netapp_login = {{ options.admin_name }} +netapp_password = {{ options.admin_password }} + +{% if options.driver_handles_share_servers %} +[neutron] +username = {{ manila_plugin.authentication_data.username }} +password = {{ manila_plugin.authentication_data.password }} +project_domain_id = {{ manila_plugin.authentication_data.project_domain_id }} +project_name = {{ manila_plugin.authentication_data.project_name }} +user_domain_id = {{ manila_plugin.authentication_data.user_domain_id }} +auth_uri = {{ manila_plugin.authentication_data.auth_uri }} +auth_url = {{ manila_plugin.authentication_data.auth_url }} +auth_type = {{ manila_plugin.authentication_data.auth_type }} +{% endif %} diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..3f6ae60 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,8 @@ +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/tests/bundles/bionic-ussuri.yaml b/tests/bundles/bionic-ussuri.yaml new file mode 100644 index 0000000..a735b3d --- /dev/null +++ b/tests/bundles/bionic-ussuri.yaml @@ -0,0 +1,189 @@ +variables: + openstack-origin: &openstack-origin cloud:bionic-ussuri + +series: bionic + +comment: +- 'machines section to decide order of deployment. database sooner = faster' +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + '6': + '7': + # The following units are the nova compute units + '8': + constraints: mem=4G + '9': + constraints: mem=4G + '10': + +applications: + percona-cluster: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + options: + source: *openstack-origin + to: + - '0' + + nova-cloud-controller: + charm: cs:~openstack-charmers-next/nova-cloud-controller + num_units: 1 + options: + network-manager: Neutron + openstack-origin: *openstack-origin + to: + - '1' + + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '2' + + neutron-api: + charm: cs:~openstack-charmers-next/neutron-api + num_units: 1 + options: + openstack-origin: *openstack-origin + manage-neutron-plugin-legacy-mode: true + neutron-plugin: ovs + flat-network-providers: physnet1 + neutron-security-groups: true + to: + - '3' + + neutron-openvswitch: + charm: cs:~openstack-charmers-next/neutron-openvswitch + + neutron-gateway: + charm: cs:~openstack-charmers-next/neutron-gateway + num_units: 1 + options: + openstack-origin: *openstack-origin + bridge-mappings: physnet1:br-ex + to: + - '4' + + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '5' + + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + source: *openstack-origin + to: + - '6' + + placement: + charm: cs:~openstack-charmers-next/placement + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '7' + + nova-compute: + charm: cs:~openstack-charmers-next/nova-compute + num_units: 2 + storage: + ephemeral-device: '40G' + options: + openstack-origin: *openstack-origin + config-flags: default_ephemeral_format=ext4 + to: + - '8' + - '9' + + manila: + charm: cs:~openstack-charmers-next/manila + num_units: 1 + options: + openstack-origin: *openstack-origin + default-share-backend: netapp-ontap + to: + - '10' + + manila-netapp: + charm: ../../manila-netapp.charm + options: + driver-handles-share-servers: False + +relations: + - - 'manila:shared-db' + - 'percona-cluster:shared-db' + - - 'manila' + - 'rabbitmq-server' + - - 'manila' + - 'keystone' + - - 'manila:manila-plugin' + - 'manila-netapp:manila-plugin' + + - - 'keystone:shared-db' + - 'percona-cluster:shared-db' + + - - 'neutron-api:shared-db' + - 'percona-cluster:shared-db' + - - 'neutron-api:amqp' + - 'rabbitmq-server:amqp' + - - 'neutron-api:identity-service' + - 'keystone:identity-service' + - - 'neutron-api:neutron-api' + - 'nova-cloud-controller:neutron-api' + - - 'neutron-api:neutron-plugin-api' + - 'neutron-gateway:neutron-plugin-api' + + - - 'nova-cloud-controller:shared-db' + - 'percona-cluster:shared-db' + - - 'nova-cloud-controller:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-cloud-controller:identity-service' + - 'keystone:identity-service' + - - 'nova-cloud-controller:cloud-compute' + - 'nova-compute:cloud-compute' + - - 'nova-cloud-controller:image-service' + - 'glance:image-service' + - - 'nova-cloud-controller:quantum-network-service' + - 'neutron-gateway:quantum-network-service' + + - - 'nova-compute:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-compute:image-service' + - 'glance:image-service' + - - 'nova-compute:neutron-plugin' + - 'neutron-openvswitch:neutron-plugin' + + - - 'neutron-gateway:amqp' + - 'rabbitmq-server:amqp' + + - - 'neutron-openvswitch:amqp' + - 'rabbitmq-server:amqp' + + - - 'glance:shared-db' + - 'percona-cluster:shared-db' + - - 'glance:amqp' + - 'rabbitmq-server:amqp' + - - 'glance:identity-service' + - 'keystone:identity-service' + + - - 'placement:shared-db' + - 'percona-cluster:shared-db' + - - 'placement:amqp' + - 'rabbitmq-server:amqp' + - - 'placement:identity-service' + - 'keystone:identity-service' + - - 'placement:placement' + - 'nova-cloud-controller:placement' diff --git a/tests/bundles/focal-ussuri.yaml b/tests/bundles/focal-ussuri.yaml new file mode 100644 index 0000000..f369422 --- /dev/null +++ b/tests/bundles/focal-ussuri.yaml @@ -0,0 +1,220 @@ +variables: + openstack-origin: &openstack-origin distro + +series: focal + +comment: +- 'machines section to decide order of deployment. database sooner = faster' +machines: + '0': + constraints: mem=3072M + '1': + constraints: mem=3072M + '2': + constraints: mem=3072M + '3': + '4': + '5': + '6': + '7': + '8': + '9': + # The following units are the nova compute units + '10': + constraints: mem=4G + '11': + constraints: mem=4G + '12': + +applications: + manila-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + keystone-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + neutron-api-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + nova-cloud-controller-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + glance-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + placement-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + + mysql-innodb-cluster: + charm: cs:~openstack-charmers-next/mysql-innodb-cluster + num_units: 3 + options: + source: *openstack-origin + to: + - '0' + - '1' + - '2' + + nova-cloud-controller: + charm: cs:~openstack-charmers-next/nova-cloud-controller + num_units: 1 + options: + network-manager: Neutron + openstack-origin: *openstack-origin + to: + - '3' + + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '4' + + neutron-api: + charm: cs:~openstack-charmers-next/neutron-api + num_units: 1 + options: + openstack-origin: *openstack-origin + manage-neutron-plugin-legacy-mode: true + neutron-plugin: ovs + flat-network-providers: physnet1 + neutron-security-groups: true + to: + - '5' + + neutron-openvswitch: + charm: cs:~openstack-charmers-next/neutron-openvswitch + + neutron-gateway: + charm: cs:~openstack-charmers-next/neutron-gateway + num_units: 1 + options: + openstack-origin: *openstack-origin + bridge-mappings: physnet1:br-ex + to: + - '6' + + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '7' + + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + source: *openstack-origin + to: + - '8' + + placement: + charm: cs:~openstack-charmers-next/placement + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '9' + + nova-compute: + charm: cs:~openstack-charmers-next/nova-compute + num_units: 2 + storage: + ephemeral-device: '40G' + options: + openstack-origin: *openstack-origin + config-flags: default_ephemeral_format=ext4 + to: + - '10' + - '11' + + manila: + charm: cs:~openstack-charmers-next/manila + num_units: 1 + options: + openstack-origin: *openstack-origin + default-share-backend: netapp-ontap + to: + - '12' + + manila-netapp: + charm: ../../manila-netapp.charm + options: + driver-handles-share-servers: False + +relations: + - - 'manila:shared-db' + - 'manila-mysql-router:shared-db' + - - 'manila-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'manila' + - 'rabbitmq-server' + - - 'manila' + - 'keystone' + - - 'manila:manila-plugin' + - 'manila-netapp:manila-plugin' + + - - 'keystone:shared-db' + - 'keystone-mysql-router:shared-db' + - - 'keystone-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + + - - 'neutron-api:shared-db' + - 'neutron-api-mysql-router:shared-db' + - - 'neutron-api-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'neutron-api:amqp' + - 'rabbitmq-server:amqp' + - - 'neutron-api:identity-service' + - 'keystone:identity-service' + - - 'neutron-api:neutron-api' + - 'nova-cloud-controller:neutron-api' + - - 'neutron-api:neutron-plugin-api' + - 'neutron-gateway:neutron-plugin-api' + + - - 'nova-cloud-controller:shared-db' + - 'nova-cloud-controller-mysql-router:shared-db' + - - 'nova-cloud-controller-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'nova-cloud-controller:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-cloud-controller:identity-service' + - 'keystone:identity-service' + - - 'nova-cloud-controller:cloud-compute' + - 'nova-compute:cloud-compute' + - - 'nova-cloud-controller:image-service' + - 'glance:image-service' + - - 'nova-cloud-controller:quantum-network-service' + - 'neutron-gateway:quantum-network-service' + + - - 'nova-compute:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-compute:image-service' + - 'glance:image-service' + - - 'nova-compute:neutron-plugin' + - 'neutron-openvswitch:neutron-plugin' + + - - 'neutron-gateway:amqp' + - 'rabbitmq-server:amqp' + + - - 'neutron-openvswitch:amqp' + - 'rabbitmq-server:amqp' + + - - 'glance:shared-db' + - 'glance-mysql-router:shared-db' + - - 'glance-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'glance:amqp' + - 'rabbitmq-server:amqp' + - - 'glance:identity-service' + - 'keystone:identity-service' + + - - 'placement:shared-db' + - 'placement-mysql-router:shared-db' + - - 'placement-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'placement:amqp' + - 'rabbitmq-server:amqp' + - - 'placement:identity-service' + - 'keystone:identity-service' + - - 'placement:placement' + - 'nova-cloud-controller:placement' diff --git a/tests/bundles/focal-victoria.yaml b/tests/bundles/focal-victoria.yaml new file mode 100644 index 0000000..76850b6 --- /dev/null +++ b/tests/bundles/focal-victoria.yaml @@ -0,0 +1,220 @@ +variables: + openstack-origin: &openstack-origin cloud:focal-victoria + +series: focal + +comment: +- 'machines section to decide order of deployment. database sooner = faster' +machines: + '0': + constraints: mem=3072M + '1': + constraints: mem=3072M + '2': + constraints: mem=3072M + '3': + '4': + '5': + '6': + '7': + '8': + '9': + # The following units are the nova compute units + '10': + constraints: mem=4G + '11': + constraints: mem=4G + '12': + +applications: + manila-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + keystone-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + neutron-api-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + nova-cloud-controller-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + glance-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + placement-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + + mysql-innodb-cluster: + charm: cs:~openstack-charmers-next/mysql-innodb-cluster + num_units: 3 + options: + source: *openstack-origin + to: + - '0' + - '1' + - '2' + + nova-cloud-controller: + charm: cs:~openstack-charmers-next/nova-cloud-controller + num_units: 1 + options: + network-manager: Neutron + openstack-origin: *openstack-origin + to: + - '3' + + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '4' + + neutron-api: + charm: cs:~openstack-charmers-next/neutron-api + num_units: 1 + options: + openstack-origin: *openstack-origin + manage-neutron-plugin-legacy-mode: true + neutron-plugin: ovs + flat-network-providers: physnet1 + neutron-security-groups: true + to: + - '5' + + neutron-openvswitch: + charm: cs:~openstack-charmers-next/neutron-openvswitch + + neutron-gateway: + charm: cs:~openstack-charmers-next/neutron-gateway + num_units: 1 + options: + openstack-origin: *openstack-origin + bridge-mappings: physnet1:br-ex + to: + - '6' + + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '7' + + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + source: *openstack-origin + to: + - '8' + + placement: + charm: cs:~openstack-charmers-next/placement + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '9' + + nova-compute: + charm: cs:~openstack-charmers-next/nova-compute + num_units: 2 + storage: + ephemeral-device: '40G' + options: + openstack-origin: *openstack-origin + config-flags: default_ephemeral_format=ext4 + to: + - '10' + - '11' + + manila: + charm: cs:~openstack-charmers-next/manila + num_units: 1 + options: + openstack-origin: *openstack-origin + default-share-backend: netapp-ontap + to: + - '12' + + manila-netapp: + charm: ../../manila-netapp.charm + options: + driver-handles-share-servers: False + +relations: + - - 'manila:shared-db' + - 'manila-mysql-router:shared-db' + - - 'manila-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'manila' + - 'rabbitmq-server' + - - 'manila' + - 'keystone' + - - 'manila:manila-plugin' + - 'manila-netapp:manila-plugin' + + - - 'keystone:shared-db' + - 'keystone-mysql-router:shared-db' + - - 'keystone-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + + - - 'neutron-api:shared-db' + - 'neutron-api-mysql-router:shared-db' + - - 'neutron-api-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'neutron-api:amqp' + - 'rabbitmq-server:amqp' + - - 'neutron-api:identity-service' + - 'keystone:identity-service' + - - 'neutron-api:neutron-api' + - 'nova-cloud-controller:neutron-api' + - - 'neutron-api:neutron-plugin-api' + - 'neutron-gateway:neutron-plugin-api' + + - - 'nova-cloud-controller:shared-db' + - 'nova-cloud-controller-mysql-router:shared-db' + - - 'nova-cloud-controller-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'nova-cloud-controller:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-cloud-controller:identity-service' + - 'keystone:identity-service' + - - 'nova-cloud-controller:cloud-compute' + - 'nova-compute:cloud-compute' + - - 'nova-cloud-controller:image-service' + - 'glance:image-service' + - - 'nova-cloud-controller:quantum-network-service' + - 'neutron-gateway:quantum-network-service' + + - - 'nova-compute:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-compute:image-service' + - 'glance:image-service' + - - 'nova-compute:neutron-plugin' + - 'neutron-openvswitch:neutron-plugin' + + - - 'neutron-gateway:amqp' + - 'rabbitmq-server:amqp' + + - - 'neutron-openvswitch:amqp' + - 'rabbitmq-server:amqp' + + - - 'glance:shared-db' + - 'glance-mysql-router:shared-db' + - - 'glance-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'glance:amqp' + - 'rabbitmq-server:amqp' + - - 'glance:identity-service' + - 'keystone:identity-service' + + - - 'placement:shared-db' + - 'placement-mysql-router:shared-db' + - - 'placement-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'placement:amqp' + - 'rabbitmq-server:amqp' + - - 'placement:identity-service' + - 'keystone:identity-service' + - - 'placement:placement' + - 'nova-cloud-controller:placement' diff --git a/tests/bundles/groovy-victoria.yaml b/tests/bundles/groovy-victoria.yaml new file mode 100644 index 0000000..1e677ce --- /dev/null +++ b/tests/bundles/groovy-victoria.yaml @@ -0,0 +1,220 @@ +variables: + openstack-origin: &openstack-origin distro + +series: groovy + +comment: +- 'machines section to decide order of deployment. database sooner = faster' +machines: + '0': + constraints: mem=3072M + '1': + constraints: mem=3072M + '2': + constraints: mem=3072M + '3': + '4': + '5': + '6': + '7': + '8': + '9': + # The following units are the nova compute units + '10': + constraints: mem=4G + '11': + constraints: mem=4G + '12': + +applications: + manila-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + keystone-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + neutron-api-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + nova-cloud-controller-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + glance-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + placement-mysql-router: + charm: cs:~openstack-charmers-next/mysql-router + + mysql-innodb-cluster: + charm: cs:~openstack-charmers-next/mysql-innodb-cluster + num_units: 3 + options: + source: *openstack-origin + to: + - '0' + - '1' + - '2' + + nova-cloud-controller: + charm: cs:~openstack-charmers-next/nova-cloud-controller + num_units: 1 + options: + network-manager: Neutron + openstack-origin: *openstack-origin + to: + - '3' + + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '4' + + neutron-api: + charm: cs:~openstack-charmers-next/neutron-api + num_units: 1 + options: + openstack-origin: *openstack-origin + manage-neutron-plugin-legacy-mode: true + neutron-plugin: ovs + flat-network-providers: physnet1 + neutron-security-groups: true + to: + - '5' + + neutron-openvswitch: + charm: cs:~openstack-charmers-next/neutron-openvswitch + + neutron-gateway: + charm: cs:~openstack-charmers-next/neutron-gateway + num_units: 1 + options: + openstack-origin: *openstack-origin + bridge-mappings: physnet1:br-ex + to: + - '6' + + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '7' + + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + source: *openstack-origin + to: + - '8' + + placement: + charm: cs:~openstack-charmers-next/placement + num_units: 1 + options: + openstack-origin: *openstack-origin + to: + - '9' + + nova-compute: + charm: cs:~openstack-charmers-next/nova-compute + num_units: 2 + storage: + ephemeral-device: '40G' + options: + openstack-origin: *openstack-origin + config-flags: default_ephemeral_format=ext4 + to: + - '10' + - '11' + + manila: + charm: cs:~openstack-charmers-next/manila + num_units: 1 + options: + openstack-origin: *openstack-origin + default-share-backend: netapp-ontap + to: + - '12' + + manila-netapp: + charm: ../../manila-netapp.charm + options: + driver-handles-share-servers: False + +relations: + - - 'manila:shared-db' + - 'manila-mysql-router:shared-db' + - - 'manila-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'manila' + - 'rabbitmq-server' + - - 'manila' + - 'keystone' + - - 'manila:manila-plugin' + - 'manila-netapp:manila-plugin' + + - - 'keystone:shared-db' + - 'keystone-mysql-router:shared-db' + - - 'keystone-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + + - - 'neutron-api:shared-db' + - 'neutron-api-mysql-router:shared-db' + - - 'neutron-api-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'neutron-api:amqp' + - 'rabbitmq-server:amqp' + - - 'neutron-api:identity-service' + - 'keystone:identity-service' + - - 'neutron-api:neutron-api' + - 'nova-cloud-controller:neutron-api' + - - 'neutron-api:neutron-plugin-api' + - 'neutron-gateway:neutron-plugin-api' + + - - 'nova-cloud-controller:shared-db' + - 'nova-cloud-controller-mysql-router:shared-db' + - - 'nova-cloud-controller-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'nova-cloud-controller:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-cloud-controller:identity-service' + - 'keystone:identity-service' + - - 'nova-cloud-controller:cloud-compute' + - 'nova-compute:cloud-compute' + - - 'nova-cloud-controller:image-service' + - 'glance:image-service' + - - 'nova-cloud-controller:quantum-network-service' + - 'neutron-gateway:quantum-network-service' + + - - 'nova-compute:amqp' + - 'rabbitmq-server:amqp' + - - 'nova-compute:image-service' + - 'glance:image-service' + - - 'nova-compute:neutron-plugin' + - 'neutron-openvswitch:neutron-plugin' + + - - 'neutron-gateway:amqp' + - 'rabbitmq-server:amqp' + + - - 'neutron-openvswitch:amqp' + - 'rabbitmq-server:amqp' + + - - 'glance:shared-db' + - 'glance-mysql-router:shared-db' + - - 'glance-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'glance:amqp' + - 'rabbitmq-server:amqp' + - - 'glance:identity-service' + - 'keystone:identity-service' + + - - 'placement:shared-db' + - 'placement-mysql-router:shared-db' + - - 'placement-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + - - 'placement:amqp' + - 'rabbitmq-server:amqp' + - - 'placement:identity-service' + - 'keystone:identity-service' + - - 'placement:placement' + - 'nova-cloud-controller:placement' diff --git a/tests/bundles/overlays/local-charm-overlay.yaml.j2 b/tests/bundles/overlays/local-charm-overlay.yaml.j2 new file mode 100644 index 0000000..f605ccd --- /dev/null +++ b/tests/bundles/overlays/local-charm-overlay.yaml.j2 @@ -0,0 +1,7 @@ +applications: + manila-netapp: + options: + vserver-name: {{ TEST_MANILA_NETAPP_VSERVER_NAME }} + management-address: {{ TEST_MANILA_NETAPP_MANAGEMENT_ADDRESS }} + admin-name: {{ TEST_MANILA_NETAPP_ADMIN_NAME }} + admin-password: {{ TEST_MANILA_NETAPP_ADMIN_PASSWORD }} diff --git a/tests/tests.yaml b/tests/tests.yaml new file mode 100644 index 0000000..e890505 --- /dev/null +++ b/tests/tests.yaml @@ -0,0 +1,27 @@ +charm_name: manila-netapp + +gate_bundles: +- bionic-ussuri +- focal-ussuri +- focal-victoria +- groovy-victoria + +smoke_bundles: +- bionic-ussuri + +target_deploy_status: {} + +configure: + - zaza.openstack.charm_tests.glance.setup.add_lts_image + - zaza.openstack.charm_tests.neutron.setup.basic_overcloud_network + - zaza.openstack.charm_tests.nova.setup.create_flavors + - zaza.openstack.charm_tests.nova.setup.manage_ssh_key + - zaza.openstack.charm_tests.keystone.setup.add_demo_user + - zaza.openstack.charm_tests.manila_netapp.setup.setup_netapp_share_type + +tests: + - zaza.openstack.charm_tests.manila_netapp.tests.ManilaNetAppNFSTest + +tests_options: + force_deploy: + - groovy-victoria diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..d87b1d3 --- /dev/null +++ b/tox.ini @@ -0,0 +1,121 @@ +# Operator charm (with zaza): tox.ini + +[tox] +envlist = pep8,py3 +skipsdist = True +# NOTE: Avoid build/test env pollution by not enabling sitepackages. +sitepackages = False +# NOTE: Avoid false positives by not skipping missing interpreters. +skip_missing_interpreters = False + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 + CHARM_DIR={envdir} +install_command = + pip install {opts} {packages} +commands = stestr run --slowest {posargs} +whitelist_externals = + git + ln + charm-init.sh +passenv = HOME TERM CS_* OS_* TEST_* +deps = -r{toxinidir}/test-requirements.txt + +[testenv:py35] +basepython = python3.5 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:py36] +basepython = python3.6 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:py37] +basepython = python3.7 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:py3] +basepython = python3 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:pep8] +basepython = python3 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt +commands = flake8 {posargs} src unit_tests tests + +[testenv:cover] +# Technique based heavily upon +# https://github.com/openstack/nova/blob/master/tox.ini +basepython = python3 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt +setenv = + {[testenv]setenv} + PYTHON=coverage run +commands = + coverage erase + stestr run --slowest {posargs} + coverage combine + coverage html -d cover + coverage xml -o cover/coverage.xml + coverage report + +[coverage:run] +branch = True +concurrency = multiprocessing +parallel = True +source = + . +omit = + .tox/* + */charmhelpers/* + unit_tests/* + +[testenv:venv] +basepython = python3 +commands = {posargs} + +[testenv:build] +basepython = python3 +deps = -r{toxinidir}/build-requirements.txt +commands = + charmcraft build --verbose + +[testenv:update-deps] +basepython = python3 +deps = +commands = + ./charm-init.sh -u + +[testenv:func-noop] +basepython = python3 +commands = + functest-run-suite --help + +[testenv:func] +basepython = python3 +commands = + functest-run-suite --keep-model + +[testenv:func-smoke] +basepython = python3 +commands = + functest-run-suite --keep-model --smoke + +[testenv:func-dev] +basepython = python3 +commands = + functest-run-suite --keep-model --dev + +[testenv:func-target] +basepython = python3 +commands = + functest-run-suite --keep-model --bundle {posargs} + +[flake8] +ignore = E402,E226