From e2a58aa47dc94fecf314d7b7c786d8feccfc0946 Mon Sep 17 00:00:00 2001 From: Marc Koderer Date: Thu, 27 Jun 2013 12:05:56 +0200 Subject: [PATCH] Add interface class for backup drivers This fix introduces an interface class to define the structure of all backup drivers. It also renames backup/service to backup/driver. To be backward compatible a mapping functionality is introduced to map old backup services to backup drivers. Implements: blueprint refactor-backup-service Change-Id: Ic3fca567111f4bd1b221689c73cd5c3bab4a777b --- cinder/backup/driver.py | 33 ++++++++++++++ .../backup/{services => drivers}/__init__.py | 0 cinder/backup/{services => drivers}/ceph.py | 20 +++++---- cinder/backup/{services => drivers}/swift.py | 18 ++++---- cinder/backup/manager.py | 43 +++++++++++++------ cinder/tests/backup/fake_service.py | 5 ++- cinder/tests/conf_fixture.py | 4 +- cinder/tests/fake_flags.py | 4 +- cinder/tests/test_backup.py | 13 +++++- cinder/tests/test_backup_ceph.py | 22 +++++----- cinder/tests/test_backup_swift.py | 30 ++++++------- etc/cinder/cinder.conf.sample | 4 +- 12 files changed, 131 insertions(+), 65 deletions(-) create mode 100644 cinder/backup/driver.py rename cinder/backup/{services => drivers}/__init__.py (100%) rename cinder/backup/{services => drivers}/ceph.py (97%) rename cinder/backup/{services => drivers}/swift.py (98%) diff --git a/cinder/backup/driver.py b/cinder/backup/driver.py new file mode 100644 index 000000000..c158954d0 --- /dev/null +++ b/cinder/backup/driver.py @@ -0,0 +1,33 @@ +# Copyright (C) 2013 Deutsche Telekom AG +# All Rights Reserved. +# +# 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. +# +"""Base class for all backup drivers.""" + +from cinder.db import base + + +class BackupDriver(base.Base): + + def backup(self, backup, volume_file): + """Starts a backup of a specified volume""" + raise NotImplementedError() + + def restore(self, backup, volume_id, volume_file): + """Restores a saved backup""" + raise NotImplementedError() + + def delete(self, backup): + """Deletes a saved backup""" + raise NotImplementedError() diff --git a/cinder/backup/services/__init__.py b/cinder/backup/drivers/__init__.py similarity index 100% rename from cinder/backup/services/__init__.py rename to cinder/backup/drivers/__init__.py diff --git a/cinder/backup/services/ceph.py b/cinder/backup/drivers/ceph.py similarity index 97% rename from cinder/backup/services/ceph.py rename to cinder/backup/drivers/ceph.py index 9ff65c115..3ab882289 100644 --- a/cinder/backup/services/ceph.py +++ b/cinder/backup/drivers/ceph.py @@ -15,15 +15,17 @@ """Ceph Backup Service Implementation""" -from cinder.db import base +import os +import time + +import eventlet +from oslo.config import cfg + +from cinder.backup.driver import BackupDriver from cinder import exception from cinder.openstack.common import log as logging from cinder import units import cinder.volume.drivers.rbd as rbddriver -import eventlet -import os -from oslo.config import cfg -import time try: import rados @@ -54,11 +56,11 @@ CONF = cfg.CONF CONF.register_opts(service_opts) -class CephBackupService(base.Base): +class CephBackupDriver(BackupDriver): """Backup up Cinder volumes to Ceph Object Store""" def __init__(self, context, db_driver=None): - super(CephBackupService, self).__init__(db_driver) + super(CephBackupDriver, self).__init__(db_driver) self.rbd = rbd self.rados = rados self.context = context @@ -271,5 +273,5 @@ class CephBackupService(base.Base): LOG.debug(_("delete '%s' finished") % (backup_id)) -def get_backup_service(context): - return CephBackupService(context) +def get_backup_driver(context): + return CephBackupDriver(context) diff --git a/cinder/backup/services/swift.py b/cinder/backup/drivers/swift.py similarity index 98% rename from cinder/backup/services/swift.py rename to cinder/backup/drivers/swift.py index eba984476..f4146f50c 100644 --- a/cinder/backup/services/swift.py +++ b/cinder/backup/drivers/swift.py @@ -40,7 +40,7 @@ import StringIO import eventlet from oslo.config import cfg -from cinder.db import base +from cinder.backup.driver import BackupDriver from cinder import exception from cinder.openstack.common import log as logging from cinder.openstack.common import timeutils @@ -83,11 +83,11 @@ CONF = cfg.CONF CONF.register_opts(swiftbackup_service_opts) -class SwiftBackupService(base.Base): +class SwiftBackupDriver(BackupDriver): """Provides backup, restore and delete of backup objects within Swift.""" - SERVICE_VERSION = '1.0.0' - SERVICE_VERSION_MAPPING = {'1.0.0': '_restore_v1'} + DRIVER_VERSION = '1.0.0' + DRIVER_VERSION_MAPPING = {'1.0.0': '_restore_v1'} def _get_compressor(self, algorithm): try: @@ -134,7 +134,7 @@ class SwiftBackupService(base.Base): preauthtoken=self.context.auth_token, starting_backoff=self.swift_backoff) - super(SwiftBackupService, self).__init__(db_driver) + super(SwiftBackupDriver, self).__init__(db_driver) def _check_container_exists(self, container): LOG.debug(_('_check_container_exists: container: %s') % container) @@ -192,7 +192,7 @@ class SwiftBackupService(base.Base): ' metadata filename: %(filename)s') % {'container': container, 'filename': filename}) metadata = {} - metadata['version'] = self.SERVICE_VERSION + metadata['version'] = self.DRIVER_VERSION metadata['backup_id'] = backup['id'] metadata['volume_id'] = volume_id metadata['backup_name'] = backup['display_name'] @@ -421,7 +421,7 @@ class SwiftBackupService(base.Base): metadata_version = metadata['version'] LOG.debug(_('Restoring swift backup version %s'), metadata_version) try: - restore_func = getattr(self, self.SERVICE_VERSION_MAPPING.get( + restore_func = getattr(self, self.DRIVER_VERSION_MAPPING.get( metadata_version)) except TypeError: err = (_('No support to restore swift backup version %s') @@ -467,5 +467,5 @@ class SwiftBackupService(base.Base): LOG.debug(_('delete %s finished') % backup['id']) -def get_backup_service(context): - return SwiftBackupService(context) +def get_backup_driver(context): + return SwiftBackupDriver(context) diff --git a/cinder/backup/manager.py b/cinder/backup/manager.py index 471445467..b4eba2eac 100755 --- a/cinder/backup/manager.py +++ b/cinder/backup/manager.py @@ -46,11 +46,17 @@ from cinder.openstack.common import log as logging LOG = logging.getLogger(__name__) backup_manager_opts = [ - cfg.StrOpt('backup_service', - default='cinder.backup.services.swift', - help='Service to use for backups.'), + cfg.StrOpt('backup_driver', + default='cinder.backup.drivers.swift', + help='Driver to use for backups.', + deprecated_name='backup_service'), ] +# This map doesn't need to be extended in the future since it's only +# for old backup services +mapper = {'cinder.backup.services.swift': 'cinder.backup.drivers.swift', + 'cinder.backup.services.ceph': 'cinder.backup.drivers.ceph'} + CONF = cfg.CONF CONF.register_opts(backup_manager_opts) @@ -61,7 +67,7 @@ class BackupManager(manager.SchedulerDependentManager): RPC_API_VERSION = '1.0' def __init__(self, service_name=None, *args, **kwargs): - self.service = importutils.import_module(CONF.backup_service) + self.service = importutils.import_module(self.driver_name) self.az = CONF.storage_availability_zone self.volume_manager = importutils.import_object( CONF.volume_manager) @@ -70,6 +76,19 @@ class BackupManager(manager.SchedulerDependentManager): *args, **kwargs) self.driver.db = self.db + @property + def driver_name(self): + """This function maps old backup services to backup drivers.""" + + return self._map_service_to_driver(CONF.backup_driver) + + def _map_service_to_driver(self, service): + """Maps services to drivers.""" + + if service in mapper: + return mapper[service] + return service + def init_host(self): """Do any initialization that needs to be run if this is a standalone service. @@ -124,7 +143,7 @@ class BackupManager(manager.SchedulerDependentManager): {'backup_id': backup_id, 'volume_id': volume_id}) self.db.backup_update(context, backup_id, {'host': self.host, 'service': - CONF.backup_service}) + self.driver_name}) expected_status = 'backing-up' actual_status = volume['status'] @@ -152,7 +171,7 @@ class BackupManager(manager.SchedulerDependentManager): raise exception.InvalidBackup(reason=err) try: - backup_service = self.service.get_backup_service(context) + backup_service = self.service.get_backup_driver(context) self.driver.backup_volume(context, backup, backup_service) except Exception as err: with excutils.save_and_reraise_exception(): @@ -210,8 +229,8 @@ class BackupManager(manager.SchedulerDependentManager): volume['id'], volume['size'], backup['id'], backup['size']) - backup_service = backup['service'] - configured_service = CONF.backup_service + backup_service = self._map_service_to_driver(backup['service']) + configured_service = self.driver_name if backup_service != configured_service: err = _('restore_backup aborted, the backup service currently' ' configured [%(configured_service)s] is not the' @@ -225,7 +244,7 @@ class BackupManager(manager.SchedulerDependentManager): raise exception.InvalidBackup(reason=err) try: - backup_service = self.service.get_backup_service(context) + backup_service = self.service.get_backup_driver(context) self.driver.restore_backup(context, backup, volume, backup_service) except Exception as err: @@ -261,9 +280,9 @@ class BackupManager(manager.SchedulerDependentManager): 'fail_reason': err}) raise exception.InvalidBackup(reason=err) - backup_service = backup['service'] + backup_service = self._map_service_to_driver(backup['service']) if backup_service is not None: - configured_service = CONF.backup_service + configured_service = self.driver_name if backup_service != configured_service: err = _('delete_backup aborted, the backup service currently' ' configured [%(configured_service)s] is not the' @@ -277,7 +296,7 @@ class BackupManager(manager.SchedulerDependentManager): raise exception.InvalidBackup(reason=err) try: - backup_service = self.service.get_backup_service(context) + backup_service = self.service.get_backup_driver(context) backup_service.delete(backup) except Exception as err: with excutils.save_and_reraise_exception(): diff --git a/cinder/tests/backup/fake_service.py b/cinder/tests/backup/fake_service.py index c8a182eb2..a78d516e6 100644 --- a/cinder/tests/backup/fake_service.py +++ b/cinder/tests/backup/fake_service.py @@ -13,13 +13,14 @@ # License for the specific language governing permissions and limitations # under the License. +from cinder.backup.driver import BackupDriver from cinder.db import base from cinder.openstack.common import log as logging LOG = logging.getLogger(__name__) -class FakeBackupService(base.Base): +class FakeBackupService(BackupDriver): def __init__(self, context, db_driver=None): super(FakeBackupService, self).__init__(db_driver) @@ -37,5 +38,5 @@ class FakeBackupService(base.Base): raise IOError('fake') -def get_backup_service(context): +def get_backup_driver(context): return FakeBackupService(context) diff --git a/cinder/tests/conf_fixture.py b/cinder/tests/conf_fixture.py index 54ce228bc..cd42a8262 100644 --- a/cinder/tests/conf_fixture.py +++ b/cinder/tests/conf_fixture.py @@ -26,7 +26,7 @@ CONF.import_opt('iscsi_num_targets', 'cinder.volume.drivers.lvm') CONF.import_opt('policy_file', 'cinder.policy') CONF.import_opt('volume_driver', 'cinder.volume.manager') CONF.import_opt('xiv_proxy', 'cinder.volume.drivers.xiv') -CONF.import_opt('backup_service', 'cinder.backup.manager') +CONF.import_opt('backup_driver', 'cinder.backup.manager') def_vol_type = 'fake_vol_type' @@ -45,4 +45,4 @@ def set_defaults(conf): conf.set_default('sqlite_synchronous', False) conf.set_default('policy_file', 'cinder/tests/policy.json') conf.set_default('xiv_proxy', 'cinder.tests.test_xiv.XIVFakeProxyDriver') - conf.set_default('backup_service', 'cinder.tests.backup.fake_service') + conf.set_default('backup_driver', 'cinder.tests.backup.fake_service') diff --git a/cinder/tests/fake_flags.py b/cinder/tests/fake_flags.py index 36922abac..96eae3d4a 100644 --- a/cinder/tests/fake_flags.py +++ b/cinder/tests/fake_flags.py @@ -24,7 +24,7 @@ flags.DECLARE('iscsi_num_targets', 'cinder.volume.drivers.lvm') flags.DECLARE('policy_file', 'cinder.policy') flags.DECLARE('volume_driver', 'cinder.volume.manager') flags.DECLARE('xiv_proxy', 'cinder.volume.drivers.xiv') -flags.DECLARE('backup_service', 'cinder.backup.manager') +flags.DECLARE('backup_driver', 'cinder.backup.manager') def_vol_type = 'fake_vol_type' @@ -42,4 +42,4 @@ def set_defaults(conf): conf.set_default('sqlite_synchronous', False) conf.set_default('policy_file', 'cinder/tests/policy.json') conf.set_default('xiv_proxy', 'cinder.tests.test_xiv.XIVFakeProxyDriver') - conf.set_default('backup_service', 'cinder.tests.backup.fake_service') + conf.set_default('backup_driver', 'cinder.tests.backup.fake_service') diff --git a/cinder/tests/test_backup.py b/cinder/tests/test_backup.py index c7a363ad7..de23b58c6 100644 --- a/cinder/tests/test_backup.py +++ b/cinder/tests/test_backup.py @@ -77,7 +77,7 @@ class BackupTestCase(test.TestCase): backup['container'] = container backup['status'] = status backup['fail_reason'] = '' - backup['service'] = CONF.backup_service + backup['service'] = CONF.backup_driver backup['size'] = size backup['object_count'] = object_count return db.backup_create(self.ctxt, backup)['id'] @@ -407,3 +407,14 @@ class BackupTestCase(test.TestCase): ctxt_read_deleted = context.get_admin_context('yes') backups = db.backup_get_all_by_host(ctxt_read_deleted, 'testhost') self.assertEqual(len(backups), 2) + + def test_backup_manager_driver_name(self): + """"Test mapping between backup services and backup drivers.""" + + old_setting = CONF.backup_driver + setattr(cfg.CONF, 'backup_driver', "cinder.backup.services.swift") + backup_mgr = \ + importutils.import_object(CONF.backup_manager) + self.assertEqual('cinder.backup.drivers.swift', + backup_mgr.driver_name) + setattr(cfg.CONF, 'backup_driver', old_setting) diff --git a/cinder/tests/test_backup_ceph.py b/cinder/tests/test_backup_ceph.py index b65e474f0..a25fccde7 100644 --- a/cinder/tests/test_backup_ceph.py +++ b/cinder/tests/test_backup_ceph.py @@ -19,11 +19,11 @@ import os import tempfile import uuid -from cinder.backup.services.ceph import CephBackupService +from cinder.backup.drivers.ceph import CephBackupDriver from cinder.tests.backup.fake_rados import mock_rados from cinder.tests.backup.fake_rados import mock_rbd -from cinder.backup.services import ceph +from cinder.backup.drivers import ceph from cinder import context from cinder import db from cinder import exception @@ -73,7 +73,7 @@ class BackupCephTestCase(test.TestCase): self.volume_file.seek(0) def test_get_rbd_support(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) self.assertFalse(hasattr(service.rbd, 'RBD_FEATURE_LAYERING')) self.assertFalse(hasattr(service.rbd, 'RBD_FEATURE_STRIPINGV2')) @@ -95,7 +95,7 @@ class BackupCephTestCase(test.TestCase): self.assertEquals(features, 1 | 2) def test_tranfer_data_from_rbd(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as test_file: self.volume_file.seek(0) @@ -117,7 +117,7 @@ class BackupCephTestCase(test.TestCase): self.assertEquals(checksum.digest(), self.checksum.digest()) def test_tranfer_data_to_rbd(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as test_file: checksum = hashlib.sha256() @@ -135,7 +135,7 @@ class BackupCephTestCase(test.TestCase): self.assertEquals(checksum.digest(), self.checksum.digest()) def test_backup_volume_from_file(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as test_file: checksum = hashlib.sha256() @@ -157,21 +157,21 @@ class BackupCephTestCase(test.TestCase): super(BackupCephTestCase, self).tearDown() def test_backup_error1(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) backup = db.backup_get(self.ctxt, self.backup_id) self._create_volume_db_entry(self.vol_id, 0) self.assertRaises(exception.InvalidParameterValue, service.backup, backup, self.volume_file) def test_backup_error2(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) backup = db.backup_get(self.ctxt, self.backup_id) self._create_volume_db_entry(self.vol_id, 1) self.assertRaises(exception.BackupVolumeInvalidType, service.backup, backup, None) def test_backup_good(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) backup = db.backup_get(self.ctxt, self.backup_id) self._create_volume_db_entry(self.vol_id, 1) @@ -190,7 +190,7 @@ class BackupCephTestCase(test.TestCase): self.assertEquals(checksum.digest(), self.checksum.digest()) def test_restore(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) self._create_volume_db_entry(self.vol_id, 1) backup = db.backup_get(self.ctxt, self.backup_id) @@ -213,7 +213,7 @@ class BackupCephTestCase(test.TestCase): self.assertEquals(checksum.digest(), self.checksum.digest()) def test_delete(self): - service = CephBackupService(self.ctxt) + service = CephBackupDriver(self.ctxt) self._create_volume_db_entry(self.vol_id, 1) backup = db.backup_get(self.ctxt, self.backup_id) diff --git a/cinder/tests/test_backup_swift.py b/cinder/tests/test_backup_swift.py index 2c5f97f97..c3f0262a2 100644 --- a/cinder/tests/test_backup_swift.py +++ b/cinder/tests/test_backup_swift.py @@ -25,7 +25,7 @@ import zlib from swiftclient import client as swift -from cinder.backup.services.swift import SwiftBackupService +from cinder.backup.drivers.swift import SwiftBackupDriver from cinder import context from cinder import db from cinder import exception @@ -81,7 +81,7 @@ class BackupSwiftTestCase(test.TestCase): def test_backup_uncompressed(self): self._create_backup_db_entry() self.flags(backup_compression_algorithm='none') - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) service.backup(backup, self.volume_file) @@ -89,7 +89,7 @@ class BackupSwiftTestCase(test.TestCase): def test_backup_bz2(self): self._create_backup_db_entry() self.flags(backup_compression_algorithm='bz2') - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) service.backup(backup, self.volume_file) @@ -97,14 +97,14 @@ class BackupSwiftTestCase(test.TestCase): def test_backup_zlib(self): self._create_backup_db_entry() self.flags(backup_compression_algorithm='zlib') - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) service.backup(backup, self.volume_file) def test_backup_default_container(self): self._create_backup_db_entry(container=None) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) service.backup(backup, self.volume_file) @@ -114,7 +114,7 @@ class BackupSwiftTestCase(test.TestCase): def test_backup_custom_container(self): container_name = 'fake99' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) service.backup(backup, self.volume_file) @@ -124,7 +124,7 @@ class BackupSwiftTestCase(test.TestCase): def test_create_backup_container_check_wraps_socket_error(self): container_name = 'socket_error_on_head' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) self.assertRaises(exception.SwiftConnectionFailed, @@ -134,7 +134,7 @@ class BackupSwiftTestCase(test.TestCase): def test_create_backup_put_object_wraps_socket_error(self): container_name = 'socket_error_on_put' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) self.volume_file.seek(0) backup = db.backup_get(self.ctxt, 123) self.assertRaises(exception.SwiftConnectionFailed, @@ -143,7 +143,7 @@ class BackupSwiftTestCase(test.TestCase): def test_restore(self): self._create_backup_db_entry() - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as volume_file: backup = db.backup_get(self.ctxt, 123) @@ -152,7 +152,7 @@ class BackupSwiftTestCase(test.TestCase): def test_restore_wraps_socket_error(self): container_name = 'socket_error_on_get' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as volume_file: backup = db.backup_get(self.ctxt, 123) @@ -163,7 +163,7 @@ class BackupSwiftTestCase(test.TestCase): def test_restore_unsupported_version(self): container_name = 'unsupported_version' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) with tempfile.NamedTemporaryFile() as volume_file: backup = db.backup_get(self.ctxt, 123) @@ -173,21 +173,21 @@ class BackupSwiftTestCase(test.TestCase): def test_delete(self): self._create_backup_db_entry() - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) backup = db.backup_get(self.ctxt, 123) service.delete(backup) def test_delete_wraps_socket_error(self): container_name = 'socket_error_on_delete' self._create_backup_db_entry(container=container_name) - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) backup = db.backup_get(self.ctxt, 123) self.assertRaises(exception.SwiftConnectionFailed, service.delete, backup) def test_get_compressor(self): - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) compressor = service._get_compressor('None') self.assertEquals(compressor, None) compressor = service._get_compressor('zlib') @@ -197,7 +197,7 @@ class BackupSwiftTestCase(test.TestCase): self.assertRaises(ValueError, service._get_compressor, 'fake') def test_check_container_exists(self): - service = SwiftBackupService(self.ctxt) + service = SwiftBackupDriver(self.ctxt) exists = service._check_container_exists('fake_container') self.assertEquals(exists, True) exists = service._check_container_exists('missing_container') diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index 5c877d41b..666ebc1af 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -323,11 +323,11 @@ # # Service to use for backups. (string value) -#backup_service=cinder.backup.services.swift +#backup_driver=cinder.backup.drivers.swift # -# Options defined in cinder.backup.services.swift +# Options defined in cinder.backup.drivers.swift # # The URL of the Swift endpoint (string value) -- 2.45.2