| From 89a7a3bf5fb34198d595aa906cdf3ee9f6647f48 Mon Sep 17 00:00:00 2001 |
| From: Biser Milanov <biser.milanov@storpool.com> |
| Date: Mon, 14 Oct 2024 14:25:22 +0300 |
| Subject: [PATCH] StorPool: Use os-brick instead of packages `storpool` and |
| `storpool.spopenstack` |
| |
| Stop depending on modules `storpool` and `storpool.spopenstack` for |
| access to the StorPool API and reading the StorPool configuration from |
| files. Use the new new in-tree implementation introduced in `os-brick`. |
| |
| Change-Id: Ieb6be04133e1639b3fa6e3a322604b366e909d81 |
| --- |
| .../unit/volume/drivers/test_storpool.py | 168 +++++++--------- |
| cinder/volume/drivers/storpool.py | 183 +++++++++--------- |
| .../drivers/storpool-volume-driver.rst | 8 - |
| ...-config-code-in-tree-92cfe30690b78ef1.yaml | 8 + |
| requirements.txt | 2 +- |
| 5 files changed, 173 insertions(+), 196 deletions(-) |
| create mode 100644 releasenotes/notes/storpool-move-api-and-config-code-in-tree-92cfe30690b78ef1.yaml |
| |
| diff --git a/cinder/tests/unit/volume/drivers/test_storpool.py b/cinder/tests/unit/volume/drivers/test_storpool.py |
| index 44707d0b8..2015c734d 100644 |
| --- a/cinder/tests/unit/volume/drivers/test_storpool.py |
| +++ b/cinder/tests/unit/volume/drivers/test_storpool.py |
| @@ -16,21 +16,13 @@ |
| |
| import itertools |
| import re |
| -import sys |
| from unittest import mock |
| |
| import ddt |
| +from os_brick.initiator import storpool_utils |
| +from os_brick.tests.initiator import test_storpool_utils |
| from oslo_utils import units |
| |
| - |
| -fakeStorPool = mock.Mock() |
| -fakeStorPool.spopenstack = mock.Mock() |
| -fakeStorPool.spapi = mock.Mock() |
| -fakeStorPool.spconfig = mock.Mock() |
| -fakeStorPool.sptypes = mock.Mock() |
| -sys.modules['storpool'] = fakeStorPool |
| - |
| - |
| from cinder import exception |
| from cinder.tests.unit import fake_constants |
| from cinder.tests.unit import test |
| @@ -64,64 +56,52 @@ def mock_volume_types(f): |
| |
| |
| def volumeName(vid): |
| - return 'os--volume--{id}'.format(id=vid) |
| - |
| - |
| -def snapshotName(vtype, vid): |
| - return 'os--snap--{t}--{id}'.format(t=vtype, id=vid) |
| - |
| - |
| -class MockDisk(object): |
| - def __init__(self, diskId): |
| - self.id = diskId |
| - self.generationLeft = -1 |
| - self.agCount = 14 |
| - self.agFree = 12 |
| - self.agAllocated = 1 |
| - |
| - |
| -class MockVolume(object): |
| - def __init__(self, v): |
| - self.name = v['name'] |
| - |
| - |
| -class MockTemplate(object): |
| - def __init__(self, name): |
| - self.name = name |
| + return 'os--volume-{id}'.format(id=vid) |
| |
| |
| -class MockApiError(Exception): |
| - def __init__(self, msg): |
| - super(MockApiError, self).__init__(msg) |
| +def snapshotName(vtype, vid, more=None): |
| + return 'os--{t}--{m}--snapshot-{id}'.format( |
| + t=vtype, |
| + m="none" if more is None else more, |
| + id=vid |
| + ) |
| |
| |
| class MockAPI(object): |
| - def __init__(self): |
| - self._disks = {diskId: MockDisk(diskId) for diskId in (1, 2, 3, 4)} |
| - self._disks[3].generationLeft = 42 |
| - |
| - self._templates = [MockTemplate(name) for name in ('ssd', 'hdd')] |
| - |
| - def setlog(self, log): |
| - self._log = log |
| - |
| - def disksList(self): |
| + def __init__(self, *args): |
| + self._disks = {} |
| + for disk_id in [1, 2, 3, 4]: |
| + self._disks[disk_id] = { |
| + 'id': disk_id, |
| + 'generationLeft': -1, |
| + 'agCount': 14, |
| + 'agFree': 12, |
| + 'agAllocated': 1 |
| + } |
| + self._disks[3]['generationLeft'] = 42 |
| + |
| + self._templates = [{'name': name} for name in ('ssd', 'hdd')] |
| + |
| + def disks_list(self): |
| return self._disks |
| |
| - def snapshotCreate(self, vname, snap): |
| + def snapshot_create(self, vname, snap): |
| snapshots[snap['name']] = dict(volumes[vname]) |
| |
| - def snapshotUpdate(self, snap, data): |
| + def snapshot_update(self, snap, data): |
| sdata = snapshots[snap] |
| sdata.update(data) |
| |
| - def snapshotDelete(self, name): |
| + def snapshot_delete(self, name): |
| del snapshots[name] |
| |
| - def volumeCreate(self, vol): |
| + def volume_create(self, vol): |
| name = vol['name'] |
| if name in volumes: |
| - raise MockApiError('volume already exists') |
| + raise storpool_utils.StorPoolAPIError( |
| + 'none', |
| + {'error': { |
| + 'descr': 'volume already exists'}}) |
| data = dict(vol) |
| |
| if 'parent' in vol and 'template' not in vol: |
| @@ -139,19 +119,22 @@ class MockAPI(object): |
| |
| volumes[name] = data |
| |
| - def volumeDelete(self, name): |
| + def volume_delete(self, name): |
| del volumes[name] |
| |
| - def volumesList(self): |
| - return [MockVolume(v[1]) for v in volumes.items()] |
| + def volumes_list(self): |
| + the_volumes = [] |
| + for volume in volumes: |
| + the_volumes.append({'name': volume}) |
| + return the_volumes |
| |
| - def volumeTemplatesList(self): |
| + def volume_templates_list(self): |
| return self._templates |
| |
| - def volumesReassign(self, json): |
| + def volumes_reassign(self, json): |
| pass |
| |
| - def volumeUpdate(self, name, data): |
| + def volume_update(self, name, data): |
| if 'size' in data: |
| volumes[name]['size'] = data['size'] |
| |
| @@ -162,54 +145,23 @@ class MockAPI(object): |
| volumes[new_name]['name'] = new_name |
| del volumes[name] |
| |
| - def volumeRevert(self, name, data): |
| + def volume_revert(self, name, data): |
| if name not in volumes: |
| - raise MockApiError('No such volume {name}'.format(name=name)) |
| + raise storpool_utils.StorPoolAPIError( |
| + 'none', |
| + {'error': { |
| + 'descr': 'No such volume {name}'.format(name=name)}}) |
| |
| snapname = data['toSnapshot'] |
| if snapname not in snapshots: |
| - raise MockApiError('No such snapshot {name}'.format(name=snapname)) |
| + raise storpool_utils.StorPoolAPIError( |
| + 'none', |
| + {'error': { |
| + 'descr': 'No such snapshot {name}'.format(name=snapname)}}) |
| |
| volumes[name] = dict(snapshots[snapname]) |
| |
| |
| -class MockAttachDB(object): |
| - def __init__(self, log): |
| - self._api = MockAPI() |
| - |
| - def api(self): |
| - return self._api |
| - |
| - def volumeName(self, vid): |
| - return volumeName(vid) |
| - |
| - def snapshotName(self, vtype, vid): |
| - return snapshotName(vtype, vid) |
| - |
| - |
| -def MockVolumeRevertDesc(toSnapshot): |
| - return {'toSnapshot': toSnapshot} |
| - |
| - |
| -def MockVolumeUpdateDesc(size): |
| - return {'size': size} |
| - |
| - |
| -def MockSPConfig(section = 's01'): |
| - res = {} |
| - m = re.match('^s0*([A-Za-z0-9]+)$', section) |
| - if m: |
| - res['SP_OURID'] = m.group(1) |
| - return res |
| - |
| - |
| -fakeStorPool.spapi.ApiError = MockApiError |
| -fakeStorPool.spconfig.SPConfig = MockSPConfig |
| -fakeStorPool.spopenstack.AttachDB = MockAttachDB |
| -fakeStorPool.sptypes.VolumeRevertDesc = MockVolumeRevertDesc |
| -fakeStorPool.sptypes.VolumeUpdateDesc = MockVolumeUpdateDesc |
| - |
| - |
| class MockVolumeDB(object): |
| """Simulate a Cinder database with a volume_get() method.""" |
| |
| @@ -227,7 +179,16 @@ class MockVolumeDB(object): |
| } |
| |
| |
| +def MockSPConfig(section = 's01'): |
| + res = {} |
| + m = re.match('^s0*([A-Za-z0-9]+)$', section) |
| + if m: |
| + res['SP_OURID'] = m.group(1) |
| + return res |
| + |
| + |
| @ddt.ddt |
| +@mock.patch('os_brick.initiator.storpool_utils.get_conf', MockSPConfig) |
| class StorPoolTestCase(test.TestCase): |
| |
| def setUp(self): |
| @@ -243,7 +204,16 @@ class StorPoolTestCase(test.TestCase): |
| |
| self.driver = driver.StorPoolDriver(execute=mock_exec, |
| configuration=self.cfg) |
| - self.driver.check_for_setup_error() |
| + |
| + with ( |
| + mock.patch( |
| + 'os_brick.initiator.storpool_utils.get_conf' |
| + ) as get_conf, |
| + mock.patch( |
| + 'os_brick.initiator.storpool_utils.StorPoolAPI', MockAPI) |
| + ): |
| + get_conf.return_value = test_storpool_utils.SP_CONF |
| + self.driver.check_for_setup_error() |
| |
| @ddt.data( |
| (5, TypeError), |
| diff --git a/cinder/volume/drivers/storpool.py b/cinder/volume/drivers/storpool.py |
| index a8200a7f1..2dc7bb6be 100644 |
| --- a/cinder/volume/drivers/storpool.py |
| +++ b/cinder/volume/drivers/storpool.py |
| @@ -17,10 +17,10 @@ |
| |
| import platform |
| |
| +from os_brick.initiator import storpool_utils |
| from oslo_config import cfg |
| from oslo_log import log as logging |
| from oslo_utils import excutils |
| -from oslo_utils import importutils |
| from oslo_utils import units |
| |
| from cinder.common import constants |
| @@ -34,13 +34,6 @@ from cinder.volume import volume_types |
| |
| LOG = logging.getLogger(__name__) |
| |
| -storpool = importutils.try_import('storpool') |
| -if storpool: |
| - from storpool import spapi |
| - from storpool import spconfig |
| - from storpool import spopenstack |
| - from storpool import sptypes |
| - |
| |
| storpool_opts = [ |
| cfg.StrOpt('storpool_template', |
| @@ -93,9 +86,13 @@ class StorPoolDriver(driver.VolumeDriver): |
| add ignore_errors to the internal _detach_volume() method |
| 1.2.3 - Advertise some more driver capabilities. |
| 2.0.0 - Implement revert_to_snapshot(). |
| + 2.1.0 - Use the new API client in os-brick to communicate with the |
| + StorPool API instead of packages `storpool` and |
| + `storpool.spopenstack` |
| + |
| """ |
| |
| - VERSION = '2.0.0' |
| + VERSION = '2.1.0' |
| CI_WIKI_NAME = 'StorPool_distributed_storage_CI' |
| |
| def __init__(self, *args, **kwargs): |
| @@ -104,7 +101,8 @@ class StorPoolDriver(driver.VolumeDriver): |
| self._sp_config = None |
| self._ourId = None |
| self._ourIdInt = None |
| - self._attach = None |
| + self._sp_api = None |
| + self._volume_prefix = None |
| |
| @staticmethod |
| def get_driver_options(): |
| @@ -131,7 +129,8 @@ class StorPoolDriver(driver.VolumeDriver): |
| |
| def create_volume(self, volume): |
| size = int(volume['size']) * units.Gi |
| - name = self._attach.volumeName(volume['id']) |
| + name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| template = self._template_from_volume(volume) |
| |
| create_request = {'name': name, 'size': size} |
| @@ -142,8 +141,8 @@ class StorPoolDriver(driver.VolumeDriver): |
| self.configuration.storpool_replication |
| |
| try: |
| - self._attach.api().volumeCreate(create_request) |
| - except spapi.ApiError as e: |
| + self._sp_api.volume_create(create_request) |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| def _storpool_client_id(self, connector): |
| @@ -151,7 +150,7 @@ class StorPoolDriver(driver.VolumeDriver): |
| if hostname == self.host or hostname == CONF.host: |
| hostname = platform.node() |
| try: |
| - cfg = spconfig.SPConfig(section=hostname) |
| + cfg = storpool_utils.get_conf(section=hostname) |
| return int(cfg['SP_OURID']) |
| except KeyError: |
| return 65 |
| @@ -174,30 +173,36 @@ class StorPoolDriver(driver.VolumeDriver): |
| pass |
| |
| def create_snapshot(self, snapshot): |
| - volname = self._attach.volumeName(snapshot['volume_id']) |
| - name = self._attach.snapshotName('snap', snapshot['id']) |
| + volname = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, snapshot['volume_id']) |
| + name = storpool_utils.os_to_sp_snapshot_name( |
| + self._volume_prefix, 'snap', snapshot['id']) |
| try: |
| - self._attach.api().snapshotCreate(volname, {'name': name}) |
| - except spapi.ApiError as e: |
| + self._sp_api.snapshot_create(volname, {'name': name}) |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| def create_volume_from_snapshot(self, volume, snapshot): |
| size = int(volume['size']) * units.Gi |
| - volname = self._attach.volumeName(volume['id']) |
| - name = self._attach.snapshotName('snap', snapshot['id']) |
| + volname = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| + name = storpool_utils.os_to_sp_snapshot_name( |
| + self._volume_prefix, 'snap', snapshot['id']) |
| try: |
| - self._attach.api().volumeCreate({ |
| + self._sp_api.volume_create({ |
| 'name': volname, |
| 'size': size, |
| 'parent': name |
| }) |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| def create_cloned_volume(self, volume, src_vref): |
| - refname = self._attach.volumeName(src_vref['id']) |
| + refname = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, src_vref['id']) |
| size = int(volume['size']) * units.Gi |
| - volname = self._attach.volumeName(volume['id']) |
| + volname = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| |
| src_volume = self.db.volume_get( |
| context.get_admin_context(), |
| @@ -213,50 +218,51 @@ class StorPoolDriver(driver.VolumeDriver): |
| if template == src_template: |
| LOG.info('Using baseOn to clone a volume into the same template') |
| try: |
| - self._attach.api().volumeCreate({ |
| + self._sp_api.volume_create({ |
| 'name': volname, |
| 'size': size, |
| 'baseOn': refname, |
| }) |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| return None |
| |
| - snapname = self._attach.snapshotName('clone', volume['id']) |
| + snapname = storpool_utils.os_to_sp_snapshot_name( |
| + self._volume_prefix, 'clone', volume['id']) |
| LOG.info( |
| 'A transient snapshot for a %(src)s -> %(dst)s template change', |
| {'src': src_template, 'dst': template}) |
| try: |
| - self._attach.api().snapshotCreate(refname, {'name': snapname}) |
| - except spapi.ApiError as e: |
| + self._sp_api.snapshot_create(refname, {'name': snapname}) |
| + except storpool_utils.StorPoolAPIError as e: |
| if e.name != 'objectExists': |
| raise self._backendException(e) |
| |
| try: |
| try: |
| - self._attach.api().snapshotUpdate( |
| + self._sp_api.snapshot_update( |
| snapname, |
| {'template': template}, |
| ) |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| try: |
| - self._attach.api().volumeCreate({ |
| + self._sp_api.volume_create({ |
| 'name': volname, |
| 'size': size, |
| 'parent': snapname |
| }) |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| try: |
| - self._attach.api().snapshotUpdate( |
| + self._sp_api.snapshot_update( |
| snapname, |
| {'tags': {'transient': '1.0'}}, |
| ) |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| except Exception: |
| with excutils.save_and_reraise_exception(): |
| @@ -264,8 +270,8 @@ class StorPoolDriver(driver.VolumeDriver): |
| LOG.warning( |
| 'Something went wrong, removing the transient snapshot' |
| ) |
| - self._attach.api().snapshotDelete(snapname) |
| - except spapi.ApiError as e: |
| + self._sp_api.snapshot_delete(snapname) |
| + except storpool_utils.StorPoolAPIError as e: |
| LOG.error( |
| 'Could not delete the %(name)s snapshot: %(err)s', |
| {'name': snapname, 'err': str(e)} |
| @@ -278,57 +284,59 @@ class StorPoolDriver(driver.VolumeDriver): |
| pass |
| |
| def delete_volume(self, volume): |
| - name = self._attach.volumeName(volume['id']) |
| + name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| try: |
| - self._attach.api().volumesReassign( |
| - json=[{"volume": name, "detach": "all"}]) |
| - self._attach.api().volumeDelete(name) |
| - except spapi.ApiError as e: |
| + self._sp_api.volumes_reassign([{"volume": name, "detach": "all"}]) |
| + self._sp_api.volume_delete(name) |
| + except storpool_utils.StorPoolAPIError as e: |
| if e.name == 'objectDoesNotExist': |
| pass |
| else: |
| raise self._backendException(e) |
| |
| def delete_snapshot(self, snapshot): |
| - name = self._attach.snapshotName('snap', snapshot['id']) |
| + name = storpool_utils.os_to_sp_snapshot_name( |
| + self._volume_prefix, 'snap', snapshot['id']) |
| try: |
| - self._attach.api().volumesReassign( |
| - json=[{"snapshot": name, "detach": "all"}]) |
| - self._attach.api().snapshotDelete(name) |
| - except spapi.ApiError as e: |
| + self._sp_api.volumes_reassign( |
| + [{"snapshot": name, "detach": "all"}]) |
| + self._sp_api.snapshot_delete(name) |
| + except storpool_utils.StorPoolAPIError as e: |
| if e.name == 'objectDoesNotExist': |
| pass |
| else: |
| raise self._backendException(e) |
| |
| def check_for_setup_error(self): |
| - if storpool is None: |
| - msg = _('storpool libraries not found') |
| - raise exception.VolumeBackendAPIException(data=msg) |
| - |
| - self._attach = spopenstack.AttachDB(log=LOG) |
| try: |
| - self._attach.api() |
| + self._sp_config = storpool_utils.get_conf() |
| + self._sp_api = storpool_utils.StorPoolAPI( |
| + self._sp_config["SP_API_HTTP_HOST"], |
| + self._sp_config["SP_API_HTTP_PORT"], |
| + self._sp_config["SP_AUTH_TOKEN"]) |
| + self._volume_prefix = self._sp_config.get( |
| + "SP_OPENSTACK_VOLUME_PREFIX", "os") |
| except Exception as e: |
| LOG.error("StorPoolDriver API initialization failed: %s", e) |
| raise |
| |
| def _update_volume_stats(self): |
| try: |
| - dl = self._attach.api().disksList() |
| - templates = self._attach.api().volumeTemplatesList() |
| - except spapi.ApiError as e: |
| + dl = self._sp_api.disks_list() |
| + templates = self._sp_api.volume_templates_list() |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| total = 0 |
| used = 0 |
| free = 0 |
| agSize = 512 * units.Mi |
| for (id, desc) in dl.items(): |
| - if desc.generationLeft != -1: |
| + if desc['generationLeft'] != -1: |
| continue |
| - total += desc.agCount * agSize |
| - used += desc.agAllocated * agSize |
| - free += desc.agFree * agSize * 4096 / (4096 + 128) |
| + total += desc['agCount'] * agSize |
| + used += desc['agAllocated'] * agSize |
| + free += desc['agFree'] * agSize * 4096 / (4096 + 128) |
| |
| # Report the free space as if all new volumes will be created |
| # with StorPool replication 3; anything else is rare. |
| @@ -347,8 +355,8 @@ class StorPoolDriver(driver.VolumeDriver): |
| pools = [dict(space, pool_name='default')] |
| |
| pools += [dict(space, |
| - pool_name='template_' + t.name, |
| - storpool_template=t.name |
| + pool_name='template_' + t['name'], |
| + storpool_template=t['name'] |
| ) for t in templates] |
| |
| self._stats = { |
| @@ -367,11 +375,11 @@ class StorPoolDriver(driver.VolumeDriver): |
| |
| def extend_volume(self, volume, new_size): |
| size = int(new_size) * units.Gi |
| - name = self._attach.volumeName(volume['id']) |
| + name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| try: |
| - upd = sptypes.VolumeUpdateDesc(size=size) |
| - self._attach.api().volumeUpdate(name, upd) |
| - except spapi.ApiError as e: |
| + self._sp_api.volume_update(name, {'size': size}) |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| def ensure_export(self, context, volume): |
| @@ -409,11 +417,11 @@ class StorPoolDriver(driver.VolumeDriver): |
| update['replication'] = repl |
| |
| if update: |
| - name = self._attach.volumeName(volume['id']) |
| + name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| try: |
| - upd = sptypes.VolumeUpdateDesc(**update) |
| - self._attach.api().volumeUpdate(name, upd) |
| - except spapi.ApiError as e: |
| + self._sp_api.volume_update(name, **update) |
| + except storpool_utils.StorPoolAPIError as e: |
| raise self._backendException(e) |
| |
| return True |
| @@ -421,10 +429,12 @@ class StorPoolDriver(driver.VolumeDriver): |
| def update_migrated_volume(self, context, volume, new_volume, |
| original_volume_status): |
| orig_id = volume['id'] |
| - orig_name = self._attach.volumeName(orig_id) |
| + orig_name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, orig_id) |
| temp_id = new_volume['id'] |
| - temp_name = self._attach.volumeName(temp_id) |
| - vols = {v.name: True for v in self._attach.api().volumesList()} |
| + temp_name = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, temp_id) |
| + vols = {v['name']: True for v in self._sp_api.volumes_list()} |
| if temp_name not in vols: |
| LOG.error('StorPool update_migrated_volume(): it seems ' |
| 'that the StorPool volume "%(tid)s" was not ' |
| @@ -444,20 +454,17 @@ class StorPoolDriver(driver.VolumeDriver): |
| try: |
| LOG.debug('- rename "%(orig)s" to "%(int)s"', |
| {'orig': orig_name, 'int': int_name}) |
| - self._attach.api().volumeUpdate(orig_name, |
| - {'rename': int_name}) |
| + self._sp_api.volume_update(orig_name, {'rename': int_name}) |
| |
| LOG.debug('- rename "%(temp)s" to "%(orig)s"', |
| {'temp': temp_name, 'orig': orig_name}) |
| - self._attach.api().volumeUpdate(temp_name, |
| - {'rename': orig_name}) |
| + self._sp_api.volume_update(temp_name, {'rename': orig_name}) |
| |
| LOG.debug('- rename "%(int)s" to "%(temp)s"', |
| {'int': int_name, 'temp': temp_name}) |
| - self._attach.api().volumeUpdate(int_name, |
| - {'rename': temp_name}) |
| + self._sp_api.volume_update(int_name, {'rename': temp_name}) |
| return {'_name_id': None} |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| LOG.error('StorPool update_migrated_volume(): ' |
| 'could not rename a volume: ' |
| '%(err)s', |
| @@ -465,10 +472,9 @@ class StorPoolDriver(driver.VolumeDriver): |
| return {'_name_id': new_volume['_name_id'] or new_volume['id']} |
| |
| try: |
| - self._attach.api().volumeUpdate(temp_name, |
| - {'rename': orig_name}) |
| + self._sp_api.volume_update(temp_name, {'rename': orig_name}) |
| return {'_name_id': None} |
| - except spapi.ApiError as e: |
| + except storpool_utils.StorPoolAPIError as e: |
| LOG.error('StorPool update_migrated_volume(): ' |
| 'could not rename %(tname)s to %(oname)s: ' |
| '%(err)s', |
| @@ -476,12 +482,13 @@ class StorPoolDriver(driver.VolumeDriver): |
| return {'_name_id': new_volume['_name_id'] or new_volume['id']} |
| |
| def revert_to_snapshot(self, context, volume, snapshot): |
| - volname = self._attach.volumeName(volume['id']) |
| - snapname = self._attach.snapshotName('snap', snapshot['id']) |
| + volname = storpool_utils.os_to_sp_volume_name( |
| + self._volume_prefix, volume['id']) |
| + snapname = storpool_utils.os_to_sp_snapshot_name( |
| + self._volume_prefix, 'snap', snapshot['id']) |
| try: |
| - rev = sptypes.VolumeRevertDesc(toSnapshot=snapname) |
| - self._attach.api().volumeRevert(volname, rev) |
| - except spapi.ApiError as e: |
| + self._sp_api.volume_revert(volname, {'toSnapshot': snapname}) |
| + except storpool_utils.StorPoolAPIError as e: |
| LOG.error('StorPool revert_to_snapshot(): could not revert ' |
| 'the %(vol_id)s volume to the %(snap_id)s snapshot: ' |
| '%(err)s', |
| diff --git a/doc/source/configuration/block-storage/drivers/storpool-volume-driver.rst b/doc/source/configuration/block-storage/drivers/storpool-volume-driver.rst |
| index d2c5895a9..e9209b0cc 100644 |
| --- a/doc/source/configuration/block-storage/drivers/storpool-volume-driver.rst |
| +++ b/doc/source/configuration/block-storage/drivers/storpool-volume-driver.rst |
| @@ -26,14 +26,6 @@ Prerequisites |
| images, then the node running the ``cinder-volume`` service must also have |
| access to the StorPool data network and run the ``storpool_block`` service. |
| |
| -* All nodes that need to access the StorPool API (the compute nodes and |
| - the node running the ``cinder-volume`` service) must have the following |
| - packages installed: |
| - |
| - * storpool-config (part of the StorPool installation) |
| - * the storpool Python bindings package |
| - * the storpool.spopenstack Python helper package |
| - |
| Configuring the StorPool volume driver |
| -------------------------------------- |
| |
| diff --git a/releasenotes/notes/storpool-move-api-and-config-code-in-tree-92cfe30690b78ef1.yaml b/releasenotes/notes/storpool-move-api-and-config-code-in-tree-92cfe30690b78ef1.yaml |
| new file mode 100644 |
| index 000000000..13c2cbd65 |
| --- /dev/null |
| +++ b/releasenotes/notes/storpool-move-api-and-config-code-in-tree-92cfe30690b78ef1.yaml |
| @@ -0,0 +1,8 @@ |
| +--- |
| +other: |
| + - | |
| + Use the new implementation in os-brick for communicating with the |
| + StorPool API and reading StorPool configuration files. |
| + |
| + The StorPool backend no longer requires the OpenStack nodes to have |
| + the Python packages `storpool` and `storpool.spopenstack` installed. |
| diff --git a/requirements.txt b/requirements.txt |
| index c7aee22ec..fbb911648 100644 |
| --- a/requirements.txt |
| +++ b/requirements.txt |
| @@ -50,7 +50,7 @@ tenacity>=6.3.1 # Apache-2.0 |
| WebOb>=1.8.6 # MIT |
| oslo.i18n>=5.1.0 # Apache-2.0 |
| oslo.vmware>=3.10.0 # Apache-2.0 |
| -os-brick>=6.0.0 # Apache-2.0 |
| +os-brick>=6.10.0 # Apache-2.0 |
| os-win>=5.5.0 # Apache-2.0 |
| tooz>=2.8.0 # Apache-2.0 |
| google-api-python-client>=1.11.0 # Apache-2.0 |
| -- |
| 2.43.0 |
| |