Initial Cookiecutter Commit.
Change-Id: Icc6bc9f3a991f100cc3a3e83ef673b52c16e0504
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e6425e1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+build
+layers
+.tox
+interfaces
+.testrepository
+.stestr
+*__pycache__*
+*.pyc
+/*.charm
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
new file mode 100644
index 0000000..6ac1507
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+StorPool Storage Backend for Cinder
+-------------------------------
+
+Overview
+========
+
+This charm provides a StorPool storage backend for use with the Cinder
+charm.
+
+To use:
+
+ juju deploy cinder
+ juju deploy cinder-storpool
+ juju add-relation cinder-storpool cinder
+
+Configuration
+=============
+
+See config.yaml for details of configuration options.
diff --git a/build-requirements.txt b/build-requirements.txt
new file mode 100644
index 0000000..b6d2452
--- /dev/null
+++ b/build-requirements.txt
@@ -0,0 +1,7 @@
+# NOTES(lourot):
+# * We don't install charmcraft via pip anymore because it anyway spins up a
+# container and scp the system's charmcraft snap inside it. So the charmcraft
+# snap is necessary on the system anyway.
+# * `tox -e build` successfully validated with charmcraft 1.2.1
+
+cffi==1.14.6; python_version < '3.6' # cffi 1.15.0 drops support for py35.
diff --git a/charmcraft.yaml b/charmcraft.yaml
new file mode 100644
index 0000000..ff59b02
--- /dev/null
+++ b/charmcraft.yaml
@@ -0,0 +1,35 @@
+type: charm
+
+parts:
+ charm:
+ after:
+ - update-certificates
+ charm-python-packages:
+ # NOTE(lourot): see
+ # * https://github.com/canonical/charmcraft/issues/551
+ - setuptools
+ build-packages:
+ - git
+
+ update-certificates:
+ plugin: nil
+ # See https://github.com/canonical/charmcraft/issues/658
+ override-build: |
+ apt update
+ apt install -y ca-certificates
+ update-ca-certificates
+
+bases:
+ - build-on:
+ - name: ubuntu
+ channel: "20.04"
+ architectures:
+ - amd64
+ - s390x
+ - ppc64el
+ - arm64
+ run-on:
+ - name: ubuntu
+ channel: "20.04"
+ - name: ubuntu
+ channel: "21.10"
diff --git a/config.yaml b/config.yaml
new file mode 100644
index 0000000..37c3b74
--- /dev/null
+++ b/config.yaml
@@ -0,0 +1,38 @@
+options:
+ driver-source:
+ type: string
+ default:
+ description: |
+ Optional configuration to support use of additional sources such as:
+ - ppa:myteam/ppa
+ - cloud:trusty-proposed/kilo
+ - http://my.archive.com/ubuntu main
+ The last option should be used in conjunction with the key configuration
+ option.
+ driver-key:
+ type: string
+ default:
+ description: |
+ Key ID to import to the apt keyring to support use with arbitary source
+ configuration from outside of Launchpad archives or PPA's.
+ use-multipath:
+ type: boolean
+ default: True
+ description: |
+ Whether to use a multipath connection for iSCSI or FC in Cinder
+ volume service. Enabling multipath for VMs is managed by the
+ "use-multipath" option in the nova-compute charm.
+ protocol:
+ type: string
+ default:
+ description: |
+ SAN protocol to use. Choose between iscsi or fc.
+ volume-backend-name:
+ type: string
+ description: |
+ Volume backend name for the backend. The default value is the
+ application name in the Juju model, e.g. "cinder-mybackend"
+ if it's deployed as `juju deploy cinder-storpool cinder-mybackend`.
+ A common backend name can be set to multiple backends with the
+ same characters so that those can be treated as a single virtual
+ backend associated with a single volume type.
diff --git a/metadata.yaml b/metadata.yaml
new file mode 100644
index 0000000..203a5db
--- /dev/null
+++ b/metadata.yaml
@@ -0,0 +1,23 @@
+name: cinder-storpool
+summary: StorPool integration for OpenStack Block Storage
+maintainer: OpenStack Charmers <openstack-charmers@lists.ubuntu.com>
+description: |
+ Cinder is the block storage service for the Openstack project.
+ .
+ This charm provides a StorPool backend for Cinder
+tags:
+ - openstack
+ - storage
+ - file-servers
+ - misc
+series:
+ - focal
+subordinate: true
+provides:
+ storage-backend:
+ interface: cinder-backend
+ scope: container
+requires:
+ juju-info:
+ interface: juju-info
+ scope: container
diff --git a/osci.yaml b/osci.yaml
new file mode 100644
index 0000000..018c4a6
--- /dev/null
+++ b/osci.yaml
@@ -0,0 +1,8 @@
+- project:
+ templates:
+ - charm-unit-jobs-py38
+ - charm-unit-jobs-py39
+ vars:
+ needs_charm_build: true
+ charm_build_name: storpool
+ build_type: charmcraft
diff --git a/pip.sh b/pip.sh
new file mode 100755
index 0000000..9a7e6b0
--- /dev/null
+++ b/pip.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+#
+# This file is managed centrally by release-tools and should not be modified
+# within individual charm repos. See the 'global' dir contents for available
+# choices of tox.ini for OpenStack Charms:
+# https://github.com/openstack-charmers/release-tools
+#
+# setuptools 58.0 dropped the support for use_2to3=true which is needed to
+# install blessings (an indirect dependency of charm-tools).
+#
+# More details on the beahvior of tox and virtualenv creation can be found at
+# https://github.com/tox-dev/tox/issues/448
+#
+# This script is wrapper to force the use of the pinned versions early in the
+# process when the virtualenv was created and upgraded before installing the
+# depedencies declared in the target.
+pip install 'pip<20.3' 'setuptools<50.0.0'
+pip "$@"
diff --git a/rename.sh b/rename.sh
new file mode 100755
index 0000000..d0c35c9
--- /dev/null
+++ b/rename.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+charm=$(grep "charm_build_name" osci.yaml | awk '{print $2}')
+echo "renaming ${charm}_*.charm to ${charm}.charm"
+echo -n "pwd: "
+pwd
+ls -al
+echo "Removing bad downloaded charm maybe?"
+if [[ -e "${charm}.charm" ]];
+then
+ rm "${charm}.charm"
+fi
+echo "Renaming charm here."
+mv ${charm}_*.charm ${charm}.charm
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..86315ca
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+ops
+git+https://opendev.org/openstack/charm-ops-openstack#egg=ops_openstack
diff --git a/src/charm.py b/src/charm.py
new file mode 100755
index 0000000..e7ec370
--- /dev/null
+++ b/src/charm.py
@@ -0,0 +1,59 @@
+#! /usr/bin/env python3
+
+# Copyright 2021 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.
+
+
+from ops_openstack.plugins.classes import CinderStoragePluginCharm
+from ops_openstack.core import charm_class, get_charm_class_for_release
+from ops.main import main
+
+
+class CinderCharmBase(CinderStoragePluginCharm):
+
+ PACKAGES = ['cinder-common']
+ MANDATORY_CONFIG = ['protocol']
+ # Overriden from the parent. May be set depending on the charm's properties
+ stateless = True
+ active_active = True
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def cinder_configuration(self, config):
+ # Return the configuration to be set by the principal.
+ backend_name = config.get('volume-backend-name',
+ self.framework.model.app.name)
+ volume_driver = ''
+ options = [
+ ('volume_driver', volume_driver),
+ ('volume_backend_name', backend_name),
+ ]
+
+ if config.get('use-multipath'):
+ options.extend([
+ ('use_multipath_for_image_xfer', True),
+ ('enforce_multipath_for_image_xfer', True)
+ ])
+
+ return options
+
+
+@charm_class
+class CinderStorPoolCharm(CinderCharmBase):
+ release = 'yoga'
+
+
+if __name__ == '__main__':
+ main(get_charm_class_for_release())
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..e6f71d3
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,17 @@
+# 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>=4.0.1; python_version >= '3.6'
+stestr>=2.2.0
+requests>=2.18.4
+psutil
+# oslo.i18n dropped py35 support
+oslo.i18n<4.0.0
+git+https://github.com/openstack-charmers/zaza.git#egg=zaza
+git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack
+pytz # workaround for 14.04 pip/tox
+pyudev # for ceph-* charm unit tests (not mocked?)
+cffi==1.14.6; python_version < '3.6' # cffi 1.15.0 drops support for py35.
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000..d002a1e
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,18 @@
+# Overview
+
+This directory provides Zaza test definitions and bundles to verify basic
+deployment functionality from the perspective of this charm, its requirements
+and its features, as exercised in a subset of the full OpenStack deployment
+test bundle topology.
+
+Run the smoke tests with:
+
+```bash
+cd ../
+tox -e build
+tox -e func-smoke
+```
+
+For full details on functional testing of OpenStack charms please refer to
+the [functional testing](https://docs.openstack.org/charm-guide/latest/reference/testing.html#functional-testing)
+section of the OpenStack Charm Guide.
diff --git a/tests/bundles/focal-yoga.yaml b/tests/bundles/focal-yoga.yaml
new file mode 100644
index 0000000..f9a4df4
--- /dev/null
+++ b/tests/bundles/focal-yoga.yaml
@@ -0,0 +1,76 @@
+series: focal
+variables:
+ openstack-origin: &openstack-origin distro
+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':
+ constraints: mem=4G root-disk=16G
+local_overlay_enabled: false
+relations:
+ - - keystone:shared-db
+ - keystone-mysql-router:shared-db
+ - - keystone-mysql-router:db-router
+ - mysql-innodb-cluster:db-router
+ - - cinder:shared-db
+ - cinder-mysql-router:shared-db
+ - - cinder-mysql-router:db-router
+ - mysql-innodb-cluster:db-router
+ - - cinder:identity-service
+ - keystone:identity-service
+ - - cinder:amqp
+ - rabbitmq-server:amqp
+ - - cinder:storage-backend
+ - cinder-storpool:storage-backend
+applications:
+ mysql-innodb-cluster:
+ charm: cs:~openstack-charmers-next/mysql-innodb-cluster
+ num_units: 3
+ options:
+ source: *openstack-origin
+ to:
+ - '0'
+ - '1'
+ - '2'
+ rabbitmq-server:
+ charm: cs:~openstack-charmers-next/rabbitmq-server
+ num_units: 1
+ options:
+ source: *openstack-origin
+ to:
+ - '3'
+ keystone:
+ charm: cs:~openstack-charmers-next/keystone
+ options:
+ openstack-origin: *openstack-origin
+ num_units: 1
+ to:
+ - '4'
+ keystone-mysql-router:
+ charm: cs:~openstack-charmers-next/mysql-router
+ cinder:
+ charm: cs:~openstack-charmers-next/cinder
+ num_units: 1
+ storage:
+ block-devices: '40G'
+ options:
+ openstack-origin: *openstack-origin
+ block-device: None
+ overwrite: "true"
+ ephemeral-unmount: /mnt
+ to:
+ - '5'
+ cinder-storpool:
+ charm: ../../cinder-storpool.charm
+ options:
+# Add config options here
+ cinder-mysql-router:
+ charm: cs:~openstack-charmers-next/mysql-router
diff --git a/tests/tests.py b/tests/tests.py
new file mode 100644
index 0000000..69507e1
--- /dev/null
+++ b/tests/tests.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+# Copyright 2022 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.
+
+"""Encapsulate cinder-storpool testing."""
+
+from zaza.openstack.charm_tests.cinder_backend.tests import CinderBackendTest
+
+
+class CinderStorPoolTest(CinderBackendTest):
+ """Encapsulate StorPool tests."""
+
+ backend_name = 'StorPool'
+
+ expected_config_content = {
+ 'StorPool': {
+ 'volume-backend-name': ['StorPool'],
+ }}
diff --git a/tests/tests.yaml b/tests/tests.yaml
new file mode 100644
index 0000000..3787ac4
--- /dev/null
+++ b/tests/tests.yaml
@@ -0,0 +1,9 @@
+charm_name: cinder-storpool
+tests:
+ - tests.tests.CinderStorPoolTest
+configure:
+ - zaza.openstack.charm_tests.keystone.setup.add_demo_user
+gate_bundles:
+ - focal-yoga
+smoke_bundles:
+ - focal-yoga
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..6a95b66
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,150 @@
+# 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
+# NOTES:
+# * We avoid the new dependency resolver by pinning pip < 20.3, see
+# https://github.com/pypa/pip/issues/9187
+# * Pinning dependencies requires tox >= 3.2.0, see
+# https://tox.readthedocs.io/en/latest/config.html#conf-requires
+# * It is also necessary to pin virtualenv as a newer virtualenv would still
+# lead to fetching the latest pip in the func* tox targets, see
+# https://stackoverflow.com/a/38133283
+# * It is necessary to declare setuptools as a dependency otherwise tox will
+# fail very early at not being able to load it. The version pinning is in
+# line with `pip.sh`.
+requires = pip < 20.3
+ virtualenv < 20.0
+ setuptools < 50.0.0
+# NOTE: https://wiki.canonical.com/engineering/OpenStack/InstallLatestToxOnOsci
+minversion = 3.2.0
+
+[testenv]
+setenv = VIRTUAL_ENV={envdir}
+ PYTHONHASHSEED=0
+ CHARM_DIR={envdir}
+install_command =
+ pip install {opts} {packages}
+commands = stestr run --slowest {posargs}
+allowlist_externals =
+ git
+ bash
+ charmcraft
+ rename.sh
+passenv = HOME TERM CS_* OS_* TEST_*
+deps = -r{toxinidir}/test-requirements.txt
+
+[testenv:py35]
+basepython = python3.5
+# python3.5 is irrelevant on a focal+ charm.
+commands = /bin/true
+
+[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:py38]
+basepython = python3.8
+deps = -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
+
+[testenv:py39]
+basepython = python3.9
+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
+# NOTE(lourot): charmcraft 1.0.0 used to generate
+# cinder-StorPool.charm, which is the behaviour expected
+# by OSCI. However charmcraft 1.2.1 now generates
+# cinder-StorPool_ubuntu-20.04-amd64.charm instead.
+# In order to keep the old behaviour we rename the file at the end.
+commands =
+ charmcraft clean
+ charmcraft -v build
+ {toxinidir}/rename.sh
+
+[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 E902 because the unit_tests directory is missing in the built charm.
+ignore = E402,E226,W503,W504,E902
diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py
new file mode 100644
index 0000000..8381d13
--- /dev/null
+++ b/unit_tests/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2021 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/unit_tests/test_cinder_storpool_charm.py b/unit_tests/test_cinder_storpool_charm.py
new file mode 100644
index 0000000..44b44cd
--- /dev/null
+++ b/unit_tests/test_cinder_storpool_charm.py
@@ -0,0 +1,51 @@
+# Copyright 2016 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 unittest
+from src.charm import CinderCharmBase
+from ops.model import ActiveStatus
+from ops.testing import Harness
+
+
+class TestCinderStorPoolCharm(unittest.TestCase):
+
+ def setUp(self):
+ self.harness = Harness(CinderCharmBase)
+ self.addCleanup(self.harness.cleanup)
+ self.harness.begin()
+ self.harness.set_leader(True)
+ backend = self.harness.add_relation('storage-backend', 'cinder')
+ self.harness.update_config({'volume-backend-name': 'test'})
+ self.harness.add_relation_unit(backend, 'cinder/0')
+
+ def test_cinder_base(self):
+ self.assertEqual(
+ self.harness.framework.model.app.name,
+ 'cinder-storpool')
+ # Test that charm is active upon installation.
+ self.harness.update_config({})
+ self.assertTrue(isinstance(
+ self.harness.model.unit.status, ActiveStatus))
+
+ def test_multipath_config(self):
+ self.harness.update_config({'use-multipath': True})
+ conf = dict(self.harness.charm.cinder_configuration(
+ dict(self.harness.model.config)))
+ self.assertEqual(conf['volume_backend_name'], 'test')
+ self.assertTrue(conf.get('use_multipath_for_image_xfer'))
+ self.assertTrue(conf.get('enforce_multipath_for_image_xfer'))
+
+ def test_cinder_configuration(self):
+ # Add check here that configuration is as expected.
+ pass