Add support for microversion 2.33

This change allows novaclient to get several hypervisors
with the help of new optional parameters 'limit' and 'marker'
which were added to hipervisor-list command.

Change-Id: Ib723fb1dc1cd57b6f796bb93e0dd8ddf2da4b2a0
This commit is contained in:
Andrey Volkov 2016-08-01 17:38:14 +03:00
parent 48da89e2a2
commit 6bbcedb000
8 changed files with 126 additions and 12 deletions

View File

@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
API_MAX_VERSION = api_versions.APIVersion("2.32")
API_MAX_VERSION = api_versions.APIVersion("2.33")

View File

@ -16,6 +16,7 @@ import sys
import mock
from oslo_utils import encodeutils
import six
from six.moves.urllib import parse
from novaclient import base
from novaclient import exceptions
@ -437,3 +438,22 @@ class RecordTimeTestCase(test_utils.TestCase):
with utils.record_time(times, False, 'x'):
pass
self.assertEqual(0, len(times))
class PrepareQueryStringTestCase(test_utils.TestCase):
def test_convert_dict_to_string(self):
ustr = b'?\xd0\xbf=1&\xd1\x80=2'
if six.PY3:
# in py3 real unicode symbols will be urlencoded
ustr = ustr.decode('utf8')
cases = (
({}, ''),
({'2': 2, '10': 1}, '?10=1&2=2'),
({'abc': 1, 'abc1': 2}, '?abc=1&abc1=2'),
({b'\xd0\xbf': 1, b'\xd1\x80': 2}, ustr),
({(1, 2): '1', (3, 4): '2'}, '?(1, 2)=1&(3, 4)=2')
)
for case in cases:
self.assertEqual(
case[1],
parse.unquote_plus(utils.prepare_query_string(case[0])))

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from novaclient import api_versions
from novaclient.tests.unit.fixture_data import client
from novaclient.tests.unit.fixture_data import hypervisors as data
from novaclient.tests.unit import utils
@ -185,3 +186,16 @@ class HypervisorsTest(utils.FixturedTestCase):
# Test for Bug #1370415, the line below used to raise AttributeError
self.assertEqual("<HypervisorStats: 2 Hypervisors>",
result.__repr__())
class HypervisorsV233Test(HypervisorsTest):
def setUp(self):
super(HypervisorsV233Test, self).setUp()
self.cs.api_version = api_versions.APIVersion("2.33")
def test_use_limit_marker_params(self):
params = {'limit': 10, 'marker': 'fake-marker'}
self.cs.hypervisors.list(**params)
for k, v in params.items():
self.assertIn('%s=%s' % (k, v),
self.requests.last_request.path_url)

View File

@ -2154,6 +2154,11 @@ class ShellTest(utils.TestCase):
self.run_command('hypervisor-list --matching hyper')
self.assert_called('GET', '/os-hypervisors/hyper/search')
def test_hypervisor_list_limit_marker(self):
self.run_command('hypervisor-list --limit 10 --marker hyper1',
api_version='2.33')
self.assert_called('GET', '/os-hypervisors?limit=10&marker=hyper1')
def test_hypervisor_servers(self):
self.run_command('hypervisor-servers hyper')
self.assert_called('GET', '/os-hypervisors/hyper/servers')

View File

@ -24,6 +24,7 @@ from oslo_utils import encodeutils
import pkg_resources
import prettytable
import six
from six.moves.urllib import parse
from novaclient import exceptions
from novaclient.i18n import _
@ -465,3 +466,9 @@ def record_time(times, enabled, *args):
yield
end = time.time()
times.append((' '.join(args), start, end))
def prepare_query_string(params):
"""Convert dict params to query string"""
params = sorted(params.items(), key=lambda x: x[0])
return '?%s' % parse.urlencode(params) if params else ''

View File

@ -19,7 +19,9 @@ Hypervisors interface (1.1 extension).
from six.moves.urllib import parse
from novaclient import api_versions
from novaclient import base
from novaclient import utils
class Hypervisor(base.Resource):
@ -33,14 +35,35 @@ class HypervisorManager(base.ManagerWithFind):
resource_class = Hypervisor
is_alphanum_id_allowed = True
def _list_base(self, detailed=True, marker=None, limit=None):
path = '/os-hypervisors'
if detailed:
path += '/detail'
params = {}
if limit is not None:
params['limit'] = int(limit)
if marker is not None:
params['marker'] = str(marker)
path += utils.prepare_query_string(params)
return self._list(path, 'hypervisors')
@api_versions.wraps("2.0", "2.32")
def list(self, detailed=True):
"""
Get a list of hypervisors.
"""
detail = ""
if detailed:
detail = "/detail"
return self._list('/os-hypervisors%s' % detail, 'hypervisors')
return self._list_base(detailed=detailed)
@api_versions.wraps("2.33")
def list(self, detailed=True, marker=None, limit=None):
"""
Get a list of hypervisors.
:param marker: Begin returning hypervisor that appear later in the
keypair list than that represented by this keypair name
(optional).
:param limit: maximum number of keypairs to return (optional).
"""
return self._list_base(detailed=detailed, marker=marker, limit=limit)
def search(self, hypervisor_match, servers=False):
"""

View File

@ -3980,6 +3980,22 @@ def _find_hypervisor(cs, hypervisor):
return utils.find_resource(cs.hypervisors, hypervisor)
def _do_hypervisor_list(cs, matching=None, limit=None, marker=None):
columns = ['ID', 'Hypervisor hostname', 'State', 'Status']
if matching:
utils.print_list(cs.hypervisors.search(matching), columns)
else:
params = {}
if limit is not None:
params['limit'] = limit
if marker is not None:
params['marker'] = marker
# Since we're not outputting detail data, choose
# detailed=False for server-side efficiency
utils.print_list(cs.hypervisors.list(False, **params), columns)
@api_versions.wraps("2.0", "2.32")
@utils.arg(
'--matching',
metavar='<hostname>',
@ -3987,13 +4003,37 @@ def _find_hypervisor(cs, hypervisor):
help=_('List hypervisors matching the given <hostname>.'))
def do_hypervisor_list(cs, args):
"""List hypervisors."""
columns = ['ID', 'Hypervisor hostname', 'State', 'Status']
if args.matching:
utils.print_list(cs.hypervisors.search(args.matching), columns)
else:
# Since we're not outputting detail data, choose
# detailed=False for server-side efficiency
utils.print_list(cs.hypervisors.list(False), columns)
_do_hypervisor_list(cs, matching=args.matching)
@api_versions.wraps("2.33")
@utils.arg(
'--matching',
metavar='<hostname>',
default=None,
help=_('List hypervisors matching the given <hostname>. '
'If matching is used limit and marker options will be ignored.'))
@utils.arg(
'--marker',
dest='marker',
metavar='<marker>',
default=None,
help=_('The last hypervisor of the previous page; displays list of '
'hypervisors after "marker".'))
@utils.arg(
'--limit',
dest='limit',
metavar='<limit>',
type=int,
default=None,
help=_("Maximum number of hypervisors to display. If limit == -1, all "
"hypervisors will be displayed. If limit is bigger than "
"'osapi_max_limit' option of Nova API, limit 'osapi_max_limit' "
"will be used instead."))
def do_hypervisor_list(cs, args):
"""List hypervisors."""
_do_hypervisor_list(
cs, matching=args.matching, limit=args.limit, marker=args.marker)
@utils.arg(

View File

@ -0,0 +1,5 @@
---
features:
- Added microversion v2.33 that adds pagination support for hypervisors with
the help of new optional parameters 'limit' and 'marker' which were added
to hypervisor-list command.