Optimize heat.Resource.get_by_node
Use memoization and a dict to cache the node-resource relation. Also use LookupError instead of http.NotFound, so that we get proper tracebacks. Change-Id: Ic71c2fecaaca07ba070d896070efe8b094df8a78
This commit is contained in:
parent
eba24f6e51
commit
fa1a02d811
@ -16,7 +16,6 @@ import urlparse
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
import heatclient
|
import heatclient
|
||||||
from horizon import exceptions
|
|
||||||
from horizon.utils import memoized
|
from horizon.utils import memoized
|
||||||
from openstack_dashboard.api import base
|
from openstack_dashboard.api import base
|
||||||
from openstack_dashboard.api import heat
|
from openstack_dashboard.api import heat
|
||||||
@ -398,7 +397,15 @@ class Resource(base.APIResourceWrapper):
|
|||||||
self._role = kwargs['role']
|
self._role = kwargs['role']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_node(cls, request, node, all_resources=None):
|
@memoized.memoized
|
||||||
|
def _resources_by_nodes(cls, request):
|
||||||
|
return dict(
|
||||||
|
(resource.physical_resource_id, resource)
|
||||||
|
for resource in cls.list_all_resources(request)
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_by_node(cls, request, node):
|
||||||
"""Return the specified Heat Resource given a Node
|
"""Return the specified Heat Resource given a Node
|
||||||
|
|
||||||
:param request: request object
|
:param request: request object
|
||||||
@ -407,22 +414,11 @@ class Resource(base.APIResourceWrapper):
|
|||||||
:param node: node to match
|
:param node: node to match
|
||||||
:type node: tuskar_ui.api.node.Node
|
:type node: tuskar_ui.api.node.Node
|
||||||
|
|
||||||
:return: matching Resource, or None if no Resource matches
|
:return: matching Resource, or raises LookupError if no
|
||||||
the Node
|
resource matches the node
|
||||||
:rtype: tuskar_ui.api.heat.Resource
|
:rtype: tuskar_ui.api.heat.Resource
|
||||||
"""
|
"""
|
||||||
# TODO(tzumainn): this is terribly inefficient, but I don't see a
|
return cls._resources_by_nodes(request)[node.instance_uuid]
|
||||||
# better way. Maybe if Heat set some node metadata. . . ?
|
|
||||||
if node.instance_uuid:
|
|
||||||
if all_resources is None:
|
|
||||||
resource_list = cls.list_all_resources(request)
|
|
||||||
else:
|
|
||||||
resource_list = all_resources
|
|
||||||
for resource in resource_list:
|
|
||||||
if resource.physical_resource_id == node.instance_uuid:
|
|
||||||
return resource
|
|
||||||
msg = _('Could not find resource matching node "%s"') % node.uuid
|
|
||||||
raise exceptions.NotFound(msg)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def list_all_resources(cls, request):
|
def list_all_resources(cls, request):
|
||||||
|
@ -16,7 +16,6 @@ import itertools
|
|||||||
|
|
||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from horizon import exceptions
|
|
||||||
from horizon import tabs
|
from horizon import tabs
|
||||||
from horizon.utils import functions
|
from horizon.utils import functions
|
||||||
from openstack_dashboard.api import base as api_base
|
from openstack_dashboard.api import base as api_base
|
||||||
@ -242,16 +241,16 @@ class ProvisionedTab(BaseTab):
|
|||||||
nodes, prev, more = self._nodes_info
|
nodes, prev, more = self._nodes_info
|
||||||
|
|
||||||
if nodes:
|
if nodes:
|
||||||
all_resources = api.heat.Resource.list_all_resources(self.request)
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
try:
|
try:
|
||||||
resource = api.heat.Resource.get_by_node(
|
resource = api.heat.Resource.get_by_node(
|
||||||
self.request, node, all_resources=all_resources)
|
self.request, node)
|
||||||
|
except LookupError:
|
||||||
|
node.role_name = '-'
|
||||||
|
else:
|
||||||
node.role_name = resource.role.name
|
node.role_name = resource.role.name
|
||||||
node.role_id = resource.role.id
|
node.role_id = resource.role.id
|
||||||
node.stack_id = resource.stack.id
|
node.stack_id = resource.stack.id
|
||||||
except exceptions.NotFound:
|
|
||||||
node.role_name = '-'
|
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
@ -302,10 +301,11 @@ class DetailOverviewTab(tabs.Tab):
|
|||||||
context = {'node': node}
|
context = {'node': node}
|
||||||
try:
|
try:
|
||||||
resource = api.heat.Resource.get_by_node(self.request, node)
|
resource = api.heat.Resource.get_by_node(self.request, node)
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
context['role'] = resource.role
|
context['role'] = resource.role
|
||||||
context['stack'] = resource.stack
|
context['stack'] = resource.stack
|
||||||
except exceptions.NotFound:
|
|
||||||
pass
|
|
||||||
if node.instance_uuid:
|
if node.instance_uuid:
|
||||||
if api_base.is_service_enabled(self.request, 'metering'):
|
if api_base.is_service_enabled(self.request, 'metering'):
|
||||||
# Meter configuration in the following format:
|
# Meter configuration in the following format:
|
||||||
|
@ -250,8 +250,8 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||||||
}),
|
}),
|
||||||
patch('tuskar_ui.api.heat.Resource', **{
|
patch('tuskar_ui.api.heat.Resource', **{
|
||||||
'spec_set': ['get_by_node'],
|
'spec_set': ['get_by_node'],
|
||||||
'get_by_node.side_effect': (
|
'get_by_node.side_effect': lambda *args, **kwargs: {}[None],
|
||||||
self._raise_horizon_exception_not_found),
|
# Raises LookupError
|
||||||
}),
|
}),
|
||||||
) as (mock_node, mock_heat):
|
) as (mock_node, mock_heat):
|
||||||
res = self.client.get(
|
res = self.client.get(
|
||||||
|
@ -92,11 +92,12 @@ class DetailView(horizon_tables.DataTableView, RoleMixin, StackMixin):
|
|||||||
# by getting the resource for all nodes at once
|
# by getting the resource for all nodes at once
|
||||||
try:
|
try:
|
||||||
resource = api.heat.Resource.get_by_node(self.request, node)
|
resource = api.heat.Resource.get_by_node(self.request, node)
|
||||||
|
except LookupError:
|
||||||
|
node.role_name = '-'
|
||||||
|
else:
|
||||||
node.role_name = resource.role.name
|
node.role_name = resource.role.name
|
||||||
node.role_id = resource.role.id
|
node.role_id = resource.role.id
|
||||||
node.stack_id = resource.stack.id
|
node.stack_id = resource.stack.id
|
||||||
except horizon_exceptions.NotFound:
|
|
||||||
node.role_name = '-'
|
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user