f4058ea217
Change-Id: I805ff6a68925f9214645c192eb986a70f30bf714
623 lines
23 KiB
Python
623 lines
23 KiB
Python
# Copyright 2013 Canonical Ltd.
|
|
# 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.
|
|
""" Tests for Ceph backup service """
|
|
|
|
import hashlib
|
|
import os
|
|
import tempfile
|
|
import time
|
|
import uuid
|
|
|
|
import eventlet
|
|
|
|
from cinder.backup.drivers import ceph
|
|
from cinder import context
|
|
from cinder import db
|
|
from cinder import exception
|
|
from cinder.openstack.common import log as logging
|
|
from cinder.openstack.common import processutils
|
|
from cinder import test
|
|
from cinder.tests.backup.fake_rados import mock_rados
|
|
from cinder.tests.backup.fake_rados import mock_rbd
|
|
from cinder import units
|
|
from cinder.volume.drivers import rbd as rbddriver
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class BackupCephTestCase(test.TestCase):
|
|
"""Test Case for backup to Ceph object store"""
|
|
|
|
def _create_volume_db_entry(self, id, size):
|
|
vol = {'id': id, 'size': size, 'status': 'available'}
|
|
return db.volume_create(self.ctxt, vol)['id']
|
|
|
|
def _create_backup_db_entry(self, backupid, volid, size):
|
|
backup = {'id': backupid, 'size': size, 'volume_id': volid}
|
|
return db.backup_create(self.ctxt, backup)['id']
|
|
|
|
def fake_execute_w_exception(*args, **kwargs):
|
|
raise processutils.ProcessExecutionError()
|
|
|
|
def time_inc(self):
|
|
self.counter += 1
|
|
return self.counter
|
|
|
|
def _get_wrapped_rbd_io(self, rbd_image):
|
|
rbd_meta = rbddriver.RBDImageMetadata(rbd_image, 'pool_foo',
|
|
'user_foo', 'conf_foo')
|
|
return rbddriver.RBDImageIOWrapper(rbd_meta)
|
|
|
|
def setUp(self):
|
|
super(BackupCephTestCase, self).setUp()
|
|
self.ctxt = context.get_admin_context()
|
|
|
|
self.volume_id = str(uuid.uuid4())
|
|
self.backup_id = str(uuid.uuid4())
|
|
|
|
# Setup librbd stubs
|
|
self.stubs.Set(ceph, 'rados', mock_rados)
|
|
self.stubs.Set(ceph, 'rbd', mock_rbd)
|
|
|
|
self._create_backup_db_entry(self.backup_id, self.volume_id, 1)
|
|
|
|
self.chunk_size = 1024
|
|
self.num_chunks = 128
|
|
self.length = self.num_chunks * self.chunk_size
|
|
|
|
self.checksum = hashlib.sha256()
|
|
|
|
# Create a file with some data in it
|
|
self.volume_file = tempfile.NamedTemporaryFile()
|
|
for i in xrange(0, self.num_chunks):
|
|
data = os.urandom(self.chunk_size)
|
|
self.checksum.update(data)
|
|
self.volume_file.write(data)
|
|
|
|
self.volume_file.seek(0)
|
|
|
|
# Always trigger an exception if a command is executed since it should
|
|
# always be dealt with gracefully. At time of writing on rbd
|
|
# export/import-diff is executed and if they fail we expect to find
|
|
# alternative means of backing up.
|
|
fake_exec = self.fake_execute_w_exception
|
|
self.service = ceph.CephBackupDriver(self.ctxt, execute=fake_exec)
|
|
|
|
# Ensure that time.time() always returns more than the last time it was
|
|
# called to avoid div by zero errors.
|
|
self.counter = float(0)
|
|
self.stubs.Set(time, 'time', self.time_inc)
|
|
self.stubs.Set(eventlet, 'sleep', lambda *args: None)
|
|
|
|
def test_get_rbd_support(self):
|
|
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_LAYERING'))
|
|
self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_STRIPINGV2'))
|
|
|
|
oldformat, features = self.service._get_rbd_support()
|
|
self.assertTrue(oldformat)
|
|
self.assertEqual(features, 0)
|
|
|
|
self.service.rbd.RBD_FEATURE_LAYERING = 1
|
|
|
|
oldformat, features = self.service._get_rbd_support()
|
|
self.assertFalse(oldformat)
|
|
self.assertEqual(features, 1)
|
|
|
|
self.service.rbd.RBD_FEATURE_STRIPINGV2 = 2
|
|
|
|
oldformat, features = self.service._get_rbd_support()
|
|
self.assertFalse(oldformat)
|
|
self.assertEqual(features, 1 | 2)
|
|
|
|
def _set_common_backup_stubs(self, service):
|
|
self.stubs.Set(self.service, '_get_rbd_support', lambda: (True, 3))
|
|
self.stubs.Set(self.service, 'get_backup_snaps',
|
|
lambda *args, **kwargs: None)
|
|
|
|
def rbd_size(inst):
|
|
return self.chunk_size * self.num_chunks
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'size', rbd_size)
|
|
|
|
def _set_common_restore_stubs(self, service):
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
def rbd_size(inst):
|
|
return self.chunk_size * self.num_chunks
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'size', rbd_size)
|
|
|
|
def test_get_most_recent_snap(self):
|
|
last = 'backup.%s.snap.9824923.1212' % (uuid.uuid4())
|
|
|
|
def list_snaps(inst, *args):
|
|
return [{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4())},
|
|
{'name': 'backup.%s.snap.1321319.3235' % (uuid.uuid4())},
|
|
{'name': last},
|
|
{'name': 'backup.%s.snap.3824923.1412' % (uuid.uuid4())}]
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'list_snaps', list_snaps)
|
|
|
|
snap = self.service._get_most_recent_snap(self.service.rbd.Image())
|
|
|
|
self.assertEqual(last, snap)
|
|
|
|
def test_get_backup_snap_name(self):
|
|
snap_name = 'backup.%s.snap.3824923.1412' % (uuid.uuid4())
|
|
|
|
def mock_get_backup_snaps(inst, *args):
|
|
return [{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4()),
|
|
'backup_id': str(uuid.uuid4())},
|
|
{'name': snap_name,
|
|
'backup_id': self.backup_id}]
|
|
|
|
self.stubs.Set(self.service, 'get_backup_snaps', lambda *args: None)
|
|
name = self.service._get_backup_snap_name(self.service.rbd.Image(),
|
|
'base_foo',
|
|
self.backup_id)
|
|
self.assertIsNone(name)
|
|
|
|
self.stubs.Set(self.service, 'get_backup_snaps', mock_get_backup_snaps)
|
|
name = self.service._get_backup_snap_name(self.service.rbd.Image(),
|
|
'base_foo',
|
|
self.backup_id)
|
|
self.assertEqual(name, snap_name)
|
|
|
|
def test_get_backup_snaps(self):
|
|
|
|
def list_snaps(inst, *args):
|
|
return [{'name': 'backup.%s.snap.6423868.2342' % (uuid.uuid4())},
|
|
{'name': 'backup.%s.wambam.6423868.2342' % (uuid.uuid4())},
|
|
{'name': 'backup.%s.snap.1321319.3235' % (uuid.uuid4())},
|
|
{'name': 'bbbackup.%s.snap.1321319.3235' % (uuid.uuid4())},
|
|
{'name': 'backup.%s.snap.3824923.1412' % (uuid.uuid4())}]
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'list_snaps', list_snaps)
|
|
snaps = self.service.get_backup_snaps(self.service.rbd.Image())
|
|
self.assertTrue(len(snaps) == 3)
|
|
|
|
def test_transfer_data_from_rbd_to_file(self):
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
self.volume_file.seek(0)
|
|
|
|
def read_data(inst, offset, length):
|
|
return self.volume_file.read(self.length)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'read', read_data)
|
|
|
|
rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image())
|
|
self.service._transfer_data(rbd_io, 'src_foo', test_file,
|
|
'dest_foo', self.length)
|
|
|
|
checksum = hashlib.sha256()
|
|
test_file.seek(0)
|
|
for c in xrange(0, self.num_chunks):
|
|
checksum.update(test_file.read(self.chunk_size))
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_transfer_data_from_rbd_to_rbd(self):
|
|
def rbd_size(inst):
|
|
return self.chunk_size * self.num_chunks
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
self.volume_file.seek(0)
|
|
checksum = hashlib.sha256()
|
|
|
|
def read_data(inst, offset, length):
|
|
return self.volume_file.read(self.length)
|
|
|
|
def write_data(inst, data, offset):
|
|
checksum.update(data)
|
|
test_file.write(data)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'read', read_data)
|
|
self.stubs.Set(self.service.rbd.Image, 'size', rbd_size)
|
|
self.stubs.Set(self.service.rbd.Image, 'write', write_data)
|
|
|
|
rbd1 = self.service.rbd.Image()
|
|
rbd2 = self.service.rbd.Image()
|
|
|
|
src_rbd_io = self._get_wrapped_rbd_io(rbd1)
|
|
dest_rbd_io = self._get_wrapped_rbd_io(rbd2)
|
|
self.service._transfer_data(src_rbd_io, 'src_foo', dest_rbd_io,
|
|
'dest_foo', self.length)
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_transfer_data_from_file_to_rbd(self):
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
self.volume_file.seek(0)
|
|
checksum = hashlib.sha256()
|
|
|
|
def write_data(inst, data, offset):
|
|
checksum.update(data)
|
|
test_file.write(data)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'write', write_data)
|
|
|
|
rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image())
|
|
self.service._transfer_data(self.volume_file, 'src_foo',
|
|
rbd_io, 'dest_foo', self.length)
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_transfer_data_from_file_to_file(self):
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
self.volume_file.seek(0)
|
|
checksum = hashlib.sha256()
|
|
|
|
self.service._transfer_data(self.volume_file, 'src_foo', test_file,
|
|
'dest_foo', self.length)
|
|
|
|
checksum = hashlib.sha256()
|
|
test_file.seek(0)
|
|
for c in xrange(0, self.num_chunks):
|
|
checksum.update(test_file.read(self.chunk_size))
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_backup_volume_from_file(self):
|
|
self._create_volume_db_entry(self.volume_id, 1)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
checksum = hashlib.sha256()
|
|
|
|
def write_data(inst, data, offset):
|
|
checksum.update(data)
|
|
test_file.write(data)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'write', write_data)
|
|
|
|
self.stubs.Set(self.service, '_discard_bytes',
|
|
lambda *args: None)
|
|
|
|
self.service.backup(backup, self.volume_file)
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_get_backup_base_name(self):
|
|
name = self.service._get_backup_base_name(self.volume_id,
|
|
diff_format=True)
|
|
self.assertEqual(name, "volume-%s.backup.base" % (self.volume_id))
|
|
|
|
self.assertRaises(exception.InvalidParameterValue,
|
|
self.service._get_backup_base_name,
|
|
self.volume_id)
|
|
|
|
name = self.service._get_backup_base_name(self.volume_id, '1234')
|
|
self.assertEqual(name,
|
|
"volume-%s.backup.%s" % (self.volume_id, '1234'))
|
|
|
|
def test_backup_volume_from_rbd(self):
|
|
self._create_volume_db_entry(self.volume_id, 1)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
backup_name = self.service._get_backup_base_name(self.backup_id,
|
|
diff_format=True)
|
|
|
|
self.stubs.Set(self.service, '_try_delete_base_image',
|
|
lambda *args, **kwargs: None)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
checksum = hashlib.sha256()
|
|
|
|
def write_data(inst, data, offset):
|
|
checksum.update(data)
|
|
test_file.write(data)
|
|
|
|
def read_data(inst, offset, length):
|
|
return self.volume_file.read(self.length)
|
|
|
|
def rbd_list(inst, ioctx):
|
|
return [backup_name]
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'read', read_data)
|
|
self.stubs.Set(self.service.rbd.Image, 'write', write_data)
|
|
self.stubs.Set(self.service.rbd.RBD, 'list', rbd_list)
|
|
|
|
self.stubs.Set(self.service, '_discard_bytes',
|
|
lambda *args: None)
|
|
|
|
meta = rbddriver.RBDImageMetadata(self.service.rbd.Image(),
|
|
'pool_foo', 'user_foo',
|
|
'conf_foo')
|
|
rbd_io = rbddriver.RBDImageIOWrapper(meta)
|
|
|
|
self.service.backup(backup, rbd_io)
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_backup_vol_length_0(self):
|
|
self._set_common_backup_stubs(self.service)
|
|
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
self._create_volume_db_entry(self.volume_id, 0)
|
|
self.assertRaises(exception.InvalidParameterValue, self.service.backup,
|
|
backup, self.volume_file)
|
|
|
|
def test_restore(self):
|
|
self._create_volume_db_entry(self.volume_id, 1)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
self._set_common_restore_stubs(self.service)
|
|
|
|
backup_name = self.service._get_backup_base_name(self.backup_id,
|
|
diff_format=True)
|
|
|
|
def rbd_list(inst, ioctx):
|
|
return [backup_name]
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'list', rbd_list)
|
|
|
|
self.stubs.Set(self.service, '_discard_bytes', lambda *args: None)
|
|
|
|
with tempfile.NamedTemporaryFile() as test_file:
|
|
self.volume_file.seek(0)
|
|
|
|
def read_data(inst, offset, length):
|
|
return self.volume_file.read(self.length)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'read', read_data)
|
|
|
|
self.service.restore(backup, self.volume_id, test_file)
|
|
|
|
checksum = hashlib.sha256()
|
|
test_file.seek(0)
|
|
for c in xrange(0, self.num_chunks):
|
|
checksum.update(test_file.read(self.chunk_size))
|
|
|
|
# Ensure the files are equal
|
|
self.assertEqual(checksum.digest(), self.checksum.digest())
|
|
|
|
def test_discard_bytes(self):
|
|
self.service._discard_bytes(mock_rbd(), 123456, 0)
|
|
calls = []
|
|
|
|
def _setter(*args, **kwargs):
|
|
calls.append(True)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'discard', _setter)
|
|
|
|
self.service._discard_bytes(mock_rbd(), 123456, 0)
|
|
self.assertTrue(len(calls) == 0)
|
|
|
|
image = mock_rbd().Image()
|
|
wrapped_rbd = self._get_wrapped_rbd_io(image)
|
|
self.service._discard_bytes(wrapped_rbd, 123456, 1234)
|
|
self.assertTrue(len(calls) == 1)
|
|
|
|
self.stubs.Set(image, 'write', _setter)
|
|
wrapped_rbd = self._get_wrapped_rbd_io(image)
|
|
self.stubs.Set(self.service, '_file_is_rbd',
|
|
lambda *args: False)
|
|
self.service._discard_bytes(wrapped_rbd, 0,
|
|
self.service.chunk_size * 2)
|
|
self.assertTrue(len(calls) == 3)
|
|
|
|
def test_delete_backup_snapshot(self):
|
|
snap_name = 'backup.%s.snap.3824923.1412' % (uuid.uuid4())
|
|
base_name = self.service._get_backup_base_name(self.volume_id,
|
|
diff_format=True)
|
|
|
|
self.stubs.Set(self.service, '_get_backup_snap_name',
|
|
lambda *args: snap_name)
|
|
|
|
self.stubs.Set(self.service, 'get_backup_snaps',
|
|
lambda *args: None)
|
|
|
|
rem = self.service._delete_backup_snapshot(mock_rados(), base_name,
|
|
self.backup_id)
|
|
|
|
self.assertEqual(rem, (snap_name, 0))
|
|
|
|
def test_try_delete_base_image_diff_format(self):
|
|
# don't create volume db entry since it should not be required
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
backup_name = self.service._get_backup_base_name(self.volume_id,
|
|
diff_format=True)
|
|
|
|
snap_name = self.service._get_new_snap_name(self.backup_id)
|
|
snaps = [{'name': snap_name}]
|
|
|
|
def rbd_list(*args):
|
|
return [backup_name]
|
|
|
|
def list_snaps(*args):
|
|
return snaps
|
|
|
|
def remove_snap(*args):
|
|
snaps.pop()
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'remove_snap', remove_snap)
|
|
self.stubs.Set(self.service.rbd.Image, 'list_snaps', list_snaps)
|
|
self.stubs.Set(self.service.rbd.RBD, 'list', rbd_list)
|
|
|
|
# Must be something mutable
|
|
remove_called = []
|
|
|
|
def remove(inst, ioctx, name):
|
|
remove_called.append(True)
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'remove', remove)
|
|
self.service.delete(backup)
|
|
self.assertTrue(remove_called[0])
|
|
|
|
def test_try_delete_base_image(self):
|
|
# don't create volume db entry since it should not be required
|
|
self._create_volume_db_entry(self.volume_id, 1)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
backup_name = self.service._get_backup_base_name(self.volume_id,
|
|
self.backup_id)
|
|
|
|
def rbd_list(inst, ioctx):
|
|
return [backup_name]
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'list', rbd_list)
|
|
|
|
# Must be something mutable
|
|
remove_called = []
|
|
|
|
self.stubs.Set(self.service, 'get_backup_snaps',
|
|
lambda *args, **kwargs: None)
|
|
|
|
def remove(inst, ioctx, name):
|
|
remove_called.append(True)
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'remove', remove)
|
|
self.service.delete(backup)
|
|
self.assertTrue(remove_called[0])
|
|
|
|
def test_try_delete_base_image_busy(self):
|
|
"""This should induce retries then raise rbd.ImageBusy."""
|
|
# don't create volume db entry since it should not be required
|
|
self._create_volume_db_entry(self.volume_id, 1)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
backup_name = self.service._get_backup_base_name(self.volume_id,
|
|
self.backup_id)
|
|
|
|
def rbd_list(inst, ioctx):
|
|
return [backup_name]
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'list', rbd_list)
|
|
|
|
# Must be something mutable
|
|
remove_called = []
|
|
|
|
self.stubs.Set(self.service, 'get_backup_snaps',
|
|
lambda *args, **kwargs: None)
|
|
|
|
def remove(inst, ioctx, name):
|
|
raise self.service.rbd.ImageBusy("image busy")
|
|
|
|
self.stubs.Set(self.service.rbd.RBD, 'remove', remove)
|
|
|
|
self.assertRaises(self.service.rbd.ImageBusy,
|
|
self.service._try_delete_base_image,
|
|
backup['id'], backup['volume_id'])
|
|
|
|
def test_delete(self):
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
def del_base_image(*args):
|
|
pass
|
|
|
|
self.stubs.Set(self.service, '_try_delete_base_image',
|
|
lambda *args: None)
|
|
|
|
self.service.delete(backup)
|
|
|
|
def test_delete_image_not_found(self):
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
|
|
def del_base_image(*args):
|
|
raise self.service.rbd.ImageNotFound
|
|
|
|
self.stubs.Set(self.service, '_try_delete_base_image',
|
|
lambda *args: None)
|
|
|
|
# ImageNotFound exception is caught so that db entry can be cleared
|
|
self.service.delete(backup)
|
|
|
|
def test_diff_restore_allowed_true(self):
|
|
restore_point = 'restore.foo'
|
|
is_allowed = (True, restore_point)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
alt_volume_id = str(uuid.uuid4())
|
|
volume_size = 1
|
|
self._create_volume_db_entry(alt_volume_id, volume_size)
|
|
alt_volume = db.volume_get(self.ctxt, alt_volume_id)
|
|
rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image())
|
|
|
|
self.stubs.Set(self.service, '_get_restore_point',
|
|
lambda *args: restore_point)
|
|
self.stubs.Set(self.service, '_rbd_has_extents',
|
|
lambda *args: False)
|
|
self.stubs.Set(self.service, '_rbd_image_exists',
|
|
lambda *args: (True, 'foo'))
|
|
self.stubs.Set(self.service, '_file_is_rbd',
|
|
lambda *args: True)
|
|
self.stubs.Set(self.service.rbd.Image, 'size',
|
|
lambda *args: volume_size * units.GiB)
|
|
|
|
resp = self.service._diff_restore_allowed('foo', backup, alt_volume,
|
|
rbd_io, mock_rados())
|
|
self.assertEqual(resp, is_allowed)
|
|
|
|
def _set_service_stub(self, method, retval):
|
|
self.stubs.Set(self.service, method, lambda *args, **kwargs: retval)
|
|
|
|
def test_diff_restore_allowed_false(self):
|
|
volume_size = 1
|
|
not_allowed = (False, None)
|
|
backup = db.backup_get(self.ctxt, self.backup_id)
|
|
self._create_volume_db_entry(self.volume_id, volume_size)
|
|
original_volume = db.volume_get(self.ctxt, self.volume_id)
|
|
rbd_io = self._get_wrapped_rbd_io(self.service.rbd.Image())
|
|
|
|
test_args = 'foo', backup, original_volume, rbd_io, mock_rados()
|
|
|
|
self._set_service_stub('_get_restore_point', None)
|
|
resp = self.service._diff_restore_allowed(*test_args)
|
|
self.assertEqual(resp, not_allowed)
|
|
self._set_service_stub('_get_restore_point', 'restore.foo')
|
|
|
|
self._set_service_stub('_rbd_has_extents', True)
|
|
resp = self.service._diff_restore_allowed(*test_args)
|
|
self.assertEqual(resp, not_allowed)
|
|
self._set_service_stub('_rbd_has_extents', False)
|
|
|
|
self._set_service_stub('_rbd_image_exists', (False, 'foo'))
|
|
resp = self.service._diff_restore_allowed(*test_args)
|
|
self.assertEqual(resp, not_allowed)
|
|
self._set_service_stub('_rbd_image_exists', None)
|
|
|
|
self.stubs.Set(self.service.rbd.Image, 'size',
|
|
lambda *args, **kwargs: volume_size * units.GiB * 2)
|
|
resp = self.service._diff_restore_allowed(*test_args)
|
|
self.assertEqual(resp, not_allowed)
|
|
self.stubs.Set(self.service.rbd.Image, 'size',
|
|
lambda *args, **kwargs: volume_size * units.GiB)
|
|
|
|
self._set_service_stub('_file_is_rbd', False)
|
|
resp = self.service._diff_restore_allowed(*test_args)
|
|
self.assertEqual(resp, not_allowed)
|
|
self._set_service_stub('_file_is_rbd', True)
|
|
|
|
def tearDown(self):
|
|
self.volume_file.close()
|
|
self.stubs.UnsetAll()
|
|
super(BackupCephTestCase, self).tearDown()
|