From 07260236ab2179579e0d0d2f9b7fb8027652dc32 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Thu, 4 Sep 2014 03:45:13 +0000 Subject: [PATCH] Make findall support server side filtering Instead of listing all servers and doing clientside filtering, use the servers filtering on name.the server's list already supports filtering so just pass a search_opts dictionary into list(). This should speed up nova commands when a user has large numbers of servers. Change-Id: I6deea8523754ff213f43bd059fb00f34fc0e1a12 Closes-Bug: #1202179 --- novaclient/base.py | 20 ++++++++++++++------ novaclient/tests/v1_1/test_shell.py | 14 +++++++------- novaclient/tests/v3/test_shell.py | 4 ++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/novaclient/base.py b/novaclient/base.py index ff8308bde..173eda085 100644 --- a/novaclient/base.py +++ b/novaclient/base.py @@ -131,9 +131,6 @@ class ManagerWithFind(Manager): def find(self, **kwargs): """ Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. """ matches = self.findall(**kwargs) num_matches = len(matches) @@ -148,9 +145,6 @@ class ManagerWithFind(Manager): def findall(self, **kwargs): """ Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. """ found = [] searches = kwargs.items() @@ -173,6 +167,20 @@ class ManagerWithFind(Manager): del tmp_kwargs['is_public'] searches = tmp_kwargs.items() + if 'search_opts' in list_argspec.args: + # pass search_opts in to do server side based filtering. + # TODO(jogo) not all search_opts support regex, find way to + # identify when to use regex and when to use string matching. + # volumes does not support regex while servers does. So when + # doing findall on servers some client side filtering is still + # needed. + if "human_id" in kwargs: + list_kwargs['search_opts'] = {"name": kwargs["human_id"]} + elif "name" in kwargs: + list_kwargs['search_opts'] = {"name": kwargs["name"]} + elif "display_name" in kwargs: + list_kwargs['search_opts'] = {"name": kwargs["display_name"]} + listing = self.list(**list_kwargs) for obj in listing: diff --git a/novaclient/tests/v1_1/test_shell.py b/novaclient/tests/v1_1/test_shell.py index 9005759b4..fc5696045 100644 --- a/novaclient/tests/v1_1/test_shell.py +++ b/novaclient/tests/v1_1/test_shell.py @@ -857,7 +857,7 @@ class ShellTest(utils.TestCase): def test_rebuild(self): output = self.run_command('rebuild sample-server 1') - self.assert_called('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', pos=-6) self.assert_called('GET', '/servers/1234', pos=-5) self.assert_called('GET', '/images/1', pos=-4) self.assert_called('POST', '/servers/1234/action', @@ -869,7 +869,7 @@ class ShellTest(utils.TestCase): def test_rebuild_password(self): output = self.run_command('rebuild sample-server 1' ' --rebuild-password asdf') - self.assert_called('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', pos=-6) self.assert_called('GET', '/servers/1234', pos=-5) self.assert_called('GET', '/images/1', pos=-4) self.assert_called('POST', '/servers/1234/action', @@ -881,7 +881,7 @@ class ShellTest(utils.TestCase): def test_rebuild_preserve_ephemeral(self): self.run_command('rebuild sample-server 1 --preserve-ephemeral') - self.assert_called('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', pos=-6) self.assert_called('GET', '/servers/1234', pos=-5) self.assert_called('GET', '/images/1', pos=-4) self.assert_called('POST', '/servers/1234/action', @@ -893,7 +893,7 @@ class ShellTest(utils.TestCase): def test_rebuild_name_meta(self): self.run_command('rebuild sample-server 1 --name asdf --meta ' 'foo=bar') - self.assert_called('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', pos=-6) self.assert_called('GET', '/servers/1234', pos=-5) self.assert_called('GET', '/images/1', pos=-4) self.assert_called('POST', '/servers/1234/action', @@ -1043,10 +1043,10 @@ 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('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', 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?name=sample-server2', pos=-3) self.assert_called('GET', '/servers/5678', pos=-2) self.assert_called('DELETE', '/servers/5678', pos=-1) @@ -1995,7 +1995,7 @@ class ShellTest(utils.TestCase): def test_volume_show(self): self.run_command('volume-show Work') - self.assert_called('GET', '/volumes', pos=-2) + self.assert_called('GET', '/volumes?name=Work', pos=-2) self.assert_called( 'GET', '/volumes/15e59938-07d5-11e1-90e3-e3dffe0c5983', diff --git a/novaclient/tests/v3/test_shell.py b/novaclient/tests/v3/test_shell.py index 569ddabcb..0b6b747cf 100644 --- a/novaclient/tests/v3/test_shell.py +++ b/novaclient/tests/v3/test_shell.py @@ -655,10 +655,10 @@ 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('GET', '/servers', pos=-6) + self.assert_called('GET', '/servers?name=sample-server', 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?name=sample-server2', pos=-3) self.assert_called('GET', '/servers/5678', pos=-2) self.assert_called('DELETE', '/servers/5678', pos=-1)