Add volume size verify for replica based on master

According bug description, replica should has volume size at least
as much as the master. Otherwise it maybe cause exception for
replica data. To solve this problem,I added judgement for volume
size when create a replica, which not smaller than master
volume size. And make this function as configurable by
CONF.verify_replica_volume_size.
Also provide a test case to validate the method.

Change-Id: I5e110ce672c1b1715bca1727d70d656301cd0d43
Closes-Bug: #1357500
This commit is contained in:
wangyao 2017-08-14 22:31:26 +08:00
parent 3ea7d210b8
commit 8e2bb674c4
5 changed files with 28 additions and 8 deletions

View File

@ -278,6 +278,10 @@ common_opts = [
help='Enable verification of Swift checksum before starting '
'restore. Makes sure the checksum of original backup matches '
'the checksum of the Swift backup file.'),
cfg.BoolOpt('verify_replica_volume_size', default=True,
help='Require the replica volume size to be greater than '
'or equal to the size of the master volume '
'during replica creation.'),
cfg.StrOpt('storage_strategy', default='SwiftStorage',
help="Default strategy to store backups."),
cfg.StrOpt('storage_namespace',

View File

@ -955,6 +955,14 @@ class Instance(BuiltInstance):
raise exception.Forbidden(
_("Cannot create a replica of a replica %(id)s.")
% {'id': slave_of_id})
if (CONF.verify_replica_volume_size
and replica_source.volume_size > volume_size):
raise exception.Forbidden(
_("Replica volume size should not be smaller than"
" master's, replica volume size: %(replica_size)s"
" and master volume size: %(master_size)s.")
% {'replica_size': volume_size,
'master_size': replica_source.volume_size})
# load the replica source status to check if
# source is available
load_simple_instance_server_status(

View File

@ -681,7 +681,7 @@ class CreateInstance(object):
instance_info.dbaas_datastore = CONFIG.dbaas_datastore
instance_info.dbaas_datastore_version = CONFIG.dbaas_datastore_version
if VOLUME_SUPPORT:
instance_info.volume = {'size': CONFIG.get('trove_volume_size', 1)}
instance_info.volume = {'size': CONFIG.get('trove_volume_size', 2)}
else:
instance_info.volume = None

View File

@ -91,7 +91,7 @@ def create_slave():
result = instance_info.dbaas.instances.create(
instance_info.name + "_slave",
instance_info.dbaas_flavor_href,
instance_info.volume,
{'size': 2},
datastore=instance_info.dbaas_datastore,
datastore_version=instance_info.dbaas_datastore_version,
nics=instance_info.nics,

View File

@ -351,7 +351,8 @@ class TestReplication(trove_testtools.TestCase):
InstanceTasks.NONE,
id=str(uuid.uuid4()),
name="TestMasterInstance",
datastore_version_id=self.datastore_version.id)
datastore_version_id=self.datastore_version.id,
volume_size=2)
self.master.set_task_status(InstanceTasks.NONE)
self.master.save()
self.master_status = InstanceServiceStatus(
@ -381,7 +382,7 @@ class TestReplication(trove_testtools.TestCase):
self.assertRaises(exception.UnprocessableEntity,
Instance.create,
None, 'name', 1, "UUID", [], [], self.datastore,
self.datastore_version, 1,
self.datastore_version, 2,
None, slave_of_id=self.master.id)
@patch('trove.instance.models.LOG')
@ -389,7 +390,7 @@ class TestReplication(trove_testtools.TestCase):
self.assertRaises(exception.NotFound,
Instance.create,
None, 'name', 1, "UUID", [], [], self.datastore,
self.datastore_version, 1,
self.datastore_version, 2,
None, slave_of_id=str(uuid.uuid4()))
def test_create_replica_from_replica(self):
@ -406,13 +407,13 @@ class TestReplication(trove_testtools.TestCase):
self.replica_info.save()
self.assertRaises(exception.Forbidden, Instance.create,
None, 'name', 2, "UUID", [], [], self.datastore,
self.datastore_version, 1,
self.datastore_version, 2,
None, slave_of_id=self.replica_info.id)
def test_create_replica_with_users(self):
self.users.append({"name": "testuser", "password": "123456"})
self.assertRaises(exception.ReplicaCreateWithUsersDatabasesError,
Instance.create, None, 'name', 1, "UUID", [],
Instance.create, None, 'name', 2, "UUID", [],
self.users, self.datastore, self.datastore_version,
1, None, slave_of_id=self.master.id)
@ -421,9 +422,16 @@ class TestReplication(trove_testtools.TestCase):
self.assertRaises(exception.ReplicaCreateWithUsersDatabasesError,
Instance.create, None, 'name', 1, "UUID",
self.databases, [], self.datastore,
self.datastore_version, 1, None,
self.datastore_version, 2, None,
slave_of_id=self.master.id)
def test_replica_volume_size_smaller_than_master(self):
self.assertRaises(exception.Forbidden,
Instance.create,
None, 'name', 1, "UUID", [], [], self.datastore,
self.datastore_version, 1,
None, slave_of_id=self.master.id)
def trivial_key_function(id):
return id * id