Fix volume retype with migration as non-admin
As a non-admin user, when retyping a volume from type A -> B, where both types are in different backends, Cinder will complete the operation but the volumes will not be migrated. This happens because the retype operation relies in getting the extra_specs information to the related type, but extra_specs is only avaiable in admin context. Closes-bug: #1657806 Change-Id: Id9f39ddab3a3648b8721b711ecf78c18c8293451
This commit is contained in:
parent
183dca0f91
commit
7aecdf919c
|
@ -58,6 +58,9 @@ class BaseVolumeTestCase(test.TestCase):
|
||||||
# assertions with the notification code, it's part of an
|
# assertions with the notification code, it's part of an
|
||||||
# elastic-recheck query so don't remove it or change it.
|
# elastic-recheck query so don't remove it or change it.
|
||||||
self.project_id = '7f265bd4-3a85-465e-a899-5dc4854a86d3'
|
self.project_id = '7f265bd4-3a85-465e-a899-5dc4854a86d3'
|
||||||
|
self.user_context = context.RequestContext(user_id=fake.USER_ID,
|
||||||
|
project_id=self.project_id,
|
||||||
|
is_admin=False)
|
||||||
self.context.project_id = self.project_id
|
self.context.project_id = self.project_id
|
||||||
self.volume_params = {
|
self.volume_params = {
|
||||||
'status': 'creating',
|
'status': 'creating',
|
||||||
|
|
|
@ -53,8 +53,8 @@ def create_snapshot(volume_id, size=1, metadata=None, ctxt=None,
|
||||||
metadata = metadata or {}
|
metadata = metadata or {}
|
||||||
snap = objects.Snapshot(ctxt or context.get_admin_context())
|
snap = objects.Snapshot(ctxt or context.get_admin_context())
|
||||||
snap.volume_size = size
|
snap.volume_size = size
|
||||||
snap.user_id = fake.USER_ID
|
snap.user_id = kwargs.get('user_id', fake.USER_ID)
|
||||||
snap.project_id = fake.PROJECT_ID
|
snap.project_id = kwargs.get('project_id', fake.PROJECT_ID)
|
||||||
snap.volume_id = volume_id
|
snap.volume_id = volume_id
|
||||||
snap.status = "creating"
|
snap.status = "creating"
|
||||||
if metadata is not None:
|
if metadata is not None:
|
||||||
|
@ -710,7 +710,10 @@ class VolumeMigrationTestCase(base.BaseVolumeTestCase):
|
||||||
volume.previous_status = 'available'
|
volume.previous_status = 'available'
|
||||||
volume.save()
|
volume.save()
|
||||||
if snap:
|
if snap:
|
||||||
create_snapshot(volume.id, size=volume.size)
|
create_snapshot(volume.id, size=volume.size,
|
||||||
|
user_id=self.user_context.user_id,
|
||||||
|
project_id=self.user_context.project_id,
|
||||||
|
ctxt=self.user_context)
|
||||||
if driver or diff_equal:
|
if driver or diff_equal:
|
||||||
host_obj = {'host': CONF.host, 'capabilities': {}}
|
host_obj = {'host': CONF.host, 'capabilities': {}}
|
||||||
else:
|
else:
|
||||||
|
@ -746,9 +749,11 @@ class VolumeMigrationTestCase(base.BaseVolumeTestCase):
|
||||||
with mock.patch.object(self.volume.driver, 'retype') as _retype,\
|
with mock.patch.object(self.volume.driver, 'retype') as _retype,\
|
||||||
mock.patch.object(volume_types, 'volume_types_diff') as _diff,\
|
mock.patch.object(volume_types, 'volume_types_diff') as _diff,\
|
||||||
mock.patch.object(self.volume, 'migrate_volume') as _mig,\
|
mock.patch.object(self.volume, 'migrate_volume') as _mig,\
|
||||||
mock.patch.object(db.sqlalchemy.api, 'volume_get') as mock_get:
|
mock.patch.object(db.sqlalchemy.api, 'volume_get') as _vget,\
|
||||||
mock_get.return_value = volume
|
mock.patch.object(context.RequestContext, 'elevated') as _ctx:
|
||||||
|
_vget.return_value = volume
|
||||||
_retype.return_value = driver
|
_retype.return_value = driver
|
||||||
|
_ctx.return_value = self.context
|
||||||
returned_diff = {
|
returned_diff = {
|
||||||
'encryption': {},
|
'encryption': {},
|
||||||
'qos_specs': {},
|
'qos_specs': {},
|
||||||
|
|
|
@ -2305,10 +2305,11 @@ class VolumeManager(manager.CleanableManager,
|
||||||
# We already got the new reservations
|
# We already got the new reservations
|
||||||
new_reservations = reservations
|
new_reservations = reservations
|
||||||
|
|
||||||
# If volume types have the same contents, no need to do anything
|
# If volume types have the same contents, no need to do anything.
|
||||||
|
# Use the admin contex to be able to access volume extra_specs
|
||||||
retyped = False
|
retyped = False
|
||||||
diff, all_equal = volume_types.volume_types_diff(
|
diff, all_equal = volume_types.volume_types_diff(
|
||||||
context, volume.volume_type_id, new_type_id)
|
context.elevated(), volume.volume_type_id, new_type_id)
|
||||||
if all_equal:
|
if all_equal:
|
||||||
retyped = True
|
retyped = True
|
||||||
|
|
||||||
|
@ -2328,7 +2329,9 @@ class VolumeManager(manager.CleanableManager,
|
||||||
not diff.get('encryption') and
|
not diff.get('encryption') and
|
||||||
self._is_our_backend(host['host'], host.get('cluster_name'))):
|
self._is_our_backend(host['host'], host.get('cluster_name'))):
|
||||||
try:
|
try:
|
||||||
new_type = volume_types.get_volume_type(context, new_type_id)
|
new_type = volume_types.get_volume_type(context.elevated(),
|
||||||
|
new_type_id)
|
||||||
|
with volume.obj_as_admin():
|
||||||
ret = self.driver.retype(context,
|
ret = self.driver.retype(context,
|
||||||
volume,
|
volume,
|
||||||
new_type,
|
new_type,
|
||||||
|
|
Loading…
Reference in New Issue