Merge "ceph backup support for EXCLUSIVE_LOCK and JOURNALING features"
This commit is contained in:
commit
7127e28507
@ -88,6 +88,9 @@ service_opts = [
|
||||
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.'),
|
||||
cfg.BoolOpt('backup_ceph_image_journals', default=False,
|
||||
help='If True, apply JOURNALING and EXCLUSIVE_LOCK feature '
|
||||
'bits to the backup RBD objects to allow mirroring'),
|
||||
cfg.BoolOpt('restore_discard_excess_bytes', default=True,
|
||||
help='If True, always discard excess bytes when restoring '
|
||||
'volumes i.e. pad with zeroes.')
|
||||
@ -222,6 +225,16 @@ class CephBackupDriver(driver.BackupDriver):
|
||||
"""Determine if striping is supported by our version of librbd."""
|
||||
return hasattr(self.rbd, 'RBD_FEATURE_STRIPINGV2')
|
||||
|
||||
@property
|
||||
def _supports_exclusive_lock(self):
|
||||
"""Determine if exclusive-lock is supported by librbd."""
|
||||
return hasattr(self.rbd, 'RBD_FEATURE_EXCLUSIVE_LOCK')
|
||||
|
||||
@property
|
||||
def _supports_journaling(self):
|
||||
"""Determine if journaling is supported by our version of librbd."""
|
||||
return hasattr(self.rbd, 'RBD_FEATURE_JOURNALING')
|
||||
|
||||
def _get_rbd_support(self):
|
||||
"""Determine RBD features supported by our version of librbd."""
|
||||
old_format = True
|
||||
@ -233,6 +246,25 @@ class CephBackupDriver(driver.BackupDriver):
|
||||
old_format = False
|
||||
features |= self.rbd.RBD_FEATURE_STRIPINGV2
|
||||
|
||||
# journaling requires exclusive_lock; check both together
|
||||
if CONF.backup_ceph_image_journals:
|
||||
if self._supports_exclusive_lock and self._supports_journaling:
|
||||
old_format = False
|
||||
features |= (self.rbd.RBD_FEATURE_EXCLUSIVE_LOCK |
|
||||
self.rbd.RBD_FEATURE_JOURNALING)
|
||||
else:
|
||||
# FIXME (tasker): when the backup manager supports loading the
|
||||
# driver during its initialization, this exception should be
|
||||
# moved to the driver's initialization so that it can stop
|
||||
# the service from starting when the underyling RBD does not
|
||||
# support the requested features.
|
||||
LOG.error(_LE("RBD journaling not supported - unable to "
|
||||
"support per image mirroring in backup pool"))
|
||||
raise exception.BackupInvalidCephArgs(
|
||||
_("Image Journaling set but RBD backend does "
|
||||
"not support journaling")
|
||||
)
|
||||
|
||||
return (old_format, features)
|
||||
|
||||
def _connect_to_rados(self, pool=None):
|
||||
|
@ -22,6 +22,7 @@ import uuid
|
||||
import mock
|
||||
from os_brick.initiator import linuxrbd
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import units
|
||||
import six
|
||||
@ -42,6 +43,8 @@ from cinder.tests.unit import fake_constants as fake
|
||||
# NOTE: this must be initialised in test setUp().
|
||||
RAISED_EXCEPTIONS = []
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class MockException(Exception):
|
||||
|
||||
@ -202,8 +205,13 @@ class BackupCephTestCase(test.TestCase):
|
||||
def test_get_rbd_support(self):
|
||||
del self.service.rbd.RBD_FEATURE_LAYERING
|
||||
del self.service.rbd.RBD_FEATURE_STRIPINGV2
|
||||
del self.service.rbd.RBD_FEATURE_EXCLUSIVE_LOCK
|
||||
del self.service.rbd.RBD_FEATURE_JOURNALING
|
||||
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_LAYERING'))
|
||||
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_STRIPINGV2'))
|
||||
self.assertFalse(hasattr(self.service.rbd,
|
||||
'RBD_FEATURE_EXCLUSIVE_LOCK'))
|
||||
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_JOURNALING'))
|
||||
|
||||
oldformat, features = self.service._get_rbd_support()
|
||||
self.assertTrue(oldformat)
|
||||
@ -221,6 +229,28 @@ class BackupCephTestCase(test.TestCase):
|
||||
self.assertFalse(oldformat)
|
||||
self.assertEqual(1 | 2, features)
|
||||
|
||||
# initially, backup_ceph_image_journals = False. test that
|
||||
# the flags are defined, but that they are not returned.
|
||||
self.service.rbd.RBD_FEATURE_EXCLUSIVE_LOCK = 4
|
||||
|
||||
oldformat, features = self.service._get_rbd_support()
|
||||
self.assertFalse(oldformat)
|
||||
self.assertEqual(1 | 2, features)
|
||||
|
||||
self.service.rbd.RBD_FEATURE_JOURNALING = 64
|
||||
|
||||
oldformat, features = self.service._get_rbd_support()
|
||||
self.assertFalse(oldformat)
|
||||
self.assertEqual(1 | 2, features)
|
||||
|
||||
# test that the config setting properly sets the FEATURE bits.
|
||||
# because journaling requires exclusive-lock, these are set
|
||||
# at the same time.
|
||||
CONF.set_override("backup_ceph_image_journals", True)
|
||||
oldformat, features = self.service._get_rbd_support()
|
||||
self.assertFalse(oldformat)
|
||||
self.assertEqual(1 | 2 | 4 | 64, features)
|
||||
|
||||
@common_mocks
|
||||
def test_get_most_recent_snap(self):
|
||||
last = 'backup.%s.snap.9824923.1212' % (uuid.uuid4())
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Added new BoolOpt ``backup_ceph_image_journals`` for enabling the Ceph
|
||||
image features required to support RBD mirroring of Cinder backup pool.
|
Loading…
x
Reference in New Issue
Block a user