Add options to "volume backup list" command
Add "--name", "--status", "--volume", "--marker" (v2 only) and "--limit" (v2 only) options to "volume backup list" command Change-Id: If20cb7650f2359d393ee314d9e055a8659c73009 Closes-Bug: #1612484 Closes-Bug: #1639712
This commit is contained in:
parent
0e3e05098c
commit
e07b0e0919
|
@ -88,12 +88,43 @@ List volume backups
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
os volume backup list
|
os volume backup list
|
||||||
|
[--long]
|
||||||
|
[--name <name>]
|
||||||
|
[--status <status>]
|
||||||
|
[--volume <volume>]
|
||||||
|
[--marker <marker>]
|
||||||
|
[--limit <limit>]
|
||||||
|
|
||||||
.. _volume_backup_list-backup:
|
.. _volume_backup_list-backup:
|
||||||
.. option:: --long
|
.. option:: --long
|
||||||
|
|
||||||
List additional fields in output
|
List additional fields in output
|
||||||
|
|
||||||
|
.. options:: --name <name>
|
||||||
|
|
||||||
|
Filters results by the backup name
|
||||||
|
|
||||||
|
.. options:: --status <status>
|
||||||
|
|
||||||
|
Filters results by the backup status
|
||||||
|
('creating', 'available', 'deleting', 'error', 'restoring' or 'error_restoring')
|
||||||
|
|
||||||
|
.. options:: --volume <volume>
|
||||||
|
|
||||||
|
Filters results by the volume which they backup (name or ID)"
|
||||||
|
|
||||||
|
.. options:: --marker <marker>
|
||||||
|
|
||||||
|
The last backup of the previous page (name or ID)
|
||||||
|
|
||||||
|
*Volume version 2 only*
|
||||||
|
|
||||||
|
.. options:: --limit <limit>
|
||||||
|
|
||||||
|
Maximum number of backups to display
|
||||||
|
|
||||||
|
*Volume version 2 only*
|
||||||
|
|
||||||
volume backup restore
|
volume backup restore
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -249,26 +249,60 @@ class TestBackupList(TestBackup):
|
||||||
|
|
||||||
self.volumes_mock.list.return_value = [self.volume]
|
self.volumes_mock.list.return_value = [self.volume]
|
||||||
self.backups_mock.list.return_value = self.backups
|
self.backups_mock.list.return_value = self.backups
|
||||||
|
self.volumes_mock.get.return_value = self.volume
|
||||||
# Get the command to test
|
# Get the command to test
|
||||||
self.cmd = backup.ListVolumeBackup(self.app, None)
|
self.cmd = backup.ListVolumeBackup(self.app, None)
|
||||||
|
|
||||||
def test_backup_list_without_options(self):
|
def test_backup_list_without_options(self):
|
||||||
arglist = []
|
arglist = []
|
||||||
verifylist = [("long", False)]
|
verifylist = [
|
||||||
|
("long", False),
|
||||||
|
("name", None),
|
||||||
|
("status", None),
|
||||||
|
("volume", None),
|
||||||
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
search_opts = {
|
||||||
|
"name": None,
|
||||||
|
"status": None,
|
||||||
|
"volume_id": None,
|
||||||
|
}
|
||||||
|
self.volumes_mock.get.assert_not_called
|
||||||
|
self.backups_mock.list.assert_called_with(
|
||||||
|
search_opts=search_opts,
|
||||||
|
)
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, list(data))
|
self.assertEqual(self.data, list(data))
|
||||||
|
|
||||||
def test_backup_list_with_options(self):
|
def test_backup_list_with_options(self):
|
||||||
arglist = ["--long"]
|
arglist = [
|
||||||
verifylist = [("long", True)]
|
"--long",
|
||||||
|
"--name", self.backups[0].name,
|
||||||
|
"--status", "error",
|
||||||
|
"--volume", self.volume.id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
("long", True),
|
||||||
|
("name", self.backups[0].name),
|
||||||
|
("status", "error"),
|
||||||
|
("volume", self.volume.id),
|
||||||
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
search_opts = {
|
||||||
|
"name": self.backups[0].name,
|
||||||
|
"status": "error",
|
||||||
|
"volume_id": self.volume.id,
|
||||||
|
}
|
||||||
|
self.volumes_mock.get.assert_called_once_with(self.volume.id)
|
||||||
|
self.backups_mock.list.assert_called_with(
|
||||||
|
search_opts=search_opts,
|
||||||
|
)
|
||||||
self.assertEqual(self.columns_long, columns)
|
self.assertEqual(self.columns_long, columns)
|
||||||
self.assertEqual(self.data_long, list(data))
|
self.assertEqual(self.data_long, list(data))
|
||||||
|
|
||||||
|
|
|
@ -280,26 +280,73 @@ class TestBackupList(TestBackup):
|
||||||
|
|
||||||
self.volumes_mock.list.return_value = [self.volume]
|
self.volumes_mock.list.return_value = [self.volume]
|
||||||
self.backups_mock.list.return_value = self.backups
|
self.backups_mock.list.return_value = self.backups
|
||||||
|
self.volumes_mock.get.return_value = self.volume
|
||||||
|
self.backups_mock.get.return_value = self.backups[0]
|
||||||
# Get the command to test
|
# Get the command to test
|
||||||
self.cmd = backup.ListVolumeBackup(self.app, None)
|
self.cmd = backup.ListVolumeBackup(self.app, None)
|
||||||
|
|
||||||
def test_backup_list_without_options(self):
|
def test_backup_list_without_options(self):
|
||||||
arglist = []
|
arglist = []
|
||||||
verifylist = [("long", False)]
|
verifylist = [
|
||||||
|
("long", False),
|
||||||
|
("name", None),
|
||||||
|
("status", None),
|
||||||
|
("volume", None),
|
||||||
|
("marker", None),
|
||||||
|
("limit", None),
|
||||||
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
search_opts = {
|
||||||
|
"name": None,
|
||||||
|
"status": None,
|
||||||
|
"volume_id": None,
|
||||||
|
}
|
||||||
|
self.volumes_mock.get.assert_not_called
|
||||||
|
self.backups_mock.get.assert_not_called
|
||||||
|
self.backups_mock.list.assert_called_with(
|
||||||
|
search_opts=search_opts,
|
||||||
|
marker=None,
|
||||||
|
limit=None,
|
||||||
|
)
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, list(data))
|
self.assertEqual(self.data, list(data))
|
||||||
|
|
||||||
def test_backup_list_with_options(self):
|
def test_backup_list_with_options(self):
|
||||||
arglist = ["--long"]
|
arglist = [
|
||||||
verifylist = [("long", True)]
|
"--long",
|
||||||
|
"--name", self.backups[0].name,
|
||||||
|
"--status", "error",
|
||||||
|
"--volume", self.volume.id,
|
||||||
|
"--marker", self.backups[0].id,
|
||||||
|
"--limit", "3",
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
("long", True),
|
||||||
|
("name", self.backups[0].name),
|
||||||
|
("status", "error"),
|
||||||
|
("volume", self.volume.id),
|
||||||
|
("marker", self.backups[0].id),
|
||||||
|
("limit", 3),
|
||||||
|
]
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
search_opts = {
|
||||||
|
"name": self.backups[0].name,
|
||||||
|
"status": "error",
|
||||||
|
"volume_id": self.volume.id,
|
||||||
|
}
|
||||||
|
self.volumes_mock.get.assert_called_once_with(self.volume.id)
|
||||||
|
self.backups_mock.get.assert_called_once_with(self.backups[0].id)
|
||||||
|
self.backups_mock.list.assert_called_with(
|
||||||
|
search_opts=search_opts,
|
||||||
|
marker=self.backups[0].id,
|
||||||
|
limit=3,
|
||||||
|
)
|
||||||
self.assertEqual(self.columns_long, columns)
|
self.assertEqual(self.columns_long, columns)
|
||||||
self.assertEqual(self.data_long, list(data))
|
self.assertEqual(self.data_long, list(data))
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,30 @@ class ListVolumeBackup(command.Lister):
|
||||||
default=False,
|
default=False,
|
||||||
help=_('List additional fields in output'),
|
help=_('List additional fields in output'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--name",
|
||||||
|
metavar="<name>",
|
||||||
|
help=_("Filters results by the backup name")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--status",
|
||||||
|
metavar="<status>",
|
||||||
|
choices=['creating', 'available', 'deleting',
|
||||||
|
'error', 'restoring', 'error_restoring'],
|
||||||
|
help=_("Filters results by the backup status "
|
||||||
|
"('creating', 'available', 'deleting', "
|
||||||
|
"'error', 'restoring' or 'error_restoring')")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--volume",
|
||||||
|
metavar="<volume>",
|
||||||
|
help=_("Filters results by the volume which they "
|
||||||
|
"backup (name or ID)")
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
def _format_volume_id(volume_id):
|
def _format_volume_id(volume_id):
|
||||||
"""Return a volume name if available
|
"""Return a volume name if available
|
||||||
|
@ -180,13 +201,24 @@ class ListVolumeBackup(command.Lister):
|
||||||
# Cache the volume list
|
# Cache the volume list
|
||||||
volume_cache = {}
|
volume_cache = {}
|
||||||
try:
|
try:
|
||||||
for s in self.app.client_manager.volume.volumes.list():
|
for s in volume_client.volumes.list():
|
||||||
volume_cache[s.id] = s
|
volume_cache[s.id] = s
|
||||||
except Exception:
|
except Exception:
|
||||||
# Just forget it if there's any trouble
|
# Just forget it if there's any trouble
|
||||||
pass
|
pass
|
||||||
|
|
||||||
data = self.app.client_manager.volume.backups.list()
|
filter_volume_id = None
|
||||||
|
if parsed_args.volume:
|
||||||
|
filter_volume_id = utils.find_resource(volume_client.volumes,
|
||||||
|
parsed_args.volume).id
|
||||||
|
search_opts = {
|
||||||
|
'name': parsed_args.name,
|
||||||
|
'status': parsed_args.status,
|
||||||
|
'volume_id': filter_volume_id,
|
||||||
|
}
|
||||||
|
data = volume_client.backups.list(
|
||||||
|
search_opts=search_opts,
|
||||||
|
)
|
||||||
|
|
||||||
return (column_headers,
|
return (column_headers,
|
||||||
(utils.get_item_properties(
|
(utils.get_item_properties(
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from osc_lib.cli import parseractions
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
from osc_lib import exceptions
|
from osc_lib import exceptions
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
@ -179,9 +180,42 @@ class ListVolumeBackup(command.Lister):
|
||||||
default=False,
|
default=False,
|
||||||
help=_("List additional fields in output")
|
help=_("List additional fields in output")
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--name",
|
||||||
|
metavar="<name>",
|
||||||
|
help=_("Filters results by the backup name")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--status",
|
||||||
|
metavar="<status>",
|
||||||
|
choices=['creating', 'available', 'deleting',
|
||||||
|
'error', 'restoring', 'error_restoring'],
|
||||||
|
help=_("Filters results by the backup status "
|
||||||
|
"('creating', 'available', 'deleting', "
|
||||||
|
"'error', 'restoring' or 'error_restoring')")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--volume",
|
||||||
|
metavar="<volume>",
|
||||||
|
help=_("Filters results by the volume which they "
|
||||||
|
"backup (name or ID)")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
help=_('The last backup of the previous page (name or ID)'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
type=int,
|
||||||
|
action=parseractions.NonNegativeAction,
|
||||||
|
metavar='<limit>',
|
||||||
|
help=_('Maximum number of backups to display'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
def _format_volume_id(volume_id):
|
def _format_volume_id(volume_id):
|
||||||
"""Return a volume name if available
|
"""Return a volume name if available
|
||||||
|
@ -207,13 +241,30 @@ class ListVolumeBackup(command.Lister):
|
||||||
# Cache the volume list
|
# Cache the volume list
|
||||||
volume_cache = {}
|
volume_cache = {}
|
||||||
try:
|
try:
|
||||||
for s in self.app.client_manager.volume.volumes.list():
|
for s in volume_client.volumes.list():
|
||||||
volume_cache[s.id] = s
|
volume_cache[s.id] = s
|
||||||
except Exception:
|
except Exception:
|
||||||
# Just forget it if there's any trouble
|
# Just forget it if there's any trouble
|
||||||
pass
|
pass
|
||||||
|
|
||||||
data = self.app.client_manager.volume.backups.list()
|
filter_volume_id = None
|
||||||
|
if parsed_args.volume:
|
||||||
|
filter_volume_id = utils.find_resource(volume_client.volumes,
|
||||||
|
parsed_args.volume).id
|
||||||
|
marker_backup_id = None
|
||||||
|
if parsed_args.marker:
|
||||||
|
marker_backup_id = utils.find_resource(volume_client.backups,
|
||||||
|
parsed_args.marker).id
|
||||||
|
search_opts = {
|
||||||
|
'name': parsed_args.name,
|
||||||
|
'status': parsed_args.status,
|
||||||
|
'volume_id': filter_volume_id,
|
||||||
|
}
|
||||||
|
data = volume_client.backups.list(
|
||||||
|
search_opts=search_opts,
|
||||||
|
marker=marker_backup_id,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
)
|
||||||
|
|
||||||
return (column_headers,
|
return (column_headers,
|
||||||
(utils.get_item_properties(
|
(utils.get_item_properties(
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``--name``, ``--status``, ``--volume``, ``--marker`` and ``--limit`` options
|
||||||
|
to ``volume backup list`` command
|
||||||
|
[Bug `1639712 <https://bugs.launchpad.net/bugs/1639712>`_]
|
Loading…
Reference in New Issue