Support pool-aware drivers
This patch adds pool support to cinderlib. The Backend class now has the property `pool_names` with available pools in the driver. When creating a volume we can specify `pool_name` to use a specific pool. Pool is stored as part of the `host` field in volumes. The `host` field now follows Cinder's naming "host@backend#pool".
This commit is contained in:
parent
09abcf4df4
commit
c491c71f47
|
@ -13,6 +13,7 @@ History
|
||||||
|
|
||||||
- Provide better message when device is not available.
|
- Provide better message when device is not available.
|
||||||
- Backend name stored in host instead of in the AZ (backward incompatible).
|
- Backend name stored in host instead of in the AZ (backward incompatible).
|
||||||
|
- Support multi-pool drivers.
|
||||||
|
|
||||||
0.2.2 (2018-07-24)
|
0.2.2 (2018-07-24)
|
||||||
------------------
|
------------------
|
||||||
|
|
|
@ -76,6 +76,14 @@ class Backend(object):
|
||||||
self.driver.set_initialized()
|
self.driver.set_initialized()
|
||||||
self._driver_cfg = driver_cfg
|
self._driver_cfg = driver_cfg
|
||||||
self._volumes = None
|
self._volumes = None
|
||||||
|
# init_capabilities already calls get_volume_stats with refresh=True
|
||||||
|
# so we can call it without refresh to get pool names.
|
||||||
|
self._pool_names = tuple(pool['pool_name']
|
||||||
|
for pool in self.get_volume_stats()['pools'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pool_names(self):
|
||||||
|
return self._pool_names
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<cinderlib.Backend %s>' % self.id
|
return '<cinderlib.Backend %s>' % self.id
|
||||||
|
|
|
@ -275,17 +275,16 @@ class Volume(NamedObject):
|
||||||
|
|
||||||
_ignore_keys = ('id', CONNECTIONS_OVO_FIELD, 'snapshots')
|
_ignore_keys = ('id', CONNECTIONS_OVO_FIELD, 'snapshots')
|
||||||
|
|
||||||
def __init__(self, backend_or_vol, **kwargs):
|
def __init__(self, backend_or_vol, pool_name=None, **kwargs):
|
||||||
# Accept backend name for convenience
|
# Accept backend name for convenience
|
||||||
if isinstance(backend_or_vol, six.string_types):
|
if isinstance(backend_or_vol, six.string_types):
|
||||||
kwargs.setdefault('host',
|
backend_name = backend_or_vol
|
||||||
'%s@%s' % (CONFIGURED_HOST, backend_or_vol))
|
|
||||||
backend_or_vol = self._get_backend(backend_or_vol)
|
backend_or_vol = self._get_backend(backend_or_vol)
|
||||||
elif isinstance(backend_or_vol, self.backend_class):
|
elif isinstance(backend_or_vol, self.backend_class):
|
||||||
kwargs.setdefault('host',
|
backend_name = backend_or_vol.id
|
||||||
'%s@%s' % (CONFIGURED_HOST, backend_or_vol.id))
|
|
||||||
# Accept a volume as additional source data
|
|
||||||
elif isinstance(backend_or_vol, Volume):
|
elif isinstance(backend_or_vol, Volume):
|
||||||
|
backend_name, pool = backend_or_vol._ovo.host.split('#')
|
||||||
|
pool_name = pool_name or pool
|
||||||
for key in backend_or_vol._ovo.fields:
|
for key in backend_or_vol._ovo.fields:
|
||||||
if (backend_or_vol._ovo.obj_attr_is_set(key) and
|
if (backend_or_vol._ovo.obj_attr_is_set(key) and
|
||||||
key not in self._ignore_keys):
|
key not in self._ignore_keys):
|
||||||
|
@ -307,6 +306,13 @@ class Volume(NamedObject):
|
||||||
self._populate_data()
|
self._populate_data()
|
||||||
self.local_attach = None
|
self.local_attach = None
|
||||||
|
|
||||||
|
# If we overwrote the host, then we ignore pool_name and don't set a
|
||||||
|
# default value or copy the one from the source either.
|
||||||
|
if 'host' not in kwargs and '__ovo' not in kwargs:
|
||||||
|
pool_name = pool_name or backend_or_vol.pool_names[0]
|
||||||
|
self._ovo.host = ('%s@%s#%s' %
|
||||||
|
(CONFIGURED_HOST, backend_name, pool_name))
|
||||||
|
|
||||||
if qos_specs or extra_specs:
|
if qos_specs or extra_specs:
|
||||||
if qos_specs:
|
if qos_specs:
|
||||||
qos_specs = cinder_objs.QualityOfServiceSpecs(
|
qos_specs = cinder_objs.QualityOfServiceSpecs(
|
||||||
|
|
|
@ -253,4 +253,9 @@ relevant sections:
|
||||||
|
|
||||||
- `global_setup` has been covered in the :doc:`initialization` section.
|
- `global_setup` has been covered in the :doc:`initialization` section.
|
||||||
|
|
||||||
|
- `pool_names` tuple with all the pools available in the driver. Non pool
|
||||||
|
aware drivers will have only 1 pool and use the name of the backend as its
|
||||||
|
name. Pool aware drivers may report multiple values, which can be passed to
|
||||||
|
the `create_volume` method in the `pool_name` parameter.
|
||||||
|
|
||||||
.. _OpenStack's Cinder volume driver configuration documentation: https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-drivers.html
|
.. _OpenStack's Cinder volume driver configuration documentation: https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-drivers.html
|
||||||
|
|
|
@ -109,9 +109,15 @@ Some of the fields we could be interested in are:
|
||||||
|
|
||||||
- `host`: Used to store the backend name information together with the host
|
- `host`: Used to store the backend name information together with the host
|
||||||
name where cinderlib is running. This information is stored as a string in
|
name where cinderlib is running. This information is stored as a string in
|
||||||
the form of *host@backend*. This is an optional parameter, and passing it to
|
the form of *host@backend#pool*. This is an optional parameter, and passing
|
||||||
`create_volume` will override default value. Issues will arise if parameter
|
it to `create_volume` will override default value, allowing us caller to
|
||||||
doesn't contain correct information.
|
request a specific pool for multi-pool backends, though we recommend using
|
||||||
|
the `pool_name` parameter instead. Issues will arise if parameter doesn't
|
||||||
|
contain correct information.
|
||||||
|
|
||||||
|
- `pool_name`: Pool name to use when creating the volume. Default is to use
|
||||||
|
the first or only pool. To know possible values for a backend use the
|
||||||
|
`pool_names` property on the *Backend* instance.
|
||||||
|
|
||||||
- `size`: Volume size in GBi.
|
- `size`: Volume size in GBi.
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,4 @@ class FakeBackend(cinderlib.Backend):
|
||||||
cinderlib.Backend.backends[driver_name] = self
|
cinderlib.Backend.backends[driver_name] = self
|
||||||
self._driver_cfg = {'volume_backend_name': driver_name}
|
self._driver_cfg = {'volume_backend_name': driver_name}
|
||||||
self.driver = mock.Mock()
|
self.driver = mock.Mock()
|
||||||
|
self._pool_names = (driver_name,)
|
||||||
|
|
Loading…
Reference in New Issue