Only display the bootable volume snapshots when creating instance

The volume snapshot of non-bootable volume could not be as the instance source.
But now,when we select volume snapshot as source, not only bootable volume
snapshots but also non-bootable ones show up.

Change-Id: I36cd02f34029eedb693047a1bf3f01dad05aa1b3
Closes-Bug: #1748724
This commit is contained in:
wangliangyu 2018-02-11 18:14:31 +08:00
parent 9ab701b5e2
commit fd67e0f664
4 changed files with 122 additions and 52 deletions

View File

@ -52,6 +52,7 @@ SEC_GROUP_ROLE_PREFIX = \
workflows.update_instance.INSTANCE_SEC_GROUP_SLUG + "_role_"
AVAILABLE = api.cinder.VOLUME_STATE_AVAILABLE
VOLUME_SEARCH_OPTS = dict(status=AVAILABLE, bootable=True)
VOLUME_BOOTABLE_SEARCH_OPTS = dict(bootable=True)
SNAPSHOT_SEARCH_OPTS = dict(status=AVAILABLE)
@ -2058,9 +2059,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2224,9 +2228,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2332,9 +2339,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
})
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2473,9 +2483,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2594,9 +2607,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
})
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2692,9 +2708,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self._check_glance_image_list_detailed(count=5)
self._check_neutron_network_and_port_list()
self._check_nova_lists(flavor_count=3)
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2761,9 +2780,11 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ServerGroups': True,
})
self.mock_server_group_list.return_value = []
volumes = [v for v in self.cinder_volumes.list()
if (getattr(v, 'bootable', 'false') == 'true')]
snapshots = [v for v in self.cinder_volume_snapshots.list()
if (v.status == AVAILABLE)]
self.mock_volume_list.return_value = []
self.mock_volume_list.return_value = volumes
self.mock_volume_snapshot_list.return_value = snapshots
self.mock_server_create.return_value = None
self.mock_tenant_quota_usages.return_value = quota_usages
@ -2803,9 +2824,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
})
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -2970,9 +2994,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3077,9 +3104,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3190,9 +3220,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3298,9 +3331,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
})
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3393,9 +3429,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
'ConfigDrive': 1,
'ServerGroups': 1,
})
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3582,9 +3621,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
network_id=net.id,
tenant_id=self.tenant.id)
for net in self.networks.list()])
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3716,9 +3758,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self._check_neutron_network_and_port_list()
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -3960,9 +4005,12 @@ class InstanceLaunchInstanceTests(InstanceTestBase,
self.mock_server_group_list.assert_called_once_with(
helpers.IsHttpRequest())
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(),
search_opts=SNAPSHOT_SEARCH_OPTS)
@ -4084,8 +4132,12 @@ class InstanceTests2(InstanceTestBase, InstanceTableTestMixin):
html=True,
msg_prefix="The default key pair was not selected.")
self.mock_volume_list.assert_called_once_with(
helpers.IsHttpRequest(), search_opts=VOLUME_SEARCH_OPTS)
self.mock_volume_list.assert_has_calls([
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_SEARCH_OPTS),
mock.call(helpers.IsHttpRequest(),
search_opts=VOLUME_BOOTABLE_SEARCH_OPTS),
])
self.mock_volume_snapshot_list.assert_called_once_with(
helpers.IsHttpRequest(), search_opts=SNAPSHOT_SEARCH_OPTS)
self._check_glance_image_list_detailed(count=5)

View File

@ -489,9 +489,12 @@ class SetInstanceDetailsAction(workflows.Action):
try:
if cinder.is_volume_service_enabled(request):
available = api.cinder.VOLUME_STATE_AVAILABLE
volumes = [v.id for v in cinder.volume_list(
self.request, search_opts=dict(bootable=True))]
snapshots = [self._get_volume_display_name(s)
for s in cinder.volume_snapshot_list(
self.request, search_opts=dict(status=available))]
self.request, search_opts=dict(status=available))
if s.volume_id in volumes]
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve list of volume '

View File

@ -678,8 +678,20 @@
}
function onGetVolumeSnapshots(data) {
cinderAPI.getVolumes({bootable: 1}).then(function (volumes) {
onGetBootableVolumeSnapshots(volumes.data.items, data.data.items);
});
}
function onGetBootableVolumeSnapshots(bootableVolumes, volumeSnapshots) {
var bootableVolumeIds = [];
bootableVolumes.forEach(function(volume) {
bootableVolumeIds.push(volume.id);
});
model.volumeSnapshots.length = 0;
push.apply(model.volumeSnapshots, data.data.items);
push.apply(model.volumeSnapshots, volumeSnapshots.filter(function (volumeSnapshot) {
return bootableVolumeIds.indexOf(volumeSnapshot.volume_id) !== -1;
}));
addAllowedBootSource(
model.volumeSnapshots,
bootSourceTypes.VOLUME_SNAPSHOT,

View File

@ -229,7 +229,9 @@
return deferred.promise;
},
getVolumeSnapshots: function() {
var snapshots = [ { id: 'snap-1' }, { id: 'snap-2' } ];
var snapshots = [ { id: 'snap-1', volume_id: 'vol-1' },
{ id: 'snap-2', volume_id: 'vol-2' },
{ id: 'snap-3', volume_id: 'vol-3' } ];
var deferred = $q.defer();
deferred.resolve({ data: { items: snapshots } });
@ -682,7 +684,8 @@
expect(model.volumes.length).toBe(0);
expect(model.volumes).toEqual([]);
expect(model.volumeSnapshots.length).toBe(2);
expect(model.volumeSnapshots).toEqual([{ id: 'snap-1' }, { id: 'snap-2' }]);
expect(model.volumeSnapshots).toEqual([{ id: 'snap-1', volume_id: 'vol-1' },
{ id: 'snap-2', volume_id: 'vol-2' }]);
expect(model.allowedBootSources).toBeDefined();
expect(model.allowedBootSources.length).toBe(3);
expect(model.allowedBootSources).toContain(IMAGE);