summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorheha <zhanghanqun@unitedstack.com>2015-07-31 18:26:33 +0800
committerlin-hua-cheng <os.lcheng@gmail.com>2015-08-06 17:02:46 -0700
commitdc6fe04895287647f6bf5a977b398659edfda822 (patch)
tree65162568c19d7d6075c04b11a7eba47fc349fe36 /openstackclient
parentbd022cb58c1172e3f237ce99840eb43085fd33d4 (diff)
downloadpython-openstackclient-dc6fe04895287647f6bf5a977b398659edfda822.tar.gz
Add list feature to volume v2
"volume list" is not in the v2. Co-Authored-By: Lin Hua Cheng <os.lcheng@gmail.com> implements bp: volume-v2 Change-Id: I9f4585202f5f9ec5f4c091278fc6c4036efb1290
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/tests/volume/v2/fakes.py6
-rw-r--r--openstackclient/tests/volume/v2/test_volume.py214
-rw-r--r--openstackclient/volume/v2/volume.py109
3 files changed, 328 insertions, 1 deletions
diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py
index a95bc94b..0d8c2024 100644
--- a/openstackclient/tests/volume/v2/fakes.py
+++ b/openstackclient/tests/volume/v2/fakes.py
@@ -15,11 +15,15 @@
import copy
import mock
+from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import fakes
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
from openstackclient.tests import utils
+volume_attachment_server = copy.deepcopy(compute_fakes.SERVER)
+volume_attachment_server['device'] = 'device'
+
volume_id = "ce26708d-a7f8-4b4b-9861-4a80256615a6"
volume_name = "fake_volume"
volume_description = "fake description"
@@ -34,7 +38,7 @@ volume_metadata = {
volume_metadata_str = "Alpha='a', Beta='b', Gamma='g'"
volume_snapshot_id = 1
volume_availability_zone = "nova"
-volume_attachments = ["fake_attachments"]
+volume_attachments = [volume_attachment_server]
VOLUME = {
"id": volume_id,
diff --git a/openstackclient/tests/volume/v2/test_volume.py b/openstackclient/tests/volume/v2/test_volume.py
index 4fffefa4..348ae377 100644
--- a/openstackclient/tests/volume/v2/test_volume.py
+++ b/openstackclient/tests/volume/v2/test_volume.py
@@ -495,6 +495,220 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(datalist, data)
+class TestVolumeList(TestVolume):
+
+ def setUp(self):
+ super(TestVolumeList, self).setUp()
+
+ self.volumes_mock.list.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.VOLUME),
+ loaded=True,
+ ),
+ ]
+
+ self.users_mock.get.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.USER),
+ loaded=True,
+ ),
+ ]
+
+ self.projects_mock.get.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ ),
+ ]
+
+ # Get the command object to test
+ self.cmd = volume.ListVolume(self.app, None)
+
+ def test_volume_list_no_options(self):
+ arglist = []
+ verifylist = [
+ ('long', False),
+ ('all_projects', False),
+ ('name', None),
+ ('status', None),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ collist = [
+ 'ID',
+ 'Display Name',
+ 'Status',
+ 'Size',
+ 'Attached to',
+ ]
+ self.assertEqual(collist, columns)
+
+ server = volume_fakes.volume_attachment_server['id']
+ device = volume_fakes.volume_attachment_server['device']
+ msg = 'Attached to %s on %s ' % (server, device)
+ datalist = ((
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_status,
+ volume_fakes.volume_size,
+ msg,
+ ), )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_volume_list_all_projects_option(self):
+ arglist = [
+ '--all-projects',
+ ]
+ verifylist = [
+ ('long', False),
+ ('all_projects', True),
+ ('name', None),
+ ('status', None),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ collist = [
+ 'ID',
+ 'Display Name',
+ 'Status',
+ 'Size',
+ 'Attached to',
+ ]
+ self.assertEqual(collist, columns)
+
+ server = volume_fakes.volume_attachment_server['id']
+ device = volume_fakes.volume_attachment_server['device']
+ msg = 'Attached to %s on %s ' % (server, device)
+ datalist = ((
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_status,
+ volume_fakes.volume_size,
+ msg,
+ ), )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_volume_list_name(self):
+ arglist = [
+ '--name', volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('long', False),
+ ('all_projects', False),
+ ('name', volume_fakes.volume_name),
+ ('status', None),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ collist = (
+ 'ID',
+ 'Display Name',
+ 'Status',
+ 'Size',
+ 'Attached to',
+ )
+ self.assertEqual(collist, tuple(columns))
+
+ server = volume_fakes.volume_attachment_server['id']
+ device = volume_fakes.volume_attachment_server['device']
+ msg = 'Attached to %s on %s ' % (server, device)
+
+ datalist = ((
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_status,
+ volume_fakes.volume_size,
+ msg,
+ ), )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_volume_list_status(self):
+ arglist = [
+ '--status', volume_fakes.volume_status,
+ ]
+ verifylist = [
+ ('long', False),
+ ('all_projects', False),
+ ('name', None),
+ ('status', volume_fakes.volume_status),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ collist = (
+ 'ID',
+ 'Display Name',
+ 'Status',
+ 'Size',
+ 'Attached to',
+ )
+ self.assertEqual(collist, tuple(columns))
+
+ server = volume_fakes.volume_attachment_server['id']
+ device = volume_fakes.volume_attachment_server['device']
+ msg = 'Attached to %s on %s ' % (server, device)
+ datalist = ((
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_status,
+ volume_fakes.volume_size,
+ msg,
+ ), )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_volume_list_long(self):
+ arglist = [
+ '--long',
+ ]
+ verifylist = [
+ ('long', True),
+ ('all_projects', False),
+ ('name', None),
+ ('status', None),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ collist = [
+ 'ID',
+ 'Display Name',
+ 'Status',
+ 'Size',
+ 'Type',
+ 'Bootable',
+ 'Attached to',
+ 'Properties',
+ ]
+ self.assertEqual(collist, columns)
+
+ server = volume_fakes.volume_attachment_server['id']
+ device = volume_fakes.volume_attachment_server['device']
+ msg = 'Attached to %s on %s ' % (server, device)
+ datalist = ((
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_status,
+ volume_fakes.volume_size,
+ volume_fakes.volume_type,
+ '',
+ msg,
+ "Alpha='a', Beta='b', Gamma='g'",
+ ), )
+ self.assertEqual(datalist, tuple(data))
+
+
class TestVolumeShow(TestVolume):
def setUp(self):
super(TestVolumeShow, self).setUp()
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index d4536f51..fe4a3ff6 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -14,9 +14,12 @@
"""Volume V2 Volume action implementations"""
+import copy
import logging
+import os
from cliff import command
+from cliff import lister
from cliff import show
import six
@@ -189,6 +192,112 @@ class DeleteVolume(command.Command):
return
+class ListVolume(lister.Lister):
+ """List volumes"""
+
+ log = logging.getLogger(__name__ + '.ListVolume')
+
+ def get_parser(self, prog_name):
+ parser = super(ListVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ '--all-projects',
+ action='store_true',
+ default=bool(int(os.environ.get("ALL_PROJECTS", 0))),
+ help='Include all projects (admin only)',
+ )
+ parser.add_argument(
+ '--long',
+ action='store_true',
+ default=False,
+ help='List additional fields in output',
+ )
+ parser.add_argument(
+ '--name',
+ metavar='<name>',
+ help='Filter results by name',
+ )
+ parser.add_argument(
+ '--status',
+ metavar='<status>',
+ help='Filter results by status',
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+
+ volume_client = self.app.client_manager.volume
+ compute_client = self.app.client_manager.compute
+
+ def _format_attach(attachments):
+ """Return a formatted string of a volume's attached instances
+
+ :param volume: a volume.attachments field
+ :rtype: a string of formatted instances
+ """
+
+ msg = ''
+ for attachment in attachments:
+ server = attachment['id']
+ if server in server_cache:
+ server = server_cache[server].name
+ device = attachment['device']
+ msg += 'Attached to %s on %s ' % (server, device)
+ return msg
+
+ if parsed_args.long:
+ columns = [
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Size',
+ 'Volume Type',
+ 'Bootable',
+ 'Attachments',
+ 'Metadata',
+ ]
+ column_headers = copy.deepcopy(columns)
+ column_headers[1] = 'Display Name'
+ column_headers[4] = 'Type'
+ column_headers[6] = 'Attached to'
+ column_headers[7] = 'Properties'
+ else:
+ columns = [
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Size',
+ 'Attachments',
+ ]
+ column_headers = copy.deepcopy(columns)
+ column_headers[1] = 'Display Name'
+ column_headers[4] = 'Attached to'
+
+ # Cache the server list
+ server_cache = {}
+ try:
+ for s in compute_client.servers.list():
+ server_cache[s.id] = s
+ except Exception:
+ # Just forget it if there's any trouble
+ pass
+
+ search_opts = {
+ 'all_projects': parsed_args.all_projects,
+ 'display_name': parsed_args.name,
+ 'status': parsed_args.status,
+ }
+
+ data = volume_client.volumes.list(search_opts=search_opts)
+
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ formatters={'Metadata': utils.format_dict,
+ 'Attachments': _format_attach},
+ ) for s in data))
+
+
class SetVolume(show.ShowOne):
"""Set volume properties"""