Merge "Ephemeral volume support"
This commit is contained in:
commit
ce0d39fd2a
@ -101,6 +101,18 @@
|
||||
"id": 10,
|
||||
"name": "m1.rd-tiny",
|
||||
"ram": 512
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "eph.rd-tiny",
|
||||
"ram": 512,
|
||||
"local_storage": 1
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "eph.rd-smaller",
|
||||
"ram": 768,
|
||||
"local_storage": 2
|
||||
}
|
||||
|
||||
],
|
||||
|
@ -157,6 +157,26 @@ class VolumeCreationFailure(ReddwarfError):
|
||||
message = _("Failed to create a volume in Nova.")
|
||||
|
||||
|
||||
class VolumeSizeNotSpecified(BadRequest):
|
||||
|
||||
message = _("Volume size was not specified.")
|
||||
|
||||
|
||||
class LocalStorageNotSpecified(BadRequest):
|
||||
|
||||
message = _("Local storage not specified in flavor ID: %(flavor)s.")
|
||||
|
||||
|
||||
class LocalStorageNotSupported(ReddwarfError):
|
||||
|
||||
message = _("Local storage support is not enabled.")
|
||||
|
||||
|
||||
class VolumeNotSupported(ReddwarfError):
|
||||
|
||||
message = _("Volume support is not enabled.")
|
||||
|
||||
|
||||
class TaskManagerError(ReddwarfError):
|
||||
|
||||
message = _("An error occurred communicating with the task manager: "
|
||||
|
@ -376,6 +376,7 @@ class Controller(object):
|
||||
exception.BadValue,
|
||||
exception.DatabaseAlreadyExists,
|
||||
exception.UserAlreadyExists,
|
||||
exception.LocalStorageNotSpecified,
|
||||
],
|
||||
webob.exc.HTTPNotFound: [
|
||||
exception.NotFound,
|
||||
@ -398,6 +399,10 @@ class Controller(object):
|
||||
exception.VolumeCreationFailure,
|
||||
exception.UpdateGuestError,
|
||||
],
|
||||
webob.exc.HTTPNotImplemented: [
|
||||
exception.VolumeNotSupported,
|
||||
exception.LocalStorageNotSupported
|
||||
],
|
||||
}
|
||||
|
||||
def create_resource(self):
|
||||
|
@ -68,6 +68,8 @@ class InstanceStatus(object):
|
||||
|
||||
|
||||
def validate_volume_size(size):
|
||||
if size is None:
|
||||
raise exception.VolumeSizeNotSpecified()
|
||||
max_size = CONF.max_accepted_volume_size
|
||||
if long(size) > max_size:
|
||||
msg = ("Volume 'size' cannot exceed maximum "
|
||||
@ -336,9 +338,11 @@ class BaseInstance(SimpleInstance):
|
||||
self.update_db(task_status=InstanceTasks.DELETING)
|
||||
task_api.API(self.context).delete_instance(self.id)
|
||||
|
||||
deltas = {'instances': -1}
|
||||
if CONF.reddwarf_volume_support:
|
||||
deltas['volumes'] = -self.volume_size
|
||||
return run_with_quotas(self.tenant_id,
|
||||
{'instances': -1,
|
||||
'volumes': -self.volume_size},
|
||||
deltas,
|
||||
_delete_resources)
|
||||
|
||||
def _delete_resources(self):
|
||||
@ -415,13 +419,25 @@ class Instance(BuiltInstance):
|
||||
def create(cls, context, name, flavor_id, image_id,
|
||||
databases, users, service_type, volume_size, backup_id):
|
||||
|
||||
client = create_nova_client(context)
|
||||
try:
|
||||
flavor = client.flavors.get(flavor_id)
|
||||
except nova_exceptions.NotFound:
|
||||
raise exception.FlavorNotFound(uuid=flavor_id)
|
||||
|
||||
deltas = {'instances': 1}
|
||||
if CONF.reddwarf_volume_support:
|
||||
validate_volume_size(volume_size)
|
||||
deltas['volumes'] = volume_size
|
||||
else:
|
||||
if volume_size is not None:
|
||||
raise exception.VolumeNotSupported()
|
||||
ephemeral_support = CONF.device_path
|
||||
if ephemeral_support and flavor.ephemeral == 0:
|
||||
raise exception.LocalStorageNotSpecified(flavor=flavor_id)
|
||||
|
||||
def _create_resources():
|
||||
client = create_nova_client(context)
|
||||
security_groups = None
|
||||
try:
|
||||
flavor = client.flavors.get(flavor_id)
|
||||
except nova_exceptions.NotFound:
|
||||
raise exception.FlavorNotFound(uuid=flavor_id)
|
||||
|
||||
if backup_id is not None:
|
||||
backup_info = Backup.get_by_id(backup_id)
|
||||
@ -464,9 +480,8 @@ class Instance(BuiltInstance):
|
||||
|
||||
return SimpleInstance(context, db_info, service_status)
|
||||
|
||||
validate_volume_size(volume_size)
|
||||
return run_with_quotas(context.tenant,
|
||||
{'instances': 1, 'volumes': volume_size},
|
||||
deltas,
|
||||
_create_resources)
|
||||
|
||||
def resize_flavor(self, new_flavor_id):
|
||||
@ -483,8 +498,18 @@ class Instance(BuiltInstance):
|
||||
old_flavor = client.flavors.get(self.flavor_id)
|
||||
new_flavor_size = new_flavor.ram
|
||||
old_flavor_size = old_flavor.ram
|
||||
if new_flavor_size == old_flavor_size:
|
||||
raise exception.CannotResizeToSameSize()
|
||||
if CONF.reddwarf_volume_support:
|
||||
if new_flavor.ephemeral != 0:
|
||||
raise exception.LocalStorageNotSupported()
|
||||
if new_flavor_size == old_flavor_size:
|
||||
raise exception.CannotResizeToSameSize()
|
||||
elif CONF.device_path is not None:
|
||||
# ephemeral support enabled
|
||||
if new_flavor.ephemeral == 0:
|
||||
raise exception.LocalStorageNotSpecified(flavor=new_flavor_id)
|
||||
if (new_flavor_size == old_flavor_size and
|
||||
new_flavor.ephemeral == new_flavor.ephemeral):
|
||||
raise exception.CannotResizeToSameSize()
|
||||
|
||||
# Set the task to RESIZING and begin the async call before returning.
|
||||
self.update_db(task_status=InstanceTasks.RESIZING)
|
||||
|
@ -196,7 +196,7 @@ class InstanceController(wsgi.Controller):
|
||||
users = populate_users(body['instance'].get('users', []))
|
||||
except ValueError as ve:
|
||||
raise exception.BadRequest(msg=ve)
|
||||
if body['instance'].get('volume', None) is not None:
|
||||
if 'volume' in body['instance']:
|
||||
try:
|
||||
volume_size = int(body['instance']['volume']['size'])
|
||||
except ValueError as e:
|
||||
|
@ -50,8 +50,8 @@ class LimitViews(object):
|
||||
data = []
|
||||
abs_view = dict()
|
||||
abs_view["verb"] = "ABSOLUTE"
|
||||
abs_view["maxTotalInstances"] = self.abs_limits.get("instances", 0)
|
||||
abs_view["maxTotalVolumes"] = self.abs_limits.get("volumes", 0)
|
||||
for resource_name, abs_limit in self.abs_limits.items():
|
||||
abs_view["max_" + resource_name] = abs_limit
|
||||
|
||||
data.append(abs_view)
|
||||
for l in self.rate_limits:
|
||||
|
@ -310,8 +310,9 @@ QUOTAS = QuotaEngine()
|
||||
|
||||
''' Define all kind of resources here '''
|
||||
resources = [Resource(Resource.INSTANCES, 'max_instances_per_user'),
|
||||
Resource(Resource.VOLUMES, 'max_volumes_per_user'),
|
||||
Resource(Resource.BACKUPS, 'max_backups_per_user')]
|
||||
if CONF.reddwarf_volume_support:
|
||||
resources.append(Resource(Resource.VOLUMES, 'max_volumes_per_user'))
|
||||
|
||||
QUOTAS.register_resources(resources)
|
||||
|
||||
|
@ -219,17 +219,9 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin):
|
||||
def _create_server_volume_individually(self, flavor_id, image_id,
|
||||
security_groups, service_type,
|
||||
volume_size):
|
||||
volume_info = None
|
||||
block_device_mapping = None
|
||||
server = None
|
||||
try:
|
||||
volume_info = self._create_volume(volume_size)
|
||||
block_device_mapping = volume_info['block_device']
|
||||
except Exception as e:
|
||||
msg = "Error provisioning volume for instance."
|
||||
err = inst_models.InstanceTasks.BUILDING_ERROR_VOLUME
|
||||
self._log_and_raise(e, msg, err)
|
||||
|
||||
volume_info = self._build_volume_info(volume_size)
|
||||
block_device_mapping = volume_info['block_device']
|
||||
try:
|
||||
server = self._create_server(flavor_id, image_id, security_groups,
|
||||
service_type, block_device_mapping)
|
||||
@ -242,6 +234,28 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin):
|
||||
self._log_and_raise(e, msg, err)
|
||||
return server, volume_info
|
||||
|
||||
def _build_volume_info(self, volume_size=None):
|
||||
volume_info = None
|
||||
volume_support = CONF.reddwarf_volume_support
|
||||
LOG.debug(_("reddwarf volume support = %s") % volume_support)
|
||||
if volume_support:
|
||||
try:
|
||||
volume_info = self._create_volume(volume_size)
|
||||
except Exception as e:
|
||||
msg = "Error provisioning volume for instance."
|
||||
err = inst_models.InstanceTasks.BUILDING_ERROR_VOLUME
|
||||
self._log_and_raise(e, msg, err)
|
||||
else:
|
||||
LOG.debug(_("device_path = %s") % CONF.device_path)
|
||||
LOG.debug(_("mount_point = %s") % CONF.mount_point)
|
||||
volume_info = {
|
||||
'block_device': None,
|
||||
'device_path': CONF.device_path,
|
||||
'mount_point': CONF.mount_point,
|
||||
'volumes': None,
|
||||
}
|
||||
return volume_info
|
||||
|
||||
def _log_and_raise(self, exc, message, task_status):
|
||||
LOG.error(message)
|
||||
LOG.error(exc)
|
||||
@ -253,18 +267,6 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin):
|
||||
LOG.info("Entering create_volume")
|
||||
LOG.debug(_("Starting to create the volume for the instance"))
|
||||
|
||||
volume_support = CONF.reddwarf_volume_support
|
||||
LOG.debug(_("reddwarf volume support = %s") % volume_support)
|
||||
if (volume_size is None or
|
||||
volume_support is False):
|
||||
volume_info = {
|
||||
'block_device': None,
|
||||
'device_path': None,
|
||||
'mount_point': None,
|
||||
'volumes': None,
|
||||
}
|
||||
return volume_info
|
||||
|
||||
volume_client = create_nova_volume_client(self.context)
|
||||
volume_desc = ("mysql volume for %s" % self.id)
|
||||
volume_ref = volume_client.volumes.create(
|
||||
|
@ -67,7 +67,7 @@ class AfterBackupCreation(object):
|
||||
@test
|
||||
def test_instance_action_right_after_backup_create(self):
|
||||
"""test any instance action while backup is running"""
|
||||
assert_unprocessable(instance_info.dbaas.instances.resize_volume,
|
||||
assert_unprocessable(instance_info.dbaas.instances.resize_instance,
|
||||
instance_info.id, 1)
|
||||
|
||||
@test
|
||||
|
@ -114,6 +114,9 @@ class InstanceTestInfo(object):
|
||||
instance_info = InstanceTestInfo()
|
||||
dbaas = None # Rich client used throughout this test.
|
||||
dbaas_admin = None # Same as above, with admin privs.
|
||||
VOLUME_SUPPORT = CONFIG.get('reddwarf_volume_support', False)
|
||||
EPHEMERAL_SUPPORT = not VOLUME_SUPPORT and CONFIG.get('device_path',
|
||||
'/dev/vdb') is not None
|
||||
|
||||
|
||||
# This is like a cheat code which allows the tests to skip creating a new
|
||||
@ -186,7 +189,11 @@ class InstanceSetup(object):
|
||||
|
||||
@test
|
||||
def test_find_flavor(self):
|
||||
flavor_name = CONFIG.values.get('instance_flavor_name', 'm1.tiny')
|
||||
if EPHEMERAL_SUPPORT:
|
||||
flavor_name = CONFIG.values.get('instance_eph_flavor_name',
|
||||
'eph.rd-tiny')
|
||||
else:
|
||||
flavor_name = CONFIG.values.get('instance_flavor_name', 'm1.tiny')
|
||||
flavors = dbaas.find_flavors_by_name(flavor_name)
|
||||
assert_equal(len(flavors), 1, "Number of flavors with name '%s' "
|
||||
"found was '%d'." % (flavor_name, len(flavors)))
|
||||
@ -245,14 +252,15 @@ class CreateInstanceQuotaTest(unittest.TestCase):
|
||||
self.test_info = copy.deepcopy(instance_info)
|
||||
|
||||
def tearDown(self):
|
||||
quota_dict = {'instances': CONFIG.reddwarf_max_instances_per_user,
|
||||
'volumes': CONFIG.reddwarf_max_volumes_per_user}
|
||||
quota_dict = {'instances': CONFIG.reddwarf_max_instances_per_user}
|
||||
if VOLUME_SUPPORT:
|
||||
quota_dict['volumes'] = CONFIG.reddwarf_max_volumes_per_user
|
||||
dbaas_admin.quota.update(self.test_info.user.tenant_id,
|
||||
quota_dict)
|
||||
|
||||
def test_instance_size_too_big(self):
|
||||
vol_ok = CONFIG.get('reddwarf_volume_support', False)
|
||||
if 'reddwarf_max_accepted_volume_size' in CONFIG.values and vol_ok:
|
||||
if ('reddwarf_max_accepted_volume_size' in CONFIG.values and
|
||||
VOLUME_SUPPORT):
|
||||
too_big = CONFIG.reddwarf_max_accepted_volume_size
|
||||
|
||||
self.test_info.volume = {'size': too_big + 1}
|
||||
@ -263,6 +271,18 @@ class CreateInstanceQuotaTest(unittest.TestCase):
|
||||
self.test_info.dbaas_flavor_href,
|
||||
self.test_info.volume)
|
||||
|
||||
def test_update_quota_invalid_resource_should_fail(self):
|
||||
quota_dict = {'invalid_resource': 100}
|
||||
assert_raises(exceptions.NotFound, dbaas_admin.quota.update,
|
||||
self.test_info.user.tenant_id, quota_dict)
|
||||
|
||||
def test_update_quota_volume_should_fail_volume_not_supported(self):
|
||||
if VOLUME_SUPPORT:
|
||||
raise SkipTest("Volume support needs to be disabled")
|
||||
quota_dict = {'volumes': 100}
|
||||
assert_raises(exceptions.NotFound, dbaas_admin.quota.update,
|
||||
self.test_info.user.tenant_id, quota_dict)
|
||||
|
||||
def test_create_too_many_instances(self):
|
||||
instance_quota = 0
|
||||
quota_dict = {'instances': instance_quota}
|
||||
@ -273,10 +293,13 @@ class CreateInstanceQuotaTest(unittest.TestCase):
|
||||
|
||||
assert_equal(new_quotas['instances'], quota_dict['instances'])
|
||||
assert_equal(0, verify_quota['instances'])
|
||||
assert_equal(CONFIG.reddwarf_max_volumes_per_user,
|
||||
verify_quota['volumes'])
|
||||
self.test_info.volume = None
|
||||
|
||||
if VOLUME_SUPPORT:
|
||||
assert_equal(CONFIG.reddwarf_max_volumes_per_user,
|
||||
verify_quota['volumes'])
|
||||
self.test_info.volume = {'size': 1}
|
||||
|
||||
self.test_info.volume = {'size': 1}
|
||||
self.test_info.name = "too_many_instances"
|
||||
assert_raises(exceptions.OverLimit,
|
||||
dbaas.instances.create,
|
||||
@ -287,6 +310,8 @@ class CreateInstanceQuotaTest(unittest.TestCase):
|
||||
assert_equal(413, dbaas.last_http_code)
|
||||
|
||||
def test_create_instances_total_volume_exceeded(self):
|
||||
if not VOLUME_SUPPORT:
|
||||
raise SkipTest("Volume support not enabled")
|
||||
volume_quota = 3
|
||||
quota_dict = {'volumes': volume_quota}
|
||||
self.test_info.volume = {'size': volume_quota + 1}
|
||||
@ -307,13 +332,14 @@ class CreateInstanceQuotaTest(unittest.TestCase):
|
||||
@test(depends_on_classes=[InstanceSetup],
|
||||
groups=[GROUP, GROUP_START, GROUP_START_SIMPLE, tests.INSTANCES],
|
||||
runs_after_groups=[tests.PRE_INSTANCES, 'dbaas_quotas'])
|
||||
class CreateInstance(unittest.TestCase):
|
||||
class CreateInstance(object):
|
||||
"""Test to create a Database Instance
|
||||
|
||||
If the call returns without raising an exception this test passes.
|
||||
|
||||
"""
|
||||
|
||||
@test
|
||||
def test_create(self):
|
||||
databases = []
|
||||
databases.append({"name": "firstdb", "character_set": "latin2",
|
||||
@ -324,7 +350,7 @@ class CreateInstance(unittest.TestCase):
|
||||
users.append({"name": "lite", "password": "litepass",
|
||||
"databases": [{"name": "firstdb"}]})
|
||||
instance_info.users = users
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if VOLUME_SUPPORT:
|
||||
instance_info.volume = {'size': 1}
|
||||
else:
|
||||
instance_info.volume = None
|
||||
@ -361,7 +387,7 @@ class CreateInstance(unittest.TestCase):
|
||||
# Check these attrs only are returned in create response
|
||||
expected_attrs = ['created', 'flavor', 'addresses', 'id', 'links',
|
||||
'name', 'status', 'updated']
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if VOLUME_SUPPORT:
|
||||
expected_attrs.append('volume')
|
||||
if CONFIG.reddwarf_dns_support:
|
||||
expected_attrs.append('hostname')
|
||||
@ -373,31 +399,52 @@ class CreateInstance(unittest.TestCase):
|
||||
# Don't CheckInstance if the instance already exists.
|
||||
check.flavor()
|
||||
check.links(result._info['links'])
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if VOLUME_SUPPORT:
|
||||
check.volume()
|
||||
|
||||
@test(enabled=VOLUME_SUPPORT)
|
||||
def test_create_failure_with_empty_volume(self):
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
instance_name = "instance-failure-with-no-volume-size"
|
||||
databases = []
|
||||
volume = {}
|
||||
assert_raises(exceptions.BadRequest, dbaas.instances.create,
|
||||
instance_name, instance_info.dbaas_flavor_href,
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
instance_name = "instance-failure-with-no-volume-size"
|
||||
databases = []
|
||||
volume = {}
|
||||
assert_raises(exceptions.BadRequest, dbaas.instances.create,
|
||||
instance_name, instance_info.dbaas_flavor_href,
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
|
||||
@test(enabled=VOLUME_SUPPORT)
|
||||
def test_create_failure_with_no_volume_size(self):
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
instance_name = "instance-failure-with-no-volume-size"
|
||||
databases = []
|
||||
volume = {'size': None}
|
||||
assert_raises(exceptions.BadRequest, dbaas.instances.create,
|
||||
instance_name, instance_info.dbaas_flavor_href,
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
instance_name = "instance-failure-with-no-volume-size"
|
||||
databases = []
|
||||
volume = {'size': None}
|
||||
assert_raises(exceptions.BadRequest, dbaas.instances.create,
|
||||
instance_name, instance_info.dbaas_flavor_href,
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
|
||||
@test(enabled=not VOLUME_SUPPORT)
|
||||
def test_create_failure_with_volume_size_and_volume_disabled(self):
|
||||
instance_name = "instance-failure-volume-size_and_volume_disabled"
|
||||
databases = []
|
||||
volume = {'size': 2}
|
||||
assert_raises(exceptions.HTTPNotImplemented, dbaas.instances.create,
|
||||
instance_name, instance_info.dbaas_flavor_href,
|
||||
volume, databases)
|
||||
assert_equal(501, dbaas.last_http_code)
|
||||
|
||||
@test(enabled=EPHEMERAL_SUPPORT)
|
||||
def test_create_failure_with_no_ephemeral_flavor(self):
|
||||
instance_name = "instance-failure-with-no-ephemeral-flavor"
|
||||
databases = []
|
||||
flavor_name = CONFIG.values.get('instance_flavor_name', 'm1.tiny')
|
||||
flavors = dbaas.find_flavors_by_name(flavor_name)
|
||||
assert_raises(exceptions.BadRequest, dbaas.instances.create,
|
||||
instance_name, flavors[0].id, None, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
|
||||
@test
|
||||
def test_create_failure_with_no_name(self):
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if VOLUME_SUPPORT:
|
||||
volume = {'size': 1}
|
||||
else:
|
||||
volume = None
|
||||
@ -408,8 +455,9 @@ class CreateInstance(unittest.TestCase):
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
|
||||
@test
|
||||
def test_create_failure_with_spaces_for_name(self):
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if VOLUME_SUPPORT:
|
||||
volume = {'size': 1}
|
||||
else:
|
||||
volume = None
|
||||
@ -420,6 +468,7 @@ class CreateInstance(unittest.TestCase):
|
||||
volume, databases)
|
||||
assert_equal(400, dbaas.last_http_code)
|
||||
|
||||
@test
|
||||
def test_mgmt_get_instance_on_create(self):
|
||||
if CONFIG.test_mgmt:
|
||||
result = dbaas_admin.management.show(instance_info.id)
|
||||
@ -777,7 +826,9 @@ class TestInstanceListing(object):
|
||||
|
||||
@test
|
||||
def test_index_list(self):
|
||||
expected_attrs = ['id', 'links', 'name', 'status', 'flavor', 'volume']
|
||||
expected_attrs = ['id', 'links', 'name', 'status', 'flavor']
|
||||
if VOLUME_SUPPORT:
|
||||
expected_attrs.append('volume')
|
||||
instances = dbaas.instances.list()
|
||||
assert_equal(200, dbaas.last_http_code)
|
||||
for instance in instances:
|
||||
@ -793,7 +844,9 @@ class TestInstanceListing(object):
|
||||
@test
|
||||
def test_get_instance(self):
|
||||
expected_attrs = ['created', 'databases', 'flavor', 'hostname', 'id',
|
||||
'links', 'name', 'status', 'updated', 'volume', 'ip']
|
||||
'links', 'name', 'status', 'updated', 'ip']
|
||||
if VOLUME_SUPPORT:
|
||||
expected_attrs.append('volume')
|
||||
instance = dbaas.instances.get(instance_info.id)
|
||||
assert_equal(200, dbaas.last_http_code)
|
||||
instance_dict = instance._info
|
||||
@ -829,7 +882,7 @@ class TestInstanceListing(object):
|
||||
def test_get_legacy_status_notfound(self):
|
||||
assert_raises(exceptions.NotFound, dbaas.instances.get, -2)
|
||||
|
||||
@test(enabled=CONFIG.values["reddwarf_volume_support"])
|
||||
@test(enabled=VOLUME_SUPPORT)
|
||||
def test_volume_found(self):
|
||||
instance = dbaas.instances.get(instance_info.id)
|
||||
if create_new_instance():
|
||||
@ -960,7 +1013,7 @@ class DeleteInstance(object):
|
||||
" time: %s" % (str(instance_info.id), attempts, str(ex)))
|
||||
|
||||
@time_out(30)
|
||||
@test(enabled=CONFIG.values["reddwarf_volume_support"],
|
||||
@test(enabled=VOLUME_SUPPORT,
|
||||
depends_on=[test_delete])
|
||||
def test_volume_is_deleted(self):
|
||||
raise SkipTest("Cannot test volume is deleted from db.")
|
||||
@ -1105,14 +1158,13 @@ class CheckInstance(AttrCheck):
|
||||
self.links(self.instance['flavor']['links'])
|
||||
|
||||
def volume_key_exists(self):
|
||||
if CONFIG.values['reddwarf_volume_support']:
|
||||
if 'volume' not in self.instance:
|
||||
self.fail("'volume' not found in instance.")
|
||||
return False
|
||||
return True
|
||||
if 'volume' not in self.instance:
|
||||
self.fail("'volume' not found in instance.")
|
||||
return False
|
||||
return True
|
||||
|
||||
def volume(self):
|
||||
if not CONFIG.values["reddwarf_volume_support"]:
|
||||
if not VOLUME_SUPPORT:
|
||||
return
|
||||
if self.volume_key_exists():
|
||||
expected_attrs = ['size']
|
||||
@ -1122,7 +1174,7 @@ class CheckInstance(AttrCheck):
|
||||
msg="Volumes")
|
||||
|
||||
def used_volume(self):
|
||||
if not CONFIG.values["reddwarf_volume_support"]:
|
||||
if not VOLUME_SUPPORT:
|
||||
return
|
||||
if self.volume_key_exists():
|
||||
expected_attrs = ['size', 'used']
|
||||
@ -1131,6 +1183,8 @@ class CheckInstance(AttrCheck):
|
||||
msg="Volumes")
|
||||
|
||||
def volume_mgmt(self):
|
||||
if not VOLUME_SUPPORT:
|
||||
return
|
||||
if self.volume_key_exists():
|
||||
expected_attrs = ['description', 'id', 'name', 'size']
|
||||
self.attrs_exist(self.instance['volume'], expected_attrs,
|
||||
@ -1152,6 +1206,8 @@ class CheckInstance(AttrCheck):
|
||||
msg="Guest status")
|
||||
|
||||
def mgmt_volume(self):
|
||||
if not VOLUME_SUPPORT:
|
||||
return
|
||||
expected_attrs = ['description', 'id', 'name', 'size']
|
||||
self.attrs_exist(self.instance['volume'], expected_attrs,
|
||||
msg="Volume")
|
||||
@ -1183,7 +1239,13 @@ class BadInstanceStatusBug():
|
||||
# can be used as another case. This all boils back to the same
|
||||
# piece of code so I'm not sure if it's relevant or not but could
|
||||
# be done.
|
||||
result = self.client.instances.create('testbox', 1, {'size': 5})
|
||||
size = None
|
||||
if VOLUME_SUPPORT:
|
||||
size = {'size': 5}
|
||||
|
||||
result = self.client.instances.create('testbox',
|
||||
instance_info.dbaas_flavor_href,
|
||||
size)
|
||||
id = result.id
|
||||
self.instances.append(id)
|
||||
|
||||
|
@ -25,11 +25,14 @@ from proboscis import SkipTest
|
||||
from reddwarf import tests
|
||||
from reddwarf.tests.util.check import Checker
|
||||
from reddwarfclient.exceptions import BadRequest
|
||||
from reddwarfclient.exceptions import HTTPNotImplemented
|
||||
from reddwarfclient.exceptions import UnprocessableEntity
|
||||
from reddwarf.tests.api.instances import GROUP as INSTANCE_GROUP
|
||||
from reddwarf.tests.api.instances import GROUP_START
|
||||
from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests.api.instances import assert_unprocessable
|
||||
from reddwarf.tests.api.instances import VOLUME_SUPPORT
|
||||
from reddwarf.tests.api.instances import EPHEMERAL_SUPPORT
|
||||
from reddwarf.tests import util
|
||||
from reddwarf.tests.util.server_connection import create_server_connection
|
||||
from reddwarf.tests.util import poll_until
|
||||
@ -326,7 +329,7 @@ class StopTests(RebootTestBase):
|
||||
Confirms the get call behaves appropriately while an instance is
|
||||
down.
|
||||
"""
|
||||
if not CONFIG.reddwarf_volume_support:
|
||||
if not VOLUME_SUPPORT:
|
||||
raise SkipTest("Not testing volumes.")
|
||||
instance = self.dbaas.instances.get(self.instance_id)
|
||||
with TypeCheck("instance", instance) as check:
|
||||
@ -416,14 +419,33 @@ class ResizeInstanceTest(ActionTestBase):
|
||||
assert_raises(BadRequest, self.dbaas.instances.resize_instance,
|
||||
self.instance_id, self.flavor_id)
|
||||
|
||||
@test(enabled=VOLUME_SUPPORT)
|
||||
def test_instance_resize_to_ephemeral_in_volume_support_should_fail(self):
|
||||
flavor_name = CONFIG.values.get('instance_bigger_eph_flavor_name',
|
||||
'eph.rd-smaller')
|
||||
flavors = self.dbaas.find_flavors_by_name(flavor_name)
|
||||
assert_raises(HTTPNotImplemented, self.dbaas.instances.resize_instance,
|
||||
self.instance_id, flavors[0].id)
|
||||
|
||||
@test(enabled=EPHEMERAL_SUPPORT)
|
||||
def test_instance_resize_to_non_ephemeral_flavor_should_fail(self):
|
||||
flavor_name = CONFIG.values.get('instance_bigger_flavor_name',
|
||||
'm1-small')
|
||||
flavors = self.dbaas.find_flavors_by_name(flavor_name)
|
||||
assert_raises(BadRequest, self.dbaas.instances.resize_instance,
|
||||
self.instance_id, flavors[0].id)
|
||||
|
||||
def obtain_flavor_ids(self):
|
||||
old_id = self.instance.flavor['id']
|
||||
self.expected_old_flavor_id = old_id
|
||||
res = instance_info.dbaas.find_flavor_and_self_href(old_id)
|
||||
self.expected_dbaas_flavor, _dontcare_ = res
|
||||
|
||||
flavor_name = CONFIG.values.get('instance_bigger_flavor_name',
|
||||
'm1.small')
|
||||
if EPHEMERAL_SUPPORT:
|
||||
flavor_name = CONFIG.values.get('instance_bigger_eph_flavor_name',
|
||||
'eph.rd-smaller')
|
||||
else:
|
||||
flavor_name = CONFIG.values.get('instance_bigger_flavor_name',
|
||||
'm1.small')
|
||||
flavors = self.dbaas.find_flavors_by_name(flavor_name)
|
||||
assert_equal(len(flavors), 1, "Number of flavors with name '%s' "
|
||||
"found was '%d'." % (flavor_name, len(flavors)))
|
||||
@ -548,7 +570,7 @@ def resize_should_not_delete_users():
|
||||
|
||||
@test(runs_after=[ResizeInstanceTest], depends_on=[create_user],
|
||||
groups=[GROUP, tests.INSTANCES],
|
||||
enabled=CONFIG.reddwarf_volume_support)
|
||||
enabled=VOLUME_SUPPORT)
|
||||
class ResizeInstanceVolume(object):
|
||||
""" Resize the volume of the instance """
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import time
|
||||
|
||||
from proboscis import after_class
|
||||
from proboscis import before_class
|
||||
from proboscis import test
|
||||
from proboscis.asserts import *
|
||||
@ -11,6 +10,8 @@ from reddwarf.tests.util import create_dbaas_client
|
||||
from reddwarf.tests.util import poll_until
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.util.users import Requirements
|
||||
from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests.api.instances import VOLUME_SUPPORT
|
||||
|
||||
|
||||
class TestBase(object):
|
||||
@ -21,7 +22,12 @@ class TestBase(object):
|
||||
self.dbaas = create_dbaas_client(self.user)
|
||||
|
||||
def create_instance(self, name, size=1):
|
||||
result = self.dbaas.instances.create(name, 1, {'size': size}, [], [])
|
||||
volume = None
|
||||
if VOLUME_SUPPORT:
|
||||
volume = {'size': size}
|
||||
result = self.dbaas.instances.create(name,
|
||||
instance_info.dbaas_flavor_href,
|
||||
volume, [], [])
|
||||
return result.id
|
||||
|
||||
def wait_for_instance_status(self, instance_id, status="ACTIVE"):
|
||||
@ -73,8 +79,12 @@ class ErroredInstanceDelete(TestBase):
|
||||
super(ErroredInstanceDelete, self).set_up()
|
||||
# Create an instance that fails during server prov.
|
||||
self.server_error = self.create_instance('test_SERVER_ERROR')
|
||||
# Create an instance that fails during volume prov.
|
||||
self.volume_error = self.create_instance('test_VOLUME_ERROR', size=9)
|
||||
if VOLUME_SUPPORT:
|
||||
# Create an instance that fails during volume prov.
|
||||
self.volume_error = self.create_instance('test_VOLUME_ERROR',
|
||||
size=9)
|
||||
else:
|
||||
self.volume_error = None
|
||||
# Create an instance that fails during DNS prov.
|
||||
#self.dns_error = self.create_instance('test_DNS_ERROR')
|
||||
# Create an instance that fails while it's been deleted the first time.
|
||||
@ -85,7 +95,7 @@ class ErroredInstanceDelete(TestBase):
|
||||
def delete_server_error(self):
|
||||
self.delete_errored_instance(self.server_error)
|
||||
|
||||
@test
|
||||
@test(enabled=VOLUME_SUPPORT)
|
||||
@time_out(20)
|
||||
def delete_volume_error(self):
|
||||
self.delete_errored_instance(self.volume_error)
|
||||
|
@ -30,6 +30,8 @@ from reddwarf.tests import util
|
||||
from reddwarf.tests.util import create_client
|
||||
from reddwarf.tests.util import poll_until
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.api.instances import VOLUME_SUPPORT
|
||||
from reddwarf.tests.api.instances import EPHEMERAL_SUPPORT
|
||||
|
||||
|
||||
@test(groups=["dbaas.api.instances.down"])
|
||||
@ -40,13 +42,21 @@ class TestBase(object):
|
||||
def set_up(self):
|
||||
self.client = create_client(is_admin=False)
|
||||
self.mgmt_client = create_client(is_admin=True)
|
||||
flavor_name = test_config.values.get('instance_flavor_name', 'm1.tiny')
|
||||
|
||||
if EPHEMERAL_SUPPORT:
|
||||
flavor_name = test_config.values.get('instance_eph_flavor_name',
|
||||
'eph.rd-tiny')
|
||||
flavor2_name = test_config.values.get(
|
||||
'instance_bigger_eph_flavor_name', 'eph.rd-smaller')
|
||||
else:
|
||||
flavor_name = test_config.values.get('instance_flavor_name',
|
||||
'm1.tiny')
|
||||
flavor2_name = test_config.values.get(
|
||||
'instance_bigger_flavor_name', 'm1.small')
|
||||
flavors = self.client.find_flavors_by_name(flavor_name)
|
||||
self.flavor_id = flavors[0].id
|
||||
self.name = "TEST_" + str(datetime.now())
|
||||
# Get the resize to flavor.
|
||||
flavor2_name = test_config.values.get('instance_bigger_flavor_name',
|
||||
'm1.small')
|
||||
flavors2 = self.client.find_flavors_by_name(flavor2_name)
|
||||
self.new_flavor_id = flavors2[0].id
|
||||
assert_not_equal(self.flavor_id, self.new_flavor_id)
|
||||
@ -58,8 +68,11 @@ class TestBase(object):
|
||||
|
||||
@test
|
||||
def create_instance(self):
|
||||
volume = None
|
||||
if VOLUME_SUPPORT:
|
||||
volume = {'size': 1}
|
||||
initial = self.client.instances.create(self.name, self.flavor_id,
|
||||
{'size': 1}, [], [])
|
||||
volume, [], [])
|
||||
self.id = initial.id
|
||||
self._wait_for_active()
|
||||
|
||||
@ -82,7 +95,8 @@ class TestBase(object):
|
||||
def put_into_shutdown_state_2(self):
|
||||
self._shutdown_instance()
|
||||
|
||||
@test(depends_on=[put_into_shutdown_state_2])
|
||||
@test(depends_on=[put_into_shutdown_state_2],
|
||||
enabled=VOLUME_SUPPORT)
|
||||
@time_out(60 * 5)
|
||||
def resize_volume_in_shutdown_state(self):
|
||||
self.client.instances.resize_volume(self.id, 2)
|
||||
|
@ -10,11 +10,13 @@ from reddwarf.tests.util import create_dbaas_client
|
||||
from reddwarfclient import exceptions
|
||||
from datetime import datetime
|
||||
from reddwarf.tests.util.users import Users
|
||||
from reddwarf.tests.config import CONFIG
|
||||
|
||||
GROUP = "dbaas.api.limits"
|
||||
DEFAULT_RATE = 200
|
||||
DEFAULT_MAX_VOLUMES = 100
|
||||
DEFAULT_MAX_INSTANCES = 55
|
||||
DEFAULT_MAX_BACKUPS = 5
|
||||
|
||||
|
||||
@test(groups=[GROUP])
|
||||
@ -72,8 +74,10 @@ class Limits(object):
|
||||
# remove the abs_limits from the rate limits
|
||||
abs_limits = d.pop("ABSOLUTE", None)
|
||||
assert_equal(abs_limits.verb, "ABSOLUTE")
|
||||
assert_equal(int(abs_limits.maxTotalInstances), DEFAULT_MAX_INSTANCES)
|
||||
assert_equal(int(abs_limits.maxTotalVolumes), DEFAULT_MAX_VOLUMES)
|
||||
assert_equal(int(abs_limits.max_instances), DEFAULT_MAX_INSTANCES)
|
||||
assert_equal(int(abs_limits.max_backups), DEFAULT_MAX_BACKUPS)
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
assert_equal(int(abs_limits.max_volumes), DEFAULT_MAX_VOLUMES)
|
||||
|
||||
for k in d:
|
||||
assert_equal(d[k].verb, k)
|
||||
@ -93,8 +97,10 @@ class Limits(object):
|
||||
abs_limits = d["ABSOLUTE"]
|
||||
get = d["GET"]
|
||||
|
||||
assert_equal(int(abs_limits.maxTotalInstances), DEFAULT_MAX_INSTANCES)
|
||||
assert_equal(int(abs_limits.maxTotalVolumes), DEFAULT_MAX_VOLUMES)
|
||||
assert_equal(int(abs_limits.max_instances), DEFAULT_MAX_INSTANCES)
|
||||
assert_equal(int(abs_limits.max_backups), DEFAULT_MAX_BACKUPS)
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
assert_equal(int(abs_limits.max_volumes), DEFAULT_MAX_VOLUMES)
|
||||
assert_equal(get.verb, "GET")
|
||||
assert_equal(get.unit, "MINUTE")
|
||||
assert_true(int(get.remaining) <= DEFAULT_RATE - 5)
|
||||
@ -119,10 +125,13 @@ class Limits(object):
|
||||
|
||||
assert_equal(get.verb, "GET")
|
||||
assert_equal(get.unit, "MINUTE")
|
||||
assert_equal(int(abs_limits.maxTotalInstances),
|
||||
assert_equal(int(abs_limits.max_instances),
|
||||
DEFAULT_MAX_INSTANCES)
|
||||
assert_equal(int(abs_limits.maxTotalVolumes),
|
||||
DEFAULT_MAX_VOLUMES)
|
||||
assert_equal(int(abs_limits.max_backups),
|
||||
DEFAULT_MAX_BACKUPS)
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
assert_equal(int(abs_limits.max_volumes),
|
||||
DEFAULT_MAX_VOLUMES)
|
||||
|
||||
except exceptions.OverLimit:
|
||||
encountered = True
|
||||
|
@ -27,6 +27,7 @@ from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.util import create_dbaas_client
|
||||
from reddwarf.tests.util import poll_until
|
||||
from reddwarf.tests.config import CONFIG
|
||||
from reddwarf.tests.util.users import Requirements
|
||||
from reddwarf.tests.api.instances import existing_instance
|
||||
|
||||
@ -188,8 +189,14 @@ class AccountWithBrokenInstance(object):
|
||||
self.client = create_dbaas_client(self.user)
|
||||
self.name = 'test_SERVER_ERROR'
|
||||
# Create an instance with a broken compute instance.
|
||||
self.response = self.client.instances.create(self.name, 1,
|
||||
{'size': 1}, [])
|
||||
volume = None
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
volume = {'size': 1}
|
||||
self.response = self.client.instances.create(
|
||||
self.name,
|
||||
instance_info.dbaas_flavor_href,
|
||||
volume,
|
||||
[])
|
||||
poll_until(lambda: self.client.instances.get(self.response.id),
|
||||
lambda instance: instance.status == 'ERROR',
|
||||
time_out=10)
|
||||
|
@ -110,7 +110,8 @@ def mgmt_instance_get():
|
||||
server.has_element("name", basestring)
|
||||
server.has_element("status", basestring)
|
||||
server.has_element("tenant_id", basestring)
|
||||
if CONFIG.reddwarf_main_instance_has_volume:
|
||||
if (CONFIG.reddwarf_volume_support and
|
||||
CONFIG.reddwarf_main_instance_has_volume):
|
||||
with CollectionCheck("volume", api_instance.volume) as volume:
|
||||
volume.has_element("attachments", list)
|
||||
volume.has_element("availability_zone", basestring)
|
||||
@ -134,8 +135,14 @@ class WhenMgmtInstanceGetIsCalledButServerIsNotReady(object):
|
||||
# Fake volume will fail if the size is 13.
|
||||
# TODO(tim.simpson): This would be a lot nicer looking if we used a
|
||||
# traditional mock framework.
|
||||
response = self.client.instances.create('test_SERVER_ERROR', 1,
|
||||
{'size': 13}, [])
|
||||
body = None
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
body = {'size': 13}
|
||||
response = self.client.instances.create(
|
||||
'test_SERVER_ERROR',
|
||||
instance_info.dbaas_flavor_href,
|
||||
body,
|
||||
[])
|
||||
poll_until(lambda: self.client.instances.get(response.id),
|
||||
lambda instance: instance.status == 'ERROR',
|
||||
time_out=10)
|
||||
@ -201,8 +208,10 @@ class MgmtInstancesIndex(object):
|
||||
'task_description',
|
||||
'tenant_id',
|
||||
'updated',
|
||||
'volume',
|
||||
]
|
||||
if CONFIG.reddwarf_volume_support:
|
||||
expected_fields.append('volume')
|
||||
|
||||
index = self.client.management.index()
|
||||
for instance in index:
|
||||
with Check() as check:
|
||||
|
@ -4,6 +4,8 @@ from proboscis import after_class
|
||||
from proboscis import before_class
|
||||
from proboscis.asserts import Check
|
||||
from reddwarf.tests.config import CONFIG
|
||||
from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests.api.instances import VOLUME_SUPPORT
|
||||
from reddwarfclient import exceptions
|
||||
import json
|
||||
import requests
|
||||
@ -22,10 +24,13 @@ class MalformedJson(object):
|
||||
self.reqs = Requirements(is_admin=False)
|
||||
self.user = CONFIG.users.find_user(self.reqs)
|
||||
self.dbaas = create_dbaas_client(self.user)
|
||||
volume = None
|
||||
if VOLUME_SUPPORT:
|
||||
volume = {"size": 1}
|
||||
self.instance = self.dbaas.instances.create(
|
||||
name="qe_instance",
|
||||
flavor_id=1,
|
||||
volume={"size": 1},
|
||||
flavor_id=instance_info.dbaas_flavor_href,
|
||||
volume=volume,
|
||||
databases=[{"name": "firstdb", "character_set": "latin2",
|
||||
"collate": "latin2_general_ci"}])
|
||||
|
||||
|
@ -32,13 +32,13 @@ FAKE_HOSTS = ["fake_host_1", "fake_host_2"]
|
||||
|
||||
class FakeFlavor(object):
|
||||
|
||||
def __init__(self, id, disk, name, ram):
|
||||
def __init__(self, id, disk, name, ram, ephemeral=0, vcpus=10):
|
||||
self.id = id
|
||||
self.disk = disk
|
||||
self.name = name
|
||||
self.ram = ram
|
||||
self.vcpus = 10
|
||||
self.ephemeral = 0
|
||||
self.vcpus = vcpus
|
||||
self.ephemeral = ephemeral
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
@ -69,6 +69,8 @@ class FakeFlavors(object):
|
||||
self._add(8, 2, "m1.rd-smaller", 768)
|
||||
self._add(9, 10, "tinier", 506)
|
||||
self._add(10, 2, "m1.rd-tiny", 512)
|
||||
self._add(11, 0, "eph.rd-tiny", 512, 1)
|
||||
self._add(12, 20, "eph.rd-smaller", 768, 2)
|
||||
|
||||
def _add(self, *args, **kwargs):
|
||||
new_flavor = FakeFlavor(*args, **kwargs)
|
||||
|
@ -44,8 +44,9 @@ class BaseLimitTestSuite(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseLimitTestSuite, self).setUp()
|
||||
self.absolute_limits = {"maxTotalInstances": 55,
|
||||
"maxTotalVolumes": 100}
|
||||
self.absolute_limits = {"max_instances": 55,
|
||||
"max_volumes": 100,
|
||||
"max_backups": 40}
|
||||
|
||||
|
||||
class LimitsControllerTest(BaseLimitTestSuite):
|
||||
@ -60,8 +61,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
|
||||
when(QUOTAS).get_all_quotas_by_tenant(any()).thenReturn({})
|
||||
|
||||
view = limit_controller.index(req, "test_tenant_id")
|
||||
expected = {'limits': [{'maxTotalInstances': 0,
|
||||
'verb': 'ABSOLUTE', 'maxTotalVolumes': 0}]}
|
||||
expected = {'limits': [{'verb': 'ABSOLUTE'}]}
|
||||
self.assertEqual(expected, view._data)
|
||||
|
||||
def test_limit_index(self):
|
||||
@ -111,6 +111,10 @@ class LimitsControllerTest(BaseLimitTestSuite):
|
||||
resource="instances",
|
||||
hard_limit=100),
|
||||
|
||||
"backups": Quota(tenant_id=tenant_id,
|
||||
resource="backups",
|
||||
hard_limit=40),
|
||||
|
||||
"volumes": Quota(tenant_id=tenant_id,
|
||||
resource="volumes",
|
||||
hard_limit=55)}
|
||||
@ -124,9 +128,10 @@ class LimitsControllerTest(BaseLimitTestSuite):
|
||||
expected = {
|
||||
'limits': [
|
||||
{
|
||||
'maxTotalInstances': 100,
|
||||
'max_instances': 100,
|
||||
'max_backups': 40,
|
||||
'verb': 'ABSOLUTE',
|
||||
'maxTotalVolumes': 55
|
||||
'max_volumes': 55
|
||||
},
|
||||
{
|
||||
'regex': '.*',
|
||||
@ -752,9 +757,7 @@ class LimitsViewsTest(testtools.TestCase):
|
||||
self.assertIsNotNone(view_data)
|
||||
|
||||
data = view_data.data()
|
||||
expected = {'limits': [{'maxTotalInstances': 0,
|
||||
'verb': 'ABSOLUTE',
|
||||
'maxTotalVolumes': 0}]}
|
||||
expected = {'limits': [{'verb': 'ABSOLUTE'}]}
|
||||
|
||||
self.assertEqual(expected, data)
|
||||
|
||||
@ -797,15 +800,16 @@ class LimitsViewsTest(testtools.TestCase):
|
||||
"resetTime": 1311272226
|
||||
}
|
||||
]
|
||||
abs_view = {"instances": 55, "volumes": 100}
|
||||
abs_view = {"instances": 55, "volumes": 100, "backups": 40}
|
||||
|
||||
view_data = views.LimitViews(abs_view, rate_limits)
|
||||
self.assertIsNotNone(view_data)
|
||||
|
||||
data = view_data.data()
|
||||
expected = {'limits': [{'maxTotalInstances': 55,
|
||||
expected = {'limits': [{'max_instances': 55,
|
||||
'max_backups': 40,
|
||||
'verb': 'ABSOLUTE',
|
||||
'maxTotalVolumes': 100},
|
||||
'max_volumes': 100},
|
||||
{'regex': '.*',
|
||||
'nextAvailable': '2011-07-21T18:17:06Z',
|
||||
'uri': '*',
|
||||
|
@ -110,7 +110,22 @@ class QuotaControllerTest(testtools.TestCase):
|
||||
verify(quota, never).save()
|
||||
self.assertEquals(200, result.status)
|
||||
|
||||
def test_update_resource_(self):
|
||||
def test_update_resource_instance(self):
|
||||
instance_quota = mock(Quota)
|
||||
when(DatabaseModelBase).find_by(
|
||||
tenant_id=FAKE_TENANT2,
|
||||
resource='instances').thenReturn(instance_quota)
|
||||
body = {'quotas': {'instances': 2}}
|
||||
result = self.controller.update(self.req, body, FAKE_TENANT1,
|
||||
FAKE_TENANT2)
|
||||
verify(instance_quota, times=1).save()
|
||||
self.assertTrue('instances' in result._data['quotas'])
|
||||
self.assertEquals(200, result.status)
|
||||
self.assertEquals(2, result._data['quotas']['instances'])
|
||||
|
||||
@testtools.skipIf(not CONF.reddwarf_volume_support,
|
||||
'Volume support is not enabled')
|
||||
def test_update_resource_volume(self):
|
||||
instance_quota = mock(Quota)
|
||||
when(DatabaseModelBase).find_by(
|
||||
tenant_id=FAKE_TENANT2,
|
||||
@ -123,7 +138,7 @@ class QuotaControllerTest(testtools.TestCase):
|
||||
result = self.controller.update(self.req, body, FAKE_TENANT1,
|
||||
FAKE_TENANT2)
|
||||
verify(instance_quota, never).save()
|
||||
self.assertFalse('instances' in result._data)
|
||||
self.assertFalse('instances' in result._data['quotas'])
|
||||
verify(volume_quota, times=1).save()
|
||||
self.assertEquals(200, result.status)
|
||||
self.assertEquals(10, result._data['quotas']['volumes'])
|
||||
|
Loading…
Reference in New Issue
Block a user