summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/image/v1/image.py2
-rw-r--r--openstackclient/image/v2/image.py2
-rw-r--r--openstackclient/network/v2/network.py57
-rw-r--r--openstackclient/network/v2/port.py54
-rw-r--r--openstackclient/network/v2/router.py21
-rw-r--r--openstackclient/tests/functional/volume/v2/test_volume_type.py5
-rw-r--r--openstackclient/tests/unit/network/v2/fakes.py29
-rw-r--r--openstackclient/tests/unit/network/v2/test_network.py55
-rw-r--r--openstackclient/tests/unit/network/v2/test_port.py2
-rw-r--r--openstackclient/tests/unit/network/v2/test_router.py8
-rw-r--r--openstackclient/tests/unit/test_shell.py2
-rw-r--r--openstackclient/tests/unit/volume/v1/test_volume.py136
-rw-r--r--openstackclient/tests/unit/volume/v2/test_snapshot.py28
-rw-r--r--openstackclient/tests/unit/volume/v2/test_type.py27
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume.py148
-rw-r--r--openstackclient/volume/v1/volume.py38
-rw-r--r--openstackclient/volume/v2/volume.py38
-rw-r--r--openstackclient/volume/v2/volume_snapshot.py39
-rw-r--r--openstackclient/volume/v2/volume_type.py29
19 files changed, 633 insertions, 87 deletions
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index eb79cd2f..1f239b67 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -39,7 +39,7 @@ from openstackclient.i18n import _
DEFAULT_CONTAINER_FORMAT = 'bare'
DEFAULT_DISK_FORMAT = 'raw'
DISK_CHOICES = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2", "vhdx",
- "vdi", "iso"]
+ "vdi", "iso", "ploop"]
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 1d167605..55eb7eb1 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -33,7 +33,7 @@ from openstackclient.identity import common
DEFAULT_CONTAINER_FORMAT = 'bare'
DEFAULT_DISK_FORMAT = 'raw'
DISK_CHOICES = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2", "vhdx",
- "vdi", "iso"]
+ "vdi", "iso", "ploop"]
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 1c06c462..26cd02c6 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -19,6 +19,7 @@ from osc_lib import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
+from openstackclient.network import sdk_utils
def _format_admin_state(item):
@@ -31,13 +32,33 @@ def _format_router_external(item):
_formatters = {
'subnets': utils.format_list,
+ 'subnet_ids': utils.format_list,
'admin_state_up': _format_admin_state,
+ 'is_admin_state_up': _format_admin_state,
'router:external': _format_router_external,
+ 'is_router_external': _format_router_external,
'availability_zones': utils.format_list,
'availability_zone_hints': utils.format_list,
}
+def _get_network_columns(item):
+ column_map = {
+ 'subnet_ids': 'subnets',
+ 'is_admin_state_up': 'admin_state_up',
+ 'is_router_external': 'router:external',
+ 'is_port_security_enabled': 'port_security_enabled',
+ 'provider_network_type': 'provider:network_type',
+ 'provider_physical_network': 'provider:physical_network',
+ 'provider_segmentation_id': 'provider:segmentation_id',
+ 'is_shared': 'shared',
+ 'ipv4_address_scope_id': 'ipv4_address_scope',
+ 'ipv6_address_scope_id': 'ipv6_address_scope',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
+
+
def _get_columns(item):
columns = list(item.keys())
if 'tenant_id' in columns:
@@ -162,6 +183,8 @@ def _get_attrs_compute(client_manager, parsed_args):
return attrs
+# TODO(sindhu): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateNetwork(common.NetworkAndComputeShowOne):
_description = _("Create new network")
@@ -275,9 +298,9 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
def take_action_network(self, client, parsed_args):
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_network(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_network_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
attrs = _get_attrs_compute(self.app.client_manager, parsed_args)
@@ -313,6 +336,8 @@ class DeleteNetwork(common.NetworkAndComputeDelete):
client.networks.delete(network.id)
+# TODO(sindhu): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class ListNetwork(common.NetworkAndComputeLister):
_description = _("List networks")
@@ -405,12 +430,12 @@ class ListNetwork(common.NetworkAndComputeLister):
'id',
'name',
'status',
- 'tenant_id',
- 'admin_state_up',
- 'shared',
- 'subnets',
+ 'project_id',
+ 'is_admin_state_up',
+ 'is_shared',
+ 'subnet_ids',
'provider_network_type',
- 'router:external',
+ 'is_router_external',
'availability_zones',
)
column_headers = (
@@ -429,7 +454,7 @@ class ListNetwork(common.NetworkAndComputeLister):
columns = (
'id',
'name',
- 'subnets'
+ 'subnet_ids'
)
column_headers = (
'ID',
@@ -441,16 +466,20 @@ class ListNetwork(common.NetworkAndComputeLister):
if parsed_args.external:
args['router:external'] = True
+ args['is_router_external'] = True
elif parsed_args.internal:
args['router:external'] = False
+ args['is_router_external'] = False
if parsed_args.name is not None:
args['name'] = parsed_args.name
if parsed_args.enable:
args['admin_state_up'] = True
+ args['is_admin_state_up'] = True
elif parsed_args.disable:
args['admin_state_up'] = False
+ args['is_admin_state_up'] = False
if parsed_args.project:
project = identity_common.find_project(
@@ -459,21 +488,27 @@ class ListNetwork(common.NetworkAndComputeLister):
parsed_args.project_domain,
)
args['tenant_id'] = project.id
+ args['project_id'] = project.id
if parsed_args.share:
args['shared'] = True
+ args['is_shared'] = True
elif parsed_args.no_share:
args['shared'] = False
+ args['is_shared'] = False
if parsed_args.status:
args['status'] = parsed_args.status
if parsed_args.provider_network_type:
args['provider:network_type'] = parsed_args.provider_network_type
+ args['provider_network_type'] = parsed_args.provider_network_type
if parsed_args.physical_network:
args['provider:physical_network'] = parsed_args.physical_network
+ args['provider_physical_network'] = parsed_args.physical_network
if parsed_args.segmentation_id:
args['provider:segmentation_id'] = parsed_args.segmentation_id
+ args['provider_segmentation_id'] = parsed_args.segmentation_id
data = client.networks(**args)
@@ -504,6 +539,8 @@ class ListNetwork(common.NetworkAndComputeLister):
) for s in data))
+# TODO(sindhu): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class SetNetwork(command.Command):
_description = _("Set network properties")
@@ -619,9 +656,9 @@ class ShowNetwork(common.NetworkAndComputeShowOne):
def take_action_network(self, client, parsed_args):
obj = client.find_network(parsed_args.network, ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_network_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
obj = utils.find_resource(
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index bce3e2d3..4525da18 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -25,6 +25,7 @@ from osc_lib import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+from openstackclient.network import sdk_utils
LOG = logging.getLogger(__name__)
@@ -36,34 +37,33 @@ def _format_admin_state(state):
_formatters = {
'admin_state_up': _format_admin_state,
+ 'is_admin_state_up': _format_admin_state,
'allowed_address_pairs': utils.format_list_of_dicts,
'binding_profile': utils.format_dict,
'binding_vif_details': utils.format_dict,
+ 'binding:profile': utils.format_dict,
+ 'binding:vif_details': utils.format_dict,
'dns_assignment': utils.format_list_of_dicts,
'extra_dhcp_opts': utils.format_list_of_dicts,
'fixed_ips': utils.format_list_of_dicts,
+ 'security_group_ids': utils.format_list,
'security_groups': utils.format_list,
}
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- if 'project_id' not in columns:
- columns.append('project_id')
- binding_columns = [
- 'binding:host_id',
- 'binding:profile',
- 'binding:vif_details',
- 'binding:vif_type',
- 'binding:vnic_type',
- ]
- for binding_column in binding_columns:
- if binding_column in columns:
- columns.remove(binding_column)
- columns.append(binding_column.replace('binding:', 'binding_', 1))
- return tuple(sorted(columns))
+ column_map = {
+ 'binding:host_id': 'binding_host_id',
+ 'binding:profile': 'binding_profile',
+ 'binding:vif_details': 'binding_vif_details',
+ 'binding:vif_type': 'binding_vif_type',
+ 'binding:vnic_type': 'binding_vnic_type',
+ 'is_admin_state_up': 'admin_state_up',
+ 'is_port_security_enabled': 'port_security_enabled',
+ 'security_group_ids': 'security_groups',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
class JSONKeyValueAction(argparse.Action):
@@ -244,6 +244,8 @@ def _add_updatable_args(parser):
)
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreatePort(command.ShowOne):
_description = _("Create a new port")
@@ -349,10 +351,10 @@ class CreatePort(command.ShowOne):
attrs['security_groups'] = []
obj = client.create_port(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return (columns, data)
+ return (display_columns, data)
class DeletePort(command.Command):
@@ -389,6 +391,8 @@ class DeletePort(command.Command):
raise exceptions.CommandError(msg)
+# TODO(abhiraut): Use only the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class ListPort(command.Lister):
_description = _("List ports")
@@ -451,7 +455,7 @@ class ListPort(command.Lister):
filters = {}
if parsed_args.long:
- columns += ('security_groups', 'device_owner',)
+ columns += ('security_group_ids', 'device_owner',)
column_headers += ('Security Groups', 'Device Owner',)
if parsed_args.device_owner is not None:
filters['device_owner'] = parsed_args.device_owner
@@ -479,6 +483,8 @@ class ListPort(command.Lister):
) for s in data))
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class SetPort(command.Command):
_description = _("Set port properties")
@@ -621,11 +627,13 @@ class ShowPort(command.ShowOne):
def take_action(self, parsed_args):
client = self.app.client_manager.network
obj = client.find_port(parsed_args.port, ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return (columns, data)
+ return (display_columns, data)
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class UnsetPort(command.Command):
_description = _("Unset port properties")
@@ -666,7 +674,7 @@ class UnsetPort(command.Command):
def take_action(self, parsed_args):
client = self.app.client_manager.network
obj = client.find_port(parsed_args.port, ignore_missing=False)
- # SDK ignores update() if it recieves a modified obj and attrs
+ # SDK ignores update() if it receives a modified obj and attrs
# To handle the same tmp_obj is created in all take_action of
# Unset* classes
tmp_fixed_ips = copy.deepcopy(obj.fixed_ips)
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index cdd634d0..61a005e6 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -52,6 +52,7 @@ def _format_routes(routes):
_formatters = {
'admin_state_up': _format_admin_state,
+ 'is_admin_state_up': _format_admin_state,
'external_gateway_info': _format_external_gateway_info,
'availability_zones': utils.format_list,
'availability_zone_hints': utils.format_list,
@@ -62,6 +63,9 @@ _formatters = {
def _get_columns(item):
column_map = {
'tenant_id': 'project_id',
+ 'is_ha': 'ha',
+ 'is_distributed': 'distributed',
+ 'is_admin_state_up': 'admin_state_up',
}
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
@@ -150,6 +154,8 @@ class AddSubnetToRouter(command.Command):
subnet_id=subnet.id)
+# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateRouter(command.ShowOne):
_description = _("Create a new router")
@@ -255,6 +261,8 @@ class DeleteRouter(command.Command):
raise exceptions.CommandError(msg)
+# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class ListRouter(command.Lister):
_description = _("List routers")
@@ -297,10 +305,10 @@ class ListRouter(command.Lister):
'id',
'name',
'status',
- 'admin_state_up',
- 'distributed',
- 'ha',
- 'tenant_id',
+ 'is_admin_state_up',
+ 'is_distributed',
+ 'is_ha',
+ 'project_id',
)
column_headers = (
'ID',
@@ -319,8 +327,10 @@ class ListRouter(command.Lister):
if parsed_args.enable:
args['admin_state_up'] = True
+ args['is_admin_state_up'] = True
elif parsed_args.disable:
args['admin_state_up'] = False
+ args['is_admin_state_up'] = False
if parsed_args.project:
project_id = identity_common.find_project(
@@ -329,6 +339,7 @@ class ListRouter(command.Lister):
parsed_args.project_domain,
).id
args['tenant_id'] = project_id
+ args['project_id'] = project_id
if parsed_args.long:
columns = columns + (
'routes',
@@ -407,6 +418,8 @@ class RemoveSubnetFromRouter(command.Command):
subnet_id=subnet.id)
+# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class SetRouter(command.Command):
_description = _("Set router properties")
diff --git a/openstackclient/tests/functional/volume/v2/test_volume_type.py b/openstackclient/tests/functional/volume/v2/test_volume_type.py
index d8bd3a96..b4df5b2d 100644
--- a/openstackclient/tests/functional/volume/v2/test_volume_type.py
+++ b/openstackclient/tests/functional/volume/v2/test_volume_type.py
@@ -42,6 +42,11 @@ class VolumeTypeTests(common.BaseVolumeTests):
raw_output = self.openstack('volume type list' + opts)
self.assertIn(self.NAME, raw_output)
+ def test_volume_type_list_default(self):
+ opts = self.get_opts(self.HEADERS)
+ raw_output = self.openstack('volume type list --default' + opts)
+ self.assertEqual("lvmdriver-1\n", raw_output)
+
def test_volume_type_show(self):
opts = self.get_opts(self.FIELDS)
raw_output = self.openstack('volume type show ' + self.NAME + opts)
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index 97d07076..84f145fb 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -297,15 +297,17 @@ class FakeNetwork(object):
'admin_state_up': True,
'shared': False,
'subnets': ['a', 'b'],
- 'provider_network_type': 'vlan',
- 'provider_physical_network': 'physnet1',
- 'provider_segmentation_id': "400",
+ 'provider:network_type': 'vlan',
+ 'provider:physical_network': 'physnet1',
+ 'provider:segmentation_id': "400",
'router:external': True,
'availability_zones': [],
'availability_zone_hints': [],
'is_default': False,
'port_security_enabled': True,
'qos_policy_id': 'qos-policy-id-' + uuid.uuid4().hex,
+ 'ipv4_address_scope': 'ipv4' + uuid.uuid4().hex,
+ 'ipv6_address_scope': 'ipv6' + uuid.uuid4().hex,
}
# Overwrite default attributes.
@@ -317,8 +319,21 @@ class FakeNetwork(object):
# Set attributes with special mapping in OpenStack SDK.
network.project_id = network_attrs['tenant_id']
network.is_router_external = network_attrs['router:external']
+ network.is_admin_state_up = network_attrs['admin_state_up']
network.is_port_security_enabled = \
network_attrs['port_security_enabled']
+ network.subnet_ids = network_attrs['subnets']
+ network.is_shared = network_attrs['shared']
+ network.provider_network_type = \
+ network_attrs['provider:network_type']
+ network.provider_physical_network = \
+ network_attrs['provider:physical_network']
+ network.provider_segmentation_id = \
+ network_attrs['provider:segmentation_id']
+ network.ipv4_address_scope_id = \
+ network_attrs['ipv4_address_scope']
+ network.ipv6_address_scope_id = \
+ network_attrs['ipv6_address_scope']
return network
@@ -461,12 +476,15 @@ class FakePort(object):
loaded=True)
# Set attributes with special mappings in OpenStack SDK.
- port.project_id = port_attrs['tenant_id']
port.binding_host_id = port_attrs['binding:host_id']
port.binding_profile = port_attrs['binding:profile']
port.binding_vif_details = port_attrs['binding:vif_details']
port.binding_vif_type = port_attrs['binding:vif_type']
port.binding_vnic_type = port_attrs['binding:vnic_type']
+ port.is_admin_state_up = port_attrs['admin_state_up']
+ port.is_port_security_enabled = port_attrs['port_security_enabled']
+ port.project_id = port_attrs['tenant_id']
+ port.security_group_ids = port_attrs['security_groups']
return port
@@ -834,6 +852,9 @@ class FakeRouter(object):
# Set attributes with special mapping in OpenStack SDK.
router.project_id = router_attrs['tenant_id']
+ router.is_admin_state_up = router_attrs['admin_state_up']
+ router.is_distributed = router_attrs['distributed']
+ router.is_ha = router_attrs['ha']
return router
diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py
index 96b1b102..c5283443 100644
--- a/openstackclient/tests/unit/network/v2/test_network.py
+++ b/openstackclient/tests/unit/network/v2/test_network.py
@@ -62,13 +62,15 @@ class TestCreateNetworkIdentityV3(TestNetwork):
'availability_zones',
'description',
'id',
+ 'ipv4_address_scope',
+ 'ipv6_address_scope',
'is_default',
'name',
'port_security_enabled',
'project_id',
- 'provider_network_type',
- 'provider_physical_network',
- 'provider_segmentation_id',
+ 'provider:network_type',
+ 'provider:physical_network',
+ 'provider:segmentation_id',
'qos_policy_id',
'router:external',
'shared',
@@ -82,6 +84,8 @@ class TestCreateNetworkIdentityV3(TestNetwork):
utils.format_list(_network.availability_zones),
_network.description,
_network.id,
+ _network.ipv4_address_scope_id,
+ _network.ipv6_address_scope_id,
_network.is_default,
_network.name,
_network.is_port_security_enabled,
@@ -236,13 +240,15 @@ class TestCreateNetworkIdentityV2(TestNetwork):
'availability_zones',
'description',
'id',
+ 'ipv4_address_scope',
+ 'ipv6_address_scope',
'is_default',
'name',
'port_security_enabled',
'project_id',
- 'provider_network_type',
- 'provider_physical_network',
- 'provider_segmentation_id',
+ 'provider:network_type',
+ 'provider:physical_network',
+ 'provider:segmentation_id',
'qos_policy_id',
'router:external',
'shared',
@@ -256,6 +262,8 @@ class TestCreateNetworkIdentityV2(TestNetwork):
utils.format_list(_network.availability_zones),
_network.description,
_network.id,
+ _network.ipv4_address_scope_id,
+ _network.ipv6_address_scope_id,
_network.is_default,
_network.name,
_network.is_port_security_enabled,
@@ -512,7 +520,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'router:external': True}
+ **{'router:external': True, 'is_router_external': True}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -529,7 +537,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'router:external': False}
+ **{'router:external': False, 'is_router_external': False}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -585,7 +593,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'admin_state_up': True}
+ **{'admin_state_up': True, 'is_admin_state_up': True}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -603,7 +611,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'admin_state_up': False}
+ **{'admin_state_up': False, 'is_admin_state_up': False}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -621,7 +629,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'tenant_id': project.id}
+ **{'tenant_id': project.id, 'project_id': project.id}
)
self.assertEqual(self.columns, columns)
@@ -640,7 +648,7 @@ class TestListNetwork(TestNetwork):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'tenant_id': project.id}
+ filters = {'tenant_id': project.id, 'project_id': project.id}
self.network.networks.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -658,7 +666,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'shared': True}
+ **{'shared': True, 'is_shared': True}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -675,7 +683,7 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'shared': False}
+ **{'shared': False, 'is_shared': False}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -711,7 +719,8 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'provider:network_type': network_type}
+ **{'provider:network_type': network_type,
+ 'provider_network_type': network_type}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -728,7 +737,8 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'provider:physical_network': physical_network}
+ **{'provider:physical_network': physical_network,
+ 'provider_physical_network': physical_network}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -745,7 +755,8 @@ class TestListNetwork(TestNetwork):
columns, data = self.cmd.take_action(parsed_args)
self.network.networks.assert_called_once_with(
- **{'provider:segmentation_id': segmentation_id}
+ **{'provider:segmentation_id': segmentation_id,
+ 'provider_segmentation_id': segmentation_id}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -878,13 +889,15 @@ class TestShowNetwork(TestNetwork):
'availability_zones',
'description',
'id',
+ 'ipv4_address_scope',
+ 'ipv6_address_scope',
'is_default',
'name',
'port_security_enabled',
'project_id',
- 'provider_network_type',
- 'provider_physical_network',
- 'provider_segmentation_id',
+ 'provider:network_type',
+ 'provider:physical_network',
+ 'provider:segmentation_id',
'qos_policy_id',
'router:external',
'shared',
@@ -898,6 +911,8 @@ class TestShowNetwork(TestNetwork):
utils.format_list(_network.availability_zones),
_network.description,
_network.id,
+ _network.ipv4_address_scope_id,
+ _network.ipv6_address_scope_id,
_network.is_default,
_network.name,
_network.is_port_security_enabled,
diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py
index aeb9884a..255e8116 100644
--- a/openstackclient/tests/unit/network/v2/test_port.py
+++ b/openstackclient/tests/unit/network/v2/test_port.py
@@ -324,7 +324,7 @@ class TestCreatePort(TestPort):
self.assertEqual(ref_columns, columns)
self.assertEqual(ref_data, data)
- def test_create_with_no_secuirty_groups(self):
+ def test_create_with_no_security_groups(self):
arglist = [
'--network', self._port.network_id,
'--no-security-group',
diff --git a/openstackclient/tests/unit/network/v2/test_router.py b/openstackclient/tests/unit/network/v2/test_router.py
index b0409447..8c1d5804 100644
--- a/openstackclient/tests/unit/network/v2/test_router.py
+++ b/openstackclient/tests/unit/network/v2/test_router.py
@@ -459,7 +459,7 @@ class TestListRouter(TestRouter):
columns, data = self.cmd.take_action(parsed_args)
self.network.routers.assert_called_once_with(
- **{'admin_state_up': True}
+ **{'admin_state_up': True, 'is_admin_state_up': True}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -476,7 +476,7 @@ class TestListRouter(TestRouter):
columns, data = self.cmd.take_action(parsed_args)
self.network.routers.assert_called_once_with(
- **{'admin_state_up': False}
+ **{'admin_state_up': False, 'is_admin_state_up': False}
)
self.assertEqual(self.columns, columns)
@@ -494,7 +494,7 @@ class TestListRouter(TestRouter):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'tenant_id': project.id}
+ filters = {'tenant_id': project.id, 'project_id': project.id}
self.network.routers.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -514,7 +514,7 @@ class TestListRouter(TestRouter):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'tenant_id': project.id}
+ filters = {'tenant_id': project.id, 'project_id': project.id}
self.network.routers.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
diff --git a/openstackclient/tests/unit/test_shell.py b/openstackclient/tests/unit/test_shell.py
index 3d91da9b..b9fac684 100644
--- a/openstackclient/tests/unit/test_shell.py
+++ b/openstackclient/tests/unit/test_shell.py
@@ -422,7 +422,7 @@ class TestShellArgV(TestShell):
Use the argv supplied by the test runner so we get actual Python
runtime behaviour; we only need to check the type of argv[0]
- which will alwyas be present.
+ which will always be present.
"""
with mock.patch(
diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py
index 7a44dea8..6c6d9a1d 100644
--- a/openstackclient/tests/unit/volume/v1/test_volume.py
+++ b/openstackclient/tests/unit/volume/v1/test_volume.py
@@ -431,6 +431,142 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, data)
+ def test_volume_create_with_bootable_and_readonly(self):
+ arglist = [
+ '--bootable',
+ '--read-only',
+ '--size', str(self.new_volume.size),
+ self.new_volume.display_name,
+ ]
+ verifylist = [
+ ('bootable', True),
+ ('non_bootable', False),
+ ('read_only', True),
+ ('read_write', False),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.display_name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ self.new_volume.size,
+ None,
+ None,
+ self.new_volume.display_name,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, True)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, True)
+
+ def test_volume_create_with_nonbootable_and_readwrite(self):
+ arglist = [
+ '--non-bootable',
+ '--read-write',
+ '--size', str(self.new_volume.size),
+ self.new_volume.display_name,
+ ]
+ verifylist = [
+ ('bootable', False),
+ ('non_bootable', True),
+ ('read_only', False),
+ ('read_write', True),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.display_name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ self.new_volume.size,
+ None,
+ None,
+ self.new_volume.display_name,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, False)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, False)
+
+ @mock.patch.object(volume.LOG, 'error')
+ def test_volume_create_with_bootable_and_readonly_fail(
+ self, mock_error):
+
+ self.volumes_mock.set_bootable.side_effect = (
+ exceptions.CommandError())
+
+ self.volumes_mock.update_readonly_flag.side_effect = (
+ exceptions.CommandError())
+
+ arglist = [
+ '--bootable',
+ '--read-only',
+ '--size', str(self.new_volume.size),
+ self.new_volume.display_name,
+ ]
+ verifylist = [
+ ('bootable', True),
+ ('non_bootable', False),
+ ('read_only', True),
+ ('read_write', False),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.display_name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ self.new_volume.size,
+ None,
+ None,
+ self.new_volume.display_name,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ )
+
+ self.assertEqual(2, mock_error.call_count)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, True)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, True)
+
def test_volume_create_without_size(self):
arglist = [
self.new_volume.display_name,
diff --git a/openstackclient/tests/unit/volume/v2/test_snapshot.py b/openstackclient/tests/unit/volume/v2/test_snapshot.py
index cedf21a9..8ce356ae 100644
--- a/openstackclient/tests/unit/volume/v2/test_snapshot.py
+++ b/openstackclient/tests/unit/volume/v2/test_snapshot.py
@@ -67,6 +67,7 @@ class TestSnapshotCreate(TestSnapshot):
self.volumes_mock.get.return_value = self.volume
self.snapshots_mock.create.return_value = self.new_snapshot
+ self.snapshots_mock.manage.return_value = self.new_snapshot
# Get the command object to test
self.cmd = volume_snapshot.CreateVolumeSnapshot(self.app, None)
@@ -152,6 +153,33 @@ class TestSnapshotCreate(TestSnapshot):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
+ def test_snapshot_create_without_remote_source(self):
+ arglist = [
+ '--remote-source', 'source-name=test_source_name',
+ '--remote-source', 'source-id=test_source_id',
+ '--volume', self.new_snapshot.volume_id,
+ ]
+ ref_dict = {'source-name': 'test_source_name',
+ 'source-id': 'test_source_id'}
+ verifylist = [
+ ('remote_source', ref_dict),
+ ('volume', self.new_snapshot.volume_id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.snapshots_mock.manage.assert_called_with(
+ volume_id=self.new_snapshot.volume_id,
+ ref=ref_dict,
+ name=None,
+ description=None,
+ metadata=None,
+ )
+ self.snapshots_mock.create.assert_not_called()
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
class TestSnapshotDelete(TestSnapshot):
diff --git a/openstackclient/tests/unit/volume/v2/test_type.py b/openstackclient/tests/unit/volume/v2/test_type.py
index 325872d7..0d556e13 100644
--- a/openstackclient/tests/unit/volume/v2/test_type.py
+++ b/openstackclient/tests/unit/volume/v2/test_type.py
@@ -172,7 +172,11 @@ class TestTypeList(TestType):
"Description",
"Properties"
]
-
+ data_with_default_type = [(
+ volume_types[0].id,
+ volume_types[0].name,
+ True
+ )]
data = []
for t in volume_types:
data.append((
@@ -194,6 +198,7 @@ class TestTypeList(TestType):
super(TestTypeList, self).setUp()
self.types_mock.list.return_value = self.volume_types
+ self.types_mock.default.return_value = self.volume_types[0]
# get the command to test
self.cmd = volume_type.ListVolumeType(self.app, None)
@@ -203,6 +208,7 @@ class TestTypeList(TestType):
("long", False),
("private", False),
("public", False),
+ ("default", False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -220,6 +226,7 @@ class TestTypeList(TestType):
("long", True),
("private", False),
("public", True),
+ ("default", False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -236,6 +243,7 @@ class TestTypeList(TestType):
("long", False),
("private", True),
("public", False),
+ ("default", False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -244,6 +252,23 @@ class TestTypeList(TestType):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+ def test_type_list_with_default_option(self):
+ arglist = [
+ "--default",
+ ]
+ verifylist = [
+ ("long", False),
+ ("private", False),
+ ("public", False),
+ ("default", True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.types_mock.default.assert_called_once_with()
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data_with_default_type, list(data))
+
class TestTypeSet(TestType):
diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py
index 41728342..1529c2e2 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume.py
@@ -450,6 +450,154 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, data)
+ def test_volume_create_with_bootable_and_readonly(self):
+ arglist = [
+ '--bootable',
+ '--read-only',
+ '--size', str(self.new_volume.size),
+ self.new_volume.name,
+ ]
+ verifylist = [
+ ('bootable', True),
+ ('non_bootable', False),
+ ('read_only', True),
+ ('read_write', False),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=self.new_volume.size,
+ snapshot_id=None,
+ name=self.new_volume.name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None,
+ consistencygroup_id=None,
+ source_replica=None,
+ multiattach=False,
+ scheduler_hints=None,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, True)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, True)
+
+ def test_volume_create_with_nonbootable_and_readwrite(self):
+ arglist = [
+ '--non-bootable',
+ '--read-write',
+ '--size', str(self.new_volume.size),
+ self.new_volume.name,
+ ]
+ verifylist = [
+ ('bootable', False),
+ ('non_bootable', True),
+ ('read_only', False),
+ ('read_write', True),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=self.new_volume.size,
+ snapshot_id=None,
+ name=self.new_volume.name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None,
+ consistencygroup_id=None,
+ source_replica=None,
+ multiattach=False,
+ scheduler_hints=None,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, False)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, False)
+
+ @mock.patch.object(volume.LOG, 'error')
+ def test_volume_create_with_bootable_and_readonly_fail(
+ self, mock_error):
+
+ self.volumes_mock.set_bootable.side_effect = (
+ exceptions.CommandError())
+
+ self.volumes_mock.update_readonly_flag.side_effect = (
+ exceptions.CommandError())
+
+ arglist = [
+ '--bootable',
+ '--read-only',
+ '--size', str(self.new_volume.size),
+ self.new_volume.name,
+ ]
+ verifylist = [
+ ('bootable', True),
+ ('non_bootable', False),
+ ('read_only', True),
+ ('read_write', False),
+ ('size', self.new_volume.size),
+ ('name', self.new_volume.name),
+ ]
+
+ parsed_args = self.check_parser(
+ self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=self.new_volume.size,
+ snapshot_id=None,
+ name=self.new_volume.name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None,
+ consistencygroup_id=None,
+ source_replica=None,
+ multiattach=False,
+ scheduler_hints=None,
+ )
+
+ self.assertEqual(2, mock_error.call_count)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, data)
+ self.volumes_mock.set_bootable.assert_called_with(
+ self.new_volume.id, True)
+ self.volumes_mock.update_readonly_flag.assert_called_with(
+ self.new_volume.id, True)
+
def test_volume_create_with_source_replicated(self):
self.volumes_mock.get.return_value = self.new_volume
arglist = [
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index 0087bad4..739484df 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -114,6 +114,28 @@ class CreateVolume(command.ShowOne):
help=_('Set a property on this volume '
'(repeat option to set multiple properties)'),
)
+ bootable_group = parser.add_mutually_exclusive_group()
+ bootable_group.add_argument(
+ "--bootable",
+ action="store_true",
+ help=_("Mark volume as bootable")
+ )
+ bootable_group.add_argument(
+ "--non-bootable",
+ action="store_true",
+ help=_("Mark volume as non-bootable (default)")
+ )
+ readonly_group = parser.add_mutually_exclusive_group()
+ readonly_group.add_argument(
+ "--read-only",
+ action="store_true",
+ help=_("Set volume to read-only access mode")
+ )
+ readonly_group.add_argument(
+ "--read-write",
+ action="store_true",
+ help=_("Set volume to read-write access mode (default)")
+ )
return parser
@@ -166,6 +188,22 @@ class CreateVolume(command.ShowOne):
parsed_args.property,
image,
)
+
+ if parsed_args.bootable or parsed_args.non_bootable:
+ try:
+ volume_client.volumes.set_bootable(
+ volume.id, parsed_args.bootable)
+ except Exception as e:
+ LOG.error(_("Failed to set volume bootable property: %s"), e)
+ if parsed_args.read_only or parsed_args.read_write:
+ try:
+ volume_client.volumes.update_readonly_flag(
+ volume.id,
+ parsed_args.read_only)
+ except Exception as e:
+ LOG.error(_("Failed to set volume read-only access "
+ "mode flag: %s"), e)
+
# Map 'metadata' column to 'properties'
volume._info.update(
{
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index 80abfb55..301bf5e4 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -132,6 +132,28 @@ class CreateVolume(command.ShowOne):
help=_("Allow volume to be attached more than once "
"(default to False)")
)
+ bootable_group = parser.add_mutually_exclusive_group()
+ bootable_group.add_argument(
+ "--bootable",
+ action="store_true",
+ help=_("Mark volume as bootable")
+ )
+ bootable_group.add_argument(
+ "--non-bootable",
+ action="store_true",
+ help=_("Mark volume as non-bootable (default)")
+ )
+ readonly_group = parser.add_mutually_exclusive_group()
+ readonly_group.add_argument(
+ "--read-only",
+ action="store_true",
+ help=_("Set volume to read-only access mode")
+ )
+ readonly_group.add_argument(
+ "--read-write",
+ action="store_true",
+ help=_("Set volume to read-write access mode (default)")
+ )
return parser
def take_action(self, parsed_args):
@@ -199,6 +221,22 @@ class CreateVolume(command.ShowOne):
multiattach=parsed_args.multi_attach,
scheduler_hints=parsed_args.hint,
)
+
+ if parsed_args.bootable or parsed_args.non_bootable:
+ try:
+ volume_client.volumes.set_bootable(
+ volume.id, parsed_args.bootable)
+ except Exception as e:
+ LOG.error(_("Failed to set volume bootable property: %s"), e)
+ if parsed_args.read_only or parsed_args.read_write:
+ try:
+ volume_client.volumes.update_readonly_flag(
+ volume.id,
+ parsed_args.read_only)
+ except Exception as e:
+ LOG.error(_("Failed to set volume read-only access "
+ "mode flag: %s"), e)
+
# Remove key links from being displayed
volume._info.update(
{
diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py
index d95a49a4..34b8fb82 100644
--- a/openstackclient/volume/v2/volume_snapshot.py
+++ b/openstackclient/volume/v2/volume_snapshot.py
@@ -65,6 +65,15 @@ class CreateVolumeSnapshot(command.ShowOne):
help=_("Set a property to this snapshot "
"(repeat option to set multiple properties)"),
)
+ parser.add_argument(
+ "--remote-source",
+ metavar="<key=value>",
+ action=parseractions.KeyValueAction,
+ help=_("The attribute(s) of the exsiting remote volume snapshot "
+ "(admin required) (repeat option to specify multiple "
+ "attributes) e.g.: '--remote-source source-name=test_name "
+ "--remote-source source-id=test_id'"),
+ )
return parser
def take_action(self, parsed_args):
@@ -74,13 +83,29 @@ class CreateVolumeSnapshot(command.ShowOne):
volume = parsed_args.snapshot_name
volume_id = utils.find_resource(
volume_client.volumes, volume).id
- snapshot = volume_client.volume_snapshots.create(
- volume_id,
- force=parsed_args.force,
- name=parsed_args.snapshot_name,
- description=parsed_args.description,
- metadata=parsed_args.property,
- )
+ if parsed_args.remote_source:
+ # Create a new snapshot from an existing remote snapshot source
+ if parsed_args.force:
+ msg = (_("'--force' option will not work when you create "
+ "new volume snapshot from an existing remote "
+ "volume snapshot"))
+ LOG.warning(msg)
+ snapshot = volume_client.volume_snapshots.manage(
+ volume_id=volume_id,
+ ref=parsed_args.remote_source,
+ name=parsed_args.snapshot_name,
+ description=parsed_args.description,
+ metadata=parsed_args.property,
+ )
+ else:
+ # create a new snapshot from scratch
+ snapshot = volume_client.volume_snapshots.create(
+ volume_id,
+ force=parsed_args.force,
+ name=parsed_args.snapshot_name,
+ description=parsed_args.description,
+ metadata=parsed_args.property,
+ )
snapshot._info.update(
{'properties': utils.format_dict(snapshot._info.pop('metadata'))}
)
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 42ebb53e..46466783 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -160,9 +160,16 @@ class ListVolumeType(command.Lister):
'--long',
action='store_true',
default=False,
- help=_('List additional fields in output'))
+ help=_('List additional fields in output')
+ )
public_group = parser.add_mutually_exclusive_group()
public_group.add_argument(
+ "--default",
+ action='store_true',
+ default=False,
+ help=_('List the default volume type')
+ )
+ public_group.add_argument(
"--public",
action="store_true",
help=_("List only public types")
@@ -175,6 +182,7 @@ class ListVolumeType(command.Lister):
return parser
def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
if parsed_args.long:
columns = ['ID', 'Name', 'Is Public', 'Description', 'Extra Specs']
column_headers = [
@@ -182,14 +190,16 @@ class ListVolumeType(command.Lister):
else:
columns = ['ID', 'Name', 'Is Public']
column_headers = columns
-
- is_public = None
- if parsed_args.public:
- is_public = True
- if parsed_args.private:
- is_public = False
- data = self.app.client_manager.volume.volume_types.list(
- is_public=is_public)
+ if parsed_args.default:
+ data = [volume_client.volume_types.default()]
+ else:
+ is_public = None
+ if parsed_args.public:
+ is_public = True
+ if parsed_args.private:
+ is_public = False
+ data = volume_client.volume_types.list(
+ is_public=is_public)
return (column_headers,
(utils.get_item_properties(
s, columns,
@@ -240,7 +250,6 @@ class SetVolumeType(command.Command):
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
-
result = 0
kwargs = {}
if parsed_args.name: