Merge "Enable backups on in-use volumes"
This commit is contained in:
commit
3a5fe30a1e
|
@ -668,7 +668,8 @@ def volume_backup_create(request,
|
|||
volume_id,
|
||||
container_name,
|
||||
name,
|
||||
description):
|
||||
description,
|
||||
force=False):
|
||||
# need to ensure the container name is not an empty
|
||||
# string, but pass None to get the container name
|
||||
# generated correctly
|
||||
|
@ -676,7 +677,8 @@ def volume_backup_create(request,
|
|||
volume_id,
|
||||
container=container_name if container_name else None,
|
||||
name=name,
|
||||
description=description)
|
||||
description=description,
|
||||
force=force)
|
||||
return VolumeBackup(backup)
|
||||
|
||||
|
||||
|
|
|
@ -44,11 +44,16 @@ class CreateBackupForm(forms.SelfHandlingForm):
|
|||
def handle(self, request, data):
|
||||
|
||||
try:
|
||||
volume = api.cinder.volume_get(request, data['volume_id'])
|
||||
force = False
|
||||
if volume.status == 'in-use':
|
||||
force = True
|
||||
backup = api.cinder.volume_backup_create(request,
|
||||
data['volume_id'],
|
||||
data['container_name'],
|
||||
data['name'],
|
||||
data['description'])
|
||||
data['description'],
|
||||
force=force)
|
||||
|
||||
message = _('Creating volume backup "%s"') % data['name']
|
||||
messages.info(request, message)
|
||||
|
|
|
@ -112,16 +112,50 @@ class VolumeBackupsViewTests(test.TestCase):
|
|||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_backup_create',)})
|
||||
def test_create_backup_post(self):
|
||||
@test.create_stubs({api.cinder: ('volume_backup_create', 'volume_get')})
|
||||
def test_create_backup_available(self):
|
||||
volume = self.volumes.first()
|
||||
backup = self.cinder_volume_backups.first()
|
||||
|
||||
api.cinder.volume_get(IsA(http.HttpRequest), volume.id). \
|
||||
AndReturn(volume)
|
||||
api.cinder.volume_backup_create(IsA(http.HttpRequest),
|
||||
volume.id,
|
||||
backup.container_name,
|
||||
backup.name,
|
||||
backup.description) \
|
||||
backup.description,
|
||||
force=False) \
|
||||
.AndReturn(backup)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'method': 'CreateBackupForm',
|
||||
'tenant_id': self.tenant.id,
|
||||
'volume_id': volume.id,
|
||||
'container_name': backup.container_name,
|
||||
'name': backup.name,
|
||||
'description': backup.description}
|
||||
url = reverse('horizon:project:volumes:create_backup',
|
||||
args=[volume.id])
|
||||
res = self.client.post(url, formData)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertMessageCount(error=0, warning=0)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_backup_create', 'volume_get')})
|
||||
def test_create_backup_in_use(self):
|
||||
# The second volume in the cinder test volume data is in-use
|
||||
volume = self.volumes.list()[1]
|
||||
backup = self.cinder_volume_backups.first()
|
||||
|
||||
api.cinder.volume_get(IsA(http.HttpRequest), volume.id). \
|
||||
AndReturn(volume)
|
||||
api.cinder.volume_backup_create(IsA(http.HttpRequest),
|
||||
volume.id,
|
||||
backup.container_name,
|
||||
backup.name,
|
||||
backup.description,
|
||||
force=True) \
|
||||
.AndReturn(backup)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ class CreateBackup(VolumePolicyTargetMixin, tables.LinkAction):
|
|||
|
||||
def allowed(self, request, volume=None):
|
||||
return (cinder.volume_backup_supported(request) and
|
||||
volume.status == "available")
|
||||
volume.status in ("available", "in-use"))
|
||||
|
||||
|
||||
class UploadToImage(VolumePolicyTargetMixin, tables.LinkAction):
|
||||
|
|
|
@ -1951,3 +1951,38 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||
self.assertEqual(res.get('content-type'), 'application/text')
|
||||
self.assertIn(transfer.id, res.content.decode('utf-8'))
|
||||
self.assertIn(transfer.auth_key, res.content.decode('utf-8'))
|
||||
|
||||
@test.create_stubs({cinder: ('volume_backup_supported',
|
||||
'volume_list_paged',
|
||||
'volume_snapshot_list',
|
||||
'tenant_absolute_limits',
|
||||
'volume_get'),
|
||||
api.nova: ('server_list',)})
|
||||
def test_create_backup_availability(self):
|
||||
limits = self.cinder_limits['absolute']
|
||||
|
||||
cinder.volume_backup_supported(IsA(http.HttpRequest))\
|
||||
.MultipleTimes().AndReturn(True)
|
||||
cinder.volume_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, sort_dir='desc',
|
||||
search_opts=None, paginate=True)\
|
||||
.AndReturn([self.volumes.list(), False, False])
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest),
|
||||
search_opts=None).\
|
||||
AndReturn([])
|
||||
api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
|
||||
.AndReturn([self.servers.list(), False])
|
||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest))\
|
||||
.MultipleTimes().AndReturn(limits)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL)
|
||||
table = res.context['volumes_table']
|
||||
|
||||
# Verify that the create backup action is present if and only if
|
||||
# the volume is available or in-use
|
||||
for vol in table.data:
|
||||
actions = [a.name for a in table.get_row_actions(vol)]
|
||||
self.assertEqual('backups' in actions,
|
||||
vol.status in ('available', 'in-use'))
|
||||
|
|
Loading…
Reference in New Issue