Add "--limit" and "--marker" options to "volume list" command
Add ``--limit`` option to ``volume list`` command in volume v1, add ``--limit`` and ``--marker`` options to ``volume list`` command in volume v2. Change-Id: I327a252aa83ed84166da99cf6aa80334e0e6dd44 Partial-Bug: #1612484
This commit is contained in:
parent
676a0e9696
commit
6986a32e1c
@ -121,6 +121,8 @@ List volumes
|
|||||||
[--status <status>]
|
[--status <status>]
|
||||||
[--all-projects]
|
[--all-projects]
|
||||||
[--long]
|
[--long]
|
||||||
|
[--limit <limit>]
|
||||||
|
[--marker <marker>]
|
||||||
|
|
||||||
.. option:: --project <project>
|
.. option:: --project <project>
|
||||||
|
|
||||||
@ -166,6 +168,16 @@ List volumes
|
|||||||
|
|
||||||
List additional fields in output
|
List additional fields in output
|
||||||
|
|
||||||
|
.. option:: --limit <limit>
|
||||||
|
|
||||||
|
Maximum number of volumes to display
|
||||||
|
|
||||||
|
.. option:: --marker <marker>
|
||||||
|
|
||||||
|
The last volume ID of the previous page
|
||||||
|
|
||||||
|
*Volume version 2 only*
|
||||||
|
|
||||||
volume set
|
volume set
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
@ -437,6 +438,7 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -454,6 +456,7 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', volume_fakes.volume_name),
|
('name', volume_fakes.volume_name),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -470,6 +473,7 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', volume_fakes.volume_status),
|
('status', volume_fakes.volume_status),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -486,6 +490,7 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', True),
|
('all_projects', True),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -502,6 +507,7 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
@ -532,6 +538,41 @@ class TestVolumeList(TestVolume):
|
|||||||
), )
|
), )
|
||||||
self.assertEqual(datalist, tuple(data))
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_volume_list_with_limit(self):
|
||||||
|
arglist = [
|
||||||
|
'--limit', '2',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('long', False),
|
||||||
|
('all_projects', False),
|
||||||
|
('name', None),
|
||||||
|
('status', None),
|
||||||
|
('limit', 2),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.volumes_mock.list.assert_called_once_with(
|
||||||
|
limit=2,
|
||||||
|
search_opts={
|
||||||
|
'status': None,
|
||||||
|
'display_name': None,
|
||||||
|
'all_tenants': False, }
|
||||||
|
)
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_volume_list_negative_limit(self):
|
||||||
|
arglist = [
|
||||||
|
"--limit", "-2",
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
("limit", -2),
|
||||||
|
]
|
||||||
|
self.assertRaises(argparse.ArgumentTypeError, self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
|
||||||
class TestVolumeSet(TestVolume):
|
class TestVolumeSet(TestVolume):
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
import mock
|
import mock
|
||||||
from mock import call
|
from mock import call
|
||||||
|
|
||||||
@ -553,6 +554,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -581,6 +584,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('long', False),
|
('long', False),
|
||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -611,6 +616,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('long', False),
|
('long', False),
|
||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -639,6 +646,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('long', False),
|
('long', False),
|
||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -668,6 +677,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('long', False),
|
('long', False),
|
||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -696,6 +707,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', self.mock_volume.name),
|
('name', self.mock_volume.name),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -724,6 +737,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', self.mock_volume.status),
|
('status', self.mock_volume.status),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -752,6 +767,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', True),
|
('all_projects', True),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -780,6 +797,8 @@ class TestVolumeList(TestVolume):
|
|||||||
('all_projects', False),
|
('all_projects', False),
|
||||||
('name', None),
|
('name', None),
|
||||||
('status', None),
|
('status', None),
|
||||||
|
('marker', None),
|
||||||
|
('limit', None),
|
||||||
]
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
@ -813,6 +832,58 @@ class TestVolumeList(TestVolume):
|
|||||||
), )
|
), )
|
||||||
self.assertEqual(datalist, tuple(data))
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_volume_list_with_marker_and_limit(self):
|
||||||
|
arglist = [
|
||||||
|
"--marker", self.mock_volume.id,
|
||||||
|
"--limit", "2",
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('long', False),
|
||||||
|
('all_projects', False),
|
||||||
|
('name', None),
|
||||||
|
('status', None),
|
||||||
|
('marker', self.mock_volume.id),
|
||||||
|
('limit', 2),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
|
||||||
|
server = self.mock_volume.attachments[0]['server_id']
|
||||||
|
device = self.mock_volume.attachments[0]['device']
|
||||||
|
msg = 'Attached to %s on %s ' % (server, device)
|
||||||
|
datalist = ((
|
||||||
|
self.mock_volume.id,
|
||||||
|
self.mock_volume.name,
|
||||||
|
self.mock_volume.status,
|
||||||
|
self.mock_volume.size,
|
||||||
|
msg,
|
||||||
|
), )
|
||||||
|
|
||||||
|
self.volumes_mock.list.assert_called_once_with(
|
||||||
|
marker=self.mock_volume.id,
|
||||||
|
limit=2,
|
||||||
|
search_opts={
|
||||||
|
'status': None,
|
||||||
|
'project_id': None,
|
||||||
|
'user_id': None,
|
||||||
|
'display_name': None,
|
||||||
|
'all_tenants': False, }
|
||||||
|
)
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_volume_list_negative_limit(self):
|
||||||
|
arglist = [
|
||||||
|
"--limit", "-2",
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
("limit", -2),
|
||||||
|
]
|
||||||
|
self.assertRaises(argparse.ArgumentTypeError, self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
|
||||||
class TestVolumeSet(TestVolume):
|
class TestVolumeSet(TestVolume):
|
||||||
|
|
||||||
|
@ -220,6 +220,13 @@ class ListVolume(command.Lister):
|
|||||||
default=False,
|
default=False,
|
||||||
help=_('List additional fields in output'),
|
help=_('List additional fields in output'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
type=int,
|
||||||
|
action=parseractions.NonNegativeAction,
|
||||||
|
metavar='<limit>',
|
||||||
|
help=_('Maximum number of volumes to display'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -295,7 +302,10 @@ class ListVolume(command.Lister):
|
|||||||
'status': parsed_args.status,
|
'status': parsed_args.status,
|
||||||
}
|
}
|
||||||
|
|
||||||
data = volume_client.volumes.list(search_opts=search_opts)
|
data = volume_client.volumes.list(
|
||||||
|
search_opts=search_opts,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
)
|
||||||
|
|
||||||
return (column_headers,
|
return (column_headers,
|
||||||
(utils.get_item_properties(
|
(utils.get_item_properties(
|
||||||
|
@ -246,6 +246,18 @@ class ListVolume(command.Lister):
|
|||||||
default=False,
|
default=False,
|
||||||
help=_('List additional fields in output'),
|
help=_('List additional fields in output'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
help=_('The last volume ID of the previous page'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
type=int,
|
||||||
|
action=parseractions.NonNegativeAction,
|
||||||
|
metavar='<limit>',
|
||||||
|
help=_('Maximum number of volumes to display'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -328,7 +340,11 @@ class ListVolume(command.Lister):
|
|||||||
'status': parsed_args.status,
|
'status': parsed_args.status,
|
||||||
}
|
}
|
||||||
|
|
||||||
data = volume_client.volumes.list(search_opts=search_opts)
|
data = volume_client.volumes.list(
|
||||||
|
search_opts=search_opts,
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
)
|
||||||
|
|
||||||
return (column_headers,
|
return (column_headers,
|
||||||
(utils.get_item_properties(
|
(utils.get_item_properties(
|
||||||
|
7
releasenotes/notes/bug-1612484-e8605ad8966a455e.yaml
Normal file
7
releasenotes/notes/bug-1612484-e8605ad8966a455e.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``--limit`` option to ``volume list`` command in volume v1,
|
||||||
|
add ``--limit`` and ``--marker`` options to ``volume list``
|
||||||
|
command in volume v2.
|
||||||
|
[Bug `1612484 <https://bugs.launchpad.net/bugs/1612484>`_]
|
Loading…
Reference in New Issue
Block a user