diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8d16b03..21ba49e 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -125,7 +125,7 @@ Ready to contribute? Here's how to set up `cinderlib` for local development. $ mkdir temp $ cd temp - $ sudo ../tests/functional/lvm-prepare.sh + $ sudo ../tools/lvm-prepare.sh The default configuration for the functional tests can be found in the `tests/functional/lvm.yaml` file. For additional information on this file @@ -186,7 +186,7 @@ we can just call it from the location where we want to create the file: .. code-block:: shell - $ sudo tests/functional/lvm-prepare.sh + $ sudo tools/lvm-prepare.sh Now we can use this LVM backend in *cinderlib*: diff --git a/playbooks/cinder-gate-run.yaml b/playbooks/cinder-gate-run.yaml new file mode 100644 index 0000000..2fa18ef --- /dev/null +++ b/playbooks/cinder-gate-run.yaml @@ -0,0 +1,29 @@ +- hosts: all + become: True + vars: + devstack_base_dir: "{{ devstack_base_dir|default('/opt/stack') }}" + cinderlib_dir: "{{ cinderlib_dir }}|default({{ devstack_base_dir }}/cinderlib)" + cl_log_file: "{{ devstack_base_dir }}/logs/cinderlib.txt" + cinderlib_ignore_errors: "{{ cinderlib_ignore_errors }}|default(no)" + tasks: + - name: Create temporary config directory + tempfile: + state: directory + suffix: cinderlib + register: tempdir + + - name: Convert Cinder's config to cinderlib functional test YAML + shell: + cmd: "{{ cinderlib_dir }}/tools/cinder-to-yaml.py /etc/cinder/cinder.conf {{ tempdir.path }}/cinderlib.yaml >{{ cl_log_file }} 2>&1" + ignore_errors: "{{ cinderlib_ignore_errors }}" + register: generate_config + + - name: Run cinderlib functional tests + shell: + cmd: "unit2 discover -v -s tests/functional >>{{ cl_log_file }} 2>&1" + executable: /bin/bash + chdir: "{{ cinderlib_dir }}" + environment: + CL_FTEST_CFG: "{{ tempdir.path }}/cinderlib.yaml" + when: generate_config.rc != 0 + ignore_errors: "{{ cinderlib_ignore_errors }}" diff --git a/tests/functional/base_tests.py b/tests/functional/base_tests.py index e000f97..eedda8c 100644 --- a/tests/functional/base_tests.py +++ b/tests/functional/base_tests.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import json import functools import os import subprocess @@ -72,7 +71,8 @@ class BaseFunctTestCase(unittest2.TestCase): # NOTE(geguileo): For some drivers need to use a custom sudo script # to find virtualenv commands (ie: cinder-rtstool). path = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - cls.root_helper = os.path.join(path, 'virtualenv-sudo.sh') + sudo_tool = os.path.join(path, '../../tools/virtualenv-sudo.sh') + cls.root_helper = os.path.abspath(sudo_tool) else: cls.root_helper = 'sudo' cinderlib.setup(root_helper=cls.root_helper, diff --git a/tools/cinder-to-yaml.py b/tools/cinder-to-yaml.py new file mode 100755 index 0000000..ceb673c --- /dev/null +++ b/tools/cinder-to-yaml.py @@ -0,0 +1,71 @@ +#!/bin/env python +"""Generate functional tests YAML configuration files from Cinder config file + +Functional tests require a YAML file with the backend configuration parameters. +To facilitate running them on a deployment that already has Cinder configured +(ie: devstack) this program can translate from cinder.conf to a valid YAML +file that can be used to run cinderlib functional tests. + +This program uses the oslo.config module to load configuration options instead +of using configparser directly because drivers will need variables to have the +right type (string, list, integer...), and the types are defined in the code +using oslo.config. +""" + +import sys +import yaml + +from six.moves import configparser + +from cinder.cmd import volume +volume.objects.register_all() # noqa + +from cinder.volume import configuration as config +from cinder.volume import manager + + +def convert(cinder_source, yaml_dest): + result_cfgs = [] + + # Manually parse the Cinder configuration file so we know which options are + # set. + parser = configparser.ConfigParser() + parser.read(cinder_source) + enabled_backends = parser.get('DEFAULT', 'enabled_backends') + backends = [name.strip() for name in enabled_backends.split(',') if name] + + volume.CONF(('--config-file', cinder_source), project='cinder') + + for backend in backends: + options_present = parser.options(backend) + + # Dynamically loading the driver triggers adding the specific + # configuration options to the backend_defaults section + cfg = config.Configuration(manager.volume_backend_opts, + config_group=backend) + driver_ns = cfg.volume_driver.rsplit('.', 1)[0] + __import__(driver_ns) + + # Use the backend_defaults section to extract the configuration for + # options that are present in the backend section and add them to + # the backend section. + opts = volume.CONF._groups['backend_defaults']._opts + known_present_options = [opt for opt in options_present if opt in opts] + volume_opts = [opts[option]['opt'] for option in known_present_options] + cfg.append_config_values(volume_opts) + + # Now retrieve the options that are set in the configuration file. + result_cfgs.append({option: cfg.safe_get(option) + for option in known_present_options}) + + result = {'backends': result_cfgs} + # Write the YAML to the destination + with open(yaml_dest, 'w') as f: + yaml.dump(result, f) + + +if __name__ == '__main__': + if len(sys.argv) != 3: + sys.stderr.write('Incorrect number of arguments\n') + exit(1) + convert(sys.argv[1], sys.argv[2]) diff --git a/tests/functional/lvm-prepare.sh b/tools/lvm-prepare.sh old mode 100644 new mode 100755 similarity index 100% rename from tests/functional/lvm-prepare.sh rename to tools/lvm-prepare.sh diff --git a/tests/functional/virtualenv-sudo.sh b/tools/virtualenv-sudo.sh similarity index 100% rename from tests/functional/virtualenv-sudo.sh rename to tools/virtualenv-sudo.sh