make findall in novaclient/base.py more efficient

Use /resources instead of /resources/detail to resolve
the resource ID by the name and load the details of the
resource in a separate step. This reduces the overhead
to resolve the resource ID and results in a better runtime
performance.

This patch does not solve the issue that the name resolving
takes place on the client side. For solving this issue new
Nova API methods are necessary.

fixes bug #1202179

Change-Id: Ib753b1d090cb74b2d137c68f6899dad4ae2ec1ca
This commit is contained in:
Christian Berendt 2013-07-17 16:48:04 +02:00
parent 2a45c7570f
commit 5fe9408d2e
5 changed files with 67 additions and 10 deletions

View File

@ -22,6 +22,7 @@ Base utilities to build API operation managers and objects on top of.
import abc
import contextlib
import hashlib
import inspect
import os
import six
@ -197,11 +198,23 @@ class ManagerWithFind(Manager):
found = []
searches = kwargs.items()
for obj in self.list():
detailed = True
if 'detailed' in inspect.getargspec(self.list).args:
detailed = ("human_id" not in kwargs and
"name" not in kwargs and
"display_name" not in kwargs)
listing = self.list(detailed=detailed)
else:
listing = self.list()
for obj in listing:
try:
if all(getattr(obj, attr) == value
for (attr, value) in searches):
found.append(obj)
for (attr, value) in searches):
if detailed:
found.append(obj)
else:
found.append(self.get(obj.id))
except AttributeError:
continue

View File

@ -1720,6 +1720,34 @@ class FakeHTTPClient(base_client.HTTPClient):
"links": ''}],
"metadata": {}}]})
def get_volumes(self, **kw):
return (200, {}, {"volumes": [
{"display_name": "Work",
"display_description": "volume for work",
"status": "ATTACHED",
"id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
"created_at": "2011-09-09T00:00:00Z",
"attached": "2011-11-11T00:00:00Z",
"size": 1024,
"attachments": [
{"id": "3333",
"links": ''}],
"metadata": {}}]})
def get_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw):
return (200, {}, {"volume":
{"display_name": "Work",
"display_description": "volume for work",
"status": "ATTACHED",
"id": "15e59938-07d5-11e1-90e3-e3dffe0c5983",
"created_at": "2011-09-09T00:00:00Z",
"attached": "2011-11-11T00:00:00Z",
"size": 1024,
"attachments": [
{"id": "3333",
"links": ''}],
"metadata": {}}})
def post_volumes(self, **kw):
return (200, {}, {"volume":
{"status": "creating",

View File

@ -45,7 +45,8 @@ class ImagesTest(utils.TestCase):
def test_find(self):
i = cs.images.find(name="CentOS 5.2")
self.assertEqual(i.id, 1)
cs.assert_called('GET', '/images/detail')
cs.assert_called('GET', '/images', pos=-2)
cs.assert_called('GET', '/images/1', pos=-1)
iml = cs.images.findall(status='SAVING')
self.assertEqual(len(iml), 1)

View File

@ -171,7 +171,8 @@ class ServersTest(utils.TestCase):
def test_find(self):
server = cs.servers.find(name='sample-server')
cs.assert_called('GET', '/servers/detail')
cs.assert_called('GET', '/servers', pos=-2)
cs.assert_called('GET', '/servers/1234', pos=-1)
self.assertEqual(server.name, 'sample-server')
self.assertRaises(exceptions.NoUniqueMatch, cs.servers.find,

View File

@ -536,16 +536,21 @@ class ShellTest(utils.TestCase):
def test_rebuild(self):
self.run_command('rebuild sample-server 1')
self.assert_called('GET', '/servers', pos=-8)
self.assert_called('GET', '/servers/1234', pos=-7)
self.assert_called('GET', '/images/1', pos=-6)
self.assert_called('POST', '/servers/1234/action',
{'rebuild': {'imageRef': 1}}, pos=-4)
self.assert_called('GET', '/servers/detail', pos=-3)
{'rebuild': {'imageRef': 1}}, pos=-5)
self.assert_called('GET', '/flavors/1', pos=-2)
self.assert_called('GET', '/images/2')
self.run_command('rebuild sample-server 1 --rebuild-password asdf')
self.assert_called('GET', '/servers', pos=-8)
self.assert_called('GET', '/servers/1234', pos=-7)
self.assert_called('GET', '/images/1', pos=-6)
self.assert_called('POST', '/servers/1234/action',
{'rebuild': {'imageRef': 1, 'adminPass': 'asdf'}},
pos=-4)
pos=-5)
self.assert_called('GET', '/flavors/1', pos=-2)
self.assert_called('GET', '/images/2')
@ -668,7 +673,11 @@ class ShellTest(utils.TestCase):
self.assert_called('DELETE', '/servers/1234', pos=-3)
self.assert_called('DELETE', '/servers/5678', pos=-1)
self.run_command('delete sample-server sample-server2')
self.assert_called('DELETE', '/servers/1234', pos=-3)
self.assert_called('GET', '/servers', pos=-6)
self.assert_called('GET', '/servers/1234', pos=-5)
self.assert_called('DELETE', '/servers/1234', pos=-4)
self.assert_called('GET', '/servers', pos=-3)
self.assert_called('GET', '/servers/5678', pos=-2)
self.assert_called('DELETE', '/servers/5678', pos=-1)
def test_delete_two_with_one_nonexistent(self):
@ -1518,7 +1527,12 @@ class ShellTest(utils.TestCase):
def test_volume_show(self):
self.run_command('volume-show Work')
self.assert_called('GET', '/volumes/detail')
self.assert_called('GET', '/volumes', pos=-2)
self.assert_called(
'GET',
'/volumes/15e59938-07d5-11e1-90e3-e3dffe0c5983',
pos=-1
)
def test_volume_create(self):
self.run_command('volume-create 2 --display-name Work')