Skip to content

Commit

Permalink
Merge "Add interface class for backup drivers"
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed Jul 10, 2013
2 parents ee5514f + e2a58aa commit 2f5e26a
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 65 deletions.
33 changes: 33 additions & 0 deletions 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()
File renamed without changes.
20 changes: 11 additions & 9 deletions cinder/backup/services/ceph.py → cinder/backup/drivers/ceph.py
Expand Up @@ -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
Expand Down Expand Up @@ -54,11 +56,11 @@
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
Expand Down Expand Up @@ -271,5 +273,5 @@ def delete(self, backup):
LOG.debug(_("delete '%s' finished") % (backup_id))


def get_backup_service(context):
return CephBackupService(context)
def get_backup_driver(context):
return CephBackupDriver(context)
Expand Up @@ -40,7 +40,7 @@
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
Expand Down Expand Up @@ -83,11 +83,11 @@
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:
Expand Down Expand Up @@ -134,7 +134,7 @@ def __init__(self, context, db_driver=None):
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)
Expand Down Expand Up @@ -192,7 +192,7 @@ def _write_metadata(self, backup, volume_id, container, object_list):
' 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']
Expand Down Expand Up @@ -421,7 +421,7 @@ def restore(self, backup, volume_id, volume_file):
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')
Expand Down Expand Up @@ -467,5 +467,5 @@ def delete(self, backup):
LOG.debug(_('delete %s finished') % backup['id'])


def get_backup_service(context):
return SwiftBackupService(context)
def get_backup_driver(context):
return SwiftBackupDriver(context)
43 changes: 31 additions & 12 deletions cinder/backup/manager.py
Expand Up @@ -46,11 +46,17 @@
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)

Expand All @@ -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)
Expand All @@ -70,6 +76,19 @@ def __init__(self, service_name=None, *args, **kwargs):
*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.
Expand Down Expand Up @@ -124,7 +143,7 @@ def create_backup(self, context, backup_id):
{'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']
Expand Down Expand Up @@ -152,7 +171,7 @@ def create_backup(self, context, backup_id):
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():
Expand Down Expand Up @@ -210,8 +229,8 @@ def restore_backup(self, context, backup_id, volume_id):
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'
Expand All @@ -225,7 +244,7 @@ def restore_backup(self, context, backup_id, volume_id):
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:
Expand Down Expand Up @@ -261,9 +280,9 @@ def delete_backup(self, context, backup_id):
'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'
Expand All @@ -277,7 +296,7 @@ def delete_backup(self, context, backup_id):
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():
Expand Down
5 changes: 3 additions & 2 deletions cinder/tests/backup/fake_service.py
Expand Up @@ -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)

Expand All @@ -37,5 +38,5 @@ def delete(self, backup):
raise IOError('fake')


def get_backup_service(context):
def get_backup_driver(context):
return FakeBackupService(context)
4 changes: 2 additions & 2 deletions cinder/tests/conf_fixture.py
Expand Up @@ -26,7 +26,7 @@
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'

Expand All @@ -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')
4 changes: 2 additions & 2 deletions cinder/tests/fake_flags.py
Expand Up @@ -24,7 +24,7 @@
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'


Expand All @@ -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')
13 changes: 12 additions & 1 deletion cinder/tests/test_backup.py
Expand Up @@ -77,7 +77,7 @@ def _create_backup_db_entry(self, volume_id=1, display_name='test_backup',
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']
Expand Down Expand Up @@ -407,3 +407,14 @@ def test_backup_get_all_by_host_with_deleted(self):
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)

0 comments on commit 2f5e26a

Please sign in to comment.