Support filter search for share type API

Since manila server allows filter search extra_specs and is_public,
so it's better to add this in manila client as well.

Change-Id: Ie85a7c09d4d7c6ddc31adb5125feea265ad8fced
Depends-On: Id577ae9d08dc0fae3dcac78d98ec0456f8378417
Partially-Implements: blueprint support-filter-search-for-share-type
This commit is contained in:
junboli 2018-05-02 03:53:24 +08:00 committed by lijunbo
parent 4197a71623
commit 50a1ef6e65
8 changed files with 90 additions and 6 deletions

View File

@ -27,7 +27,7 @@ from manilaclient import utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
MAX_VERSION = '2.42' MAX_VERSION = '2.43'
MIN_VERSION = '2.0' MIN_VERSION = '2.0'
DEPRECATED_VERSION = '1.0' DEPRECATED_VERSION = '1.0'
_VERSIONED_METHOD_MAP = {} _VERSIONED_METHOD_MAP = {}

View File

@ -247,16 +247,24 @@ class ManilaCLIClient(base.CLIClient):
return self.manila( return self.manila(
'type-delete %s' % share_type, microversion=microversion) 'type-delete %s' % share_type, microversion=microversion)
def list_share_types(self, list_all=True, columns=None, microversion=None): def list_share_types(self, list_all=True, columns=None, search_opts=None,
microversion=None):
"""List share types. """List share types.
:param list_all: bool -- whether to list all share types or only public :param list_all: bool -- whether to list all share types or only public
:param search_opts: dict search_opts for filter search.
:param columns: comma separated string of columns. :param columns: comma separated string of columns.
Example, "--columns id,name" Example, "--columns id,name"
""" """
cmd = 'type-list' cmd = 'type-list'
if list_all: if list_all:
cmd += ' --all' cmd += ' --all'
if search_opts is not None:
extra_specs = search_opts.get('extra_specs')
if extra_specs:
cmd += ' --extra_specs'
for spec_key in extra_specs.keys():
cmd += ' ' + spec_key + '=' + extra_specs[spec_key]
if columns is not None: if columns is not None:
cmd += ' --columns ' + columns cmd += ' --columns ' + columns
share_types_raw = self.manila(cmd, microversion=microversion) share_types_raw = self.manila(cmd, microversion=microversion)

View File

@ -334,6 +334,38 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
self.assertTrue(all('visibility' not in s for s in share_types)) self.assertTrue(all('visibility' not in s for s in share_types))
self.assertTrue(all('Visibility' not in s for s in share_types)) self.assertTrue(all('Visibility' not in s for s in share_types))
def test_list_share_type_filter_search(self):
# Fake extra spec and type name
extra_specs = {'aaaa': 'bbbb'}
# Create share type
name1 = data_utils.rand_name('manilaclient_functional_test1')
self.create_share_type(
name=name1,
driver_handles_share_servers='False')
# Create share type
name2 = data_utils.rand_name('manilaclient_functional_test2')
self.create_share_type(
name=name2,
extra_specs=extra_specs,
driver_handles_share_servers='True')
# List type by extra_specs
list_all = False
search_opts = {'extra_specs': extra_specs}
share_types = self.admin_client.list_share_types(
list_all=list_all,
search_opts=search_opts,
microversion='2.43'
)
self.assertTrue(share_types is not None)
expect = 'aaaa : bbbb'
self.assertTrue(len(share_types) == 1)
self.assertTrue(all('optional_extra_specs' in s for s in share_types))
self.assertTrue(all(s['Name'] == name2 for s in share_types))
self.assertTrue(all(s['optional_extra_specs'] ==
expect for s in share_types))
@ddt.ddt @ddt.ddt
class ShareTypeExtraSpecsReadWriteTest(base.BaseTestCase): class ShareTypeExtraSpecsReadWriteTest(base.BaseTestCase):

View File

@ -285,7 +285,7 @@ class ShellTest(test_utils.TestCase):
self.run_command, self.run_command,
'list --share-type' + separator + 'not_found_expected', 'list --share-type' + separator + 'not_found_expected',
) )
self.assert_called('GET', '/types?is_public=all') self.assert_called('GET', '/types?is_public=all&all_tenants=1')
def test_list_with_limit(self): def test_list_with_limit(self):
for separator in self.separators: for separator in self.separators:

View File

@ -150,6 +150,12 @@ class TypesTest(utils.TestCase):
cs.share_types.list(show_all=False) cs.share_types.list(show_all=False)
cs.assert_called('GET', '/types') cs.assert_called('GET', '/types')
def test_list_types_search_by_extra_specs(self):
search_opts = {'extra_specs': {'aa': 'bb'}}
cs.share_types.list(search_opts=search_opts)
expect = '/types?is_public=all&extra_specs=%7B%27aa%27%3A+%27bb%27%7D'
cs.assert_called('GET', expect)
@ddt.data(*get_valid_type_create_data_2_0()) @ddt.data(*get_valid_type_create_data_2_0())
@ddt.unpack @ddt.unpack
def test_create_2_7(self, is_public, dhss, snapshot, extra_specs): def test_create_2_7(self, is_public, dhss, snapshot, extra_specs):

View File

@ -17,11 +17,13 @@
""" """
Share Type interface. Share Type interface.
""" """
from six.moves.urllib import parse
from manilaclient import api_versions from manilaclient import api_versions
from manilaclient import base from manilaclient import base
from manilaclient.common.apiclient import base as common_base from manilaclient.common.apiclient import base as common_base
from manilaclient import exceptions from manilaclient import exceptions
from manilaclient import utils
class ShareType(common_base.Resource): class ShareType(common_base.Resource):
@ -115,6 +117,14 @@ class ShareTypeManager(base.ManagerWithFind):
query_string = '' query_string = ''
if show_all: if show_all:
query_string = '?is_public=all' query_string = '?is_public=all'
if search_opts:
search_opts = utils.unicode_key_value_to_string(search_opts)
params = sorted(
[(k, v) for (k, v) in list(search_opts.items()) if v])
if params and query_string:
query_string += "&%s" % parse.urlencode(params)
if params and not query_string:
query_string += "?%s" % parse.urlencode(params)
return self._list("/types%s" % query_string, "share_types") return self._list("/types%s" % query_string, "share_types")
def show(self, share_type): def show(self, share_type):

View File

@ -3673,7 +3673,19 @@ def _find_share_type(cs, stype):
dest='all', dest='all',
action='store_true', action='store_true',
default=False, default=False,
help='Display all share types (Admin only).') help='Display all share types whatever public or private '
'OPTIONAL: Default=False. (Admin only).')
@cliutils.arg(
'--extra-specs',
'--extra_specs',
type=str,
nargs='*',
metavar='<key=value>',
action='single_alias',
default=None,
help='Filters results by a extra specs key and value of share type that '
'was used for share creation. Available only for microversion >= '
'2.43. OPTIONAL: Default=None.')
@cliutils.arg( @cliutils.arg(
'--columns', '--columns',
metavar='<columns>', metavar='<columns>',
@ -3683,15 +3695,28 @@ def _find_share_type(cs, stype):
'example --columns "id,name".') 'example --columns "id,name".')
def do_type_list(cs, args): def do_type_list(cs, args):
"""Print a list of available 'share types'.""" """Print a list of available 'share types'."""
search_opts = None
show_all = args.all
extra_specs = _extract_extra_specs(args)
if extra_specs:
if cs.api_version < api_versions.APIVersion("2.43"):
raise exceptions.CommandError(
"Filter by 'extra_specs' is available only starting with "
"'2.43' API microversion.")
search_opts = {
'extra_specs': extra_specs
}
try: try:
default = cs.share_types.get() default = cs.share_types.get()
except exceptions.NotFound: except exceptions.NotFound:
default = None default = None
stypes = cs.share_types.list(show_all=args.all) share_types = cs.share_types.list(show_all=show_all,
search_opts=search_opts)
show_des = cs.api_version.matches( show_des = cs.api_version.matches(
api_versions.APIVersion("2.41"), api_versions.APIVersion()) api_versions.APIVersion("2.41"), api_versions.APIVersion())
_print_share_type_list(stypes, default_share_type=default, _print_share_type_list(share_types, default_share_type=default,
columns=args.columns, description=show_des) columns=args.columns, description=show_des)

View File

@ -0,0 +1,3 @@
---
features:
- Share types can now be filtered with its extra_specs.