Merge "Make API calls in Volumes view parallel"

This commit is contained in:
Zuul 2018-11-15 14:28:34 +00:00 committed by Gerrit Code Review
commit 11fbb9dbd1
3 changed files with 95 additions and 26 deletions

View File

@ -15,7 +15,6 @@
"""
Admin views for managing volumes and snapshots.
"""
from collections import OrderedDict
from django.conf import settings
from django.urls import reverse
@ -37,6 +36,7 @@ from openstack_dashboard.dashboards.admin.volumes \
import tabs as volumes_tabs
from openstack_dashboard.dashboards.project.volumes \
import views as volumes_views
from openstack_dashboard.utils import futurist_utils
class VolumesView(tables.PagedTableMixin, volumes_views.VolumeTableMixIn,
@ -61,10 +61,55 @@ class VolumesView(tables.PagedTableMixin, volumes_views.VolumeTableMixIn,
self.table.needs_filter_first = True
return volumes
volumes = []
attached_instance_ids = []
tenants = []
tenant_dict = {}
instances = []
volume_ids_with_snapshots = []
def _task_get_tenants():
# Gather our tenants to correlate against IDs
try:
tmp_tenants, __ = keystone.tenant_list(self.request)
tenants.extend(tmp_tenants)
tenant_dict.update([(t.id, t) for t in tenants])
except Exception:
msg = _('Unable to retrieve volume project information.')
exceptions.handle(self.request, msg)
def _task_get_instances():
# As long as Nova API does not allow passing attached_instance_ids
# to nova.server_list, this call can be forged to pass anything
# != None
instances.extend(self._get_instances(
search_opts={'all_tenants': True}))
# In volumes tab we don't need to know about the assignment
# instance-image, therefore fixing it to an empty value
for instance in instances:
if hasattr(instance, 'image'):
if isinstance(instance.image, dict):
instance.image['name'] = "-"
def _task_get_volumes_snapshots():
volume_ids_with_snapshots.extend(
self._get_volumes_ids_with_snapshots(
search_opts={'all_tenants': True}
))
def _task_get_volumes():
volumes.extend(self._get_volumes(search_opts=filters))
attached_instance_ids.extend(
self._get_attached_instance_ids(volumes))
if 'project' in filters:
# Keystone returns a tuple ([],false) where the first element is
# tenant list that's why the 0 is hardcoded below
tenants = keystone.tenant_list(self.request)[0]
futurist_utils.call_functions_parallel(
_task_get_tenants,
_task_get_instances,
_task_get_volumes_snapshots
)
tenant_ids = [t.id for t in tenants
if t.name == filters['project']]
if not tenant_ids:
@ -73,26 +118,18 @@ class VolumesView(tables.PagedTableMixin, volumes_views.VolumeTableMixIn,
for id in tenant_ids:
filters['project_id'] = id
volumes += self._get_volumes(search_opts=filters)
attached_instance_ids = self._get_attached_instance_ids(volumes)
else:
volumes = self._get_volumes(search_opts=filters)
futurist_utils.call_functions_parallel(
_task_get_volumes,
_task_get_tenants,
_task_get_instances,
_task_get_volumes_snapshots
)
attached_instance_ids = self._get_attached_instance_ids(volumes)
instances = self._get_instances(search_opts={'all_tenants': True},
instance_ids=attached_instance_ids)
volume_ids_with_snapshots = self._get_volumes_ids_with_snapshots(
search_opts={'all_tenants': True})
self._set_volume_attributes(
volumes, instances, volume_ids_with_snapshots)
# Gather our tenants to correlate against IDs
try:
tenants, has_more = keystone.tenant_list(self.request)
except Exception:
tenants = []
msg = _('Unable to retrieve volume project information.')
exceptions.handle(self.request, msg)
tenant_dict = OrderedDict([(t.id, t) for t in tenants])
for volume in volumes:
tenant_id = getattr(volume, "os-vol-tenant-attr:tenant_id", None)
tenant = tenant_dict.get(tenant_id, None)

View File

@ -1968,6 +1968,7 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertEqual(7, self.mock_tenant_absolute_limits.call_count)
@test.create_mocks({
api.nova: ['server_list'],
cinder: ['volume_list_paged',
'volume_snapshot_list',
'tenant_absolute_limits',
@ -1987,6 +1988,10 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
transfer.id,
transfer.auth_key)
self.assertEqual(2, self.mock_tenant_absolute_limits.call_count)
self.mock_server_list.assert_called_once()
self.mock_volume_list_paged.assert_called_once()
self.mock_volume_snapshot_list.assert_called_once()
self.mock_transfer_accept.assert_called_once()
@mock.patch.object(cinder, 'transfer_get')
def test_download_transfer_credentials(self, mock_transfer):

View File

@ -41,6 +41,7 @@ from openstack_dashboard.api import nova
from openstack_dashboard import exceptions as dashboard_exception
from openstack_dashboard.usage import quotas
from openstack_dashboard.utils import filters
from openstack_dashboard.utils import futurist_utils
from openstack_dashboard.dashboards.project.volumes \
import forms as volume_forms
@ -71,9 +72,7 @@ class VolumeTableMixIn(object):
_('Unable to retrieve volume list.'))
return []
def _get_instances(self, search_opts=None, instance_ids=None):
if not instance_ids:
return []
def _get_instances(self, search_opts=None):
try:
# TODO(tsufiev): we should pass attached_instance_ids to
# nova.server_list as soon as Nova API allows for this
@ -149,10 +148,38 @@ class VolumesView(tables.PagedTableMixin, VolumeTableMixIn,
page_title = _("Volumes")
def get_data(self):
volumes = self._get_volumes()
attached_instance_ids = self._get_attached_instance_ids(volumes)
instances = self._get_instances(instance_ids=attached_instance_ids)
volume_ids_with_snapshots = self._get_volumes_ids_with_snapshots()
volumes = []
attached_instance_ids = []
instances = []
volume_ids_with_snapshots = []
def _task_get_volumes():
volumes.extend(self._get_volumes())
attached_instance_ids.extend(
self._get_attached_instance_ids(volumes))
def _task_get_instances():
# As long as Nova API does not allow passing attached_instance_ids
# to nova.server_list, this call can be forged to pass anything
# != None
instances.extend(self._get_instances())
# In volumes tab we don't need to know about the assignment
# instance-image, therefore fixing it to an empty value
for instance in instances:
if hasattr(instance, 'image'):
if isinstance(instance.image, dict):
instance.image['name'] = "-"
def _task_get_volumes_snapshots():
volume_ids_with_snapshots.extend(
self._get_volumes_ids_with_snapshots())
futurist_utils.call_functions_parallel(
_task_get_volumes,
_task_get_instances,
_task_get_volumes_snapshots)
self._set_volume_attributes(
volumes, instances, volume_ids_with_snapshots)
self._get_groups(volumes)