Add functional testing documentation

This patch adds documentation explaining how to run the functional tests
before submitting a patch as well as how to test a specific Cinder
driver backend with cinderlib.
This commit is contained in:
Gorka Eguileor 2018-02-26 17:08:22 +01:00
parent fcf23faf85
commit dc43affa4a
7 changed files with 271 additions and 33 deletions

3
.gitignore vendored
View File

@ -65,3 +65,6 @@ target/
# pyenv python configuration file
.python-version
# Temp directory, for example for the LVM file, our custom config, etc.
temp/

View File

@ -1,5 +1,3 @@
.. highlight:: shell
============
Contributing
============
@ -70,38 +68,77 @@ Get Started!
Ready to contribute? Here's how to set up `cinderlib` for local development.
1. Fork the `cinderlib` repo on GitHub.
2. Clone your fork locally::
2. Clone your fork locally:
.. code-block:: shell
$ git clone git@github.com:YOUR_NAME_HERE/cinderlib.git
3. Install tox::
3. Install tox:
.. code-block:: shell
$ sudo dnf install python2-tox
4. Generate a virtual environment, for example for Python 2.7::
4. Generate a virtual environment, for example for Python 2.7:
.. code-block:: shell
$ tox --notest -epy27
5. Create a branch for local development::
5. Create a branch for local development:
.. code-block:: shell
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
6. When you're done making changes, you can check that your changes pass flake8
and the tests with::
and unit tests with:
.. code-block:: shell
$ tox -eflake8
$ tox -epy27
Or if you don't want to create a specific environment for flake8 you can run
things directly without tox::
things directly without tox:
.. code-block:: shell
$ source .tox/py27/bin/activate
$ flake8 cinderlib tests
$ python setup.py test
7. Commit your changes making sure the commit message is descriptive enough,
7. Run functional tests at least with the default LVM configuration:
.. code-block:: shell
$ tox -efunctional
To run the LVM functional tests you'll need to have the expected LVM VG
ready. This can be done using the script we have for this purpose (assuming
we are in the *cinderlib* base directory):
.. code-block:: shell
$ mkdir temp
$ cd temp
$ sudo ../tests/functional/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
format and running functional tests please refer to the
:doc:`validating_backends` section.
And preferably with all the backends you have at your disposal:
.. code-block:: shell
$ CL_FTESTS_CFG=temp/my-test-config.yaml tox -efunctional
8. Commit your changes making sure the commit message is descriptive enough,
covering the patch changes as well as why the patch might be necessary. The
commit message should also conform to the `50/72 rule
<https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html>`_.
@ -110,33 +147,48 @@ Ready to contribute? Here's how to set up `cinderlib` for local development.
$ git commit
8. Push your branch to GitHub::
9. Push your branch to GitHub:
.. code-block:: shell
$ git push origin name-of-your-bugfix-or-feature
9. Submit a pull request through the GitHub website.
10. Submit a pull request through the GitHub website.
LVM Backend
-----------
You may not have a fancy storage array, but that doesn't mean that you cannot
use *cinderlib*, because you can just use NFS or LVM. Here we are going to see
how to setup an LVM backend that we can use with *cinderlib*.
use *cinderlib*, because you can always the LVM driver. Here we are going to
see how to setup an LVM backend that we can use with *cinderlib*.
First you create your LVM, which is a 22GB file that is currently only using
1MB, and then you mount it as a loopback device and create a PV and VG on the
loopback device.
Before doing anything you need to make sure you have the required package, for Fedora, CentOS, and RHEL this will be the `targetcli` package, and for Ubuntu the `lio-utils` package.
.. code-block:: shell
$ dd if=/dev/zero of=cinder-volumes bs=1048576 seek=22527 count=1
$ sudo lodevice=`losetup -f`
$ sudo losetup $lodevice ./cinder-volumes
$ sudo yum install targetcli
Then we'll need to create your "storage backend", which is actually just a file
on your normal filesystem. We'll create a 22GB file with only 1MB currently
allocated (this is worse for performance, but better for space), and then we'll
mount it as a loopback device and create a PV and VG on the loopback device.
.. code-block:: shell
$ dd if=/dev/zero of=temp/cinder-volumes bs=1048576 seek=22527 count=1
$ sudo lodevice=`losetup --show -f ./cinder-volumes`
$ sudo pvcreate $lodevice
$ sudo vgcreate cinder-volumes $lodevice
$ sudo vgscan --cache
Now you can use this LVM backend in *cinderlib*:
There is a script included in the repository that will do all this for us, so
we can just call it from the location where we want to create the file:
.. code-block:: shell
$ sudo tests/functional/lvm-prepare.sh
Now we can use this LVM backend in *cinderlib*:
.. code-block:: python
@ -172,7 +224,9 @@ Before you submit a pull request, check that it meets these guidelines:
Tips
----
To run a subset of tests::
To run a subset of tests:
.. code-block:: shell
$ source .tox/py27/bin/activate
$ python -m unittest tests.test_cinderlib.TestCinderlib.test_lib_setup

View File

@ -81,16 +81,18 @@ Example
The following example uses CentOS 7 and the Cinder LVM driver, which should be
the easiest to setup and test.
First you need to setup your system::
First you need to setup your system:
# yum install -y centos-release-openstack-pike
# yum install -y openstack-cinder targetcli python-pip
# pip install cinderlib
# dd if=/dev/zero of=cinder-volumes bs=1048576 seek=22527 count=1
# lodevice=`losetup --show -f ./cinder-volumes`
# pvcreate $lodevice
# vgcreate cinder-volumes $lodevice
# vgscan --cache
.. code-block:: shell
$ sudo yum install -y centos-release-openstack-pike
$ sudo yum install -y openstack-cinder targetcli python-pip
$ sudo pip install cinderlib
$ sudo dd if=/dev/zero of=cinder-volumes bs=1048576 seek=22527 count=1
$ sudo lodevice=`losetup --show -f ./cinder-volumes`
$ sudo pvcreate $lodevice
$ sudo vgcreate cinder-volumes $lodevice
$ sudo vgscan --cache
Then you need to run `python` with a passwordless sudo user (required to
control LVM and do the attach) and execute:

View File

@ -10,7 +10,7 @@ list to keep track of the most relevant topics.
- QoS
- Support custom features via extra specs
- Unit tests
- Integration tests
- Complete functional tests
- Parameter validation
- Support using *cinderlib* without cinder to just handle the attach/detach
- Add .py examples

View File

@ -26,6 +26,7 @@ able to manage your storage.
installation
usage
contributing
validating_backends
internals
authors
todo

View File

@ -27,7 +27,8 @@ a proof of concept and not a finished product at this moment, so please
carefully go over the limitations section to avoid surprises.
Due to the limited access to Cinder backends and time constraints the list of
drivers that have been manually tested are:
drivers that have been manually tested, and using the existing limited
functional tests, are:
- LVM
- XtremIO
@ -79,7 +80,8 @@ more noticeable limitations one should be aware of are:
to be handled by the caller.
- There is no CI, or unit tests for that matter, and certainly nothing so fancy
as third party vendor CIs, so things could be broken at any point.
as third party vendor CIs, so things could be broken at any point. We only
have some automated, yet limited, functional tests.
- Only a subset of Cinder available operations are supported by the library.

View File

@ -0,0 +1,176 @@
===================
Validating a driver
===================
OK, so you have seen the project and would like to check if the Cinder driver
for your storage backend will work with *cinderlib* or not, but don't want to
spend a lot of time to do it.
In that case the best way to do it is using our functional tests with a custom
configuration file that has your driver configuration.
The environment
---------------
Before we can test anything we'll need to get our environment ready, which will
be comprised of three steps:
- Clone the *cinderlib* project:
.. code-block:: shell
$ git clone git://github.com/akrog/cinderlib
- Create the testing environment which will include the required Cinder code:
.. code-block:: shell
$ cd cinderlib
$ tox -efunctional --notest
- Install any specific packages our driver requires. Some Cinder drivers have
external dependencies that need to be manually installed. These dependencies
can be Python package or Linux binaries. If it's the former we will need to
install them in the testing virtual environment we created in the previous
step.
For example, for the Kaminario backend we need the *krest* Python package, so
here's how we would install the dependency.
.. code-block:: shell
$ source .tox/py27/bin/active
(py27) $ pip install krest
(py27) $ deactivate
To see the Python dependencies for each backend we can check the
`driver-requirements.txt
<https://raw.githubusercontent.com/openstack/cinder/stable/pike/driver-requirements.txt>`_
file from the Cinder project, or in *cinderlib*'s `setup.py` file listed in
the `extras` dictionary.
If we have binary dependencies we can copy them in `.tox/py27/bin` or just
install them globally in our system.
The configuration
-----------------
Functional test use a YAML configuration file to get the driver configuration
as well as some additional parameters for running the tests, with the default
configuration living in the `tests/functiona/lvm.yaml` file.
The configuration file currently supports 3 key-value pairs, with only one
being mandatory.
- `logs`: Boolean value defining whether we want the Cinder code to log to
stdout during the testing. Defaults to `false`.
- `venv_sudo`: Boolean value that instructs the functional tests on whether we
want to run with normal `sudo` or with a custom command that ensure that the
virtual environment's binaries are also available. This is not usually
necessary, but there are some drivers that use binaries installed by a Python
package (like the LVM that requires the `cinder-rtstool` from Cinder). This
is also necessary if we've installed a binary in the `.tox/py27/bin`
directory.
- `backends`: This is a list of dictionaries each with the configuration
parameters that are configured in the `cinder.conf` file in Cinder.
The contents of the default configuration, excluding the comments, are:
.. code-block:: yaml
logs: false
venv_sudo: true
backends:
- volume_backend_name: lvm
volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group: cinder-volumes
iscsi_protocol: iscsi
iscsi_helper: lioadm
But like the name implies, `backends` can have multiple drivers configured, and
the functional tests will run the tests on them all.
For example a configuration file with LVM, Kaminario, and XtremIO backends
would look like this:
.. code-block:: yaml
logs: false
venv_sudo: true
backends:
- volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group: cinder-volumes
iscsi_protocol: iscsi
iscsi_helper: lioadm
volume_backend_name: lvm
- volume_backend_name: xtremio
volume_driver: cinder.volume.drivers.dell_emc.xtremio.XtremIOISCSIDriver
use_multipath_for_image_xfer: true
xtremio_cluster_name: CLUSTER
san_ip: x.x.x.x
san_login: user
san_password: password
- volume_backend_name: kaminario
volume_driver: cinder.volume.drivers.kaminario.kaminario_iscsi.KaminarioISCSIDriver
use_multipath_for_image_xfer: true
san_ip: x.x.x.y
san_login: user
san_password: password
The validation
--------------
Now it's time to run the commands, for this we'll use the `tox` command passing
the location of our configuration file via environmental variable
`CL_FTESTS_CFG`:
.. code-block:: shell
$ CL_FTEST_CFG=temp/tests.yaml tox -efunctional
test_attach_detach_volume_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_attach_detach_volume_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_attach_detach_volume_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_stats_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_stats_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_stats_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_create_volume_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_create_volume_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_create_volume_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_create_delete_volume_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_create_delete_volume_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_create_delete_volume_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_create_snapshot_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_create_snapshot_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_create_snapshot_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_create_delete_snapshot_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_create_delete_snapshot_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_create_delete_snapshot_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_attach_volume_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_attach_volume_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_attach_volume_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_attach_detach_volume_via_attachment_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_attach_detach_volume_via_attachment_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_attach_detach_volume_via_attachment_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_disk_io_kaminario (tests_basic.BackendFunctBasic) ... ok
test_disk_io_lvm (tests_basic.BackendFunctBasic) ... ok
test_disk_io_xtremio (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_volume_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_volume_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_volume_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_volumes_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_volumes_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_volumes_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_times_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_times_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_connect_disconnect_multiple_times_on_xtremio (tests_basic.BackendFunctBasic) ... ok
test_stats_with_cretion_on_kaminario (tests_basic.BackendFunctBasic) ... ok
test_stats_with_cretion_on_lvm (tests_basic.BackendFunctBasic) ... ok
test_stats_with_cretion_on_xtremio (tests_basic.BackendFunctBasic) ... ok
As can be seen each test will have a meaningful name ending in the name of the
backend we have provided via the `volume_backend_name` key in the YAML file.