Ceph backup driver tidyup

Fixed typos and cleaned up log messages and docstrings.

Closes-Bug: 1276969
Change-Id: Idb1ba4f3315edb76fefc993b38b0590b4794345b
This commit is contained in:
Edward Hope-Morley 2014-02-06 11:06:02 +00:00
parent baedbeb629
commit ab937afadf
2 changed files with 114 additions and 107 deletions

View File

@ -15,12 +15,12 @@
"""Ceph Backup Service Implementation.
This driver supports backing up volumes of any type to a Ceph backend store. It
This driver supports backing up volumes of any type to a Ceph object store. It
is also capable of detecting whether the volume to be backed up is a Ceph RBD
volume and if so, attempts to perform incremental/differential backups.
volume and, if so, attempts to perform incremental/differential backups.
Support is also included for the following in the case of source volume being a
Ceph RBD volume:
Support is also included for the following in the case of a source volume being
a Ceph RBD volume:
* backing up within the same Ceph pool (not recommended)
* backing up between different Ceph pools
@ -28,10 +28,11 @@ Ceph RBD volume:
At the time of writing, differential backup support in Ceph/librbd was quite
new so this driver accounts for this by first attempting differential backup
and falling back to full backup/copy if the former fails.
and falling back to full backup/copy if the former fails. It is recommended
that you upgrade to Ceph Dumpling (>= v0.67) or above to get the best results.
If incremental backups are used, multiple backups of the same volume are stored
as snapshots so that minimal space is consumed in the backup store and
as snapshots so that minimal space is consumed in the object store and
restoring the volume takes a far reduced amount of time compared to a full
copy.
@ -41,18 +42,19 @@ was deemed the safest action to take. It is therefore recommended to always
restore to a new volume (default).
"""
import eventlet
import fcntl
import os
import re
import subprocess
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.openstack.common import strutils
from cinder import units
from cinder import utils
import cinder.volume.drivers.rbd as rbd_driver
@ -68,21 +70,23 @@ LOG = logging.getLogger(__name__)
service_opts = [
cfg.StrOpt('backup_ceph_conf', default='/etc/ceph/ceph.conf',
help='Ceph config file to use.'),
help='Ceph configuration file to use.'),
cfg.StrOpt('backup_ceph_user', default='cinder',
help='the Ceph user to connect with'),
help='The Ceph user to connect with. Default here is to use '
'the same user as for Cinder volumes. If not using cephx '
'this should be set to None.'),
cfg.IntOpt('backup_ceph_chunk_size', default=(units.MiB * 128),
help='the chunk size in bytes that a backup will be broken '
'into before transfer to backup store'),
help='The chunk size, in bytes, that a backup is broken into '
'before transfer to the Ceph object store.'),
cfg.StrOpt('backup_ceph_pool', default='backups',
help='the Ceph pool to backup to'),
help='The Ceph pool where volume backups are stored.'),
cfg.IntOpt('backup_ceph_stripe_unit', default=0,
help='RBD stripe unit to use when creating a backup image'),
help='RBD stripe unit to use when creating a backup image.'),
cfg.IntOpt('backup_ceph_stripe_count', default=0,
help='RBD stripe count to use when creating a backup image'),
help='RBD stripe count to use when creating a backup image.'),
cfg.BoolOpt('restore_discard_excess_bytes', default=True,
help='If True, always discard excess bytes when restoring '
'volumes.')
'volumes i.e. pad with zeroes.')
]
CONF = cfg.CONF
@ -90,11 +94,11 @@ CONF.register_opts(service_opts)
class CephBackupDriver(BackupDriver):
"""Backup up Cinder volumes to Ceph Object Store.
"""Backup Cinder volumes to Ceph Object Store.
This class enables backing up Cinder volumes to a Ceph object store.
Backups may be stored in their own pool or even cluster. Store location is
defined by the Ceph conf file and Service config options supplied.
defined by the Ceph conf file and service config options supplied.
If the source volume is itself an RBD volume, the backup will be performed
using incremental differential backups which *should* give a performance
@ -113,22 +117,14 @@ class CephBackupDriver(BackupDriver):
self.rbd_stripe_unit = CONF.backup_ceph_stripe_unit
self.rbd_stripe_count = CONF.backup_ceph_stripe_count
else:
LOG.info(_("rbd striping not supported - ignoring configuration "
LOG.info(_("RBD striping not supported - ignoring configuration "
"settings for rbd striping"))
self.rbd_stripe_count = 0
self.rbd_stripe_unit = 0
self._ceph_backup_user = self._utf8(CONF.backup_ceph_user)
self._ceph_backup_pool = self._utf8(CONF.backup_ceph_pool)
self._ceph_backup_conf = self._utf8(CONF.backup_ceph_conf)
@staticmethod
def _utf8(s):
"""Ensure string s is utf8 (i.e. not unicode)."""
if isinstance(s, str):
return s
return s.encode('utf8')
self._ceph_backup_user = strutils.safe_encode(CONF.backup_ceph_user)
self._ceph_backup_pool = strutils.safe_encode(CONF.backup_ceph_pool)
self._ceph_backup_conf = strutils.safe_encode(CONF.backup_ceph_conf)
def _validate_string_args(self, *args):
"""Ensure all args are non-None and non-empty."""
@ -184,7 +180,7 @@ class CephBackupDriver(BackupDriver):
conffile=self._ceph_backup_conf)
try:
client.connect()
pool_to_open = self._utf8(pool or self._ceph_backup_pool)
pool_to_open = strutils.safe_encode(pool or self._ceph_backup_pool)
ioctx = client.open_ioctx(pool_to_open)
return client, ioctx
except self.rados.Error:
@ -207,12 +203,13 @@ class CephBackupDriver(BackupDriver):
"""
# Ensure no unicode
if diff_format:
return self._utf8("volume-%s.backup.base" % (volume_id))
return strutils.safe_encode("volume-%s.backup.base" % (volume_id))
else:
if backup_id is None:
msg = _("backup_id required")
msg = _("Backup id required")
raise exception.InvalidParameterValue(msg)
return self._utf8("volume-%s.backup.%s" % (volume_id, backup_id))
return strutils.safe_encode("volume-%s.backup.%s" %
(volume_id, backup_id))
def _discard_bytes(self, volume, offset, length):
"""Trim length bytes from offset.
@ -221,7 +218,7 @@ class CephBackupDriver(BackupDriver):
and pad with zeroes.
"""
if length:
LOG.debug(_("discarding %(length)s bytes from offset %(offset)s") %
LOG.debug(_("Discarding %(length)s bytes from offset %(offset)s") %
{'length': length, 'offset': offset})
if self._file_is_rbd(volume):
volume.rbd_image.discard(offset, length)
@ -229,7 +226,7 @@ class CephBackupDriver(BackupDriver):
zeroes = '\0' * length
chunks = int(length / self.chunk_size)
for chunk in xrange(0, chunks):
LOG.debug(_("writing zeroes chunk %d") % (chunk))
LOG.debug(_("Writing zeroes chunk %d") % (chunk))
volume.write(zeroes)
volume.flush()
# yield to any other pending backups
@ -243,7 +240,7 @@ class CephBackupDriver(BackupDriver):
def _transfer_data(self, src, src_name, dest, dest_name, length):
"""Transfer data between files (Python IO objects)."""
LOG.debug(_("transferring data between '%(src)s' and '%(dest)s'") %
LOG.debug(_("Transferring data between '%(src)s' and '%(dest)s'") %
{'src': src_name, 'dest': dest_name})
chunks = int(length / self.chunk_size)
@ -266,7 +263,7 @@ class CephBackupDriver(BackupDriver):
dest.flush()
delta = (time.time() - before)
rate = (self.chunk_size / delta) / 1024
LOG.debug((_("transferred chunk %(chunk)s of %(chunks)s "
LOG.debug((_("Transferred chunk %(chunk)s of %(chunks)s "
"(%(rate)dK/s)") %
{'chunk': chunk + 1, 'chunks': chunks,
'rate': rate}))
@ -276,7 +273,7 @@ class CephBackupDriver(BackupDriver):
rem = int(length % self.chunk_size)
if rem:
LOG.debug(_("transferring remaining %s bytes") % (rem))
LOG.debug(_("Transferring remaining %s bytes") % (rem))
data = src.read(rem)
if data == '':
if CONF.restore_discard_excess_bytes:
@ -292,7 +289,7 @@ class CephBackupDriver(BackupDriver):
This will be the base image used for storing differential exports.
"""
LOG.debug(_("creating base image '%s'") % (name))
LOG.debug(_("Creating base image '%s'") % (name))
old_format, features = self._get_rbd_support()
self.rbd.RBD().create(ioctx=rados_client.ioctx,
name=name,
@ -319,10 +316,10 @@ class CephBackupDriver(BackupDriver):
snap_name = self._get_backup_snap_name(base_rbd, base_name,
backup_id)
if snap_name:
LOG.debug(_("deleting backup snapshot='%s'") % (snap_name))
LOG.debug(_("Deleting backup snapshot='%s'") % (snap_name))
base_rbd.remove_snap(snap_name)
else:
LOG.debug(_("no backup snapshot to delete"))
LOG.debug(_("No backup snapshot to delete"))
# Now check whether any snapshots remain on the base image
backup_snaps = self.get_backup_snaps(base_rbd)
@ -358,7 +355,7 @@ class CephBackupDriver(BackupDriver):
try_diff_format = True
base_name = self._get_backup_base_name(volume_id, backup_id)
LOG.debug(_("trying diff format name format basename='%s'") %
LOG.debug(_("Trying diff format name format basename='%s'") %
(base_name))
with rbd_driver.RADOSClient(self) as client:
@ -374,27 +371,27 @@ class CephBackupDriver(BackupDriver):
snap, rem = self._delete_backup_snapshot(client, base_name,
backup_id)
if rem:
msg = (_("base image still has %s snapshots so skipping "
msg = (_("Base image still has %s snapshots so skipping "
"base image delete") % (rem))
LOG.info(msg)
return
LOG.info(_("deleting base image='%s'") % (base_name))
LOG.info(_("Deleting base image='%s'") % (base_name))
# Delete base if no more snapshots
try:
self.rbd.RBD().remove(client.ioctx, base_name)
except self.rbd.ImageBusy as exc:
# Allow a retry if the image is busy
if retries > 0:
LOG.info((_("image busy, retrying %(retries)s "
LOG.info((_("Image busy, retrying %(retries)s "
"more time(s) in %(delay)ss") %
{'retries': retries, 'delay': delay}))
eventlet.sleep(delay)
else:
LOG.error(_("max retries reached - raising error"))
LOG.error(_("Max retries reached - raising error"))
raise exc
else:
LOG.debug(_("base backup image='%s' deleted)") %
LOG.debug(_("Base backup image='%s' deleted)") %
(base_name))
retries = 0
finally:
@ -402,9 +399,9 @@ class CephBackupDriver(BackupDriver):
# Since we have deleted the base image we can delete the source
# volume backup snapshot.
src_name = self._utf8(volume_id)
src_name = strutils.safe_encode(volume_id)
if src_name in self.rbd.RBD().list(client.ioctx):
LOG.debug(_("deleting source snap '%s'") % snap)
LOG.debug(_("Deleting source snapshot '%s'") % snap)
src_rbd = self.rbd.Image(client.ioctx, src_name)
try:
src_rbd.remove_snap(snap)
@ -413,14 +410,14 @@ class CephBackupDriver(BackupDriver):
def _piped_execute(self, cmd1, cmd2):
"""Pipe output of cmd1 into cmd2."""
LOG.debug("piping cmd1='%s' into..." % (' '.join(cmd1)))
LOG.debug("Piping cmd1='%s' into..." % (' '.join(cmd1)))
LOG.debug("cmd2='%s'" % (' '.join(cmd2)))
try:
p1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as e:
LOG.error("pipe1 failed - %s " % unicode(e))
LOG.error("Pipe1 failed - %s " % unicode(e))
raise
# NOTE(dosaboy): ensure that the pipe is blocking. This is to work
@ -434,7 +431,7 @@ class CephBackupDriver(BackupDriver):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as e:
LOG.error("pipe2 failed - %s " % unicode(e))
LOG.error("Pipe2 failed - %s " % unicode(e))
raise
p1.stdout.close()
@ -450,7 +447,7 @@ class CephBackupDriver(BackupDriver):
since the rbd volume/base was created, otherwise it will be those
changed since the snapshot was created.
"""
LOG.debug(_("performing differential transfer from '%(src)s' to "
LOG.debug(_("Performing differential transfer from '%(src)s' to "
"'%(dest)s'") %
{'src': src_name, 'dest': dest_name})
@ -465,17 +462,20 @@ class CephBackupDriver(BackupDriver):
if from_snap is not None:
cmd1.extend(['--from-snap', from_snap])
if src_snap:
path = self._utf8("%s/%s@%s" % (src_pool, src_name, src_snap))
path = strutils.safe_encode("%s/%s@%s" %
(src_pool, src_name, src_snap))
else:
path = self._utf8("%s/%s" % (src_pool, src_name))
path = strutils.safe_encode("%s/%s" % (src_pool, src_name))
cmd1.extend([path, '-'])
cmd2 = ['rbd', 'import-diff'] + dest_ceph_args
cmd2.extend(['-', self._utf8("%s/%s" % (dest_pool, dest_name))])
rbd_path = strutils.safe_encode("%s/%s" % (dest_pool, dest_name))
cmd2.extend(['-', rbd_path])
ret, stderr = self._piped_execute(cmd1, cmd2)
if ret:
msg = (_("rbd diff op failed - (ret=%(ret)s stderr=%(stderr)s)") %
msg = (_("RBD diff op failed - (ret=%(ret)s stderr=%(stderr)s)") %
({'ret': ret, 'stderr': stderr}))
LOG.info(msg)
raise exception.BackupRBDOperationFailed(msg)
@ -485,12 +485,12 @@ class CephBackupDriver(BackupDriver):
"""Return tuple (exists, name)."""
rbds = self.rbd.RBD().list(client.ioctx)
if name not in rbds:
msg = _("image '%s' not found - trying diff format name") % (name)
msg = _("Image '%s' not found - trying diff format name") % (name)
LOG.debug(msg)
if try_diff_format:
name = self._get_backup_base_name(volume_id, diff_format=True)
if name not in rbds:
msg = _("diff format image '%s' not found") % (name)
msg = _("Diff format image '%s' not found") % (name)
LOG.debug(msg)
return False, name
else:
@ -525,7 +525,7 @@ class CephBackupDriver(BackupDriver):
# Identify our --from-snap point (if one exists)
from_snap = self._get_most_recent_snap(source_rbd_image)
LOG.debug(_("using --from-snap '%s'") % from_snap)
LOG.debug(_("Using --from-snap '%s'") % from_snap)
base_name = self._get_backup_base_name(volume_id, diff_format=True)
image_created = False
@ -540,7 +540,7 @@ class CephBackupDriver(BackupDriver):
# If a from_snap is defined but the base does not exist, we
# ignore it since it is stale and waiting to be cleaned up.
if from_snap:
LOG.debug(_("source snap '%s' is stale so deleting") %
LOG.debug(_("Source snapshot '%s' is stale so deleting") %
(from_snap))
source_rbd_image.remove_snap(from_snap)
from_snap = None
@ -552,7 +552,7 @@ class CephBackupDriver(BackupDriver):
# If a from_snap is defined but does not exist in the back base
# then we cannot proceed (see above)
if not self._snap_exists(base_name, from_snap, client):
errmsg = (_("snap='%(snap)s' does not exist in base "
errmsg = (_("Snapshot='%(snap)s' does not exist in base "
"image='%(base)s' - aborting incremental "
"backup") %
{'snap': from_snap, 'base': base_name})
@ -563,7 +563,7 @@ class CephBackupDriver(BackupDriver):
# Snapshot source volume so that we have a new point-in-time
new_snap = self._get_new_snap_name(backup_id)
LOG.debug(_("creating backup snapshot='%s'") % (new_snap))
LOG.debug(_("Creating backup snapshot='%s'") % (new_snap))
source_rbd_image.create_snap(new_snap)
# Attempt differential backup. If this fails, perhaps because librbd
@ -583,7 +583,7 @@ class CephBackupDriver(BackupDriver):
src_snap=new_snap,
from_snap=from_snap)
LOG.debug(_("differential backup transfer completed in %.4fs") %
LOG.debug(_("Differential backup transfer completed in %.4fs") %
(time.time() - before))
# We don't need the previous snapshot (if there was one) anymore so
@ -592,7 +592,7 @@ class CephBackupDriver(BackupDriver):
source_rbd_image.remove_snap(from_snap)
except exception.BackupRBDOperationFailed:
LOG.debug(_("differential backup transfer failed"))
LOG.debug(_("Differential backup transfer failed"))
# Clean up if image was created as part of this operation
if image_created:
@ -600,7 +600,7 @@ class CephBackupDriver(BackupDriver):
base_name=base_name)
# Delete snapshot
LOG.debug(_("deleting backup snapshot='%s'") % (new_snap))
LOG.debug(_("Deleting backup snapshot='%s'") % (new_snap))
source_rbd_image.remove_snap(new_snap)
# Re-raise the exception so that caller can try another approach
@ -622,7 +622,7 @@ class CephBackupDriver(BackupDriver):
with rbd_driver.RADOSClient(self, self._ceph_backup_pool) as client:
# First create base backup image
old_format, features = self._get_rbd_support()
LOG.debug(_("creating base image='%s'") % (backup_name))
LOG.debug(_("Creating base image='%s'") % (backup_name))
self.rbd.RBD().create(ioctx=client.ioctx,
name=backup_name,
size=length,
@ -631,7 +631,7 @@ class CephBackupDriver(BackupDriver):
stripe_unit=self.rbd_stripe_unit,
stripe_count=self.rbd_stripe_count)
LOG.debug(_("copying data"))
LOG.debug(_("Copying data"))
dest_rbd = self.rbd.Image(client.ioctx, backup_name)
try:
rbd_meta = rbd_driver.RBDImageMetadata(dest_rbd,
@ -678,7 +678,8 @@ class CephBackupDriver(BackupDriver):
return backup_snaps
def _get_new_snap_name(self, backup_id):
return self._utf8("backup.%s.snap.%s" % (backup_id, time.time()))
return strutils.safe_encode("backup.%s.snap.%s" %
(backup_id, time.time()))
def _get_backup_snap_name(self, rbd_image, name, backup_id):
"""Return the name of the snapshot associated with backup_id.
@ -691,26 +692,26 @@ class CephBackupDriver(BackupDriver):
"""
snaps = self.get_backup_snaps(rbd_image)
LOG.debug(_("looking for snapshot of backup base '%s'") % (name))
LOG.debug(_("Looking for snapshot of backup base '%s'") % (name))
if not snaps:
LOG.debug(_("backup base '%s' has no snapshots") % (name))
LOG.debug(_("Backup base '%s' has no snapshots") % (name))
return None
snaps = [snap['name'] for snap in snaps
if snap['backup_id'] == backup_id]
if not snaps:
LOG.debug(_("backup '%s' has no snapshot") % (backup_id))
LOG.debug(_("Backup '%s' has no snapshot") % (backup_id))
return None
if len(snaps) > 1:
msg = (_("backup should only have one snapshot but instead has %s")
msg = (_("Backup should only have one snapshot but instead has %s")
% (len(snaps)))
LOG.error(msg)
raise exception.BackupOperationError(msg)
LOG.debug(_("found snapshot '%s'") % (snaps[0]))
LOG.debug(_("Found snapshot '%s'") % (snaps[0]))
return snaps[0]
def _get_most_recent_snap(self, rbd_image):
@ -731,7 +732,7 @@ class CephBackupDriver(BackupDriver):
Raises exception.InvalidParameterValue if volume size is 0.
"""
if int(volume['size']) == 0:
errmsg = _("need non-zero volume size")
errmsg = _("Need non-zero volume size")
raise exception.InvalidParameterValue(errmsg)
return int(volume['size']) * units.GiB
@ -761,7 +762,7 @@ class CephBackupDriver(BackupDriver):
self._backup_rbd(backup_id, volume_id, volume_file,
volume_name, length)
except exception.BackupRBDOperationFailed:
LOG.debug(_("forcing full backup"))
LOG.debug(_("Forcing full backup"))
do_full_backup = True
else:
do_full_backup = True
@ -773,7 +774,7 @@ class CephBackupDriver(BackupDriver):
self.db.backup_update(self.context, backup_id,
{'container': self._ceph_backup_pool})
LOG.debug(_("backup '%s' finished.") % (backup_id))
LOG.debug(_("Backup '%s' finished.") % (backup_id))
def _full_restore(self, backup_id, volume_id, dest_file, dest_name,
length, src_snap=None):
@ -818,7 +819,8 @@ class CephBackupDriver(BackupDriver):
"""
with rbd_driver.RADOSClient(self, self._ceph_backup_pool) as client:
adjust_size = 0
base_image = self.rbd.Image(client.ioctx, self._utf8(backup_base),
base_image = self.rbd.Image(client.ioctx,
strutils.safe_encode(backup_base),
read_only=True)
try:
if restore_length != base_image.size():
@ -829,9 +831,9 @@ class CephBackupDriver(BackupDriver):
if adjust_size:
with rbd_driver.RADOSClient(self, src_pool) as client:
dest_image = self.rbd.Image(client.ioctx,
self._utf8(restore_vol))
strutils.safe_encode(restore_vol))
try:
LOG.debug(_("adjusting restore vol size"))
LOG.debug(_("Adjusting restore vol size"))
dest_image.resize(adjust_size)
finally:
dest_image.close()
@ -843,7 +845,7 @@ class CephBackupDriver(BackupDriver):
rbd_pool = restore_file.rbd_pool
rbd_conf = restore_file.rbd_conf
LOG.debug(_("trying incremental restore from base='%(base)s' "
LOG.debug(_("Attempting incremental restore from base='%(base)s' "
"snap='%(snap)s'") %
{'base': base_name, 'snap': restore_point})
before = time.time()
@ -855,7 +857,7 @@ class CephBackupDriver(BackupDriver):
dest_user=rbd_user, dest_conf=rbd_conf,
src_snap=restore_point)
except exception.BackupRBDOperationFailed:
LOG.exception(_("differential restore failed, trying full "
LOG.exception(_("Differential restore failed, trying full "
"restore"))
raise
@ -866,7 +868,7 @@ class CephBackupDriver(BackupDriver):
self._check_restore_vol_size(base_name, restore_name, restore_length,
rbd_pool)
LOG.debug(_("restore transfer completed in %.4fs") %
LOG.debug(_("Restore transfer completed in %.4fs") %
(time.time() - before))
def _num_backup_snaps(self, backup_base_name):
@ -887,7 +889,9 @@ class CephBackupDriver(BackupDriver):
def _get_restore_point(self, base_name, backup_id):
"""Get restore point snapshot name for incremental backup.
If the backup was not incremental None is returned.
If the backup was not incremental (determined by the fact that the
base has no snapshots/restore points), None is returned. Otherwise, the
restore point associated with backup_id is returned.
"""
with rbd_driver.RADOSClient(self, self._ceph_backup_pool) as client:
base_rbd = self.rbd.Image(client.ioctx, base_name, read_only=True)
@ -913,7 +917,7 @@ class CephBackupDriver(BackupDriver):
rbd_volume.diff_iterate(0, rbd_volume.size(), None, iter_cb)
if extents:
LOG.debug(_("rbd has %s extents") % (sum(extents)))
LOG.debug(_("RBD has %s extents") % (sum(extents)))
return True
return False
@ -956,12 +960,12 @@ class CephBackupDriver(BackupDriver):
if self._rbd_has_extents(volume_file.rbd_image):
# We return the restore point so that a full copy is done
# from snapshot.
LOG.debug(_("destination has extents - forcing full copy"))
LOG.debug(_("Destination has extents - forcing full copy"))
return False, restore_point
return True, restore_point
else:
LOG.info(_("no restore point found for backup='%s', forcing "
LOG.info(_("No restore point found for backup='%s', forcing "
"full copy") % (backup['id']))
return not_allowed
@ -992,7 +996,7 @@ class CephBackupDriver(BackupDriver):
restore_point, length)
do_full_restore = False
except exception.BackupRBDOperationFailed:
LOG.debug(_("forcing full restore"))
LOG.debug(_("Forcing full restore"))
if do_full_restore:
# Otherwise full copy
@ -1002,7 +1006,7 @@ class CephBackupDriver(BackupDriver):
def restore(self, backup, volume_id, volume_file):
"""Restore the given volume backup from Ceph object store."""
target_volume = self.db.volume_get(self.context, volume_id)
LOG.debug(_('starting restore from Ceph backup=%(src)s to '
LOG.debug(_('Starting restore from Ceph backup=%(src)s to '
'volume=%(dest)s') %
{'src': backup['id'], 'dest': target_volume['name']})
@ -1013,30 +1017,30 @@ class CephBackupDriver(BackupDriver):
try:
fileno = volume_file.fileno()
except IOError:
LOG.info(_("volume_file does not support fileno() so skipping "
"fsync()"))
LOG.debug(_("Volume_file does not support fileno() so "
"skipping fsync()"))
else:
os.fsync(fileno)
LOG.debug(_('restore finished successfully.'))
LOG.debug(_('Restore finished successfully.'))
except exception.BackupOperationError as e:
LOG.error(_('restore finished with error - %s') % (e))
LOG.error(_('Restore finished with error - %s') % (e))
raise
def delete(self, backup):
"""Delete the given backup from Ceph object store."""
backup_id = backup['id']
LOG.debug(_('delete started for backup=%s') % backup['id'])
LOG.debug(_('Delete started for backup=%s') % backup['id'])
try:
self._try_delete_base_image(backup['id'], backup['volume_id'])
except self.rbd.ImageNotFound:
msg = _("rbd image not found but continuing anyway so "
msg = _("RBD image not found but continuing anyway so "
"that db entry can be removed")
LOG.warning(msg)
LOG.info(_("delete '%s' finished with warning") % (backup_id))
LOG.info(_("Delete '%s' finished with warning") % (backup_id))
else:
LOG.debug(_("delete '%s' finished") % (backup_id))
LOG.debug(_("Delete '%s' finished") % (backup_id))
def get_backup_driver(context):

View File

@ -145,29 +145,32 @@
# Options defined in cinder.backup.drivers.ceph
#
# Ceph config file to use. (string value)
# Ceph configuration file to use. (string value)
#backup_ceph_conf=/etc/ceph/ceph.conf
# the Ceph user to connect with (string value)
# The Ceph user to connect with. Default here is to use the
# same user as for Cinder volumes. If not using cephx this
# should be set to None. (string value)
#backup_ceph_user=cinder
# the chunk size in bytes that a backup will be broken into
# before transfer to backup store (integer value)
# The chunk size, in bytes, that a backup is broken into
# before transfer to the Ceph object store. (integer value)
#backup_ceph_chunk_size=134217728
# the Ceph pool to backup to (string value)
# The Ceph pool where volume backups are stored. (string
# value)
#backup_ceph_pool=backups
# RBD stripe unit to use when creating a backup image (integer
# value)
# RBD stripe unit to use when creating a backup image.
# (integer value)
#backup_ceph_stripe_unit=0
# RBD stripe count to use when creating a backup image
# RBD stripe count to use when creating a backup image.
# (integer value)
#backup_ceph_stripe_count=0
# If True, always discard excess bytes when restoring volumes.
# (boolean value)
# If True, always discard excess bytes when restoring volumes
# i.e. pad with zeroes. (boolean value)
#restore_discard_excess_bytes=true