summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/availability_zone.py2
-rw-r--r--openstackclient/common/client_config.py1
-rw-r--r--openstackclient/common/configuration.py2
-rw-r--r--openstackclient/common/extension.py2
-rw-r--r--openstackclient/common/limits.py2
-rw-r--r--openstackclient/common/module.py4
-rw-r--r--openstackclient/common/quota.py4
-rw-r--r--openstackclient/compute/v2/agent.py8
-rw-r--r--openstackclient/compute/v2/aggregate.py16
-rw-r--r--openstackclient/compute/v2/console.py4
-rw-r--r--openstackclient/compute/v2/fixedip.py4
-rw-r--r--openstackclient/compute/v2/flavor.py12
-rw-r--r--openstackclient/compute/v2/floatingip.py4
-rw-r--r--openstackclient/compute/v2/host.py7
-rw-r--r--openstackclient/compute/v2/hypervisor.py4
-rw-r--r--openstackclient/compute/v2/hypervisor_stats.py4
-rw-r--r--openstackclient/compute/v2/keypair.py8
-rw-r--r--openstackclient/compute/v2/server.py65
-rw-r--r--openstackclient/compute/v2/server_backup.py2
-rw-r--r--openstackclient/compute/v2/server_group.py8
-rw-r--r--openstackclient/compute/v2/server_image.py2
-rw-r--r--openstackclient/compute/v2/service.py6
-rw-r--r--openstackclient/compute/v2/usage.py4
-rw-r--r--openstackclient/identity/v2_0/catalog.py4
-rw-r--r--openstackclient/identity/v2_0/ec2creds.py8
-rw-r--r--openstackclient/identity/v2_0/endpoint.py8
-rw-r--r--openstackclient/identity/v2_0/project.py12
-rw-r--r--openstackclient/identity/v2_0/role.py14
-rw-r--r--openstackclient/identity/v2_0/role_assignment.py2
-rw-r--r--openstackclient/identity/v2_0/service.py8
-rw-r--r--openstackclient/identity/v2_0/token.py4
-rw-r--r--openstackclient/identity/v2_0/user.py10
-rw-r--r--openstackclient/identity/v3/catalog.py4
-rw-r--r--openstackclient/identity/v3/consumer.py10
-rw-r--r--openstackclient/identity/v3/credential.py10
-rw-r--r--openstackclient/identity/v3/domain.py10
-rw-r--r--openstackclient/identity/v3/ec2creds.py8
-rw-r--r--openstackclient/identity/v3/endpoint.py10
-rw-r--r--openstackclient/identity/v3/federation_protocol.py10
-rw-r--r--openstackclient/identity/v3/group.py16
-rw-r--r--openstackclient/identity/v3/identity_provider.py10
-rw-r--r--openstackclient/identity/v3/mapping.py12
-rw-r--r--openstackclient/identity/v3/policy.py10
-rw-r--r--openstackclient/identity/v3/project.py10
-rw-r--r--openstackclient/identity/v3/region.py10
-rw-r--r--openstackclient/identity/v3/role.py16
-rw-r--r--openstackclient/identity/v3/role_assignment.py4
-rw-r--r--openstackclient/identity/v3/service.py10
-rw-r--r--openstackclient/identity/v3/service_provider.py10
-rw-r--r--openstackclient/identity/v3/token.py10
-rw-r--r--openstackclient/identity/v3/trust.py8
-rw-r--r--openstackclient/identity/v3/unscoped_saml.py4
-rw-r--r--openstackclient/identity/v3/user.py12
-rw-r--r--openstackclient/image/client.py2
-rw-r--r--openstackclient/image/v1/image.py30
-rw-r--r--openstackclient/image/v2/image.py35
-rw-r--r--openstackclient/network/common.py17
-rw-r--r--openstackclient/network/sdk_utils.py40
-rw-r--r--openstackclient/network/v2/address_scope.py38
-rw-r--r--openstackclient/network/v2/floating_ip.py68
-rw-r--r--openstackclient/network/v2/floating_ip_pool.py4
-rw-r--r--openstackclient/network/v2/ip_availability.py4
-rw-r--r--openstackclient/network/v2/network.py65
-rw-r--r--openstackclient/network/v2/network_agent.py8
-rw-r--r--openstackclient/network/v2/network_qos_policy.py39
-rw-r--r--openstackclient/network/v2/network_rbac.py45
-rw-r--r--openstackclient/network/v2/network_segment.py23
-rw-r--r--openstackclient/network/v2/network_service_provider.py41
-rw-r--r--openstackclient/network/v2/port.py134
-rw-r--r--openstackclient/network/v2/router.py20
-rw-r--r--openstackclient/network/v2/security_group.py10
-rw-r--r--openstackclient/network/v2/security_group_rule.py156
-rw-r--r--openstackclient/network/v2/subnet.py57
-rw-r--r--openstackclient/network/v2/subnet_pool.py48
-rw-r--r--openstackclient/object/v1/account.py6
-rw-r--r--openstackclient/object/v1/container.py14
-rw-r--r--openstackclient/object/v1/object.py14
-rw-r--r--openstackclient/shell.py4
-rw-r--r--openstackclient/tests/functional/network/v2/test_network_service_provider.py26
-rw-r--r--openstackclient/tests/unit/image/v1/test_image.py6
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py14
-rw-r--r--openstackclient/tests/unit/network/test_common.py14
-rw-r--r--openstackclient/tests/unit/network/test_sdk_utils.py59
-rw-r--r--openstackclient/tests/unit/network/v2/fakes.py50
-rw-r--r--openstackclient/tests/unit/network/v2/test_floating_ip.py63
-rw-r--r--openstackclient/tests/unit/network/v2/test_network.py89
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_rbac.py40
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_service_provider.py71
-rw-r--r--openstackclient/tests/unit/network/v2/test_port.py118
-rw-r--r--openstackclient/tests/unit/network/v2/test_security_group_rule.py226
-rw-r--r--openstackclient/tests/unit/network/v2/test_subnet.py16
-rw-r--r--openstackclient/tests/unit/network/v2/test_subnet_pool.py8
-rw-r--r--openstackclient/tests/unit/volume/v1/fakes.py109
-rw-r--r--openstackclient/tests/unit/volume/v1/test_backup.py45
-rw-r--r--openstackclient/tests/unit/volume/v1/test_type.py6
-rw-r--r--openstackclient/tests/unit/volume/v1/test_volume.py160
-rw-r--r--openstackclient/tests/unit/volume/v2/fakes.py107
-rw-r--r--openstackclient/tests/unit/volume/v2/test_backup.py58
-rw-r--r--openstackclient/tests/unit/volume/v2/test_consistency_group.py276
-rw-r--r--openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py351
-rw-r--r--openstackclient/tests/unit/volume/v2/test_type.py5
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume.py197
-rw-r--r--openstackclient/volume/v1/backup.py63
-rw-r--r--openstackclient/volume/v1/qos_specs.py16
-rw-r--r--openstackclient/volume/v1/service.py4
-rw-r--r--openstackclient/volume/v1/snapshot.py12
-rw-r--r--openstackclient/volume/v1/volume.py107
-rw-r--r--openstackclient/volume/v1/volume_transfer_request.py10
-rw-r--r--openstackclient/volume/v1/volume_type.py18
-rw-r--r--openstackclient/volume/v2/backup.py84
-rw-r--r--openstackclient/volume/v2/consistency_group.py145
-rw-r--r--openstackclient/volume/v2/consistency_group_snapshot.py190
-rw-r--r--openstackclient/volume/v2/qos_specs.py16
-rw-r--r--openstackclient/volume/v2/service.py4
-rw-r--r--openstackclient/volume/v2/snapshot.py12
-rw-r--r--openstackclient/volume/v2/volume.py114
-rw-r--r--openstackclient/volume/v2/volume_transfer_request.py10
-rw-r--r--openstackclient/volume/v2/volume_type.py21
118 files changed, 3520 insertions, 791 deletions
diff --git a/openstackclient/common/availability_zone.py b/openstackclient/common/availability_zone.py
index 63c55370..b2385ef7 100644
--- a/openstackclient/common/availability_zone.py
+++ b/openstackclient/common/availability_zone.py
@@ -88,7 +88,7 @@ def _xform_network_availability_zone(az):
class ListAvailabilityZone(command.Lister):
- """List availability zones and their status"""
+ _description = _("List availability zones and their status")
def get_parser(self, prog_name):
parser = super(ListAvailabilityZone, self).get_parser(prog_name)
diff --git a/openstackclient/common/client_config.py b/openstackclient/common/client_config.py
index d6297753..1ac53f7f 100644
--- a/openstackclient/common/client_config.py
+++ b/openstackclient/common/client_config.py
@@ -151,6 +151,7 @@ class OSC_Config(config.OpenStackConfig):
# present, then do not change the behaviour. Otherwise, set the
# PROJECT_DOMAIN_ID to 'OS_DEFAULT_DOMAIN' for better usability.
if (
+ auth_type in ("password", "v3password", "v3totp") and
not config['auth'].get('project_domain_id') and
not config['auth'].get('project_domain_name')
):
diff --git a/openstackclient/common/configuration.py b/openstackclient/common/configuration.py
index 016e9191..57825bb0 100644
--- a/openstackclient/common/configuration.py
+++ b/openstackclient/common/configuration.py
@@ -23,7 +23,7 @@ REDACTED = "<redacted>"
class ShowConfiguration(command.ShowOne):
- """Display configuration details"""
+ _description = _("Display configuration details")
def get_parser(self, prog_name):
parser = super(ShowConfiguration, self).get_parser(prog_name)
diff --git a/openstackclient/common/extension.py b/openstackclient/common/extension.py
index de480016..991f3afc 100644
--- a/openstackclient/common/extension.py
+++ b/openstackclient/common/extension.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class ListExtension(command.Lister):
- """List API extensions"""
+ _description = _("List API extensions")
def get_parser(self, prog_name):
parser = super(ListExtension, self).get_parser(prog_name)
diff --git a/openstackclient/common/limits.py b/openstackclient/common/limits.py
index f7aa82f6..957f1d02 100644
--- a/openstackclient/common/limits.py
+++ b/openstackclient/common/limits.py
@@ -25,7 +25,7 @@ from openstackclient.identity import common as identity_common
class ShowLimits(command.Lister):
- """Show compute and block storage limits"""
+ _description = _("Show compute and block storage limits")
def get_parser(self, prog_name):
parser = super(ShowLimits, self).get_parser(prog_name)
diff --git a/openstackclient/common/module.py b/openstackclient/common/module.py
index 7c5fcd55..15719a30 100644
--- a/openstackclient/common/module.py
+++ b/openstackclient/common/module.py
@@ -25,7 +25,7 @@ from openstackclient.i18n import _
class ListCommand(command.Lister):
- """List recognized commands by group"""
+ _description = _("List recognized commands by group")
auth_required = False
@@ -53,7 +53,7 @@ class ListCommand(command.Lister):
class ListModule(command.ShowOne):
- """List module versions"""
+ _description = _("List module versions")
auth_required = False
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index 8f099cc9..58368c56 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -80,7 +80,7 @@ NETWORK_QUOTAS = {
class SetQuota(command.Command):
- """Set quotas for project or class"""
+ _description = _("Set quotas for project or class")
def _build_options_list(self):
if self.app.client_manager.is_network_endpoint_enabled():
@@ -186,7 +186,7 @@ class SetQuota(command.Command):
class ShowQuota(command.ShowOne):
- """Show quotas for project or class"""
+ _description = _("Show quotas for project or class")
def get_parser(self, prog_name):
parser = super(ShowQuota, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/agent.py b/openstackclient/compute/v2/agent.py
index 76c1b3b7..151dcc1e 100644
--- a/openstackclient/compute/v2/agent.py
+++ b/openstackclient/compute/v2/agent.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreateAgent(command.ShowOne):
- """Create compute agent"""
+ _description = _("Create compute agent")
def get_parser(self, prog_name):
parser = super(CreateAgent, self).get_parser(prog_name)
@@ -81,7 +81,7 @@ class CreateAgent(command.ShowOne):
class DeleteAgent(command.Command):
- """Delete compute agent(s)"""
+ _description = _("Delete compute agent(s)")
def get_parser(self, prog_name):
parser = super(DeleteAgent, self).get_parser(prog_name)
@@ -112,7 +112,7 @@ class DeleteAgent(command.Command):
class ListAgent(command.Lister):
- """List compute agents"""
+ _description = _("List compute agents")
def get_parser(self, prog_name):
parser = super(ListAgent, self).get_parser(prog_name)
@@ -142,7 +142,7 @@ class ListAgent(command.Lister):
class SetAgent(command.Command):
- """Set compute agent properties"""
+ _description = _("Set compute agent properties")
def get_parser(self, prog_name):
parser = super(SetAgent, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/aggregate.py b/openstackclient/compute/v2/aggregate.py
index 58d529e9..76ba5cc6 100644
--- a/openstackclient/compute/v2/aggregate.py
+++ b/openstackclient/compute/v2/aggregate.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class AddAggregateHost(command.ShowOne):
- """Add host to aggregate"""
+ _description = _("Add host to aggregate")
def get_parser(self, prog_name):
parser = super(AddAggregateHost, self).get_parser(prog_name)
@@ -62,7 +62,7 @@ class AddAggregateHost(command.ShowOne):
class CreateAggregate(command.ShowOne):
- """Create a new aggregate"""
+ _description = _("Create a new aggregate")
def get_parser(self, prog_name):
parser = super(CreateAggregate, self).get_parser(prog_name)
@@ -105,7 +105,7 @@ class CreateAggregate(command.ShowOne):
class DeleteAggregate(command.Command):
- """Delete existing aggregate(s)"""
+ _description = _("Delete existing aggregate(s)")
def get_parser(self, prog_name):
parser = super(DeleteAggregate, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class DeleteAggregate(command.Command):
class ListAggregate(command.Lister):
- """List all aggregates"""
+ _description = _("List all aggregates")
def get_parser(self, prog_name):
parser = super(ListAggregate, self).get_parser(prog_name)
@@ -188,7 +188,7 @@ class ListAggregate(command.Lister):
class RemoveAggregateHost(command.ShowOne):
- """Remove host from aggregate"""
+ _description = _("Remove host from aggregate")
def get_parser(self, prog_name):
parser = super(RemoveAggregateHost, self).get_parser(prog_name)
@@ -222,7 +222,7 @@ class RemoveAggregateHost(command.ShowOne):
class SetAggregate(command.Command):
- """Set aggregate properties"""
+ _description = _("Set aggregate properties")
def get_parser(self, prog_name):
parser = super(SetAggregate, self).get_parser(prog_name)
@@ -298,7 +298,7 @@ class SetAggregate(command.Command):
class ShowAggregate(command.ShowOne):
- """Display aggregate details"""
+ _description = _("Display aggregate details")
def get_parser(self, prog_name):
parser = super(ShowAggregate, self).get_parser(prog_name)
@@ -334,7 +334,7 @@ class ShowAggregate(command.ShowOne):
class UnsetAggregate(command.Command):
- """Unset aggregate properties"""
+ _description = _("Unset aggregate properties")
def get_parser(self, prog_name):
parser = super(UnsetAggregate, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/console.py b/openstackclient/compute/v2/console.py
index 02be99d5..358df501 100644
--- a/openstackclient/compute/v2/console.py
+++ b/openstackclient/compute/v2/console.py
@@ -26,7 +26,7 @@ from openstackclient.i18n import _
class ShowConsoleLog(command.Command):
- """Show server's console output"""
+ _description = _("Show server's console output")
def get_parser(self, prog_name):
parser = super(ShowConsoleLog, self).get_parser(prog_name)
@@ -64,7 +64,7 @@ class ShowConsoleLog(command.Command):
class ShowConsoleURL(command.ShowOne):
- """Show server's remote console URL"""
+ _description = _("Show server's remote console URL")
def get_parser(self, prog_name):
parser = super(ShowConsoleURL, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/fixedip.py b/openstackclient/compute/v2/fixedip.py
index c14d29fa..0c0b619e 100644
--- a/openstackclient/compute/v2/fixedip.py
+++ b/openstackclient/compute/v2/fixedip.py
@@ -24,7 +24,7 @@ from openstackclient.i18n import _
class AddFixedIP(command.Command):
- """Add fixed IP address to server"""
+ _description = _("Add fixed IP address to server")
# TODO(tangchen): Remove this class and ``ip fixed add`` command
# two cycles after Mitaka.
@@ -64,7 +64,7 @@ class AddFixedIP(command.Command):
class RemoveFixedIP(command.Command):
- """Remove fixed IP address from server"""
+ _description = _("Remove fixed IP address from server")
# TODO(tangchen): Remove this class and ``ip fixed remove`` command
# two cycles after Mitaka.
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index b3f09ce5..f20d154b 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -49,7 +49,7 @@ def _find_flavor(compute_client, flavor):
class CreateFlavor(command.ShowOne):
- """Create new flavor"""
+ _description = _("Create new flavor")
def get_parser(self, prog_name):
parser = super(CreateFlavor, self).get_parser(prog_name)
@@ -186,7 +186,7 @@ class CreateFlavor(command.ShowOne):
class DeleteFlavor(command.Command):
- """Delete flavor(s)"""
+ _description = _("Delete flavor(s)")
def get_parser(self, prog_name):
parser = super(DeleteFlavor, self).get_parser(prog_name)
@@ -219,7 +219,7 @@ class DeleteFlavor(command.Command):
class ListFlavor(command.Lister):
- """List flavors"""
+ _description = _("List flavors")
def get_parser(self, prog_name):
parser = super(ListFlavor, self).get_parser(prog_name)
@@ -303,7 +303,7 @@ class ListFlavor(command.Lister):
class SetFlavor(command.Command):
- """Set flavor properties"""
+ _description = _("Set flavor properties")
def get_parser(self, prog_name):
parser = super(SetFlavor, self).get_parser(prog_name)
@@ -366,7 +366,7 @@ class SetFlavor(command.Command):
class ShowFlavor(command.ShowOne):
- """Display flavor details"""
+ _description = _("Display flavor details")
def get_parser(self, prog_name):
parser = super(ShowFlavor, self).get_parser(prog_name)
@@ -409,7 +409,7 @@ class ShowFlavor(command.ShowOne):
class UnsetFlavor(command.Command):
- """Unset flavor properties"""
+ _description = _("Unset flavor properties")
def get_parser(self, prog_name):
parser = super(UnsetFlavor, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/floatingip.py b/openstackclient/compute/v2/floatingip.py
index 8398ea57..69595bed 100644
--- a/openstackclient/compute/v2/floatingip.py
+++ b/openstackclient/compute/v2/floatingip.py
@@ -24,7 +24,7 @@ from openstackclient.i18n import _
class AddFloatingIP(command.Command):
- """Add floating IP address to server"""
+ _description = _("Add floating IP address to server")
# TODO(tangchen): Remove this class and ``ip floating add`` command
# two cycles after Mitaka.
@@ -61,7 +61,7 @@ class AddFloatingIP(command.Command):
class RemoveFloatingIP(command.Command):
- """Remove floating IP address from server"""
+ _description = _("Remove floating IP address from server")
# TODO(tangchen): Remove this class and ``ip floating remove`` command
# two cycles after Mitaka.
diff --git a/openstackclient/compute/v2/host.py b/openstackclient/compute/v2/host.py
index 4785377e..a495b367 100644
--- a/openstackclient/compute/v2/host.py
+++ b/openstackclient/compute/v2/host.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class ListHost(command.Lister):
- """List hosts"""
+ _description = _("List hosts")
def get_parser(self, prog_name):
parser = super(ListHost, self).get_parser(prog_name)
@@ -48,7 +48,8 @@ class ListHost(command.Lister):
class SetHost(command.Command):
- """Set host properties"""
+ _description = _("Set host properties")
+
def get_parser(self, prog_name):
parser = super(SetHost, self).get_parser(prog_name)
parser.add_argument(
@@ -107,7 +108,7 @@ class SetHost(command.Command):
class ShowHost(command.Lister):
- """Display host details"""
+ _description = _("Display host details")
def get_parser(self, prog_name):
parser = super(ShowHost, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py
index 69b5d137..406aa917 100644
--- a/openstackclient/compute/v2/hypervisor.py
+++ b/openstackclient/compute/v2/hypervisor.py
@@ -26,7 +26,7 @@ from openstackclient.i18n import _
class ListHypervisor(command.Lister):
- """List hypervisors"""
+ _description = _("List hypervisors")
def get_parser(self, prog_name):
parser = super(ListHypervisor, self).get_parser(prog_name)
@@ -66,7 +66,7 @@ class ListHypervisor(command.Lister):
class ShowHypervisor(command.ShowOne):
- """Display hypervisor details"""
+ _description = _("Display hypervisor details")
def get_parser(self, prog_name):
parser = super(ShowHypervisor, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/hypervisor_stats.py b/openstackclient/compute/v2/hypervisor_stats.py
index c6fd2992..b0413005 100644
--- a/openstackclient/compute/v2/hypervisor_stats.py
+++ b/openstackclient/compute/v2/hypervisor_stats.py
@@ -17,9 +17,11 @@
from osc_lib.command import command
import six
+from openstackclient.i18n import _
+
class ShowHypervisorStats(command.ShowOne):
- """Display hypervisor stats details"""
+ _description = _("Display hypervisor stats details")
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py
index d5c682f4..a63cbfec 100644
--- a/openstackclient/compute/v2/keypair.py
+++ b/openstackclient/compute/v2/keypair.py
@@ -32,7 +32,7 @@ LOG = logging.getLogger(__name__)
class CreateKeypair(command.ShowOne):
- """Create new public or private key for server ssh access"""
+ _description = _("Create new public or private key for server ssh access")
def get_parser(self, prog_name):
parser = super(CreateKeypair, self).get_parser(prog_name)
@@ -83,7 +83,7 @@ class CreateKeypair(command.ShowOne):
class DeleteKeypair(command.Command):
- """Delete public or private key(s)"""
+ _description = _("Delete public or private key(s)")
def get_parser(self, prog_name):
parser = super(DeleteKeypair, self).get_parser(prog_name)
@@ -117,7 +117,7 @@ class DeleteKeypair(command.Command):
class ListKeypair(command.Lister):
- """List key fingerprints"""
+ _description = _("List key fingerprints")
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -134,7 +134,7 @@ class ListKeypair(command.Lister):
class ShowKeypair(command.ShowOne):
- """Display key details"""
+ _description = _("Display key details")
def get_parser(self, prog_name):
parser = super(ShowKeypair, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index df46c7df..48d8b2d0 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -175,7 +175,7 @@ def _show_progress(progress):
class AddFixedIP(command.Command):
- """Add fixed IP address to server"""
+ _description = _("Add fixed IP address to server")
def get_parser(self, prog_name):
parser = super(AddFixedIP, self).get_parser(prog_name)
@@ -205,7 +205,7 @@ class AddFixedIP(command.Command):
class AddFloatingIP(command.Command):
- """Add floating IP address to server"""
+ _description = _("Add floating IP address to server")
def get_parser(self, prog_name):
parser = super(AddFloatingIP, self).get_parser(prog_name)
@@ -232,7 +232,7 @@ class AddFloatingIP(command.Command):
class AddServerSecurityGroup(command.Command):
- """Add security group to server"""
+ _description = _("Add security group to server")
def get_parser(self, prog_name):
parser = super(AddServerSecurityGroup, self).get_parser(prog_name)
@@ -264,7 +264,7 @@ class AddServerSecurityGroup(command.Command):
class AddServerVolume(command.Command):
- """Add volume to server"""
+ _description = _("Add volume to server")
def get_parser(self, prog_name):
parser = super(AddServerVolume, self).get_parser(prog_name)
@@ -306,7 +306,7 @@ class AddServerVolume(command.Command):
class CreateServer(command.ShowOne):
- """Create a new server"""
+ _description = _("Create a new server")
def get_parser(self, prog_name):
parser = super(CreateServer, self).get_parser(prog_name)
@@ -642,7 +642,7 @@ class CreateServerDump(command.Command):
class DeleteServer(command.Command):
- """Delete server(s)"""
+ _description = _("Delete server(s)")
def get_parser(self, prog_name):
parser = super(DeleteServer, self).get_parser(prog_name)
@@ -680,7 +680,7 @@ class DeleteServer(command.Command):
class ListServer(command.Lister):
- """List servers"""
+ _description = _("List servers")
def get_parser(self, prog_name):
parser = super(ListServer, self).get_parser(prog_name)
@@ -923,7 +923,8 @@ class ListServer(command.Lister):
class LockServer(command.Command):
- """Lock server(s). A non-admin user will not be able to execute actions"""
+ _description = _("Lock server(s). A non-admin user will not be able to "
+ "execute actions")
def get_parser(self, prog_name):
parser = super(LockServer, self).get_parser(prog_name)
@@ -956,7 +957,7 @@ class LockServer(command.Command):
# then adding the groups doesn't seem to work
class MigrateServer(command.Command):
- """Migrate server to different host"""
+ _description = _("Migrate server to different host")
def get_parser(self, prog_name):
parser = super(MigrateServer, self).get_parser(prog_name)
@@ -1038,7 +1039,7 @@ class MigrateServer(command.Command):
class PauseServer(command.Command):
- """Pause server(s)"""
+ _description = _("Pause server(s)")
def get_parser(self, prog_name):
parser = super(PauseServer, self).get_parser(prog_name)
@@ -1060,7 +1061,7 @@ class PauseServer(command.Command):
class RebootServer(command.Command):
- """Perform a hard or soft server reboot"""
+ _description = _("Perform a hard or soft server reboot")
def get_parser(self, prog_name):
parser = super(RebootServer, self).get_parser(prog_name)
@@ -1114,7 +1115,7 @@ class RebootServer(command.Command):
class RebuildServer(command.ShowOne):
- """Rebuild server"""
+ _description = _("Rebuild server")
def get_parser(self, prog_name):
parser = super(RebuildServer, self).get_parser(prog_name)
@@ -1170,7 +1171,7 @@ class RebuildServer(command.ShowOne):
class RemoveFixedIP(command.Command):
- """Remove fixed IP address from server"""
+ _description = _("Remove fixed IP address from server")
def get_parser(self, prog_name):
parser = super(RemoveFixedIP, self).get_parser(prog_name)
@@ -1197,7 +1198,7 @@ class RemoveFixedIP(command.Command):
class RemoveFloatingIP(command.Command):
- """Remove floating IP address from server"""
+ _description = _("Remove floating IP address from server")
def get_parser(self, prog_name):
parser = super(RemoveFloatingIP, self).get_parser(prog_name)
@@ -1225,7 +1226,7 @@ class RemoveFloatingIP(command.Command):
class RemoveServerSecurityGroup(command.Command):
- """Remove security group from server"""
+ _description = _("Remove security group from server")
def get_parser(self, prog_name):
parser = super(RemoveServerSecurityGroup, self).get_parser(prog_name)
@@ -1257,7 +1258,7 @@ class RemoveServerSecurityGroup(command.Command):
class RemoveServerVolume(command.Command):
- """Remove volume from server"""
+ _description = _("Remove volume from server")
def get_parser(self, prog_name):
parser = super(RemoveServerVolume, self).get_parser(prog_name)
@@ -1293,7 +1294,7 @@ class RemoveServerVolume(command.Command):
class RescueServer(command.ShowOne):
- """Put server in rescue mode"""
+ _description = _("Put server in rescue mode")
def get_parser(self, prog_name):
parser = super(RescueServer, self).get_parser(prog_name)
@@ -1315,7 +1316,7 @@ class RescueServer(command.ShowOne):
class ResizeServer(command.Command):
- """Scale server to a new flavor"""
+ _description = _("Scale server to a new flavor")
def get_parser(self, prog_name):
parser = super(ResizeServer, self).get_parser(prog_name)
@@ -1380,7 +1381,7 @@ class ResizeServer(command.Command):
class RestoreServer(command.Command):
- """Restore server(s)"""
+ _description = _("Restore server(s)")
def get_parser(self, prog_name):
parser = super(RestoreServer, self).get_parser(prog_name)
@@ -1402,7 +1403,7 @@ class RestoreServer(command.Command):
class ResumeServer(command.Command):
- """Resume server(s)"""
+ _description = _("Resume server(s)")
def get_parser(self, prog_name):
parser = super(ResumeServer, self).get_parser(prog_name)
@@ -1425,7 +1426,7 @@ class ResumeServer(command.Command):
class SetServer(command.Command):
- """Set server properties"""
+ _description = _("Set server properties")
def get_parser(self, prog_name):
parser = super(SetServer, self).get_parser(prog_name)
@@ -1490,7 +1491,7 @@ class SetServer(command.Command):
class ShelveServer(command.Command):
- """Shelve server(s)"""
+ _description = _("Shelve server(s)")
def get_parser(self, prog_name):
parser = super(ShelveServer, self).get_parser(prog_name)
@@ -1512,7 +1513,7 @@ class ShelveServer(command.Command):
class ShowServer(command.ShowOne):
- """Show server details"""
+ _description = _("Show server details")
def get_parser(self, prog_name):
parser = super(ShowServer, self).get_parser(prog_name)
@@ -1546,7 +1547,7 @@ class ShowServer(command.ShowOne):
class SshServer(command.Command):
- """SSH to server"""
+ _description = _("SSH to server")
def get_parser(self, prog_name):
parser = super(SshServer, self).get_parser(prog_name)
@@ -1690,7 +1691,7 @@ class SshServer(command.Command):
class StartServer(command.Command):
- """Start server(s)."""
+ _description = _("Start server(s).")
def get_parser(self, prog_name):
parser = super(StartServer, self).get_parser(prog_name)
@@ -1712,7 +1713,7 @@ class StartServer(command.Command):
class StopServer(command.Command):
- """Stop server(s)."""
+ _description = _("Stop server(s).")
def get_parser(self, prog_name):
parser = super(StopServer, self).get_parser(prog_name)
@@ -1734,7 +1735,7 @@ class StopServer(command.Command):
class SuspendServer(command.Command):
- """Suspend server(s)"""
+ _description = _("Suspend server(s)")
def get_parser(self, prog_name):
parser = super(SuspendServer, self).get_parser(prog_name)
@@ -1757,7 +1758,7 @@ class SuspendServer(command.Command):
class UnlockServer(command.Command):
- """Unlock server(s)"""
+ _description = _("Unlock server(s)")
def get_parser(self, prog_name):
parser = super(UnlockServer, self).get_parser(prog_name)
@@ -1780,7 +1781,7 @@ class UnlockServer(command.Command):
class UnpauseServer(command.Command):
- """Unpause server(s)"""
+ _description = _("Unpause server(s)")
def get_parser(self, prog_name):
parser = super(UnpauseServer, self).get_parser(prog_name)
@@ -1803,7 +1804,7 @@ class UnpauseServer(command.Command):
class UnrescueServer(command.Command):
- """Restore server from rescue mode"""
+ _description = _("Restore server from rescue mode")
def get_parser(self, prog_name):
parser = super(UnrescueServer, self).get_parser(prog_name)
@@ -1824,7 +1825,7 @@ class UnrescueServer(command.Command):
class UnsetServer(command.Command):
- """Unset server properties"""
+ _description = _("Unset server properties")
def get_parser(self, prog_name):
parser = super(UnsetServer, self).get_parser(prog_name)
@@ -1858,7 +1859,7 @@ class UnsetServer(command.Command):
class UnshelveServer(command.Command):
- """Unshelve server(s)"""
+ _description = _("Unshelve server(s)")
def get_parser(self, prog_name):
parser = super(UnshelveServer, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/server_backup.py b/openstackclient/compute/v2/server_backup.py
index c0e2e5ee..ddcf9101 100644
--- a/openstackclient/compute/v2/server_backup.py
+++ b/openstackclient/compute/v2/server_backup.py
@@ -33,7 +33,7 @@ def _show_progress(progress):
class CreateServerBackup(command.ShowOne):
- """Create a server backup image"""
+ _description = _("Create a server backup image")
IMAGE_API_VERSIONS = {
"1": "openstackclient.image.v1.image",
diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py
index d51b1ec2..6bcfc6ae 100644
--- a/openstackclient/compute/v2/server_group.py
+++ b/openstackclient/compute/v2/server_group.py
@@ -43,7 +43,7 @@ def _get_columns(info):
class CreateServerGroup(command.ShowOne):
- """Create a new server group."""
+ _description = _("Create a new server group.")
def get_parser(self, prog_name):
parser = super(CreateServerGroup, self).get_parser(prog_name)
@@ -77,7 +77,7 @@ class CreateServerGroup(command.ShowOne):
class DeleteServerGroup(command.Command):
- """Delete existing server group(s)."""
+ _description = _("Delete existing server group(s).")
def get_parser(self, prog_name):
parser = super(DeleteServerGroup, self).get_parser(prog_name)
@@ -112,7 +112,7 @@ class DeleteServerGroup(command.Command):
class ListServerGroup(command.Lister):
- """List all server groups."""
+ _description = _("List all server groups.")
def get_parser(self, prog_name):
parser = super(ListServerGroup, self).get_parser(prog_name)
@@ -161,7 +161,7 @@ class ListServerGroup(command.Lister):
class ShowServerGroup(command.ShowOne):
- """Display server group details."""
+ _description = _("Display server group details.")
def get_parser(self, prog_name):
parser = super(ShowServerGroup, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/server_image.py b/openstackclient/compute/v2/server_image.py
index 285c7fd2..c66e0674 100644
--- a/openstackclient/compute/v2/server_image.py
+++ b/openstackclient/compute/v2/server_image.py
@@ -37,7 +37,7 @@ def _show_progress(progress):
class CreateServerImage(command.ShowOne):
- """Create a new server disk image from an existing server"""
+ _description = _("Create a new server disk image from an existing server")
IMAGE_API_VERSIONS = {
"1": "openstackclient.image.v1.image",
diff --git a/openstackclient/compute/v2/service.py b/openstackclient/compute/v2/service.py
index 53624f55..9c384f05 100644
--- a/openstackclient/compute/v2/service.py
+++ b/openstackclient/compute/v2/service.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class DeleteService(command.Command):
- """Delete compute service(s)"""
+ _description = _("Delete compute service(s)")
def get_parser(self, prog_name):
parser = super(DeleteService, self).get_parser(prog_name)
@@ -61,7 +61,7 @@ class DeleteService(command.Command):
class ListService(command.Lister):
- """List compute services"""
+ _description = _("List compute services")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -115,7 +115,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set compute service properties"""
+ _description = _("Set compute service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py
index 2f35b01b..89601ae3 100644
--- a/openstackclient/compute/v2/usage.py
+++ b/openstackclient/compute/v2/usage.py
@@ -26,7 +26,7 @@ from openstackclient.i18n import _
class ListUsage(command.Lister):
- """List resource usage per project"""
+ _description = _("List resource usage per project")
def get_parser(self, prog_name):
parser = super(ListUsage, self).get_parser(prog_name)
@@ -115,7 +115,7 @@ class ListUsage(command.Lister):
class ShowUsage(command.ShowOne):
- """Show resource usage for a single project"""
+ _description = _("Show resource usage for a single project")
def get_parser(self, prog_name):
parser = super(ShowUsage, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/catalog.py b/openstackclient/identity/v2_0/catalog.py
index 7a15cf3a..993bdd53 100644
--- a/openstackclient/identity/v2_0/catalog.py
+++ b/openstackclient/identity/v2_0/catalog.py
@@ -43,7 +43,7 @@ def _format_endpoints(eps=None):
class ListCatalog(command.Lister):
- """List services in the service catalog"""
+ _description = _("List services in the service catalog")
def take_action(self, parsed_args):
@@ -66,7 +66,7 @@ class ListCatalog(command.Lister):
class ShowCatalog(command.ShowOne):
- """Display service catalog details"""
+ _description = _("Display service catalog details")
def get_parser(self, prog_name):
parser = super(ShowCatalog, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/ec2creds.py b/openstackclient/identity/v2_0/ec2creds.py
index 4873cd55..2572c4f0 100644
--- a/openstackclient/identity/v2_0/ec2creds.py
+++ b/openstackclient/identity/v2_0/ec2creds.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateEC2Creds(command.ShowOne):
- """Create EC2 credentials"""
+ _description = _("Create EC2 credentials")
def get_parser(self, prog_name):
parser = super(CreateEC2Creds, self).get_parser(prog_name)
@@ -86,7 +86,7 @@ class CreateEC2Creds(command.ShowOne):
class DeleteEC2Creds(command.Command):
- """Delete EC2 credentials"""
+ _description = _("Delete EC2 credentials")
def get_parser(self, prog_name):
parser = super(DeleteEC2Creds, self).get_parser(prog_name)
@@ -133,7 +133,7 @@ class DeleteEC2Creds(command.Command):
class ListEC2Creds(command.Lister):
- """List EC2 credentials"""
+ _description = _("List EC2 credentials")
def get_parser(self, prog_name):
parser = super(ListEC2Creds, self).get_parser(prog_name)
@@ -168,7 +168,7 @@ class ListEC2Creds(command.Lister):
class ShowEC2Creds(command.ShowOne):
- """Display EC2 credentials details"""
+ _description = _("Display EC2 credentials details")
def get_parser(self, prog_name):
parser = super(ShowEC2Creds, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py
index 5a3b3186..7e0751a7 100644
--- a/openstackclient/identity/v2_0/endpoint.py
+++ b/openstackclient/identity/v2_0/endpoint.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateEndpoint(command.ShowOne):
- """Create new endpoint"""
+ _description = _("Create new endpoint")
def get_parser(self, prog_name):
parser = super(CreateEndpoint, self).get_parser(prog_name)
@@ -80,7 +80,7 @@ class CreateEndpoint(command.ShowOne):
class DeleteEndpoint(command.Command):
- """Delete endpoint(s)"""
+ _description = _("Delete endpoint(s)")
def get_parser(self, prog_name):
parser = super(DeleteEndpoint, self).get_parser(prog_name)
@@ -113,7 +113,7 @@ class DeleteEndpoint(command.Command):
class ListEndpoint(command.Lister):
- """List endpoints"""
+ _description = _("List endpoints")
def get_parser(self, prog_name):
parser = super(ListEndpoint, self).get_parser(prog_name)
@@ -146,7 +146,7 @@ class ListEndpoint(command.Lister):
class ShowEndpoint(command.ShowOne):
- """Display endpoint details"""
+ _description = _("Display endpoint details")
def get_parser(self, prog_name):
parser = super(ShowEndpoint, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py
index fc5c9201..8526d6bd 100644
--- a/openstackclient/identity/v2_0/project.py
+++ b/openstackclient/identity/v2_0/project.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateProject(command.ShowOne):
- """Create new project"""
+ _description = _("Create new project")
def get_parser(self, prog_name):
parser = super(CreateProject, self).get_parser(prog_name)
@@ -102,7 +102,7 @@ class CreateProject(command.ShowOne):
class DeleteProject(command.Command):
- """Delete project(s)"""
+ _description = _("Delete project(s)")
def get_parser(self, prog_name):
parser = super(DeleteProject, self).get_parser(prog_name)
@@ -126,7 +126,7 @@ class DeleteProject(command.Command):
class ListProject(command.Lister):
- """List projects"""
+ _description = _("List projects")
def get_parser(self, prog_name):
parser = super(ListProject, self).get_parser(prog_name)
@@ -152,7 +152,7 @@ class ListProject(command.Lister):
class SetProject(command.Command):
- """Set project properties"""
+ _description = _("Set project properties")
def get_parser(self, prog_name):
parser = super(SetProject, self).get_parser(prog_name)
@@ -221,7 +221,7 @@ class SetProject(command.Command):
class ShowProject(command.ShowOne):
- """Display project details"""
+ _description = _("Display project details")
def get_parser(self, prog_name):
parser = super(ShowProject, self).get_parser(prog_name)
@@ -279,7 +279,7 @@ class ShowProject(command.ShowOne):
class UnsetProject(command.Command):
- """Unset project properties"""
+ _description = _("Unset project properties")
def get_parser(self, prog_name):
parser = super(UnsetProject, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py
index b4b67bad..0a28a70a 100644
--- a/openstackclient/identity/v2_0/role.py
+++ b/openstackclient/identity/v2_0/role.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class AddRole(command.ShowOne):
- """Add role to project:user"""
+ _description = _("Add role to project:user")
def get_parser(self, prog_name):
parser = super(AddRole, self).get_parser(prog_name)
@@ -73,7 +73,7 @@ class AddRole(command.ShowOne):
class CreateRole(command.ShowOne):
- """Create new role"""
+ _description = _("Create new role")
def get_parser(self, prog_name):
parser = super(CreateRole, self).get_parser(prog_name)
@@ -109,7 +109,7 @@ class CreateRole(command.ShowOne):
class DeleteRole(command.Command):
- """Delete role(s)"""
+ _description = _("Delete role(s)")
def get_parser(self, prog_name):
parser = super(DeleteRole, self).get_parser(prog_name)
@@ -133,7 +133,7 @@ class DeleteRole(command.Command):
class ListRole(command.Lister):
- """List roles"""
+ _description = _("List roles")
def get_parser(self, prog_name):
parser = super(ListRole, self).get_parser(prog_name)
@@ -223,7 +223,7 @@ class ListRole(command.Lister):
class ListUserRole(command.Lister):
- """List user-role assignments"""
+ _description = _("List user-role assignments")
def get_parser(self, prog_name):
parser = super(ListUserRole, self).get_parser(prog_name)
@@ -293,7 +293,7 @@ class ListUserRole(command.Lister):
class RemoveRole(command.Command):
- """Remove role from project : user"""
+ _description = _("Remove role from project : user")
def get_parser(self, prog_name):
parser = super(RemoveRole, self).get_parser(prog_name)
@@ -331,7 +331,7 @@ class RemoveRole(command.Command):
class ShowRole(command.ShowOne):
- """Display role details"""
+ _description = _("Display role details")
def get_parser(self, prog_name):
parser = super(ShowRole, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/role_assignment.py b/openstackclient/identity/v2_0/role_assignment.py
index 44f55c3b..8236bbfc 100644
--- a/openstackclient/identity/v2_0/role_assignment.py
+++ b/openstackclient/identity/v2_0/role_assignment.py
@@ -21,7 +21,7 @@ from openstackclient.i18n import _ # noqa
class ListRoleAssignment(command.Lister):
- """List role assignments"""
+ _description = _("List role assignments")
def get_parser(self, prog_name):
parser = super(ListRoleAssignment, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py
index e318643c..f70f0fa9 100644
--- a/openstackclient/identity/v2_0/service.py
+++ b/openstackclient/identity/v2_0/service.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class CreateService(command.ShowOne):
- """Create new service"""
+ _description = _("Create new service")
def get_parser(self, prog_name):
parser = super(CreateService, self).get_parser(prog_name)
@@ -91,7 +91,7 @@ class CreateService(command.ShowOne):
class DeleteService(command.Command):
- """Delete service(s)"""
+ _description = _("Delete service(s)")
def get_parser(self, prog_name):
parser = super(DeleteService, self).get_parser(prog_name)
@@ -125,7 +125,7 @@ class DeleteService(command.Command):
class ListService(command.Lister):
- """List services"""
+ _description = _("List services")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class ListService(command.Lister):
class ShowService(command.ShowOne):
- """Display service details"""
+ _description = _("Display service details")
def get_parser(self, prog_name):
parser = super(ShowService, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/token.py b/openstackclient/identity/v2_0/token.py
index 4b7e988b..3b08b475 100644
--- a/openstackclient/identity/v2_0/token.py
+++ b/openstackclient/identity/v2_0/token.py
@@ -23,7 +23,7 @@ from openstackclient.i18n import _
class IssueToken(command.ShowOne):
- """Issue new token"""
+ _description = _("Issue new token")
# scoped token is optional
required_scope = False
@@ -53,7 +53,7 @@ class IssueToken(command.ShowOne):
class RevokeToken(command.Command):
- """Revoke existing token"""
+ _description = _("Revoke existing token")
def get_parser(self, prog_name):
parser = super(RevokeToken, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py
index bc091ce7..ddd5b981 100644
--- a/openstackclient/identity/v2_0/user.py
+++ b/openstackclient/identity/v2_0/user.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreateUser(command.ShowOne):
- """Create new user"""
+ _description = _("Create new user")
def get_parser(self, prog_name):
parser = super(CreateUser, self).get_parser(prog_name)
@@ -130,7 +130,7 @@ class CreateUser(command.ShowOne):
class DeleteUser(command.Command):
- """Delete user(s)"""
+ _description = _("Delete user(s)")
def get_parser(self, prog_name):
parser = super(DeleteUser, self).get_parser(prog_name)
@@ -154,7 +154,7 @@ class DeleteUser(command.Command):
class ListUser(command.Lister):
- """List users"""
+ _description = _("List users")
def get_parser(self, prog_name):
parser = super(ListUser, self).get_parser(prog_name)
@@ -242,7 +242,7 @@ class ListUser(command.Lister):
class SetUser(command.Command):
- """Set user properties"""
+ _description = _("Set user properties")
def get_parser(self, prog_name):
parser = super(SetUser, self).get_parser(prog_name)
@@ -336,7 +336,7 @@ class SetUser(command.Command):
class ShowUser(command.ShowOne):
- """Display user details"""
+ _description = _("Display user details")
def get_parser(self, prog_name):
parser = super(ShowUser, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/catalog.py b/openstackclient/identity/v3/catalog.py
index a62d0a93..28f4fada 100644
--- a/openstackclient/identity/v3/catalog.py
+++ b/openstackclient/identity/v3/catalog.py
@@ -38,7 +38,7 @@ def _format_endpoints(eps=None):
class ListCatalog(command.Lister):
- """List services in the service catalog"""
+ _description = _("List services in the service catalog")
def take_action(self, parsed_args):
@@ -61,7 +61,7 @@ class ListCatalog(command.Lister):
class ShowCatalog(command.ShowOne):
- """Display service catalog details"""
+ _description = _("Display service catalog details")
def get_parser(self, prog_name):
parser = super(ShowCatalog, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/consumer.py b/openstackclient/identity/v3/consumer.py
index b41a37ca..bcb29db4 100644
--- a/openstackclient/identity/v3/consumer.py
+++ b/openstackclient/identity/v3/consumer.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreateConsumer(command.ShowOne):
- """Create new consumer"""
+ _description = _("Create new consumer")
def get_parser(self, prog_name):
parser = super(CreateConsumer, self).get_parser(prog_name)
@@ -50,7 +50,7 @@ class CreateConsumer(command.ShowOne):
class DeleteConsumer(command.Command):
- """Delete consumer(s)"""
+ _description = _("Delete consumer(s)")
def get_parser(self, prog_name):
parser = super(DeleteConsumer, self).get_parser(prog_name)
@@ -84,7 +84,7 @@ class DeleteConsumer(command.Command):
class ListConsumer(command.Lister):
- """List consumers"""
+ _description = _("List consumers")
def take_action(self, parsed_args):
columns = ('ID', 'Description')
@@ -97,7 +97,7 @@ class ListConsumer(command.Lister):
class SetConsumer(command.Command):
- """Set consumer properties"""
+ _description = _("Set consumer properties")
def get_parser(self, prog_name):
parser = super(SetConsumer, self).get_parser(prog_name)
@@ -126,7 +126,7 @@ class SetConsumer(command.Command):
class ShowConsumer(command.ShowOne):
- """Display consumer details"""
+ _description = _("Display consumer details")
def get_parser(self, prog_name):
parser = super(ShowConsumer, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/credential.py b/openstackclient/identity/v3/credential.py
index 0ef94cf4..68287f2a 100644
--- a/openstackclient/identity/v3/credential.py
+++ b/openstackclient/identity/v3/credential.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreateCredential(command.ShowOne):
- """Create new credential"""
+ _description = _("Create new credential")
def get_parser(self, prog_name):
parser = super(CreateCredential, self).get_parser(prog_name)
@@ -78,7 +78,7 @@ class CreateCredential(command.ShowOne):
class DeleteCredential(command.Command):
- """Delete credential(s)"""
+ _description = _("Delete credential(s)")
def get_parser(self, prog_name):
parser = super(DeleteCredential, self).get_parser(prog_name)
@@ -110,7 +110,7 @@ class DeleteCredential(command.Command):
class ListCredential(command.Lister):
- """List credentials"""
+ _description = _("List credentials")
def take_action(self, parsed_args):
columns = ('ID', 'Type', 'User ID', 'Blob', 'Project ID')
@@ -124,7 +124,7 @@ class ListCredential(command.Lister):
class SetCredential(command.Command):
- """Set credential properties"""
+ _description = _("Set credential properties")
def get_parser(self, prog_name):
parser = super(SetCredential, self).get_parser(prog_name)
@@ -180,7 +180,7 @@ class SetCredential(command.Command):
class ShowCredential(command.ShowOne):
- """Display credential details"""
+ _description = _("Display credential details")
def get_parser(self, prog_name):
parser = super(ShowCredential, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py
index 76e47d32..59ab0f07 100644
--- a/openstackclient/identity/v3/domain.py
+++ b/openstackclient/identity/v3/domain.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class CreateDomain(command.ShowOne):
- """Create new domain"""
+ _description = _("Create new domain")
def get_parser(self, prog_name):
parser = super(CreateDomain, self).get_parser(prog_name)
@@ -89,7 +89,7 @@ class CreateDomain(command.ShowOne):
class DeleteDomain(command.Command):
- """Delete domain(s)"""
+ _description = _("Delete domain(s)")
def get_parser(self, prog_name):
parser = super(DeleteDomain, self).get_parser(prog_name)
@@ -122,7 +122,7 @@ class DeleteDomain(command.Command):
class ListDomain(command.Lister):
- """List domains"""
+ _description = _("List domains")
def take_action(self, parsed_args):
columns = ('ID', 'Name', 'Enabled', 'Description')
@@ -135,7 +135,7 @@ class ListDomain(command.Lister):
class SetDomain(command.Command):
- """Set domain properties"""
+ _description = _("Set domain properties")
def get_parser(self, prog_name):
parser = super(SetDomain, self).get_parser(prog_name)
@@ -186,7 +186,7 @@ class SetDomain(command.Command):
class ShowDomain(command.ShowOne):
- """Display domain details"""
+ _description = _("Display domain details")
def get_parser(self, prog_name):
parser = super(ShowDomain, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/ec2creds.py b/openstackclient/identity/v3/ec2creds.py
index 7ad01719..9854efda 100644
--- a/openstackclient/identity/v3/ec2creds.py
+++ b/openstackclient/identity/v3/ec2creds.py
@@ -55,7 +55,7 @@ def _determine_ec2_user(parsed_args, client_manager):
class CreateEC2Creds(command.ShowOne):
- """Create EC2 credentials"""
+ _description = _("Create EC2 credentials")
def get_parser(self, prog_name):
parser = super(CreateEC2Creds, self).get_parser(prog_name)
@@ -112,7 +112,7 @@ class CreateEC2Creds(command.ShowOne):
class DeleteEC2Creds(command.Command):
- """Delete EC2 credentials"""
+ _description = _("Delete EC2 credentials")
def get_parser(self, prog_name):
parser = super(DeleteEC2Creds, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class DeleteEC2Creds(command.Command):
class ListEC2Creds(command.Lister):
- """List EC2 credentials"""
+ _description = _("List EC2 credentials")
def get_parser(self, prog_name):
parser = super(ListEC2Creds, self).get_parser(prog_name)
@@ -179,7 +179,7 @@ class ListEC2Creds(command.Lister):
class ShowEC2Creds(command.ShowOne):
- """Display EC2 credentials details"""
+ _description = _("Display EC2 credentials details")
def get_parser(self, prog_name):
parser = super(ShowEC2Creds, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py
index 73b37a43..39fd49ef 100644
--- a/openstackclient/identity/v3/endpoint.py
+++ b/openstackclient/identity/v3/endpoint.py
@@ -37,7 +37,7 @@ def get_service_name(service):
class CreateEndpoint(command.ShowOne):
- """Create new endpoint"""
+ _description = _("Create new endpoint")
def get_parser(self, prog_name):
parser = super(CreateEndpoint, self).get_parser(prog_name)
@@ -99,7 +99,7 @@ class CreateEndpoint(command.ShowOne):
class DeleteEndpoint(command.Command):
- """Delete endpoint(s)"""
+ _description = _("Delete endpoint(s)")
def get_parser(self, prog_name):
parser = super(DeleteEndpoint, self).get_parser(prog_name)
@@ -133,7 +133,7 @@ class DeleteEndpoint(command.Command):
class ListEndpoint(command.Lister):
- """List endpoints"""
+ _description = _("List endpoints")
def get_parser(self, prog_name):
parser = super(ListEndpoint, self).get_parser(prog_name)
@@ -181,7 +181,7 @@ class ListEndpoint(command.Lister):
class SetEndpoint(command.Command):
- """Set endpoint properties"""
+ _description = _("Set endpoint properties")
def get_parser(self, prog_name):
parser = super(SetEndpoint, self).get_parser(prog_name)
@@ -252,7 +252,7 @@ class SetEndpoint(command.Command):
class ShowEndpoint(command.ShowOne):
- """Display endpoint details"""
+ _description = _("Display endpoint details")
def get_parser(self, prog_name):
parser = super(ShowEndpoint, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/federation_protocol.py b/openstackclient/identity/v3/federation_protocol.py
index 3fde9027..0752e8f6 100644
--- a/openstackclient/identity/v3/federation_protocol.py
+++ b/openstackclient/identity/v3/federation_protocol.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class CreateProtocol(command.ShowOne):
- """Create new federation protocol"""
+ _description = _("Create new federation protocol")
def get_parser(self, prog_name):
parser = super(CreateProtocol, self).get_parser(prog_name)
@@ -72,7 +72,7 @@ class CreateProtocol(command.ShowOne):
class DeleteProtocol(command.Command):
- """Delete federation protocol(s)"""
+ _description = _("Delete federation protocol(s)")
def get_parser(self, prog_name):
parser = super(DeleteProtocol, self).get_parser(prog_name)
@@ -113,7 +113,7 @@ class DeleteProtocol(command.Command):
class ListProtocols(command.Lister):
- """List federation protocols"""
+ _description = _("List federation protocols")
def get_parser(self, prog_name):
parser = super(ListProtocols, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class ListProtocols(command.Lister):
class SetProtocol(command.Command):
- """Set federation protocol properties"""
+ _description = _("Set federation protocol properties")
def get_parser(self, prog_name):
parser = super(SetProtocol, self).get_parser(prog_name)
@@ -179,7 +179,7 @@ class SetProtocol(command.Command):
class ShowProtocol(command.ShowOne):
- """Display federation protocol details"""
+ _description = _("Display federation protocol details")
def get_parser(self, prog_name):
parser = super(ShowProtocol, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/group.py b/openstackclient/identity/v3/group.py
index f780810a..df684c12 100644
--- a/openstackclient/identity/v3/group.py
+++ b/openstackclient/identity/v3/group.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class AddUserToGroup(command.Command):
- """Add user to group"""
+ _description = _("Add user to group")
def get_parser(self, prog_name):
parser = super(AddUserToGroup, self).get_parser(prog_name)
@@ -76,7 +76,7 @@ class AddUserToGroup(command.Command):
class CheckUserInGroup(command.Command):
- """Check user membership in group"""
+ _description = _("Check user membership in group")
def get_parser(self, prog_name):
parser = super(CheckUserInGroup, self).get_parser(prog_name)
@@ -121,7 +121,7 @@ class CheckUserInGroup(command.Command):
class CreateGroup(command.ShowOne):
- """Create new group"""
+ _description = _("Create new group")
def get_parser(self, prog_name):
parser = super(CreateGroup, self).get_parser(prog_name)
@@ -174,7 +174,7 @@ class CreateGroup(command.ShowOne):
class DeleteGroup(command.Command):
- """Delete group(s)"""
+ _description = _("Delete group(s)")
def get_parser(self, prog_name):
parser = super(DeleteGroup, self).get_parser(prog_name)
@@ -202,7 +202,7 @@ class DeleteGroup(command.Command):
class ListGroup(command.Lister):
- """List groups"""
+ _description = _("List groups")
def get_parser(self, prog_name):
parser = super(ListGroup, self).get_parser(prog_name)
@@ -262,7 +262,7 @@ class ListGroup(command.Lister):
class RemoveUserFromGroup(command.Command):
- """Remove user from group"""
+ _description = _("Remove user from group")
def get_parser(self, prog_name):
parser = super(RemoveUserFromGroup, self).get_parser(prog_name)
@@ -307,7 +307,7 @@ class RemoveUserFromGroup(command.Command):
class SetGroup(command.Command):
- """Set group properties"""
+ _description = _("Set group properties")
def get_parser(self, prog_name):
parser = super(SetGroup, self).get_parser(prog_name)
@@ -347,7 +347,7 @@ class SetGroup(command.Command):
class ShowGroup(command.ShowOne):
- """Display group details"""
+ _description = _("Display group details")
def get_parser(self, prog_name):
parser = super(ShowGroup, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py
index b6b03188..163dcb5f 100644
--- a/openstackclient/identity/v3/identity_provider.py
+++ b/openstackclient/identity/v3/identity_provider.py
@@ -27,7 +27,7 @@ LOG = logging.getLogger(__name__)
class CreateIdentityProvider(command.ShowOne):
- """Create new identity provider"""
+ _description = _("Create new identity provider")
def get_parser(self, prog_name):
parser = super(CreateIdentityProvider, self).get_parser(prog_name)
@@ -94,7 +94,7 @@ class CreateIdentityProvider(command.ShowOne):
class DeleteIdentityProvider(command.Command):
- """Delete identity provider(s)"""
+ _description = _("Delete identity provider(s)")
def get_parser(self, prog_name):
parser = super(DeleteIdentityProvider, self).get_parser(prog_name)
@@ -126,7 +126,7 @@ class DeleteIdentityProvider(command.Command):
class ListIdentityProvider(command.Lister):
- """List identity providers"""
+ _description = _("List identity providers")
def take_action(self, parsed_args):
columns = ('ID', 'Enabled', 'Description')
@@ -140,7 +140,7 @@ class ListIdentityProvider(command.Lister):
class SetIdentityProvider(command.Command):
- """Set identity provider properties"""
+ _description = _("Set identity provider properties")
def get_parser(self, prog_name):
parser = super(SetIdentityProvider, self).get_parser(prog_name)
@@ -211,7 +211,7 @@ class SetIdentityProvider(command.Command):
class ShowIdentityProvider(command.ShowOne):
- """Display identity provider details"""
+ _description = _("Display identity provider details")
def get_parser(self, prog_name):
parser = super(ShowIdentityProvider, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/mapping.py b/openstackclient/identity/v3/mapping.py
index 09181a0b..dbb1b068 100644
--- a/openstackclient/identity/v3/mapping.py
+++ b/openstackclient/identity/v3/mapping.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class _RulesReader(object):
- """Helper class capable of reading rules from files"""
+ _description = _("Helper class capable of reading rules from files")
def _read_rules(self, path):
"""Read and parse rules from path
@@ -82,7 +82,7 @@ class _RulesReader(object):
class CreateMapping(command.ShowOne, _RulesReader):
- """Create new mapping"""
+ _description = _("Create new mapping")
def get_parser(self, prog_name):
parser = super(CreateMapping, self).get_parser(prog_name)
@@ -111,7 +111,7 @@ class CreateMapping(command.ShowOne, _RulesReader):
class DeleteMapping(command.Command):
- """Delete mapping(s)"""
+ _description = _("Delete mapping(s)")
def get_parser(self, prog_name):
parser = super(DeleteMapping, self).get_parser(prog_name)
@@ -143,7 +143,7 @@ class DeleteMapping(command.Command):
class ListMapping(command.Lister):
- """List mappings"""
+ _description = _("List mappings")
def take_action(self, parsed_args):
# NOTE(marek-denis): Since rules can be long and tedious I have decided
@@ -157,7 +157,7 @@ class ListMapping(command.Lister):
class SetMapping(command.Command, _RulesReader):
- """Set mapping properties"""
+ _description = _("Set mapping properties")
def get_parser(self, prog_name):
parser = super(SetMapping, self).get_parser(prog_name)
@@ -187,7 +187,7 @@ class SetMapping(command.Command, _RulesReader):
class ShowMapping(command.ShowOne):
- """Display mapping details"""
+ _description = _("Display mapping details")
def get_parser(self, prog_name):
parser = super(ShowMapping, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/policy.py b/openstackclient/identity/v3/policy.py
index 596eae01..c511652e 100644
--- a/openstackclient/identity/v3/policy.py
+++ b/openstackclient/identity/v3/policy.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreatePolicy(command.ShowOne):
- """Create new policy"""
+ _description = _("Create new policy")
def get_parser(self, prog_name):
parser = super(CreatePolicy, self).get_parser(prog_name)
@@ -61,7 +61,7 @@ class CreatePolicy(command.ShowOne):
class DeletePolicy(command.Command):
- """Delete policy(s)"""
+ _description = _("Delete policy(s)")
def get_parser(self, prog_name):
parser = super(DeletePolicy, self).get_parser(prog_name)
@@ -93,7 +93,7 @@ class DeletePolicy(command.Command):
class ListPolicy(command.Lister):
- """List policies"""
+ _description = _("List policies")
def get_parser(self, prog_name):
parser = super(ListPolicy, self).get_parser(prog_name)
@@ -121,7 +121,7 @@ class ListPolicy(command.Lister):
class SetPolicy(command.Command):
- """Set policy properties"""
+ _description = _("Set policy properties")
def get_parser(self, prog_name):
parser = super(SetPolicy, self).get_parser(prog_name)
@@ -159,7 +159,7 @@ class SetPolicy(command.Command):
class ShowPolicy(command.ShowOne):
- """Display policy details"""
+ _description = _("Display policy details")
def get_parser(self, prog_name):
parser = super(ShowPolicy, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py
index 56c4fbc8..a6348659 100644
--- a/openstackclient/identity/v3/project.py
+++ b/openstackclient/identity/v3/project.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class CreateProject(command.ShowOne):
- """Create new project"""
+ _description = _("Create new project")
def get_parser(self, prog_name):
parser = super(CreateProject, self).get_parser(prog_name)
@@ -125,7 +125,7 @@ class CreateProject(command.ShowOne):
class DeleteProject(command.Command):
- """Delete project(s)"""
+ _description = _("Delete project(s)")
def get_parser(self, prog_name):
parser = super(DeleteProject, self).get_parser(prog_name)
@@ -160,7 +160,7 @@ class DeleteProject(command.Command):
class ListProject(command.Lister):
- """List projects"""
+ _description = _("List projects")
def get_parser(self, prog_name):
parser = super(ListProject, self).get_parser(prog_name)
@@ -216,7 +216,7 @@ class ListProject(command.Lister):
class SetProject(command.Command):
- """Set project properties"""
+ _description = _("Set project properties")
def get_parser(self, prog_name):
parser = super(SetProject, self).get_parser(prog_name)
@@ -283,7 +283,7 @@ class SetProject(command.Command):
class ShowProject(command.ShowOne):
- """Display project details"""
+ _description = _("Display project details")
def get_parser(self, prog_name):
parser = super(ShowProject, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/region.py b/openstackclient/identity/v3/region.py
index b7c51f93..d3e712e3 100644
--- a/openstackclient/identity/v3/region.py
+++ b/openstackclient/identity/v3/region.py
@@ -27,7 +27,7 @@ LOG = logging.getLogger(__name__)
class CreateRegion(command.ShowOne):
- """Create new region"""
+ _description = _("Create new region")
def get_parser(self, prog_name):
parser = super(CreateRegion, self).get_parser(prog_name)
@@ -66,7 +66,7 @@ class CreateRegion(command.ShowOne):
class DeleteRegion(command.Command):
- """Delete region(s)"""
+ _description = _("Delete region(s)")
def get_parser(self, prog_name):
parser = super(DeleteRegion, self).get_parser(prog_name)
@@ -98,7 +98,7 @@ class DeleteRegion(command.Command):
class ListRegion(command.Lister):
- """List regions"""
+ _description = _("List regions")
def get_parser(self, prog_name):
parser = super(ListRegion, self).get_parser(prog_name)
@@ -128,7 +128,7 @@ class ListRegion(command.Lister):
class SetRegion(command.Command):
- """Set region properties"""
+ _description = _("Set region properties")
def get_parser(self, prog_name):
parser = super(SetRegion, self).get_parser(prog_name)
@@ -162,7 +162,7 @@ class SetRegion(command.Command):
class ShowRegion(command.ShowOne):
- """Display region details"""
+ _description = _("Display region details")
def get_parser(self, prog_name):
parser = super(ShowRegion, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py
index 8b911746..c9d0fbf3 100644
--- a/openstackclient/identity/v3/role.py
+++ b/openstackclient/identity/v3/role.py
@@ -109,7 +109,8 @@ def _process_identity_and_resource_options(parsed_args,
class AddRole(command.Command):
- """Adds a role assignment to a user or group on a domain or project"""
+ _description = _("Adds a role assignment to a user or group on a domain "
+ "or project")
def get_parser(self, prog_name):
parser = super(AddRole, self).get_parser(prog_name)
@@ -151,7 +152,7 @@ class AddRole(command.Command):
class CreateRole(command.ShowOne):
- """Create new role"""
+ _description = _("Create new role")
def get_parser(self, prog_name):
parser = super(CreateRole, self).get_parser(prog_name)
@@ -198,7 +199,7 @@ class CreateRole(command.ShowOne):
class DeleteRole(command.Command):
- """Delete role(s)"""
+ _description = _("Delete role(s)")
def get_parser(self, prog_name):
parser = super(DeleteRole, self).get_parser(prog_name)
@@ -233,7 +234,7 @@ class DeleteRole(command.Command):
class ListRole(command.Lister):
- """List roles"""
+ _description = _("List roles")
def get_parser(self, prog_name):
parser = super(ListRole, self).get_parser(prog_name)
@@ -371,7 +372,8 @@ class ListRole(command.Lister):
class RemoveRole(command.Command):
- """Removes a role assignment from domain/project : user/group"""
+ _description = _("Removes a role assignment from domain/project : "
+ "user/group")
def get_parser(self, prog_name):
parser = super(RemoveRole, self).get_parser(prog_name)
@@ -415,7 +417,7 @@ class RemoveRole(command.Command):
class SetRole(command.Command):
- """Set role properties"""
+ _description = _("Set role properties")
def get_parser(self, prog_name):
parser = super(SetRole, self).get_parser(prog_name)
@@ -452,7 +454,7 @@ class SetRole(command.Command):
class ShowRole(command.ShowOne):
- """Display role details"""
+ _description = _("Display role details")
def get_parser(self, prog_name):
parser = super(ShowRole, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/role_assignment.py b/openstackclient/identity/v3/role_assignment.py
index d25cc6ce..9da050de 100644
--- a/openstackclient/identity/v3/role_assignment.py
+++ b/openstackclient/identity/v3/role_assignment.py
@@ -11,7 +11,7 @@
# under the License.
#
-"""Identity v3 Assignment action implementations """
+"""Identity v3 Assignment action implementations"""
from osc_lib.command import command
from osc_lib import utils
@@ -21,7 +21,7 @@ from openstackclient.identity import common
class ListRoleAssignment(command.Lister):
- """List role assignments"""
+ _description = _("List role assignments")
def get_parser(self, prog_name):
parser = super(ListRoleAssignment, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/service.py b/openstackclient/identity/v3/service.py
index 97e64dc6..7daf8919 100644
--- a/openstackclient/identity/v3/service.py
+++ b/openstackclient/identity/v3/service.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateService(command.ShowOne):
- """Create new service"""
+ _description = _("Create new service")
def get_parser(self, prog_name):
parser = super(CreateService, self).get_parser(prog_name)
@@ -81,7 +81,7 @@ class CreateService(command.ShowOne):
class DeleteService(command.Command):
- """Delete service(s)"""
+ _description = _("Delete service(s)")
def get_parser(self, prog_name):
parser = super(DeleteService, self).get_parser(prog_name)
@@ -114,7 +114,7 @@ class DeleteService(command.Command):
class ListService(command.Lister):
- """List services"""
+ _description = _("List services")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -140,7 +140,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set service properties"""
+ _description = _("Set service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
@@ -201,7 +201,7 @@ class SetService(command.Command):
class ShowService(command.ShowOne):
- """Display service details"""
+ _description = _("Display service details")
def get_parser(self, prog_name):
parser = super(ShowService, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/service_provider.py b/openstackclient/identity/v3/service_provider.py
index 8548ae1f..459dc00b 100644
--- a/openstackclient/identity/v3/service_provider.py
+++ b/openstackclient/identity/v3/service_provider.py
@@ -27,7 +27,7 @@ LOG = logging.getLogger(__name__)
class CreateServiceProvider(command.ShowOne):
- """Create new service provider"""
+ _description = _("Create new service provider")
def get_parser(self, prog_name):
parser = super(CreateServiceProvider, self).get_parser(prog_name)
@@ -87,7 +87,7 @@ class CreateServiceProvider(command.ShowOne):
class DeleteServiceProvider(command.Command):
- """Delete service provider(s)"""
+ _description = _("Delete service provider(s)")
def get_parser(self, prog_name):
parser = super(DeleteServiceProvider, self).get_parser(prog_name)
@@ -119,7 +119,7 @@ class DeleteServiceProvider(command.Command):
class ListServiceProvider(command.Lister):
- """List service providers"""
+ _description = _("List service providers")
def take_action(self, parsed_args):
service_client = self.app.client_manager.identity
@@ -134,7 +134,7 @@ class ListServiceProvider(command.Lister):
class SetServiceProvider(command.Command):
- """Set service provider properties"""
+ _description = _("Set service provider properties")
def get_parser(self, prog_name):
parser = super(SetServiceProvider, self).get_parser(prog_name)
@@ -192,7 +192,7 @@ class SetServiceProvider(command.Command):
class ShowServiceProvider(command.ShowOne):
- """Display service provider details"""
+ _description = _("Display service provider details")
def get_parser(self, prog_name):
parser = super(ShowServiceProvider, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py
index 2cd304e6..7a66f23b 100644
--- a/openstackclient/identity/v3/token.py
+++ b/openstackclient/identity/v3/token.py
@@ -25,7 +25,7 @@ from openstackclient.identity import common
class AuthorizeRequestToken(command.ShowOne):
- """Authorize a request token"""
+ _description = _("Authorize a request token")
def get_parser(self, prog_name):
parser = super(AuthorizeRequestToken, self).get_parser(prog_name)
@@ -66,7 +66,7 @@ class AuthorizeRequestToken(command.ShowOne):
class CreateAccessToken(command.ShowOne):
- """Create an access token"""
+ _description = _("Create an access token")
def get_parser(self, prog_name):
parser = super(CreateAccessToken, self).get_parser(prog_name)
@@ -112,7 +112,7 @@ class CreateAccessToken(command.ShowOne):
class CreateRequestToken(command.ShowOne):
- """Create a request token"""
+ _description = _("Create a request token")
def get_parser(self, prog_name):
parser = super(CreateRequestToken, self).get_parser(prog_name)
@@ -164,7 +164,7 @@ class CreateRequestToken(command.ShowOne):
class IssueToken(command.ShowOne):
- """Issue new token"""
+ _description = _("Issue new token")
# scoped token is optional
required_scope = False
@@ -196,7 +196,7 @@ class IssueToken(command.ShowOne):
class RevokeToken(command.Command):
- """Revoke existing token"""
+ _description = _("Revoke existing token")
def get_parser(self, prog_name):
parser = super(RevokeToken, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/trust.py b/openstackclient/identity/v3/trust.py
index bbc86adb..62d72ea1 100644
--- a/openstackclient/identity/v3/trust.py
+++ b/openstackclient/identity/v3/trust.py
@@ -24,7 +24,7 @@ from openstackclient.identity import common
class CreateTrust(command.ShowOne):
- """Create new trust"""
+ _description = _("Create new trust")
def get_parser(self, prog_name):
parser = super(CreateTrust, self).get_parser(prog_name)
@@ -131,7 +131,7 @@ class CreateTrust(command.ShowOne):
class DeleteTrust(command.Command):
- """Delete trust(s)"""
+ _description = _("Delete trust(s)")
def get_parser(self, prog_name):
parser = super(DeleteTrust, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class DeleteTrust(command.Command):
class ListTrust(command.Lister):
- """List trusts"""
+ _description = _("List trusts")
def take_action(self, parsed_args):
columns = ('ID', 'Expires At', 'Impersonation', 'Project ID',
@@ -165,7 +165,7 @@ class ListTrust(command.Lister):
class ShowTrust(command.ShowOne):
- """Display trust details"""
+ _description = _("Display trust details")
def get_parser(self, prog_name):
parser = super(ShowTrust, self).get_parser(prog_name)
diff --git a/openstackclient/identity/v3/unscoped_saml.py b/openstackclient/identity/v3/unscoped_saml.py
index f116174b..5940534a 100644
--- a/openstackclient/identity/v3/unscoped_saml.py
+++ b/openstackclient/identity/v3/unscoped_saml.py
@@ -44,7 +44,7 @@ def auth_with_unscoped_saml(func):
class ListAccessibleDomains(command.Lister):
- """List accessible domains"""
+ _description = _("List accessible domains")
@auth_with_unscoped_saml
def take_action(self, parsed_args):
@@ -59,7 +59,7 @@ class ListAccessibleDomains(command.Lister):
class ListAccessibleProjects(command.Lister):
- """List accessible projects"""
+ _description = _("List accessible projects")
@auth_with_unscoped_saml
def take_action(self, parsed_args):
diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py
index 1e086fb6..796cf28c 100644
--- a/openstackclient/identity/v3/user.py
+++ b/openstackclient/identity/v3/user.py
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
class CreateUser(command.ShowOne):
- """Create new user"""
+ _description = _("Create new user")
def get_parser(self, prog_name):
parser = super(CreateUser, self).get_parser(prog_name)
@@ -138,7 +138,7 @@ class CreateUser(command.ShowOne):
class DeleteUser(command.Command):
- """Delete user(s)"""
+ _description = _("Delete user(s)")
def get_parser(self, prog_name):
parser = super(DeleteUser, self).get_parser(prog_name)
@@ -173,7 +173,7 @@ class DeleteUser(command.Command):
class ListUser(command.Lister):
- """List users"""
+ _description = _("List users")
def get_parser(self, prog_name):
parser = super(ListUser, self).get_parser(prog_name)
@@ -273,7 +273,7 @@ class ListUser(command.Lister):
class SetUser(command.Command):
- """Set user properties"""
+ _description = _("Set user properties")
def get_parser(self, prog_name):
parser = super(SetUser, self).get_parser(prog_name)
@@ -365,7 +365,7 @@ class SetUser(command.Command):
class SetPasswordUser(command.Command):
- """Change current user password"""
+ _description = _("Change current user password")
required_scope = False
@@ -424,7 +424,7 @@ class SetPasswordUser(command.Command):
class ShowUser(command.ShowOne):
- """Display user details"""
+ _description = _("Display user details")
def get_parser(self, prog_name):
parser = super(ShowUser, self).get_parser(prog_name)
diff --git a/openstackclient/image/client.py b/openstackclient/image/client.py
index 1be6c765..b67c291f 100644
--- a/openstackclient/image/client.py
+++ b/openstackclient/image/client.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-DEFAULT_API_VERSION = '1'
+DEFAULT_API_VERSION = '2'
API_VERSION_OPTION = 'os_image_api_version'
API_NAME = "image"
API_VERSIONS = {
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index 5f669c64..eb79cd2f 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -38,6 +38,8 @@ from openstackclient.i18n import _
DEFAULT_CONTAINER_FORMAT = 'bare'
DEFAULT_DISK_FORMAT = 'raw'
+DISK_CHOICES = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2", "vhdx",
+ "vdi", "iso"]
LOG = logging.getLogger(__name__)
@@ -59,7 +61,7 @@ def _format_visibility(data):
class CreateImage(command.ShowOne):
- """Create/upload an image"""
+ _description = _("Create/upload an image")
def get_parser(self, prog_name):
parser = super(CreateImage, self).get_parser(prog_name)
@@ -89,8 +91,9 @@ class CreateImage(command.ShowOne):
"--disk-format",
default=DEFAULT_DISK_FORMAT,
metavar="<disk-format>",
- help=_("Image disk format "
- "(default: %s)") % DEFAULT_DISK_FORMAT,
+ choices=DISK_CHOICES,
+ help=_("Image disk format. The supported options are: %s. "
+ "The default format is: raw") % ', '.join(DISK_CHOICES)
)
parser.add_argument(
"--size",
@@ -277,7 +280,7 @@ class CreateImage(command.ShowOne):
class DeleteImage(command.Command):
- """Delete image(s)"""
+ _description = _("Delete image(s)")
def get_parser(self, prog_name):
parser = super(DeleteImage, self).get_parser(prog_name)
@@ -300,7 +303,7 @@ class DeleteImage(command.Command):
class ListImage(command.Lister):
- """List available images"""
+ _description = _("List available images")
def get_parser(self, prog_name):
parser = super(ListImage, self).get_parser(prog_name)
@@ -350,8 +353,9 @@ class ListImage(command.Lister):
parser.add_argument(
'--sort',
metavar="<key>[:<direction>]",
+ default='name:asc',
help=_("Sort output by selected keys and directions(asc or desc) "
- "(default: asc), multiple keys and directions can be "
+ "(default: name:asc), multiple keys and directions can be "
"specified separated by comma"),
)
return parser
@@ -440,7 +444,7 @@ class ListImage(command.Lister):
class SaveImage(command.Command):
- """Save an image locally"""
+ _description = _("Save an image locally")
def get_parser(self, prog_name):
parser = super(SaveImage, self).get_parser(prog_name)
@@ -468,7 +472,7 @@ class SaveImage(command.Command):
class SetImage(command.Command):
- """Set image properties"""
+ _description = _("Set image properties")
def get_parser(self, prog_name):
parser = super(SetImage, self).get_parser(prog_name)
@@ -502,14 +506,12 @@ class SetImage(command.Command):
container_choices,
choices=container_choices
)
- disk_choices = ["ami", "ari", "aki", "vhd", "vmdk", "raw", "qcow2",
- "vdi", "iso"]
parser.add_argument(
"--disk-format",
metavar="<disk-format>",
- help=_("Disk format of image. Acceptable formats: %s") %
- disk_choices,
- choices=disk_choices
+ choices=DISK_CHOICES,
+ help=_("Image disk format. The supported options are: %s.") %
+ ', '.join(DISK_CHOICES)
)
parser.add_argument(
"--size",
@@ -702,7 +704,7 @@ class SetImage(command.Command):
class ShowImage(command.ShowOne):
- """Display image details"""
+ _description = _("Display image details")
def get_parser(self, prog_name):
parser = super(ShowImage, self).get_parser(prog_name)
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 0712e09c..054d1612 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -32,13 +32,15 @@ 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"]
LOG = logging.getLogger(__name__)
def _format_image(image):
- """Format an image to make it more consistent with OSC operations. """
+ """Format an image to make it more consistent with OSC operations."""
info = {}
properties = {}
@@ -69,7 +71,7 @@ def _format_image(image):
class AddProjectToImage(command.ShowOne):
- """Associate project with image"""
+ _description = _("Associate project with image")
def get_parser(self, prog_name):
parser = super(AddProjectToImage, self).get_parser(prog_name)
@@ -107,7 +109,7 @@ class AddProjectToImage(command.ShowOne):
class CreateImage(command.ShowOne):
- """Create/upload an image"""
+ _description = _("Create/upload an image")
deadopts = ('size', 'location', 'copy-from', 'checksum', 'store')
@@ -140,9 +142,10 @@ class CreateImage(command.ShowOne):
parser.add_argument(
"--disk-format",
default=DEFAULT_DISK_FORMAT,
+ choices=DISK_CHOICES,
metavar="<disk-format>",
- help=_("Image disk format "
- "(default: %s)") % DEFAULT_DISK_FORMAT,
+ help=_("Image disk format. The supported options are: %s. "
+ "The default format is: raw") % ', '.join(DISK_CHOICES)
)
parser.add_argument(
"--min-disk",
@@ -361,7 +364,7 @@ class CreateImage(command.ShowOne):
class DeleteImage(command.Command):
- """Delete image(s)"""
+ _description = _("Delete image(s)")
def get_parser(self, prog_name):
parser = super(DeleteImage, self).get_parser(prog_name)
@@ -398,7 +401,7 @@ class DeleteImage(command.Command):
class ListImage(command.Lister):
- """List available images"""
+ _description = _("List available images")
def get_parser(self, prog_name):
parser = super(ListImage, self).get_parser(prog_name)
@@ -447,8 +450,9 @@ class ListImage(command.Lister):
parser.add_argument(
'--sort',
metavar="<key>[:<direction>]",
+ default='name:asc',
help=_("Sort output by selected keys and directions(asc or desc) "
- "(default: asc), multiple keys and directions can be "
+ "(default: name:asc), multiple keys and directions can be "
"specified separated by comma"),
)
parser.add_argument(
@@ -542,7 +546,7 @@ class ListImage(command.Lister):
class RemoveProjectImage(command.Command):
- """Disassociate project with image"""
+ _description = _("Disassociate project with image")
def get_parser(self, prog_name):
parser = super(RemoveProjectImage, self).get_parser(prog_name)
@@ -575,7 +579,7 @@ class RemoveProjectImage(command.Command):
class SaveImage(command.Command):
- """Save an image locally"""
+ _description = _("Save an image locally")
def get_parser(self, prog_name):
parser = super(SaveImage, self).get_parser(prog_name)
@@ -603,7 +607,7 @@ class SaveImage(command.Command):
class SetImage(command.Command):
- """Set image properties"""
+ _description = _("Set image properties")
deadopts = ('visibility',)
@@ -650,8 +654,9 @@ class SetImage(command.Command):
parser.add_argument(
"--disk-format",
metavar="<disk-format>",
- help=_("Image disk format "
- "(default: %s)") % DEFAULT_DISK_FORMAT,
+ choices=DISK_CHOICES,
+ help=_("Image disk format. The supported options are: %s") %
+ ', '.join(DISK_CHOICES)
)
protected_group = parser.add_mutually_exclusive_group()
protected_group.add_argument(
@@ -844,7 +849,7 @@ class SetImage(command.Command):
class ShowImage(command.ShowOne):
- """Display image details"""
+ _description = _("Display image details")
def get_parser(self, prog_name):
parser = super(ShowImage, self).get_parser(prog_name)
@@ -867,7 +872,7 @@ class ShowImage(command.ShowOne):
class UnsetImage(command.Command):
- """Unset image tags and properties"""
+ _description = _("Unset image tags and properties")
def get_parser(self, prog_name):
parser = super(UnsetImage, self).get_parser(prog_name)
diff --git a/openstackclient/network/common.py b/openstackclient/network/common.py
index 2b1a5656..a2e700be 100644
--- a/openstackclient/network/common.py
+++ b/openstackclient/network/common.py
@@ -14,6 +14,7 @@
import abc
import logging
+import openstack.exceptions
from osc_lib.command import command
from osc_lib import exceptions
import six
@@ -181,12 +182,16 @@ class NetworkAndComputeShowOne(command.ShowOne):
"""
def take_action(self, parsed_args):
- if self.app.client_manager.is_network_endpoint_enabled():
- return self.take_action_network(self.app.client_manager.network,
- parsed_args)
- else:
- return self.take_action_compute(self.app.client_manager.compute,
- parsed_args)
+ try:
+ if self.app.client_manager.is_network_endpoint_enabled():
+ return self.take_action_network(
+ self.app.client_manager.network, parsed_args)
+ else:
+ return self.take_action_compute(
+ self.app.client_manager.compute, parsed_args)
+ except openstack.exceptions.HttpException as exc:
+ msg = _("Error while executing command: %s") % exc.message
+ raise exceptions.CommandError(msg)
def get_parser(self, prog_name):
LOG.debug('get_parser(%s)', prog_name)
diff --git a/openstackclient/network/sdk_utils.py b/openstackclient/network/sdk_utils.py
new file mode 100644
index 00000000..7bd54e46
--- /dev/null
+++ b/openstackclient/network/sdk_utils.py
@@ -0,0 +1,40 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import six
+
+
+# Get the OSC show command display and attribute columns for an SDK resource.
+def get_osc_show_columns_for_sdk_resource(sdk_resource, osc_column_map):
+ if getattr(sdk_resource, 'allow_get', None) is not None:
+ resource_dict = sdk_resource.to_dict(
+ body=True, headers=False, ignore_none=False)
+ else:
+ resource_dict = sdk_resource
+
+ # Build the OSC column names to display for the SDK resource.
+ attr_map = {}
+ display_columns = list(resource_dict.keys())
+ for sdk_attr, osc_attr in six.iteritems(osc_column_map):
+ if sdk_attr in display_columns:
+ attr_map[osc_attr] = sdk_attr
+ display_columns.remove(sdk_attr)
+ if osc_attr not in display_columns:
+ display_columns.append(osc_attr)
+ sorted_display_columns = sorted(display_columns)
+
+ # Build the SDK attribute names for the OSC column names.
+ attr_columns = []
+ for column in sorted_display_columns:
+ new_column = attr_map[column] if column in attr_map else column
+ attr_columns.append(new_column)
+ return tuple(sorted_display_columns), tuple(attr_columns)
diff --git a/openstackclient/network/v2/address_scope.py b/openstackclient/network/v2/address_scope.py
index 6cd13f8c..0d8f80d0 100644
--- a/openstackclient/network/v2/address_scope.py
+++ b/openstackclient/network/v2/address_scope.py
@@ -21,18 +21,18 @@ 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__)
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
-
- return tuple(sorted(columns))
+ column_map = {
+ 'is_shared': 'shared',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_attrs(client_manager, parsed_args):
@@ -55,8 +55,10 @@ def _get_attrs(client_manager, parsed_args):
return attrs
+# TODO(rtheis): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateAddressScope(command.ShowOne):
- """Create a new Address Scope"""
+ _description = _("Create a new Address Scope")
def get_parser(self, prog_name):
parser = super(CreateAddressScope, self).get_parser(prog_name)
@@ -97,14 +99,14 @@ class CreateAddressScope(command.ShowOne):
client = self.app.client_manager.network
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_address_scope(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
- return (columns, data)
+ return (display_columns, data)
class DeleteAddressScope(command.Command):
- """Delete address scope(s)"""
+ _description = _("Delete address scope(s)")
def get_parser(self, prog_name):
parser = super(DeleteAddressScope, self).get_parser(prog_name)
@@ -139,7 +141,7 @@ class DeleteAddressScope(command.Command):
class ListAddressScope(command.Lister):
- """List address scopes"""
+ _description = _("List address scopes")
def take_action(self, parsed_args):
client = self.app.client_manager.network
@@ -147,8 +149,8 @@ class ListAddressScope(command.Lister):
'id',
'name',
'ip_version',
- 'shared',
- 'tenant_id',
+ 'is_shared',
+ 'project_id',
)
column_headers = (
'ID',
@@ -165,8 +167,10 @@ class ListAddressScope(command.Lister):
) for s in data))
+# TODO(rtheis): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class SetAddressScope(command.Command):
- """Set address scope properties"""
+ _description = _("Set address scope properties")
def get_parser(self, prog_name):
parser = super(SetAddressScope, self).get_parser(prog_name)
@@ -210,7 +214,7 @@ class SetAddressScope(command.Command):
class ShowAddressScope(command.ShowOne):
- """Display address scope details"""
+ _description = _("Display address scope details")
def get_parser(self, prog_name):
parser = super(ShowAddressScope, self).get_parser(prog_name)
@@ -227,7 +231,7 @@ class ShowAddressScope(command.ShowOne):
obj = client.find_address_scope(
parsed_args.address_scope,
ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
- return (columns, data)
+ return (display_columns, data)
diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py
index e8057628..c787cd2f 100644
--- a/openstackclient/network/v2/floating_ip.py
+++ b/openstackclient/network/v2/floating_ip.py
@@ -19,6 +19,14 @@ from osc_lib import utils
from openstackclient.i18n import _
from openstackclient.network import common
+from openstackclient.network import sdk_utils
+
+
+def _get_network_columns(item):
+ column_map = {
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_columns(item):
@@ -62,7 +70,7 @@ def _get_attrs(client_manager, parsed_args):
class CreateFloatingIP(common.NetworkAndComputeShowOne):
- """Create floating IP"""
+ _description = _("Create floating IP")
def update_parser_common(self, parser):
# In Compute v2 network, floating IPs could be allocated from floating
@@ -110,9 +118,9 @@ class CreateFloatingIP(common.NetworkAndComputeShowOne):
def take_action_network(self, client, parsed_args):
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_ip(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_network_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
obj = client.floating_ips.create(parsed_args.network)
@@ -122,7 +130,7 @@ class CreateFloatingIP(common.NetworkAndComputeShowOne):
class CreateIPFloating(CreateFloatingIP):
- """Create floating IP"""
+ _description = _("Create floating IP")
# TODO(tangchen): Remove this class and ``ip floating create`` command
# two cycles after Mitaka.
@@ -146,7 +154,7 @@ class CreateIPFloating(CreateFloatingIP):
class DeleteFloatingIP(common.NetworkAndComputeDelete):
- """Delete floating IP(s)"""
+ _description = _("Delete floating IP(s)")
# Used by base class to find resources in parsed_args.
resource = 'floating_ip'
@@ -171,7 +179,7 @@ class DeleteFloatingIP(common.NetworkAndComputeDelete):
class DeleteIPFloating(DeleteFloatingIP):
- """Delete floating IP(s)"""
+ _description = _("Delete floating IP(s)")
# TODO(tangchen): Remove this class and ``ip floating delete`` command
# two cycles after Mitaka.
@@ -195,9 +203,33 @@ class DeleteIPFloating(DeleteFloatingIP):
class ListFloatingIP(common.NetworkAndComputeLister):
- """List floating IP(s)"""
+ _description = _("List floating IP(s)")
+
+ def update_parser_network(self, parser):
+ parser.add_argument(
+ '--network',
+ metavar='<network>',
+ help=_("List floating IP(s) according to "
+ "given network (name or ID)")
+ )
+ parser.add_argument(
+ '--port',
+ metavar='<port>',
+ help=_("List floating IP(s) according to "
+ "given port (name or ID)")
+ )
+ parser.add_argument(
+ '--fixed-ip-address',
+ metavar='<fixed-ip-address>',
+ help=_("List floating IP(s) according to "
+ "given fixed IP address")
+ )
+
+ return parser
def take_action_network(self, client, parsed_args):
+ network_client = self.app.client_manager.network
+
columns = (
'id',
'floating_ip_address',
@@ -216,6 +248,18 @@ class ListFloatingIP(common.NetworkAndComputeLister):
)
query = {}
+
+ if parsed_args.network is not None:
+ network = network_client.find_network(parsed_args.network,
+ ignore_missing=False)
+ query['floating_network_id'] = network.id
+ if parsed_args.port is not None:
+ port = network_client.find_port(parsed_args.port,
+ ignore_missing=False)
+ query['port_id'] = port.id
+ if parsed_args.fixed_ip_address is not None:
+ query['fixed_ip_address'] = parsed_args.fixed_ip_address
+
data = client.ips(**query)
return (headers,
@@ -250,7 +294,7 @@ class ListFloatingIP(common.NetworkAndComputeLister):
class ListIPFloating(ListFloatingIP):
- """List floating IP(s)"""
+ _description = _("List floating IP(s)")
# TODO(tangchen): Remove this class and ``ip floating list`` command
# two cycles after Mitaka.
@@ -274,7 +318,7 @@ class ListIPFloating(ListFloatingIP):
class ShowFloatingIP(common.NetworkAndComputeShowOne):
- """Display floating IP details"""
+ _description = _("Display floating IP details")
def update_parser_common(self, parser):
parser.add_argument(
@@ -286,9 +330,9 @@ class ShowFloatingIP(common.NetworkAndComputeShowOne):
def take_action_network(self, client, parsed_args):
obj = client.find_ip(parsed_args.floating_ip, ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_network_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
obj = utils.find_resource(
@@ -301,7 +345,7 @@ class ShowFloatingIP(common.NetworkAndComputeShowOne):
class ShowIPFloating(ShowFloatingIP):
- """Display floating IP details"""
+ _description = _("Display floating IP details")
# TODO(tangchen): Remove this class and ``ip floating show`` command
# two cycles after Mitaka.
diff --git a/openstackclient/network/v2/floating_ip_pool.py b/openstackclient/network/v2/floating_ip_pool.py
index c78ca06a..73e94ead 100644
--- a/openstackclient/network/v2/floating_ip_pool.py
+++ b/openstackclient/network/v2/floating_ip_pool.py
@@ -23,7 +23,7 @@ from openstackclient.network import common
class ListFloatingIPPool(common.NetworkAndComputeLister):
- """List pools of floating IP addresses"""
+ _description = _("List pools of floating IP addresses")
def take_action_network(self, client, parsed_args):
msg = _("Floating ip pool operations are only available for "
@@ -43,7 +43,7 @@ class ListFloatingIPPool(common.NetworkAndComputeLister):
class ListIPFloatingPool(ListFloatingIPPool):
- """List pools of floating IP addresses"""
+ _description = _("List pools of floating IP addresses")
# TODO(tangchen): Remove this class and ``ip floating pool list`` command
# two cycles after Mitaka.
diff --git a/openstackclient/network/v2/ip_availability.py b/openstackclient/network/v2/ip_availability.py
index 1d7b2aed..5960e2fa 100644
--- a/openstackclient/network/v2/ip_availability.py
+++ b/openstackclient/network/v2/ip_availability.py
@@ -34,7 +34,7 @@ def _get_columns(item):
class ListIPAvailability(command.Lister):
- """List IP availability for network"""
+ _description = _("List IP availability for network")
def get_parser(self, prog_name):
parser = super(ListIPAvailability, self).get_parser(prog_name)
@@ -92,7 +92,7 @@ class ListIPAvailability(command.Lister):
class ShowIPAvailability(command.ShowOne):
- """Show network IP availability details"""
+ _description = _("Show network IP availability details")
def get_parser(self, prog_name):
parser = super(ShowIPAvailability, self).get_parser(prog_name)
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 40183b73..1c06c462 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -99,6 +99,13 @@ def _get_attrs(client_manager, parsed_args):
attrs['provider:physical_network'] = parsed_args.physical_network
if parsed_args.segmentation_id:
attrs['provider:segmentation_id'] = parsed_args.segmentation_id
+ if parsed_args.qos_policy is not None:
+ network_client = client_manager.network
+ _qos_policy = network_client.find_qos_policy(parsed_args.qos_policy,
+ ignore_missing=False)
+ attrs['qos_policy_id'] = _qos_policy.id
+ if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
+ attrs['qos_policy_id'] = None
# Update VLAN Transparency for networks
if parsed_args.transparent_vlan:
attrs['vlan_transparent'] = True
@@ -156,7 +163,7 @@ def _get_attrs_compute(client_manager, parsed_args):
class CreateNetwork(common.NetworkAndComputeShowOne):
- """Create new network"""
+ _description = _("Create new network")
def update_parser_common(self, parser):
parser.add_argument(
@@ -249,6 +256,11 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
help=_("Do not use the network as the default external network "
"(default)")
)
+ parser.add_argument(
+ '--qos-policy',
+ metavar='<qos-policy>',
+ help=_("QoS policy to attach to this network (name or ID)")
+ )
_add_additional_network_options(parser)
return parser
@@ -276,7 +288,7 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
class DeleteNetwork(common.NetworkAndComputeDelete):
- """Delete network(s)"""
+ _description = _("Delete network(s)")
# Used by base class to find resources in parsed_args.
resource = 'network'
@@ -302,9 +314,9 @@ class DeleteNetwork(common.NetworkAndComputeDelete):
class ListNetwork(common.NetworkAndComputeLister):
- """List networks"""
+ _description = _("List networks")
- def update_parser_common(self, parser):
+ def update_parser_network(self, parser):
router_ext_group = parser.add_mutually_exclusive_group()
router_ext_group.add_argument(
'--external',
@@ -361,6 +373,29 @@ class ListNetwork(common.NetworkAndComputeLister):
help=_("List networks according to their status "
"('ACTIVE', 'BUILD', 'DOWN', 'ERROR')")
)
+ parser.add_argument(
+ '--provider-network-type',
+ metavar='<provider-network-type>',
+ choices=['flat', 'geneve', 'gre', 'local',
+ 'vlan', 'vxlan'],
+ help=_("List networks according to their physical mechanisms. "
+ "The supported options are: flat, geneve, gre, local, "
+ "vlan, vxlan.")
+ )
+ parser.add_argument(
+ '--provider-physical-network',
+ metavar='<provider-physical-network>',
+ dest='physical_network',
+ help=_("List networks according to name of the physical network")
+ )
+ parser.add_argument(
+ '--provider-segment',
+ metavar='<provider-segment>',
+ dest='segmentation_id',
+ help=_("List networks according to VLAN ID for VLAN networks "
+ "or Tunnel ID for GENEVE/GRE/VXLAN networks")
+ )
+
return parser
def take_action_network(self, client, parsed_args):
@@ -433,6 +468,13 @@ class ListNetwork(common.NetworkAndComputeLister):
if parsed_args.status:
args['status'] = parsed_args.status
+ if 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
+ if parsed_args.segmentation_id:
+ args['provider:segmentation_id'] = parsed_args.segmentation_id
+
data = client.networks(**args)
return (column_headers,
@@ -463,7 +505,7 @@ class ListNetwork(common.NetworkAndComputeLister):
class SetNetwork(command.Command):
- """Set network properties"""
+ _description = _("Set network properties")
def get_parser(self, prog_name):
parser = super(SetNetwork, self).get_parser(prog_name)
@@ -542,6 +584,17 @@ class SetNetwork(command.Command):
action='store_true',
help=_("Do not use the network as the default external network")
)
+ qos_group = parser.add_mutually_exclusive_group()
+ qos_group.add_argument(
+ '--qos-policy',
+ metavar='<qos-policy>',
+ help=_("QoS policy to attach to this network (name or ID)")
+ )
+ qos_group.add_argument(
+ '--no-qos-policy',
+ action='store_true',
+ help=_("Remove the QoS policy attached to this network")
+ )
_add_additional_network_options(parser)
return parser
@@ -554,7 +607,7 @@ class SetNetwork(command.Command):
class ShowNetwork(common.NetworkAndComputeShowOne):
- """Show network details"""
+ _description = _("Show network details")
def update_parser_common(self, parser):
parser.add_argument(
diff --git a/openstackclient/network/v2/network_agent.py b/openstackclient/network/v2/network_agent.py
index fdb34bb7..65708499 100644
--- a/openstackclient/network/v2/network_agent.py
+++ b/openstackclient/network/v2/network_agent.py
@@ -36,7 +36,7 @@ _formatters = {
class DeleteNetworkAgent(command.Command):
- """Delete network agent(s)"""
+ _description = _("Delete network agent(s)")
def get_parser(self, prog_name):
parser = super(DeleteNetworkAgent, self).get_parser(prog_name)
@@ -70,7 +70,7 @@ class DeleteNetworkAgent(command.Command):
class ListNetworkAgent(command.Lister):
- """List network agents"""
+ _description = _("List network agents")
def take_action(self, parsed_args):
client = self.app.client_manager.network
@@ -100,7 +100,7 @@ class ListNetworkAgent(command.Lister):
class SetNetworkAgent(command.Command):
- """Set network agent properties"""
+ _description = _("Set network agent properties")
def get_parser(self, prog_name):
parser = super(SetNetworkAgent, self).get_parser(prog_name)
@@ -141,7 +141,7 @@ class SetNetworkAgent(command.Command):
class ShowNetworkAgent(command.ShowOne):
- """Display network agent details"""
+ _description = _("Display network agent details")
def get_parser(self, prog_name):
parser = super(ShowNetworkAgent, self).get_parser(prog_name)
diff --git a/openstackclient/network/v2/network_qos_policy.py b/openstackclient/network/v2/network_qos_policy.py
index a8fcfc59..5ccbe36b 100644
--- a/openstackclient/network/v2/network_qos_policy.py
+++ b/openstackclient/network/v2/network_qos_policy.py
@@ -21,17 +21,18 @@ 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__)
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'is_shared': 'shared',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_attrs(client_manager, parsed_args):
@@ -56,8 +57,10 @@ def _get_attrs(client_manager, parsed_args):
return attrs
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateNetworkQosPolicy(command.ShowOne):
- """Create a QoS policy"""
+ _description = _("Create a QoS policy")
def get_parser(self, prog_name):
parser = super(CreateNetworkQosPolicy, self).get_parser(prog_name)
@@ -96,13 +99,13 @@ class CreateNetworkQosPolicy(command.ShowOne):
client = self.app.client_manager.network
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_qos_policy(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
- return columns, data
+ return (display_columns, data)
class DeleteNetworkQosPolicy(command.Command):
- """Delete Qos Policy(s)"""
+ _description = _("Delete Qos Policy(s)")
def get_parser(self, prog_name):
parser = super(DeleteNetworkQosPolicy, self).get_parser(prog_name)
@@ -135,16 +138,18 @@ class DeleteNetworkQosPolicy(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 ListNetworkQosPolicy(command.Lister):
- """List QoS policies"""
+ _description = _("List QoS policies")
def take_action(self, parsed_args):
client = self.app.client_manager.network
columns = (
'id',
'name',
- 'shared',
- 'tenant_id',
+ 'is_shared',
+ 'project_id',
)
column_headers = (
'ID',
@@ -160,8 +165,10 @@ class ListNetworkQosPolicy(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 SetNetworkQosPolicy(command.Command):
- """Set QoS policy properties"""
+ _description = _("Set QoS policy properties")
def get_parser(self, prog_name):
parser = super(SetNetworkQosPolicy, self).get_parser(prog_name)
@@ -211,7 +218,7 @@ class SetNetworkQosPolicy(command.Command):
class ShowNetworkQosPolicy(command.ShowOne):
- """Display QoS policy details"""
+ _description = _("Display QoS policy details")
def get_parser(self, prog_name):
parser = super(ShowNetworkQosPolicy, self).get_parser(prog_name)
@@ -226,6 +233,6 @@ class ShowNetworkQosPolicy(command.ShowOne):
client = self.app.client_manager.network
obj = client.find_qos_policy(parsed_args.policy,
ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return columns, data
+ return (display_columns, data)
diff --git a/openstackclient/network/v2/network_rbac.py b/openstackclient/network/v2/network_rbac.py
index bb29579f..e837af3a 100644
--- a/openstackclient/network/v2/network_rbac.py
+++ b/openstackclient/network/v2/network_rbac.py
@@ -21,20 +21,18 @@ 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__)
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
- if 'target_tenant' in columns:
- columns.remove('target_tenant')
- columns.append('target_project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'target_tenant': 'target_project_id',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_attrs(client_manager, parsed_args):
@@ -47,9 +45,9 @@ def _get_attrs(client_manager, parsed_args):
object_id = network_client.find_network(
parsed_args.rbac_object, ignore_missing=False).id
if parsed_args.type == 'qos_policy':
- # TODO(Huanxuan Ao): Support finding a object ID by obejct name
- # after qos policy finding supported in SDK.
- object_id = parsed_args.rbac_object
+ object_id = network_client.find_qos_policy(
+ parsed_args.rbac_object,
+ ignore_missing=False).id
attrs['object_id'] = object_id
identity_client = client_manager.identity
@@ -70,16 +68,17 @@ def _get_attrs(client_manager, parsed_args):
return attrs
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateNetworkRBAC(command.ShowOne):
- """Create network RBAC policy"""
+ _description = _("Create network RBAC policy")
def get_parser(self, prog_name):
parser = super(CreateNetworkRBAC, self).get_parser(prog_name)
parser.add_argument(
'rbac_object',
metavar="<rbac-object>",
- help=_("The object to which this RBAC policy affects (name or "
- "ID for network objects, ID only for QoS policy objects)")
+ help=_("The object to which this RBAC policy affects (name or ID)")
)
parser.add_argument(
'--type',
@@ -123,13 +122,13 @@ class CreateNetworkRBAC(command.ShowOne):
client = self.app.client_manager.network
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_rbac_policy(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return columns, data
+ return display_columns, data
class DeleteNetworkRBAC(command.Command):
- """Delete network RBAC policy(s)"""
+ _description = _("Delete network RBAC policy(s)")
def get_parser(self, prog_name):
parser = super(DeleteNetworkRBAC, self).get_parser(prog_name)
@@ -163,7 +162,7 @@ class DeleteNetworkRBAC(command.Command):
class ListNetworkRBAC(command.Lister):
- """List network RBAC policies"""
+ _description = _("List network RBAC policies")
def take_action(self, parsed_args):
client = self.app.client_manager.network
@@ -186,8 +185,10 @@ class ListNetworkRBAC(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 SetNetworkRBAC(command.Command):
- """Set network RBAC policy properties"""
+ _description = _("Set network RBAC policy properties")
def get_parser(self, prog_name):
parser = super(SetNetworkRBAC, self).get_parser(prog_name)
@@ -228,7 +229,7 @@ class SetNetworkRBAC(command.Command):
class ShowNetworkRBAC(command.ShowOne):
- """Display network RBAC policy details"""
+ _description = _("Display network RBAC policy details")
def get_parser(self, prog_name):
parser = super(ShowNetworkRBAC, self).get_parser(prog_name)
@@ -243,6 +244,6 @@ class ShowNetworkRBAC(command.ShowOne):
client = self.app.client_manager.network
obj = client.find_rbac_policy(parsed_args.rbac_policy,
ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return columns, data
+ return display_columns, data
diff --git a/openstackclient/network/v2/network_segment.py b/openstackclient/network/v2/network_segment.py
index 94722f1e..709dc296 100644
--- a/openstackclient/network/v2/network_segment.py
+++ b/openstackclient/network/v2/network_segment.py
@@ -20,13 +20,18 @@ from osc_lib import exceptions
from osc_lib import utils
from openstackclient.i18n import _
+from openstackclient.network import sdk_utils
LOG = logging.getLogger(__name__)
+def _get_columns(item):
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, {})
+
+
class CreateNetworkSegment(command.ShowOne):
- """Create new network segment"""
+ _description = _("Create new network segment")
def get_parser(self, prog_name):
parser = super(CreateNetworkSegment, self).get_parser(prog_name)
@@ -84,13 +89,13 @@ class CreateNetworkSegment(command.ShowOne):
if parsed_args.segment is not None:
attrs['segmentation_id'] = parsed_args.segment
obj = client.create_segment(**attrs)
- columns = tuple(sorted(obj.keys()))
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
class DeleteNetworkSegment(command.Command):
- """Delete network segment(s)"""
+ _description = _("Delete network segment(s)")
def get_parser(self, prog_name):
parser = super(DeleteNetworkSegment, self).get_parser(prog_name)
@@ -125,7 +130,7 @@ class DeleteNetworkSegment(command.Command):
class ListNetworkSegment(command.Lister):
- """List network segments"""
+ _description = _("List network segments")
def get_parser(self, prog_name):
parser = super(ListNetworkSegment, self).get_parser(prog_name)
@@ -185,7 +190,7 @@ class ListNetworkSegment(command.Lister):
class SetNetworkSegment(command.Command):
- """Set network segment properties"""
+ _description = _("Set network segment properties")
def get_parser(self, prog_name):
parser = super(SetNetworkSegment, self).get_parser(prog_name)
@@ -219,7 +224,7 @@ class SetNetworkSegment(command.Command):
class ShowNetworkSegment(command.ShowOne):
- """Display network segment details"""
+ _description = _("Display network segment details")
def get_parser(self, prog_name):
parser = super(ShowNetworkSegment, self).get_parser(prog_name)
@@ -236,6 +241,6 @@ class ShowNetworkSegment(command.ShowOne):
parsed_args.network_segment,
ignore_missing=False
)
- columns = tuple(sorted(obj.keys()))
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
diff --git a/openstackclient/network/v2/network_service_provider.py b/openstackclient/network/v2/network_service_provider.py
new file mode 100644
index 00000000..3aa33c23
--- /dev/null
+++ b/openstackclient/network/v2/network_service_provider.py
@@ -0,0 +1,41 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+"""Network Service Providers Implementation"""
+
+from osc_lib.command import command
+from osc_lib import utils
+
+
+class ListNetworkServiceProvider(command.Lister):
+ """List Service Providers"""
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+
+ columns = (
+ 'service_type',
+ 'name',
+ 'is_default',
+ )
+ column_headers = (
+ 'Service Type',
+ 'Name',
+ 'Default',
+ )
+
+ data = client.service_providers()
+ return(column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ ) for s in data))
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index 86174d53..6cae87ee 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -109,6 +109,8 @@ def _get_attrs(client_manager, parsed_args):
'The --host-id option is deprecated, '
'please use --host instead.'
))
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
if parsed_args.fixed_ip is not None:
attrs['fixed_ips'] = parsed_args.fixed_ip
if parsed_args.device:
@@ -146,6 +148,12 @@ def _get_attrs(client_manager, parsed_args):
).id
attrs['tenant_id'] = project_id
+ if parsed_args.disable_port_security:
+ attrs['port_security_enabled'] = False
+
+ if parsed_args.enable_port_security:
+ attrs['port_security_enabled'] = True
+
return attrs
@@ -180,50 +188,55 @@ def _prepare_fixed_ips(client_manager, parsed_args):
def _add_updatable_args(parser):
- # NOTE(dtroyer): --device-id is deprecated in Mar 2016. Do not
- # remove before 3.x release or Mar 2017.
- device_group = parser.add_mutually_exclusive_group()
- device_group.add_argument(
- '--device',
- metavar='<device-id>',
- help=_("Port device ID")
- )
- device_group.add_argument(
- '--device-id',
- metavar='<device-id>',
- help=argparse.SUPPRESS,
- )
- parser.add_argument(
- '--device-owner',
- metavar='<device-owner>',
- help=_("Device owner of this port. This is the entity that uses "
- "the port (for example, network:dhcp).")
- )
- parser.add_argument(
- '--vnic-type',
- metavar='<vnic-type>',
- choices=['direct', 'direct-physical', 'macvtap',
- 'normal', 'baremetal'],
- help=_("VNIC type for this port (direct | direct-physical | "
- "macvtap | normal | baremetal, default: normal)")
- )
- # NOTE(dtroyer): --host-id is deprecated in Mar 2016. Do not
- # remove before 3.x release or Mar 2017.
- host_group = parser.add_mutually_exclusive_group()
- host_group.add_argument(
- '--host',
- metavar='<host-id>',
- help=_("Allocate port on host <host-id> (ID only)")
- )
- host_group.add_argument(
- '--host-id',
- metavar='<host-id>',
- help=argparse.SUPPRESS,
- )
+ parser.add_argument(
+ '--description',
+ metavar='<description>',
+ help=_("Description of this port")
+ )
+ # NOTE(dtroyer): --device-id is deprecated in Mar 2016. Do not
+ # remove before 3.x release or Mar 2017.
+ device_group = parser.add_mutually_exclusive_group()
+ device_group.add_argument(
+ '--device',
+ metavar='<device-id>',
+ help=_("Port device ID")
+ )
+ device_group.add_argument(
+ '--device-id',
+ metavar='<device-id>',
+ help=argparse.SUPPRESS,
+ )
+ parser.add_argument(
+ '--device-owner',
+ metavar='<device-owner>',
+ help=_("Device owner of this port. This is the entity that uses "
+ "the port (for example, network:dhcp).")
+ )
+ parser.add_argument(
+ '--vnic-type',
+ metavar='<vnic-type>',
+ choices=['direct', 'direct-physical', 'macvtap',
+ 'normal', 'baremetal'],
+ help=_("VNIC type for this port (direct | direct-physical | "
+ "macvtap | normal | baremetal, default: normal)")
+ )
+ # NOTE(dtroyer): --host-id is deprecated in Mar 2016. Do not
+ # remove before 3.x release or Mar 2017.
+ host_group = parser.add_mutually_exclusive_group()
+ host_group.add_argument(
+ '--host',
+ metavar='<host-id>',
+ help=_("Allocate port on host <host-id> (ID only)")
+ )
+ host_group.add_argument(
+ '--host-id',
+ metavar='<host-id>',
+ help=argparse.SUPPRESS,
+ )
class CreatePort(command.ShowOne):
- """Create a new port"""
+ _description = _("Create a new port")
def get_parser(self, prog_name):
parser = super(CreatePort, self).get_parser(prog_name)
@@ -297,6 +310,17 @@ class CreatePort(command.ShowOne):
action='store_true',
help=_("Associate no security groups with this port")
)
+ port_security = parser.add_mutually_exclusive_group()
+ port_security.add_argument(
+ '--enable-port-security',
+ action='store_true',
+ help=_("Enable port security for this port (Default)")
+ )
+ port_security.add_argument(
+ '--disable-port-security',
+ action='store_true',
+ help=_("Disable port security for this port")
+ )
return parser
@@ -323,7 +347,7 @@ class CreatePort(command.ShowOne):
class DeletePort(command.Command):
- """Delete port(s)"""
+ _description = _("Delete port(s)")
def get_parser(self, prog_name):
parser = super(DeletePort, self).get_parser(prog_name)
@@ -357,7 +381,7 @@ class DeletePort(command.Command):
class ListPort(command.Lister):
- """List ports"""
+ _description = _("List ports")
def get_parser(self, prog_name):
parser = super(ListPort, self).get_parser(prog_name)
@@ -385,6 +409,11 @@ class ListPort(command.Lister):
help=_("List only ports attached to this server (name or ID)"),
)
parser.add_argument(
+ '--mac-address',
+ metavar='<mac-address>',
+ help=_("List only ports with this MAC address")
+ )
+ parser.add_argument(
'--long',
action='store_true',
default=False,
@@ -429,6 +458,8 @@ class ListPort(command.Lister):
network = network_client.find_network(parsed_args.network,
ignore_missing=False)
filters['network_id'] = network.id
+ if parsed_args.mac_address:
+ filters['mac_address'] = parsed_args.mac_address
data = network_client.ports(**filters)
@@ -440,7 +471,7 @@ class ListPort(command.Lister):
class SetPort(command.Command):
- """Set port properties"""
+ _description = _("Set port properties")
def get_parser(self, prog_name):
parser = super(SetPort, self).get_parser(prog_name)
@@ -512,6 +543,17 @@ class SetPort(command.Command):
action='store_true',
help=_("Clear existing security groups associated with this port")
)
+ port_security = parser.add_mutually_exclusive_group()
+ port_security.add_argument(
+ '--enable-port-security',
+ action='store_true',
+ help=_("Enable port security for this port")
+ )
+ port_security.add_argument(
+ '--disable-port-security',
+ action='store_true',
+ help=_("Disable port security for this port")
+ )
return parser
@@ -556,7 +598,7 @@ class SetPort(command.Command):
class ShowPort(command.ShowOne):
- """Display port details"""
+ _description = _("Display port details")
def get_parser(self, prog_name):
parser = super(ShowPort, self).get_parser(prog_name)
@@ -576,7 +618,7 @@ class ShowPort(command.ShowOne):
class UnsetPort(command.Command):
- """Unset port properties"""
+ _description = _("Unset port properties")
def get_parser(self, prog_name):
parser = super(UnsetPort, self).get_parser(prog_name)
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index d96c314a..cbd412b5 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -100,7 +100,7 @@ def _get_attrs(client_manager, parsed_args):
class AddPortToRouter(command.Command):
- """Add a port to a router"""
+ _description = _("Add a port to a router")
def get_parser(self, prog_name):
parser = super(AddPortToRouter, self).get_parser(prog_name)
@@ -124,7 +124,7 @@ class AddPortToRouter(command.Command):
class AddSubnetToRouter(command.Command):
- """Add a subnet to a router"""
+ _description = _("Add a subnet to a router")
def get_parser(self, prog_name):
parser = super(AddSubnetToRouter, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class AddSubnetToRouter(command.Command):
class CreateRouter(command.ShowOne):
- """Create a new router"""
+ _description = _("Create a new router")
def get_parser(self, prog_name):
parser = super(CreateRouter, self).get_parser(prog_name)
@@ -222,7 +222,7 @@ class CreateRouter(command.ShowOne):
class DeleteRouter(command.Command):
- """Delete router(s)"""
+ _description = _("Delete router(s)")
def get_parser(self, prog_name):
parser = super(DeleteRouter, self).get_parser(prog_name)
@@ -256,7 +256,7 @@ class DeleteRouter(command.Command):
class ListRouter(command.Lister):
- """List routers"""
+ _description = _("List routers")
def get_parser(self, prog_name):
parser = super(ListRouter, self).get_parser(prog_name)
@@ -344,7 +344,7 @@ class ListRouter(command.Lister):
class RemovePortFromRouter(command.Command):
- """Remove a port from a router"""
+ _description = _("Remove a port from a router")
def get_parser(self, prog_name):
parser = super(RemovePortFromRouter, self).get_parser(prog_name)
@@ -368,7 +368,7 @@ class RemovePortFromRouter(command.Command):
class RemoveSubnetFromRouter(command.Command):
- """Remove a subnet from a router"""
+ _description = _("Remove a subnet from a router")
def get_parser(self, prog_name):
parser = super(RemoveSubnetFromRouter, self).get_parser(prog_name)
@@ -395,7 +395,7 @@ class RemoveSubnetFromRouter(command.Command):
class SetRouter(command.Command):
- """Set router properties"""
+ _description = _("Set router properties")
def get_parser(self, prog_name):
parser = super(SetRouter, self).get_parser(prog_name)
@@ -509,7 +509,7 @@ class SetRouter(command.Command):
class ShowRouter(command.ShowOne):
- """Display router details"""
+ _description = _("Display router details")
def get_parser(self, prog_name):
parser = super(ShowRouter, self).get_parser(prog_name)
@@ -529,7 +529,7 @@ class ShowRouter(command.ShowOne):
class UnsetRouter(command.Command):
- """Unset router properties"""
+ _description = _("Unset router properties")
def get_parser(self, prog_name):
parser = super(UnsetRouter, self).get_parser(prog_name)
diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py
index f832f721..554dd61d 100644
--- a/openstackclient/network/v2/security_group.py
+++ b/openstackclient/network/v2/security_group.py
@@ -95,7 +95,7 @@ def _get_columns(item):
class CreateSecurityGroup(common.NetworkAndComputeShowOne):
- """Create a new security group"""
+ _description = _("Create a new security group")
def update_parser_common(self, parser):
parser.add_argument(
@@ -165,7 +165,7 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne):
class DeleteSecurityGroup(common.NetworkAndComputeDelete):
- """Delete security group(s)"""
+ _description = _("Delete security group(s)")
# Used by base class to find resources in parsed_args.
resource = 'group'
@@ -190,7 +190,7 @@ class DeleteSecurityGroup(common.NetworkAndComputeDelete):
class ListSecurityGroup(common.NetworkAndComputeLister):
- """List security groups"""
+ _description = _("List security groups")
def update_parser_network(self, parser):
# Maintain and hide the argument for backwards compatibility.
@@ -238,7 +238,7 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
class SetSecurityGroup(common.NetworkAndComputeCommand):
- """Set security group properties"""
+ _description = _("Set security group properties")
def update_parser_common(self, parser):
parser.add_argument(
@@ -293,7 +293,7 @@ class SetSecurityGroup(common.NetworkAndComputeCommand):
class ShowSecurityGroup(common.NetworkAndComputeShowOne):
- """Display security group details"""
+ _description = _("Display security group details")
def update_parser_common(self, parser):
parser.add_argument(
diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py
index e3be44ec..b878d875 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -14,6 +14,7 @@
"""Security Group Rule action implementations"""
import argparse
+import logging
try:
from novaclient.v2 import security_group_rules as compute_secgroup_rules
@@ -28,9 +29,13 @@ import six
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
+from openstackclient.network import sdk_utils
from openstackclient.network import utils as network_utils
+LOG = logging.getLogger(__name__)
+
+
def _format_security_group_rule_show(obj):
data = network_utils.transform_compute_security_group_rule(obj)
return zip(*sorted(six.iteritems(data)))
@@ -63,11 +68,10 @@ def _format_network_port_range(rule):
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _convert_to_lowercase(string):
@@ -85,8 +89,10 @@ def _is_icmp_protocol(protocol):
return False
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
- """Create a new security group rule"""
+ _description = _("Create a new security group rule")
def update_parser_common(self, parser):
parser.add_argument(
@@ -94,22 +100,40 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
metavar='<group>',
help=_("Create rule in this security group (name or ID)")
)
- source_group = parser.add_mutually_exclusive_group()
- source_group.add_argument(
+ remote_group = parser.add_mutually_exclusive_group()
+ remote_group.add_argument(
+ "--remote-ip",
+ metavar="<ip-address>",
+ help=_("Remote IP address block (may use CIDR notation; "
+ "default for IPv4 rule: 0.0.0.0/0)"),
+ )
+ remote_group.add_argument(
+ "--remote-group",
+ metavar="<group>",
+ help=_("Remote security group (name or ID)"),
+ )
+ # Handle deprecated options
+ # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016.
+ # Do not remove before 4.x release or Nov 2017.
+ remote_group.add_argument(
"--src-ip",
metavar="<ip-address>",
- help=_("Source IP address block (may use CIDR notation; "
- "default for IPv4 rule: 0.0.0.0/0)")
+ help=argparse.SUPPRESS,
)
- source_group.add_argument(
+ remote_group.add_argument(
"--src-group",
metavar="<group>",
- help=_("Source security group (name or ID)")
+ help=argparse.SUPPRESS,
)
return parser
def update_parser_network(self, parser):
parser.add_argument(
+ '--description',
+ metavar='<description>',
+ help=_("Set security group rule description")
+ )
+ parser.add_argument(
'--dst-port',
metavar='<port-range>',
action=parseractions.RangeAction,
@@ -235,6 +259,9 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
attrs = {}
attrs['protocol'] = self._get_protocol(parsed_args)
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+
# NOTE(rtheis): A direction must be specified and ingress
# is the default.
if parsed_args.ingress or not parsed_args.egress:
@@ -277,13 +304,31 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
if parsed_args.icmp_code:
attrs['port_range_max'] = parsed_args.icmp_code
- if parsed_args.src_group is not None:
+ # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016.
+ # Do not remove before 4.x release or Nov 2017.
+ if not (parsed_args.remote_group is None and
+ parsed_args.src_group is None):
attrs['remote_group_id'] = client.find_security_group(
- parsed_args.src_group,
+ parsed_args.remote_group or parsed_args.src_group,
ignore_missing=False
).id
- elif parsed_args.src_ip is not None:
- attrs['remote_ip_prefix'] = parsed_args.src_ip
+ if parsed_args.src_group:
+ LOG.warning(
+ _("The %(old)s option is deprecated, "
+ "please use %(new)s instead.") %
+ {'old': '--src-group', 'new': '--remote-group'},
+ )
+ elif not (parsed_args.remote_ip is None and
+ parsed_args.src_ip is None):
+ attrs['remote_ip_prefix'] = (
+ parsed_args.remote_ip or parsed_args.src_ip
+ )
+ if parsed_args.src_ip:
+ LOG.warning(
+ _("The %(old)s option is deprecated, "
+ "please use %(new)s instead.") %
+ {'old': '--src-ip', 'new': '--remote-ip'},
+ )
elif attrs['ethertype'] == 'IPv4':
attrs['remote_ip_prefix'] = '0.0.0.0/0'
attrs['security_group_id'] = security_group_id
@@ -298,9 +343,9 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
# Create and show the security group rule.
obj = client.create_security_group_rule(**attrs)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
group = utils.find_resource(
@@ -312,29 +357,46 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
from_port, to_port = -1, -1
else:
from_port, to_port = parsed_args.dst_port
- src_ip = None
- if parsed_args.src_group is not None:
- parsed_args.src_group = utils.find_resource(
+
+ # NOTE(dtroyer): --src-ip and --src-group were deprecated in Nov 2016.
+ # Do not remove before 4.x release or Nov 2017.
+ remote_ip = None
+ if not (parsed_args.remote_group is None and
+ parsed_args.src_group is None):
+ parsed_args.remote_group = utils.find_resource(
client.security_groups,
- parsed_args.src_group,
+ parsed_args.remote_group or parsed_args.src_group,
).id
- if parsed_args.src_ip is not None:
- src_ip = parsed_args.src_ip
+ if parsed_args.src_group:
+ LOG.warning(
+ _("The %(old)s option is deprecated, "
+ "please use %(new)s instead.") %
+ {'old': '--src-group', 'new': '--remote-group'},
+ )
+ if not (parsed_args.remote_ip is None and
+ parsed_args.src_ip is None):
+ remote_ip = parsed_args.remote_ip or parsed_args.src_ip
+ if parsed_args.src_ip:
+ LOG.warning(
+ _("The %(old)s option is deprecated, "
+ "please use %(new)s instead.") %
+ {'old': '--src-ip', 'new': '--remote-ip'},
+ )
else:
- src_ip = '0.0.0.0/0'
+ remote_ip = '0.0.0.0/0'
obj = client.security_group_rules.create(
group.id,
protocol,
from_port,
to_port,
- src_ip,
- parsed_args.src_group,
+ remote_ip,
+ parsed_args.remote_group,
)
return _format_security_group_rule_show(obj._info)
class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
- """Delete security group rule(s)"""
+ _description = _("Delete security group rule(s)")
# Used by base class to find resources in parsed_args.
resource = 'rule'
@@ -359,7 +421,7 @@ class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
class ListSecurityGroupRule(common.NetworkAndComputeLister):
- """List security group rules"""
+ _description = _("List security group rules")
def update_parser_common(self, parser):
parser.add_argument(
@@ -380,6 +442,28 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
help=argparse.SUPPRESS
)
parser.add_argument(
+ '--protocol',
+ metavar='<protocol>',
+ type=_convert_to_lowercase,
+ help=_("List rules by the IP protocol ("
+ "ah, dhcp, egp, esp, gre, icmp, igmp, "
+ "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, "
+ "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, "
+ "udp, udplite, vrrp and integer representations [0-255])."
+ )
+ )
+ direction_group = parser.add_mutually_exclusive_group()
+ direction_group.add_argument(
+ '--ingress',
+ action='store_true',
+ help=_("List rules applied to incoming network traffic")
+ )
+ direction_group.add_argument(
+ '--egress',
+ action='store_true',
+ help=_("List rules applied to outgoing network traffic")
+ )
+ parser.add_argument(
'--long',
action='store_true',
default=False,
@@ -443,6 +527,14 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
query = {'security_group_id': security_group_id}
else:
columns = columns + ('security_group_id',)
+
+ if parsed_args.ingress:
+ query['direction'] = 'ingress'
+ if parsed_args.egress:
+ query['direction'] = 'egress'
+ if parsed_args.protocol is not None:
+ query['protocol'] = parsed_args.protocol
+
rules = list(client.security_group_rules(**query))
# Reformat the rules to display a port range instead
@@ -494,7 +586,7 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
- """Display security group rule details"""
+ _description = _("Display security group rule details")
def update_parser_common(self, parser):
parser.add_argument(
@@ -507,9 +599,9 @@ class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
def take_action_network(self, client, parsed_args):
obj = client.find_security_group_rule(parsed_args.rule,
ignore_missing=False)
- columns = _get_columns(obj)
+ display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
- return (columns, data)
+ return (display_columns, data)
def take_action_compute(self, client, parsed_args):
# NOTE(rtheis): Unfortunately, compute does not have an API
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index f1ecb5a7..292b7c06 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -23,6 +23,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__)
@@ -84,6 +85,15 @@ def _get_common_parse_arguments(parser, is_create=True):
help=_("DNS server for this subnet "
"(repeat option to set multiple DNS servers)")
)
+
+ if not is_create:
+ parser.add_argument(
+ '--no-dns-nameservers',
+ action='store_true',
+ help=_("Clear existing information of DNS Nameservers. "
+ "Specify both --dns-nameserver and --no-dns-nameserver "
+ "to overwrite the current DNS Nameserver information.")
+ )
parser.add_argument(
'--host-route',
metavar='destination=<subnet>,gateway=<ip-address>',
@@ -117,11 +127,12 @@ def _get_common_parse_arguments(parser, is_create=True):
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'is_dhcp_enabled': 'enable_dhcp',
+ 'subnet_pool_id': 'subnetpool_id',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def convert_entries_to_nexthop(entries):
@@ -217,8 +228,10 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
return attrs
+# TODO(abhiraut): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateSubnet(command.ShowOne):
- """Create a subnet"""
+ _description = _("Create a subnet")
def get_parser(self, prog_name):
parser = super(CreateSubnet, self).get_parser(prog_name)
@@ -323,13 +336,13 @@ class CreateSubnet(command.ShowOne):
client = self.app.client_manager.network
attrs = _get_attrs(self.app.client_manager, parsed_args)
obj = client.create_subnet(**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 DeleteSubnet(command.Command):
- """Delete subnet(s)"""
+ _description = _("Delete subnet(s)")
def get_parser(self, prog_name):
parser = super(DeleteSubnet, self).get_parser(prog_name)
@@ -362,8 +375,10 @@ class DeleteSubnet(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 ListSubnet(command.Lister):
- """List subnets"""
+ _description = _("List subnets")
def get_parser(self, prog_name):
parser = super(ListSubnet, self).get_parser(prog_name)
@@ -443,8 +458,10 @@ class ListSubnet(command.Lister):
filters['ip_version'] = parsed_args.ip_version
if parsed_args.dhcp:
filters['enable_dhcp'] = True
+ filters['is_dhcp_enabled'] = True
elif parsed_args.no_dhcp:
filters['enable_dhcp'] = False
+ filters['is_dhcp_enabled'] = False
if parsed_args.service_types:
filters['service_types'] = parsed_args.service_types
if parsed_args.project:
@@ -454,6 +471,7 @@ class ListSubnet(command.Lister):
parsed_args.project_domain,
).id
filters['tenant_id'] = project_id
+ filters['project_id'] = project_id
if parsed_args.network:
network_id = network_client.find_network(parsed_args.network,
ignore_missing=False).id
@@ -472,7 +490,7 @@ class ListSubnet(command.Lister):
headers += ('Project', 'DHCP', 'Name Servers',
'Allocation Pools', 'Host Routes', 'IP Version',
'Gateway', 'Service Types')
- columns += ('tenant_id', 'enable_dhcp', 'dns_nameservers',
+ columns += ('project_id', 'is_dhcp_enabled', 'dns_nameservers',
'allocation_pools', 'host_routes', 'ip_version',
'gateway_ip', 'service_types')
@@ -483,8 +501,10 @@ class ListSubnet(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 SetSubnet(command.Command):
- """Set subnet properties"""
+ _description = _("Set subnet properties")
def get_parser(self, prog_name):
parser = super(SetSubnet, self).get_parser(prog_name)
@@ -532,7 +552,10 @@ class SetSubnet(command.Command):
attrs = _get_attrs(self.app.client_manager, parsed_args,
is_create=False)
if 'dns_nameservers' in attrs:
- attrs['dns_nameservers'] += obj.dns_nameservers
+ if not parsed_args.no_dns_nameservers:
+ attrs['dns_nameservers'] += obj.dns_nameservers
+ elif parsed_args.no_dns_nameservers:
+ attrs['dns_nameservers'] = []
if 'host_routes' in attrs:
if not parsed_args.no_host_route:
attrs['host_routes'] += obj.host_routes
@@ -550,7 +573,7 @@ class SetSubnet(command.Command):
class ShowSubnet(command.ShowOne):
- """Display subnet details"""
+ _description = _("Display subnet details")
def get_parser(self, prog_name):
parser = super(ShowSubnet, self).get_parser(prog_name)
@@ -564,13 +587,13 @@ class ShowSubnet(command.ShowOne):
def take_action(self, parsed_args):
obj = self.app.client_manager.network.find_subnet(parsed_args.subnet,
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)
class UnsetSubnet(command.Command):
- """Unset subnet properties"""
+ _description = _("Unset subnet properties")
def get_parser(self, prog_name):
parser = super(UnsetSubnet, self).get_parser(prog_name)
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index a29c4518..a5a24424 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -12,6 +12,7 @@
#
"""Subnet pool action implementations"""
+
import copy
import logging
@@ -22,17 +23,21 @@ 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__)
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- columns.append('project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'default_prefix_length': 'default_prefixlen',
+ 'is_shared': 'shared',
+ 'maximum_prefix_length': 'max_prefixlen',
+ 'minimum_prefix_length': 'min_prefixlen',
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
_formatters = {
@@ -134,8 +139,10 @@ def _add_default_options(parser):
)
+# TODO(rtheis): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class CreateSubnetPool(command.ShowOne):
- """Create subnet pool"""
+ _description = _("Create subnet pool")
def get_parser(self, prog_name):
parser = super(CreateSubnetPool, self).get_parser(prog_name)
@@ -184,13 +191,13 @@ class CreateSubnetPool(command.ShowOne):
if "prefixes" not in attrs:
attrs['prefixes'] = []
obj = client.create_subnet_pool(**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 DeleteSubnetPool(command.Command):
- """Delete subnet pool(s)"""
+ _description = _("Delete subnet pool(s)")
def get_parser(self, prog_name):
parser = super(DeleteSubnetPool, self).get_parser(prog_name)
@@ -223,8 +230,10 @@ class DeleteSubnetPool(command.Command):
raise exceptions.CommandError(msg)
+# TODO(rtheis): Use only the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class ListSubnetPool(command.Lister):
- """List subnet pools"""
+ _description = _("List subnet pools")
def get_parser(self, prog_name):
parser = super(ListSubnetPool, self).get_parser(prog_name)
@@ -283,8 +292,10 @@ class ListSubnetPool(command.Lister):
filters = {}
if parsed_args.share:
filters['shared'] = True
+ filters['is_shared'] = True
elif parsed_args.no_share:
filters['shared'] = False
+ filters['is_shared'] = False
if parsed_args.default:
filters['is_default'] = True
elif parsed_args.no_default:
@@ -296,6 +307,7 @@ class ListSubnetPool(command.Lister):
parsed_args.project_domain,
).id
filters['tenant_id'] = project_id
+ filters['project_id'] = project_id
if parsed_args.name is not None:
filters['name'] = parsed_args.name
if parsed_args.address_scope:
@@ -310,8 +322,8 @@ class ListSubnetPool(command.Lister):
if parsed_args.long:
headers += ('Default Prefix Length', 'Address Scope',
'Default Subnet Pool', 'Shared')
- columns += ('default_prefixlen', 'address_scope_id',
- 'is_default', 'shared')
+ columns += ('default_prefix_length', 'address_scope_id',
+ 'is_default', 'is_shared')
return (headers,
(utils.get_item_properties(
@@ -320,8 +332,10 @@ class ListSubnetPool(command.Lister):
) for s in data))
+# TODO(rtheis): Use the SDK resource mapped attribute names once the
+# OSC minimum requirements include SDK 1.0.
class SetSubnetPool(command.Command):
- """Set subnet pool properties"""
+ _description = _("Set subnet pool properties")
def get_parser(self, prog_name):
parser = super(SetSubnetPool, self).get_parser(prog_name)
@@ -373,7 +387,7 @@ class SetSubnetPool(command.Command):
class ShowSubnetPool(command.ShowOne):
- """Display subnet pool details"""
+ _description = _("Display subnet pool details")
def get_parser(self, prog_name):
parser = super(ShowSubnetPool, self).get_parser(prog_name)
@@ -390,13 +404,13 @@ class ShowSubnetPool(command.ShowOne):
parsed_args.subnet_pool,
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)
class UnsetSubnetPool(command.Command):
- """Unset subnet pool properties"""
+ _description = _("Unset subnet pool properties")
def get_parser(self, prog_name):
parser = super(UnsetSubnetPool, self).get_parser(prog_name)
diff --git a/openstackclient/object/v1/account.py b/openstackclient/object/v1/account.py
index 2fe00ecb..4847f8bb 100644
--- a/openstackclient/object/v1/account.py
+++ b/openstackclient/object/v1/account.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class SetAccount(command.Command):
- """Set account properties"""
+ _description = _("Set account properties")
def get_parser(self, prog_name):
parser = super(SetAccount, self).get_parser(prog_name)
@@ -43,7 +43,7 @@ class SetAccount(command.Command):
class ShowAccount(command.ShowOne):
- """Display account details"""
+ _description = _("Display account details")
def take_action(self, parsed_args):
data = self.app.client_manager.object_store.account_show()
@@ -53,7 +53,7 @@ class ShowAccount(command.ShowOne):
class UnsetAccount(command.Command):
- """Unset account properties"""
+ _description = _("Unset account properties")
def get_parser(self, prog_name):
parser = super(UnsetAccount, self).get_parser(prog_name)
diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py
index 01964d0c..88fb8602 100644
--- a/openstackclient/object/v1/container.py
+++ b/openstackclient/object/v1/container.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger(__name__)
class CreateContainer(command.Lister):
- """Create new container"""
+ _description = _("Create new container")
def get_parser(self, prog_name):
parser = super(CreateContainer, self).get_parser(prog_name)
@@ -63,7 +63,7 @@ class CreateContainer(command.Lister):
class DeleteContainer(command.Command):
- """Delete container"""
+ _description = _("Delete container")
def get_parser(self, prog_name):
parser = super(DeleteContainer, self).get_parser(prog_name)
@@ -98,7 +98,7 @@ class DeleteContainer(command.Command):
class ListContainer(command.Lister):
- """List containers"""
+ _description = _("List containers")
def get_parser(self, prog_name):
parser = super(ListContainer, self).get_parser(prog_name)
@@ -168,7 +168,7 @@ class ListContainer(command.Lister):
class SaveContainer(command.Command):
- """Save container contents locally"""
+ _description = _("Save container contents locally")
def get_parser(self, prog_name):
parser = super(SaveContainer, self).get_parser(prog_name)
@@ -186,7 +186,7 @@ class SaveContainer(command.Command):
class SetContainer(command.Command):
- """Set container properties"""
+ _description = _("Set container properties")
def get_parser(self, prog_name):
parser = super(SetContainer, self).get_parser(prog_name)
@@ -213,7 +213,7 @@ class SetContainer(command.Command):
class ShowContainer(command.ShowOne):
- """Display container details"""
+ _description = _("Display container details")
def get_parser(self, prog_name):
parser = super(ShowContainer, self).get_parser(prog_name)
@@ -236,7 +236,7 @@ class ShowContainer(command.ShowOne):
class UnsetContainer(command.Command):
- """Unset container properties"""
+ _description = _("Unset container properties")
def get_parser(self, prog_name):
parser = super(UnsetContainer, self).get_parser(prog_name)
diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py
index 3c47ee04..71b6f520 100644
--- a/openstackclient/object/v1/object.py
+++ b/openstackclient/object/v1/object.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateObject(command.Lister):
- """Upload object to container"""
+ _description = _("Upload object to container")
def get_parser(self, prog_name):
parser = super(CreateObject, self).get_parser(prog_name)
@@ -81,7 +81,7 @@ class CreateObject(command.Lister):
class DeleteObject(command.Command):
- """Delete object from container"""
+ _description = _("Delete object from container")
def get_parser(self, prog_name):
parser = super(DeleteObject, self).get_parser(prog_name)
@@ -108,7 +108,7 @@ class DeleteObject(command.Command):
class ListObject(command.Lister):
- """List objects"""
+ _description = _("List objects")
def get_parser(self, prog_name):
parser = super(ListObject, self).get_parser(prog_name)
@@ -197,7 +197,7 @@ class ListObject(command.Lister):
class SaveObject(command.Command):
- """Save object locally"""
+ _description = _("Save object locally")
def get_parser(self, prog_name):
parser = super(SaveObject, self).get_parser(prog_name)
@@ -227,7 +227,7 @@ class SaveObject(command.Command):
class SetObject(command.Command):
- """Set object properties"""
+ _description = _("Set object properties")
def get_parser(self, prog_name):
parser = super(SetObject, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class SetObject(command.Command):
class ShowObject(command.ShowOne):
- """Display object details"""
+ _description = _("Display object details")
def get_parser(self, prog_name):
parser = super(ShowObject, self).get_parser(prog_name)
@@ -289,7 +289,7 @@ class ShowObject(command.ShowOne):
class UnsetObject(command.Command):
- """Unset object properties"""
+ _description = _("Unset object properties")
def get_parser(self, prog_name):
parser = super(UnsetObject, self).get_parser(prog_name)
diff --git a/openstackclient/shell.py b/openstackclient/shell.py
index be4b5283..e08eee61 100644
--- a/openstackclient/shell.py
+++ b/openstackclient/shell.py
@@ -148,10 +148,10 @@ class OpenStackShell(shell.OpenStackShell):
'auth_type': self._auth_type,
},
)
- except (IOError, OSError) as e:
+ except (IOError, OSError):
self.log.critical("Could not read clouds.yaml configuration file")
self.print_help_if_requested()
- raise e
+ raise
if not self.options.debug:
self.options.debug = None
diff --git a/openstackclient/tests/functional/network/v2/test_network_service_provider.py b/openstackclient/tests/functional/network/v2/test_network_service_provider.py
new file mode 100644
index 00000000..379de430
--- /dev/null
+++ b/openstackclient/tests/functional/network/v2/test_network_service_provider.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2016, Intel Corporation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from openstackclient.tests.functional import base
+
+
+class TestNetworkServiceProvider(base.TestCase):
+ """Functional tests for network service provider"""
+
+ SERVICE_TYPE = ['L3_ROUTER_NAT']
+
+ def test_network_service_provider_list(self):
+ raw_output = self.openstack('network service provider list')
+ self.assertIn(self.SERVICE_TYPE, raw_output)
diff --git a/openstackclient/tests/unit/image/v1/test_image.py b/openstackclient/tests/unit/image/v1/test_image.py
index aef74f04..036c8336 100644
--- a/openstackclient/tests/unit/image/v1/test_image.py
+++ b/openstackclient/tests/unit/image/v1/test_image.py
@@ -116,7 +116,7 @@ class TestImageCreate(TestImage):
self.images_mock.configure_mock(**mock_exception)
arglist = [
'--container-format', 'ovf',
- '--disk-format', 'fs',
+ '--disk-format', 'ami',
'--min-disk', '10',
'--min-ram', '4',
'--protected',
@@ -126,7 +126,7 @@ class TestImageCreate(TestImage):
]
verifylist = [
('container_format', 'ovf'),
- ('disk_format', 'fs'),
+ ('disk_format', 'ami'),
('min_disk', 10),
('min_ram', 4),
('protected', True),
@@ -147,7 +147,7 @@ class TestImageCreate(TestImage):
self.images_mock.create.assert_called_with(
name=self.new_image.name,
container_format='ovf',
- disk_format='fs',
+ disk_format='ami',
min_disk=10,
min_ram=4,
protected=True,
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index ebc9c3a7..2f2212e4 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -130,7 +130,7 @@ class TestImageCreate(TestImage):
self.images_mock.configure_mock(**mock_exception)
arglist = [
'--container-format', 'ovf',
- '--disk-format', 'fs',
+ '--disk-format', 'ami',
'--min-disk', '10',
'--min-ram', '4',
('--protected'
@@ -143,7 +143,7 @@ class TestImageCreate(TestImage):
]
verifylist = [
('container_format', 'ovf'),
- ('disk_format', 'fs'),
+ ('disk_format', 'ami'),
('min_disk', 10),
('min_ram', 4),
('protected', self.new_image.protected),
@@ -165,7 +165,7 @@ class TestImageCreate(TestImage):
self.images_mock.create.assert_called_with(
name=self.new_image.name,
container_format='ovf',
- disk_format='fs',
+ disk_format='ami',
min_disk=10,
min_ram=4,
owner=self.project.id,
@@ -193,7 +193,7 @@ class TestImageCreate(TestImage):
arglist = [
'--container-format', 'ovf',
- '--disk-format', 'fs',
+ '--disk-format', 'ami',
'--min-disk', '10',
'--min-ram', '4',
'--owner', 'unexist_owner',
@@ -203,7 +203,7 @@ class TestImageCreate(TestImage):
]
verifylist = [
('container_format', 'ovf'),
- ('disk_format', 'fs'),
+ ('disk_format', 'ami'),
('min_disk', 10),
('min_ram', 4),
('owner', 'unexist_owner'),
@@ -227,7 +227,7 @@ class TestImageCreate(TestImage):
arglist = [
'--container-format', 'ovf',
- '--disk-format', 'fs',
+ '--disk-format', 'ami',
'--min-disk', '10',
'--min-ram', '4',
'--protected',
@@ -237,7 +237,7 @@ class TestImageCreate(TestImage):
]
verifylist = [
('container_format', 'ovf'),
- ('disk_format', 'fs'),
+ ('disk_format', 'ami'),
('min_disk', 10),
('min_ram', 4),
('protected', True),
diff --git a/openstackclient/tests/unit/network/test_common.py b/openstackclient/tests/unit/network/test_common.py
index 325aad2a..4b9a754b 100644
--- a/openstackclient/tests/unit/network/test_common.py
+++ b/openstackclient/tests/unit/network/test_common.py
@@ -14,6 +14,8 @@
import argparse
import mock
+import openstack
+from openstackclient.common import exceptions
from openstackclient.network import common
from openstackclient.tests.unit import utils
@@ -172,3 +174,15 @@ class TestNetworkAndComputeShowOne(TestNetworkAndCompute):
def setUp(self):
super(TestNetworkAndComputeShowOne, self).setUp()
self.cmd = FakeNetworkAndComputeShowOne(self.app, self.namespace)
+
+ def test_take_action_with_http_exception(self):
+ with mock.patch.object(self.cmd, 'take_action_network') as m_action:
+ m_action.side_effect = openstack.exceptions.HttpException("bar")
+ self.assertRaisesRegex(exceptions.CommandError, "bar",
+ self.cmd.take_action, mock.Mock())
+
+ self.app.client_manager.network_endpoint_enabled = False
+ with mock.patch.object(self.cmd, 'take_action_compute') as m_action:
+ m_action.side_effect = openstack.exceptions.HttpException("bar")
+ self.assertRaisesRegex(exceptions.CommandError, "bar",
+ self.cmd.take_action, mock.Mock())
diff --git a/openstackclient/tests/unit/network/test_sdk_utils.py b/openstackclient/tests/unit/network/test_sdk_utils.py
new file mode 100644
index 00000000..d1efa7e4
--- /dev/null
+++ b/openstackclient/tests/unit/network/test_sdk_utils.py
@@ -0,0 +1,59 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from openstackclient.network import sdk_utils
+from openstackclient.tests.unit import utils as tests_utils
+
+
+class TestSDKUtils(tests_utils.TestCase):
+
+ def setUp(self):
+ super(TestSDKUtils, self).setUp()
+
+ def _test_get_osc_show_columns_for_sdk_resource(
+ self, sdk_resource, column_map,
+ expected_display_columns, expected_attr_columns):
+ display_columns, attr_columns = \
+ sdk_utils.get_osc_show_columns_for_sdk_resource(
+ sdk_resource, column_map)
+ self.assertEqual(expected_display_columns, display_columns)
+ self.assertEqual(expected_attr_columns, attr_columns)
+
+ def test_get_osc_show_columns_for_sdk_resource_empty(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {}, {}, tuple(), tuple())
+
+ def test_get_osc_show_columns_for_sdk_resource_empty_map(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {'foo': 'foo1'}, {},
+ ('foo',), ('foo',))
+
+ def test_get_osc_show_columns_for_sdk_resource_empty_data(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {}, {'foo': 'foo_map'},
+ ('foo_map',), ('foo_map',))
+
+ def test_get_osc_show_columns_for_sdk_resource_map(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {'foo': 'foo1'}, {'foo': 'foo_map'},
+ ('foo_map',), ('foo',))
+
+ def test_get_osc_show_columns_for_sdk_resource_map_dup(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {'foo': 'foo1', 'foo_map': 'foo1'}, {'foo': 'foo_map'},
+ ('foo_map',), ('foo',))
+
+ def test_get_osc_show_columns_for_sdk_resource_map_full(self):
+ self._test_get_osc_show_columns_for_sdk_resource(
+ {'foo': 'foo1', 'bar': 'bar1'},
+ {'foo': 'foo_map', 'new': 'bar'},
+ ('bar', 'foo_map'), ('bar', 'foo'))
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index 94727ae3..c18511f7 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -98,6 +98,7 @@ class FakeAddressScope(object):
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
+ address_scope.is_shared = address_scope_attrs['shared']
address_scope.project_id = address_scope_attrs['tenant_id']
return address_scope
@@ -291,11 +292,14 @@ class FakeNetwork(object):
'shared': False,
'subnets': ['a', 'b'],
'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,
}
# Overwrite default attributes.
@@ -427,6 +431,7 @@ class FakePort(object):
'binding:vif_details': {},
'binding:vif_type': 'ovs',
'binding:vnic_type': 'normal',
+ 'description': 'description-' + uuid.uuid4().hex,
'device_id': 'device-id-' + uuid.uuid4().hex,
'device_owner': 'compute:nova',
'dns_assignment': [{}],
@@ -741,6 +746,7 @@ class FakeNetworkQosPolicy(object):
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
+ qos_policy.is_shared = qos_policy_attrs['shared']
qos_policy.project_id = qos_policy_attrs['tenant_id']
return qos_policy
@@ -951,6 +957,8 @@ class FakeSecurityGroupRule(object):
# Set default attributes.
security_group_rule_attrs = {
+ 'description': 'security-group-rule-description-' +
+ uuid.uuid4().hex,
'direction': 'ingress',
'ethertype': 'IPv4',
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
@@ -1057,6 +1065,8 @@ class FakeSubnet(object):
loaded=True)
# Set attributes with special mappings in OpenStack SDK.
+ subnet.is_dhcp_enabled = subnet_attrs['enable_dhcp']
+ subnet.subnet_pool_id = subnet_attrs['subnetpool_id']
subnet.project_id = subnet_attrs['tenant_id']
return subnet
@@ -1216,6 +1226,11 @@ class FakeSubnetPool(object):
)
# Set attributes with special mapping in OpenStack SDK.
+ subnet_pool.default_prefix_length = \
+ subnet_pool_attrs['default_prefixlen']
+ subnet_pool.is_shared = subnet_pool_attrs['shared']
+ subnet_pool.maximum_prefix_length = subnet_pool_attrs['max_prefixlen']
+ subnet_pool.minimum_prefix_length = subnet_pool_attrs['min_prefixlen']
subnet_pool.project_id = subnet_pool_attrs['tenant_id']
return subnet_pool
@@ -1257,3 +1272,38 @@ class FakeSubnetPool(object):
if subnet_pools is None:
subnet_pools = FakeSubnetPool.create_subnet_pools(count)
return mock.Mock(side_effect=subnet_pools)
+
+
+class FakeNetworkServiceProvider(object):
+ """Fake Network Service Providers"""
+
+ @staticmethod
+ def create_one_network_service_provider(attrs=None):
+ """Create service provider"""
+ attrs = attrs or {}
+
+ service_provider = {
+ 'name': 'provider-name-' + uuid.uuid4().hex,
+ 'service_type': 'service-type-' + uuid.uuid4().hex,
+ 'default': False,
+ }
+
+ service_provider.update(attrs)
+
+ provider = fakes.FakeResource(
+ info=copy.deepcopy(service_provider),
+ loaded=True)
+ provider.is_default = service_provider['default']
+
+ return provider
+
+ @staticmethod
+ def create_network_service_providers(attrs=None, count=2):
+ """Create multiple service providers"""
+
+ service_providers = []
+ for i in range(0, count):
+ service_providers.append(FakeNetworkServiceProvider.
+ create_one_network_service_provider(
+ attrs))
+ return service_providers
diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip.py b/openstackclient/tests/unit/network/v2/test_floating_ip.py
index 578c6154..10f3067d 100644
--- a/openstackclient/tests/unit/network/v2/test_floating_ip.py
+++ b/openstackclient/tests/unit/network/v2/test_floating_ip.py
@@ -231,6 +231,12 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
# The floating ips to list up
floating_ips = network_fakes.FakeFloatingIP.create_floating_ips(count=3)
+ fake_network = network_fakes.FakeNetwork.create_one_network({
+ 'id': 'fake_network_id',
+ })
+ fake_port = network_fakes.FakePort.create_one_port({
+ 'id': 'fake_port_id',
+ })
columns = (
'ID',
@@ -256,6 +262,8 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
super(TestListFloatingIPNetwork, self).setUp()
self.network.ips = mock.Mock(return_value=self.floating_ips)
+ self.network.find_network = mock.Mock(return_value=self.fake_network)
+ self.network.find_port = mock.Mock(return_value=self.fake_port)
# Get the command object to test
self.cmd = floating_ip.ListFloatingIP(self.app, self.namespace)
@@ -267,7 +275,58 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
columns, data = self.cmd.take_action(parsed_args)
- self.network.ips.assert_called_once_with(**{})
+ self.network.ips.assert_called_once_with()
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_floating_ip_list_network(self):
+ arglist = [
+ '--network', 'fake_network_id',
+ ]
+ verifylist = [
+ ('network', 'fake_network_id'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.ips.assert_called_once_with(**{
+ 'floating_network_id': 'fake_network_id',
+ })
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_floating_ip_list_port(self):
+ arglist = [
+ '--port', 'fake_port_id',
+ ]
+ verifylist = [
+ ('port', 'fake_port_id'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.ips.assert_called_once_with(**{
+ 'port_id': 'fake_port_id',
+ })
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_floating_ip_list_fixed_ip_address(self):
+ arglist = [
+ '--fixed-ip-address', self.floating_ips[0].fixed_ip_address,
+ ]
+ verifylist = [
+ ('fixed_ip_address', self.floating_ips[0].fixed_ip_address),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.ips.assert_called_once_with(**{
+ 'fixed_ip_address': self.floating_ips[0].fixed_ip_address,
+ })
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -300,7 +359,7 @@ class TestShowFloatingIPNetwork(TestFloatingIPNetwork):
floating_ip.floating_network_id,
floating_ip.id,
floating_ip.port_id,
- floating_ip.tenant_id,
+ floating_ip.project_id,
floating_ip.router_id,
floating_ip.status,
)
diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py
index 828da4a2..96b1b102 100644
--- a/openstackclient/tests/unit/network/v2/test_network.py
+++ b/openstackclient/tests/unit/network/v2/test_network.py
@@ -53,6 +53,8 @@ class TestCreateNetworkIdentityV3(TestNetwork):
'availability_zone_hints': ["nova"],
}
)
+ qos_policy = (network_fakes.FakeNetworkQosPolicy.
+ create_one_qos_policy(attrs={'id': _network.qos_policy_id}))
columns = (
'admin_state_up',
@@ -65,6 +67,9 @@ class TestCreateNetworkIdentityV3(TestNetwork):
'port_security_enabled',
'project_id',
'provider_network_type',
+ 'provider_physical_network',
+ 'provider_segmentation_id',
+ 'qos_policy_id',
'router:external',
'shared',
'status',
@@ -82,6 +87,9 @@ class TestCreateNetworkIdentityV3(TestNetwork):
_network.is_port_security_enabled,
_network.project_id,
_network.provider_network_type,
+ _network.provider_physical_network,
+ _network.provider_segmentation_id,
+ _network.qos_policy_id,
network._format_router_external(_network.is_router_external),
_network.shared,
_network.status,
@@ -98,6 +106,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
+ self.network.find_qos_policy = mock.Mock(return_value=self.qos_policy)
def test_create_no_options(self):
arglist = []
@@ -140,6 +149,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
"--provider-network-type", "vlan",
"--provider-physical-network", "physnet1",
"--provider-segment", "400",
+ "--qos-policy", self.qos_policy.id,
"--transparent-vlan",
"--enable-port-security",
self._network.name,
@@ -156,6 +166,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
('provider_network_type', 'vlan'),
('physical_network', 'physnet1'),
('segmentation_id', '400'),
+ ('qos_policy', self.qos_policy.id),
('transparent_vlan', True),
('enable_port_security', True),
('name', self._network.name),
@@ -176,6 +187,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
'provider:network_type': 'vlan',
'provider:physical_network': 'physnet1',
'provider:segmentation_id': '400',
+ 'qos_policy_id': self.qos_policy.id,
'vlan_transparent': True,
'port_security_enabled': True,
})
@@ -229,6 +241,9 @@ class TestCreateNetworkIdentityV2(TestNetwork):
'port_security_enabled',
'project_id',
'provider_network_type',
+ 'provider_physical_network',
+ 'provider_segmentation_id',
+ 'qos_policy_id',
'router:external',
'shared',
'status',
@@ -246,6 +261,9 @@ class TestCreateNetworkIdentityV2(TestNetwork):
_network.is_port_security_enabled,
_network.project_id,
_network.provider_network_type,
+ _network.provider_physical_network,
+ _network.provider_segmentation_id,
+ _network.qos_policy_id,
network._format_router_external(_network.is_router_external),
_network.shared,
_network.status,
@@ -681,11 +699,64 @@ class TestListNetwork(TestNetwork):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+ def test_network_list_provider_network_type(self):
+ network_type = self._network[0].provider_network_type
+ arglist = [
+ '--provider-network-type', network_type,
+ ]
+ verifylist = [
+ ('provider_network_type', network_type),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.networks.assert_called_once_with(
+ **{'provider:network_type': network_type}
+ )
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_network_list_provider_physical_network(self):
+ physical_network = self._network[0].provider_physical_network
+ arglist = [
+ '--provider-physical-network', physical_network,
+ ]
+ verifylist = [
+ ('physical_network', physical_network),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.networks.assert_called_once_with(
+ **{'provider:physical_network': physical_network}
+ )
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_network_list_provider_segment(self):
+ segmentation_id = self._network[0].provider_segmentation_id
+ arglist = [
+ '--provider-segment', segmentation_id,
+ ]
+ verifylist = [
+ ('segmentation_id', segmentation_id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.networks.assert_called_once_with(
+ **{'provider:segmentation_id': segmentation_id}
+ )
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
class TestSetNetwork(TestNetwork):
# The network to set.
_network = network_fakes.FakeNetwork.create_one_network()
+ qos_policy = (network_fakes.FakeNetworkQosPolicy.
+ create_one_qos_policy(attrs={'id': _network.qos_policy_id}))
def setUp(self):
super(TestSetNetwork, self).setUp()
@@ -693,6 +764,7 @@ class TestSetNetwork(TestNetwork):
self.network.update_network = mock.Mock(return_value=None)
self.network.find_network = mock.Mock(return_value=self._network)
+ self.network.find_qos_policy = mock.Mock(return_value=self.qos_policy)
# Get the command object to test
self.cmd = network.SetNetwork(self.app, self.namespace)
@@ -711,6 +783,7 @@ class TestSetNetwork(TestNetwork):
'--provider-segment', '400',
'--no-transparent-vlan',
'--enable-port-security',
+ '--qos-policy', self.qos_policy.name,
]
verifylist = [
('network', self._network.name),
@@ -725,6 +798,7 @@ class TestSetNetwork(TestNetwork):
('segmentation_id', '400'),
('no_transparent_vlan', True),
('enable_port_security', True),
+ ('qos_policy', self.qos_policy.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -742,6 +816,7 @@ class TestSetNetwork(TestNetwork):
'provider:segmentation_id': '400',
'vlan_transparent': False,
'port_security_enabled': True,
+ 'qos_policy_id': self.qos_policy.id,
}
self.network.update_network.assert_called_once_with(
self._network, **attrs)
@@ -754,6 +829,7 @@ class TestSetNetwork(TestNetwork):
'--no-share',
'--internal',
'--disable-port-security',
+ '--no-qos-policy',
]
verifylist = [
('network', self._network.name),
@@ -761,6 +837,7 @@ class TestSetNetwork(TestNetwork):
('no_share', True),
('internal', True),
('disable_port_security', True),
+ ('no_qos_policy', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -771,6 +848,7 @@ class TestSetNetwork(TestNetwork):
'shared': False,
'router:external': False,
'port_security_enabled': False,
+ 'qos_policy_id': None,
}
self.network.update_network.assert_called_once_with(
self._network, **attrs)
@@ -805,6 +883,9 @@ class TestShowNetwork(TestNetwork):
'port_security_enabled',
'project_id',
'provider_network_type',
+ 'provider_physical_network',
+ 'provider_segmentation_id',
+ 'qos_policy_id',
'router:external',
'shared',
'status',
@@ -822,6 +903,9 @@ class TestShowNetwork(TestNetwork):
_network.is_port_security_enabled,
_network.project_id,
_network.provider_network_type,
+ _network.provider_physical_network,
+ _network.provider_segmentation_id,
+ _network.qos_policy_id,
network._format_router_external(_network.is_router_external),
_network.shared,
_network.status,
@@ -1111,10 +1195,7 @@ class TestListNetworkCompute(TestNetworkCompute):
def test_network_list_no_options(self):
arglist = []
- verifylist = [
- ('external', False),
- ('long', False),
- ]
+ verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class Lister in cliff, abstract method take_action()
diff --git a/openstackclient/tests/unit/network/v2/test_network_rbac.py b/openstackclient/tests/unit/network/v2/test_network_rbac.py
index c526ae4e..b884dbc0 100644
--- a/openstackclient/tests/unit/network/v2/test_network_rbac.py
+++ b/openstackclient/tests/unit/network/v2/test_network_rbac.py
@@ -36,6 +36,7 @@ class TestNetworkRBAC(network_fakes.TestNetworkV2):
class TestCreateNetworkRBAC(TestNetworkRBAC):
network_object = network_fakes.FakeNetwork.create_one_network()
+ qos_object = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
project = identity_fakes_v3.FakeProject.create_one_project()
rbac_policy = network_fakes.FakeNetworkRBAC.create_one_network_rbac(
attrs={'tenant_id': project.id,
@@ -71,6 +72,8 @@ class TestCreateNetworkRBAC(TestNetworkRBAC):
return_value=self.rbac_policy)
self.network.find_network = mock.Mock(
return_value=self.network_object)
+ self.network.find_qos_policy = mock.Mock(
+ return_value=self.qos_object)
self.projects_mock.get.return_value = self.project
def test_network_rbac_create_no_type(self):
@@ -194,6 +197,43 @@ class TestCreateNetworkRBAC(TestNetworkRBAC):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+ def test_network_rbac_create_qos_object(self):
+ self.rbac_policy.object_type = 'qos_policy'
+ self.rbac_policy.object_id = self.qos_object.id
+ arglist = [
+ '--type', 'qos_policy',
+ '--action', self.rbac_policy.action,
+ '--target-project', self.rbac_policy.target_tenant,
+ self.qos_object.name,
+ ]
+ verifylist = [
+ ('type', 'qos_policy'),
+ ('action', self.rbac_policy.action),
+ ('target_project', self.rbac_policy.target_tenant),
+ ('rbac_object', self.qos_object.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.create_rbac_policy.assert_called_with(**{
+ 'object_id': self.qos_object.id,
+ 'object_type': 'qos_policy',
+ 'action': self.rbac_policy.action,
+ 'target_tenant': self.rbac_policy.target_tenant,
+ })
+ self.data = [
+ self.rbac_policy.action,
+ self.rbac_policy.id,
+ self.qos_object.id,
+ 'qos_policy',
+ self.rbac_policy.tenant_id,
+ self.rbac_policy.target_tenant,
+ ]
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
class TestDeleteNetworkRBAC(TestNetworkRBAC):
diff --git a/openstackclient/tests/unit/network/v2/test_network_service_provider.py b/openstackclient/tests/unit/network/v2/test_network_service_provider.py
new file mode 100644
index 00000000..5ba85ddb
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/test_network_service_provider.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2016, Intel Corporation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import mock
+
+from openstackclient.network.v2 import network_service_provider \
+ as service_provider
+from openstackclient.tests.unit.network.v2 import fakes
+
+
+class TestNetworkServiceProvider(fakes.TestNetworkV2):
+
+ def setUp(self):
+ super(TestNetworkServiceProvider, self).setUp()
+ self.network = self.app.client_manager.network
+
+
+class TestListNetworkServiceProvider(TestNetworkServiceProvider):
+ provider_list = \
+ fakes.FakeNetworkServiceProvider.create_network_service_providers(
+ count=2
+ )
+
+ columns = (
+ 'Service Type',
+ 'Name',
+ 'Default',
+ )
+
+ data = []
+
+ for provider in provider_list:
+ data.append((
+ provider.service_type,
+ provider.name,
+ provider.is_default,
+ ))
+
+ def setUp(self):
+ super(TestListNetworkServiceProvider, self).setUp()
+ self.network.service_providers = mock.Mock(
+ return_value=self.provider_list
+ )
+
+ self.cmd = \
+ service_provider.ListNetworkServiceProvider(self.app,
+ self.namespace)
+
+ def test_network_service_provider_list(self):
+ arglist = []
+ verifylist = []
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.service_providers.assert_called_with()
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py
index 4ff278a9..9312a897 100644
--- a/openstackclient/tests/unit/network/v2/test_port.py
+++ b/openstackclient/tests/unit/network/v2/test_port.py
@@ -41,6 +41,7 @@ class TestPort(network_fakes.TestNetworkV2):
'binding_vif_details',
'binding_vif_type',
'binding_vnic_type',
+ 'description',
'device_id',
'device_owner',
'dns_assignment',
@@ -65,6 +66,7 @@ class TestPort(network_fakes.TestNetworkV2):
utils.format_dict(fake_port.binding_vif_details),
fake_port.binding_vif_type,
fake_port.binding_vnic_type,
+ fake_port.description,
fake_port.device_id,
fake_port.device_owner,
utils.format_list_of_dicts(fake_port.dns_assignment),
@@ -130,6 +132,7 @@ class TestCreatePort(TestPort):
'--mac-address', 'aa:aa:aa:aa:aa:aa',
'--fixed-ip', 'subnet=%s,ip-address=10.0.0.2'
% self.fake_subnet.id,
+ '--description', self._port.description,
'--device', 'deviceid',
'--device-owner', 'fakeowner',
'--disable',
@@ -146,6 +149,7 @@ class TestCreatePort(TestPort):
'fixed_ip',
[{'subnet': self.fake_subnet.id, 'ip-address': '10.0.0.2'}]
),
+ ('description', self._port.description),
('device', 'deviceid'),
('device_owner', 'fakeowner'),
('disable', True),
@@ -163,6 +167,7 @@ class TestCreatePort(TestPort):
'mac_address': 'aa:aa:aa:aa:aa:aa',
'fixed_ips': [{'subnet_id': self.fake_subnet.id,
'ip_address': '10.0.0.2'}],
+ 'description': self._port.description,
'device_id': 'deviceid',
'device_owner': 'fakeowner',
'admin_state_up': False,
@@ -315,6 +320,54 @@ class TestCreatePort(TestPort):
self.assertEqual(ref_columns, columns)
self.assertEqual(ref_data, data)
+ def test_create_port_security_enabled(self):
+ arglist = [
+ '--network', self._port.network_id,
+ '--enable-port-security',
+ 'test-port',
+ ]
+ verifylist = [
+ ('network', self._port.network_id,),
+ ('enable', True),
+ ('enable_port_security', True),
+ ('name', 'test-port'),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.network.create_port.assert_called_once_with(**{
+ 'admin_state_up': True,
+ 'network_id': self._port.network_id,
+ 'port_security_enabled': True,
+ 'name': 'test-port',
+ })
+
+ def test_create_port_security_disabled(self):
+ arglist = [
+ '--network', self._port.network_id,
+ '--disable-port-security',
+ 'test-port',
+ ]
+ verifylist = [
+ ('network', self._port.network_id,),
+ ('enable', True),
+ ('disable_port_security', True),
+ ('name', 'test-port'),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.network.create_port.assert_called_once_with(**{
+ 'admin_state_up': True,
+ 'network_id': self._port.network_id,
+ 'port_security_enabled': False,
+ 'name': 'test-port',
+ })
+
class TestDeletePort(TestPort):
@@ -530,12 +583,14 @@ class TestListPort(TestPort):
'--device-owner', self._ports[0].device_owner,
'--router', 'fake-router-name',
'--network', 'fake-network-name',
+ '--mac-address', self._ports[0].mac_address,
]
verifylist = [
('device_owner', self._ports[0].device_owner),
('router', 'fake-router-name'),
- ('network', 'fake-network-name')
+ ('network', 'fake-network-name'),
+ ('mac_address', self._ports[0].mac_address)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -545,7 +600,27 @@ class TestListPort(TestPort):
self.network.ports.assert_called_once_with(**{
'device_owner': self._ports[0].device_owner,
'device_id': 'fake-router-id',
- 'network_id': 'fake-network-id'
+ 'network_id': 'fake-network-id',
+ 'mac_address': self._ports[0].mac_address
+ })
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_port_list_mac_address_opt(self):
+ arglist = [
+ '--mac-address', self._ports[0].mac_address,
+ ]
+
+ verifylist = [
+ ('mac_address', self._ports[0].mac_address)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.ports.assert_called_once_with(**{
+ 'mac_address': self._ports[0].mac_address
})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -693,6 +768,7 @@ class TestSetPort(TestPort):
def test_set_that(self):
arglist = [
+ '--description', 'newDescription',
'--enable',
'--vnic-type', 'macvtap',
'--binding-profile', 'foo=bar',
@@ -701,6 +777,7 @@ class TestSetPort(TestPort):
self._port.name,
]
verifylist = [
+ ('description', 'newDescription'),
('enable', True),
('vnic_type', 'macvtap'),
('binding_profile', {'foo': 'bar'}),
@@ -717,6 +794,7 @@ class TestSetPort(TestPort):
'binding:vnic_type': 'macvtap',
'binding:profile': {'foo': 'bar'},
'binding:host_id': 'binding-host-id-xxxx',
+ 'description': 'newDescription',
'name': 'newName',
}
self.network.update_port.assert_called_once_with(self._port, **attrs)
@@ -868,6 +946,42 @@ class TestSetPort(TestPort):
self.network.update_port.assert_called_once_with(_testport, **attrs)
self.assertIsNone(result)
+ def test_port_security_enabled(self):
+ arglist = [
+ '--enable-port-security',
+ self._port.id,
+ ]
+ verifylist = [
+ ('enable_port_security', True),
+ ('port', self._port.id,)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.network.update_port.assert_called_once_with(self._port, **{
+ 'port_security_enabled': True,
+ })
+
+ def test_port_security_disabled(self):
+ arglist = [
+ '--disable-port-security',
+ self._port.id,
+ ]
+ verifylist = [
+ ('disable_port_security', True),
+ ('port', self._port.id,)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.network.update_port.assert_called_once_with(self._port, **{
+ 'port_security_enabled': False,
+ })
+
class TestShowPort(TestPort):
diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule.py b/openstackclient/tests/unit/network/v2/test_security_group_rule.py
index 96d58e5c..5fe9013e 100644
--- a/openstackclient/tests/unit/network/v2/test_security_group_rule.py
+++ b/openstackclient/tests/unit/network/v2/test_security_group_rule.py
@@ -60,6 +60,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
network_fakes.FakeSecurityGroup.create_one_security_group()
expected_columns = (
+ 'description',
'direction',
'ethertype',
'id',
@@ -81,6 +82,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.network.create_security_group_rule = mock.Mock(
return_value=self._security_group_rule)
self.expected_data = (
+ self._security_group_rule.description,
self._security_group_rule.direction,
self._security_group_rule.ethertype,
self._security_group_rule.id,
@@ -119,6 +121,15 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertRaises(tests_utils.ParserException,
self.check_parser, self.cmd, arglist, [])
+ def test_create_all_remote_options(self):
+ arglist = [
+ '--remote-ip', '10.10.0.0/24',
+ '--remote-group', self._security_group.id,
+ self._security_group.id,
+ ]
+ self.assertRaises(tests_utils.ParserException,
+ self.check_parser, self.cmd, arglist, [])
+
def test_create_bad_ethertype(self):
arglist = [
'--ethertype', 'foo',
@@ -213,7 +224,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns, columns)
self.assertEqual(self.expected_data, data)
- def test_create_source_group(self):
+ def test_create_remote_group(self):
self._setup_security_group_rule({
'port_range_max': 22,
'port_range_min': 22,
@@ -248,6 +259,34 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns, columns)
self.assertEqual(self.expected_data, data)
+ def test_create_source_group(self):
+ self._setup_security_group_rule({
+ 'remote_group_id': self._security_group.id,
+ })
+ arglist = [
+ '--ingress',
+ '--src-group', self._security_group.name,
+ self._security_group.id,
+ ]
+ verifylist = [
+ ('ingress', True),
+ ('src_group', self._security_group.name),
+ ('group', self._security_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.create_security_group_rule.assert_called_once_with(**{
+ 'direction': self._security_group_rule.direction,
+ 'ethertype': self._security_group_rule.ethertype,
+ 'protocol': self._security_group_rule.protocol,
+ 'remote_group_id': self._security_group_rule.remote_group_id,
+ 'security_group_id': self._security_group.id,
+ })
+ self.assertEqual(self.expected_columns, columns)
+ self.assertEqual(self.expected_data, data)
+
def test_create_source_ip(self):
self._setup_security_group_rule({
'protocol': 'icmp',
@@ -277,6 +316,35 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns, columns)
self.assertEqual(self.expected_data, data)
+ def test_create_remote_ip(self):
+ self._setup_security_group_rule({
+ 'protocol': 'icmp',
+ 'remote_ip_prefix': '10.0.2.0/24',
+ })
+ arglist = [
+ '--protocol', self._security_group_rule.protocol,
+ '--remote-ip', self._security_group_rule.remote_ip_prefix,
+ self._security_group.id,
+ ]
+ verifylist = [
+ ('protocol', self._security_group_rule.protocol),
+ ('remote_ip', self._security_group_rule.remote_ip_prefix),
+ ('group', self._security_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.create_security_group_rule.assert_called_once_with(**{
+ 'direction': self._security_group_rule.direction,
+ 'ethertype': self._security_group_rule.ethertype,
+ 'protocol': self._security_group_rule.protocol,
+ 'remote_ip_prefix': self._security_group_rule.remote_ip_prefix,
+ 'security_group_id': self._security_group.id,
+ })
+ self.assertEqual(self.expected_columns, columns)
+ self.assertEqual(self.expected_data, data)
+
def test_create_network_options(self):
self._setup_security_group_rule({
'direction': 'egress',
@@ -452,6 +520,33 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns, columns)
self.assertEqual(self.expected_data, data)
+ def test_create_with_description(self):
+ self._setup_security_group_rule({
+ 'description': 'Setting SGR',
+ })
+ arglist = [
+ '--description', self._security_group_rule.description,
+ self._security_group.id,
+ ]
+ verifylist = [
+ ('description', self._security_group_rule.description),
+ ('group', self._security_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = (self.cmd.take_action(parsed_args))
+
+ self.network.create_security_group_rule.assert_called_once_with(**{
+ 'description': self._security_group_rule.description,
+ 'direction': self._security_group_rule.direction,
+ 'ethertype': self._security_group_rule.ethertype,
+ 'protocol': self._security_group_rule.protocol,
+ 'remote_ip_prefix': self._security_group_rule.remote_ip_prefix,
+ 'security_group_id': self._security_group.id,
+ })
+ self.assertEqual(self.expected_columns, columns)
+ self.assertEqual(self.expected_data, data)
+
class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
@@ -498,6 +593,15 @@ class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
self.assertRaises(tests_utils.ParserException,
self.check_parser, self.cmd, arglist, [])
+ def test_create_all_remote_options(self):
+ arglist = [
+ '--remote-ip', '10.10.0.0/24',
+ '--remote-group', self._security_group.id,
+ self._security_group.id,
+ ]
+ self.assertRaises(tests_utils.ParserException,
+ self.check_parser, self.cmd, arglist, [])
+
def test_create_bad_protocol(self):
arglist = [
'--protocol', 'foo',
@@ -588,6 +692,38 @@ class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
self.assertEqual(expected_columns, columns)
self.assertEqual(expected_data, data)
+ def test_create_remote_group(self):
+ expected_columns, expected_data = self._setup_security_group_rule({
+ 'from_port': 22,
+ 'to_port': 22,
+ 'group': {'name': self._security_group.name},
+ })
+ arglist = [
+ '--dst-port', str(self._security_group_rule.from_port),
+ '--remote-group', self._security_group.name,
+ self._security_group.id,
+ ]
+ verifylist = [
+ ('dst_port', (self._security_group_rule.from_port,
+ self._security_group_rule.to_port)),
+ ('remote_group', self._security_group.name),
+ ('group', self._security_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.compute.security_group_rules.create.assert_called_once_with(
+ self._security_group.id,
+ self._security_group_rule.ip_protocol,
+ self._security_group_rule.from_port,
+ self._security_group_rule.to_port,
+ self._security_group_rule.ip_range['cidr'],
+ self._security_group.id,
+ )
+ self.assertEqual(expected_columns, columns)
+ self.assertEqual(expected_data, data)
+
def test_create_source_ip(self):
expected_columns, expected_data = self._setup_security_group_rule({
'ip_protocol': 'icmp',
@@ -620,6 +756,38 @@ class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
self.assertEqual(expected_columns, columns)
self.assertEqual(expected_data, data)
+ def test_create_remote_ip(self):
+ expected_columns, expected_data = self._setup_security_group_rule({
+ 'ip_protocol': 'icmp',
+ 'from_port': -1,
+ 'to_port': -1,
+ 'ip_range': {'cidr': '10.0.2.0/24'},
+ })
+ arglist = [
+ '--protocol', self._security_group_rule.ip_protocol,
+ '--remote-ip', self._security_group_rule.ip_range['cidr'],
+ self._security_group.id,
+ ]
+ verifylist = [
+ ('protocol', self._security_group_rule.ip_protocol),
+ ('remote_ip', self._security_group_rule.ip_range['cidr']),
+ ('group', self._security_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.compute.security_group_rules.create.assert_called_once_with(
+ self._security_group.id,
+ self._security_group_rule.ip_protocol,
+ self._security_group_rule.from_port,
+ self._security_group_rule.to_port,
+ self._security_group_rule.ip_range['cidr'],
+ None,
+ )
+ self.assertEqual(expected_columns, columns)
+ self.assertEqual(expected_data, data)
+
def test_create_proto_option(self):
expected_columns, expected_data = self._setup_security_group_rule({
'ip_protocol': 'icmp',
@@ -942,6 +1110,60 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
+ def test_list_with_protocol(self):
+ self._security_group_rule_tcp.port_range_min = 80
+ arglist = [
+ '--protocol', 'tcp',
+ ]
+ verifylist = [
+ ('protocol', 'tcp'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.security_group_rules.assert_called_once_with(**{
+ 'protocol': 'tcp',
+ })
+ self.assertEqual(self.expected_columns_no_group, columns)
+ self.assertEqual(self.expected_data_no_group, list(data))
+
+ def test_list_with_ingress(self):
+ self._security_group_rule_tcp.port_range_min = 80
+ arglist = [
+ '--ingress',
+ ]
+ verifylist = [
+ ('ingress', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.security_group_rules.assert_called_once_with(**{
+ 'direction': 'ingress',
+ })
+ self.assertEqual(self.expected_columns_no_group, columns)
+ self.assertEqual(self.expected_data_no_group, list(data))
+
+ def test_list_with_wrong_egress(self):
+ self._security_group_rule_tcp.port_range_min = 80
+ arglist = [
+ '--egress',
+ ]
+ verifylist = [
+ ('egress', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.security_group_rules.assert_called_once_with(**{
+ 'direction': 'egress',
+ })
+ self.assertEqual(self.expected_columns_no_group, columns)
+ self.assertEqual(self.expected_data_no_group, list(data))
+
class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
@@ -1075,6 +1297,7 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
network_fakes.FakeSecurityGroupRule.create_one_security_group_rule()
columns = (
+ 'description',
'direction',
'ethertype',
'id',
@@ -1088,6 +1311,7 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
)
data = (
+ _security_group_rule.description,
_security_group_rule.direction,
_security_group_rule.ethertype,
_security_group_rule.id,
diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py
index 2d51aa4a..47de5616 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet.py
@@ -636,7 +636,7 @@ class TestListSubnet(TestSubnet):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'enable_dhcp': True}
+ filters = {'enable_dhcp': True, 'is_dhcp_enabled': True}
self.network.subnets.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -652,7 +652,7 @@ class TestListSubnet(TestSubnet):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'enable_dhcp': False}
+ filters = {'enable_dhcp': False, 'is_dhcp_enabled': False}
self.network.subnets.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -685,7 +685,7 @@ class TestListSubnet(TestSubnet):
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.subnets.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -723,7 +723,7 @@ class TestListSubnet(TestSubnet):
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.subnets.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -925,13 +925,16 @@ class TestSetSubnet(TestSubnet):
{'host_routes': [{'destination': '10.20.20.0/24',
'nexthop': '10.20.20.1'}],
'allocation_pools': [{'start': '8.8.8.200',
- 'end': '8.8.8.250'}], })
+ 'end': '8.8.8.250'}],
+ 'dns_nameservers': ["10.0.0.1"], })
self.network.find_subnet = mock.Mock(return_value=_testsubnet)
arglist = [
'--host-route', 'destination=10.30.30.30/24,gateway=10.30.30.1',
'--no-host-route',
'--allocation-pool', 'start=8.8.8.100,end=8.8.8.150',
'--no-allocation-pool',
+ '--dns-nameserver', '10.1.10.1',
+ '--no-dns-nameservers',
_testsubnet.name,
]
verifylist = [
@@ -939,6 +942,8 @@ class TestSetSubnet(TestSubnet):
"destination": "10.30.30.30/24", "gateway": "10.30.30.1"}]),
('allocation_pools', [{
'start': '8.8.8.100', 'end': '8.8.8.150'}]),
+ ('dns_nameservers', ['10.1.10.1']),
+ ('no_dns_nameservers', True),
('no_host_route', True),
('no_allocation_pool', True),
]
@@ -948,6 +953,7 @@ class TestSetSubnet(TestSubnet):
'host_routes': [{
"destination": "10.30.30.30/24", "nexthop": "10.30.30.1"}],
'allocation_pools': [{'start': '8.8.8.100', 'end': '8.8.8.150'}],
+ 'dns_nameservers': ["10.1.10.1"],
}
self.network.update_subnet.assert_called_once_with(
_testsubnet, **attrs)
diff --git a/openstackclient/tests/unit/network/v2/test_subnet_pool.py b/openstackclient/tests/unit/network/v2/test_subnet_pool.py
index fa6ffff3..f12537e7 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet_pool.py
@@ -435,7 +435,7 @@ class TestListSubnetPool(TestSubnetPool):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'shared': False}
+ filters = {'shared': False, 'is_shared': False}
self.network.subnet_pools.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -451,7 +451,7 @@ class TestListSubnetPool(TestSubnetPool):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'shared': True}
+ filters = {'shared': True, 'is_shared': True}
self.network.subnet_pools.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -501,7 +501,7 @@ class TestListSubnetPool(TestSubnetPool):
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.subnet_pools.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
@@ -521,7 +521,7 @@ class TestListSubnetPool(TestSubnetPool):
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.subnet_pools.assert_called_once_with(**filters)
self.assertEqual(self.columns, columns)
diff --git a/openstackclient/tests/unit/volume/v1/fakes.py b/openstackclient/tests/unit/volume/v1/fakes.py
index a11ea491..78a8227e 100644
--- a/openstackclient/tests/unit/volume/v1/fakes.py
+++ b/openstackclient/tests/unit/volume/v1/fakes.py
@@ -23,115 +23,6 @@ from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes
from openstackclient.tests.unit import utils
-volume_id = 'vvvvvvvv-vvvv-vvvv-vvvvvvvv'
-volume_name = 'nigel'
-volume_description = 'Nigel Tufnel'
-volume_status = 'available'
-volume_size = 120
-volume_type = 'to-eleven'
-volume_zone = 'stonehenge'
-volume_metadata = {
- 'Alpha': 'a',
- 'Beta': 'b',
- 'Gamma': 'g',
-}
-volume_metadata_str = "Alpha='a', Beta='b', Gamma='g'"
-
-VOLUME = {
- 'id': volume_id,
- 'display_name': volume_name,
- 'display_description': volume_description,
- 'size': volume_size,
- 'status': volume_status,
- 'attach_status': 'detached',
- 'availability_zone': volume_zone,
- 'volume_type': volume_type,
- 'metadata': volume_metadata,
-}
-
-extension_name = 'SchedulerHints'
-extension_namespace = 'http://docs.openstack.org/'\
- 'block-service/ext/scheduler-hints/api/v2'
-extension_description = 'Pass arbitrary key/value'\
- 'pairs to the scheduler.'
-extension_updated = '2014-02-07T12:00:0-00:00'
-extension_alias = 'OS-SCH-HNT'
-extension_links = '[{"href":'\
- '"https://github.com/openstack/block-api", "type":'\
- ' "text/html", "rel": "describedby"}]'
-
-EXTENSION = {
- 'name': extension_name,
- 'namespace': extension_namespace,
- 'description': extension_description,
- 'updated': extension_updated,
- 'alias': extension_alias,
- 'links': extension_links,
-}
-
-# NOTE(dtroyer): duplicating here the minimum image info needed to test
-# volume create --image until circular references can be
-# avoided by refactoring the test fakes.
-
-image_id = 'im1'
-image_name = 'graven'
-
-
-IMAGE = {
- 'id': image_id,
- 'name': image_name,
-}
-
-type_id = "5520dc9e-6f9b-4378-a719-729911c0f407"
-type_name = "fake-lvmdriver-1"
-
-TYPE = {
- 'id': type_id,
- 'name': type_name
-}
-
-qos_id = '6f2be1de-997b-4230-b76c-a3633b59e8fb'
-qos_consumer = 'front-end'
-qos_default_consumer = 'both'
-qos_name = "fake-qos-specs"
-qos_specs = {
- 'foo': 'bar',
- 'iops': '9001'
-}
-qos_association = {
- 'association_type': 'volume_type',
- 'name': type_name,
- 'id': type_id
-}
-
-QOS = {
- 'id': qos_id,
- 'consumer': qos_consumer,
- 'name': qos_name
-}
-
-QOS_DEFAULT_CONSUMER = {
- 'id': qos_id,
- 'consumer': qos_default_consumer,
- 'name': qos_name
-}
-
-QOS_WITH_SPECS = {
- 'id': qos_id,
- 'consumer': qos_consumer,
- 'name': qos_name,
- 'specs': qos_specs
-}
-
-QOS_WITH_ASSOCIATIONS = {
- 'id': qos_id,
- 'consumer': qos_consumer,
- 'name': qos_name,
- 'specs': qos_specs,
- 'associations': [qos_association]
-}
-
-
class FakeTransfer(object):
"""Fake one or more Transfer."""
diff --git a/openstackclient/tests/unit/volume/v1/test_backup.py b/openstackclient/tests/unit/volume/v1/test_backup.py
index 32c2fd22..1097d3f1 100644
--- a/openstackclient/tests/unit/volume/v1/test_backup.py
+++ b/openstackclient/tests/unit/volume/v1/test_backup.py
@@ -249,26 +249,65 @@ class TestBackupList(TestBackup):
self.volumes_mock.list.return_value = [self.volume]
self.backups_mock.list.return_value = self.backups
+ self.volumes_mock.get.return_value = self.volume
# Get the command to test
self.cmd = backup.ListVolumeBackup(self.app, None)
def test_backup_list_without_options(self):
arglist = []
- verifylist = [("long", False)]
+ verifylist = [
+ ("long", False),
+ ("name", None),
+ ("status", None),
+ ("volume", None),
+ ('all_projects', False),
+ ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
+ search_opts = {
+ "name": None,
+ "status": None,
+ "volume_id": None,
+ "all_tenants": False,
+ }
+ 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.data, list(data))
def test_backup_list_with_options(self):
- arglist = ["--long"]
- verifylist = [("long", True)]
+ arglist = [
+ "--long",
+ "--name", self.backups[0].name,
+ "--status", "error",
+ "--volume", self.volume.id,
+ "--all-projects"
+ ]
+ verifylist = [
+ ("long", True),
+ ("name", self.backups[0].name),
+ ("status", "error"),
+ ("volume", self.volume.id),
+ ('all_projects', True),
+ ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
+ search_opts = {
+ "name": self.backups[0].name,
+ "status": "error",
+ "volume_id": self.volume.id,
+ "all_tenants": True,
+ }
+ 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.data_long, list(data))
diff --git a/openstackclient/tests/unit/volume/v1/test_type.py b/openstackclient/tests/unit/volume/v1/test_type.py
index 23a1186d..81ad8301 100644
--- a/openstackclient/tests/unit/volume/v1/test_type.py
+++ b/openstackclient/tests/unit/volume/v1/test_type.py
@@ -158,11 +158,13 @@ class TestTypeList(TestType):
columns = (
"ID",
- "Name"
+ "Name",
+ "Is Public",
)
columns_long = (
"ID",
"Name",
+ "Is Public",
"Properties"
)
@@ -171,12 +173,14 @@ class TestTypeList(TestType):
data.append((
t.id,
t.name,
+ t.is_public,
))
data_long = []
for t in volume_types:
data_long.append((
t.id,
t.name,
+ t.is_public,
utils.format_dict(t.extra_specs),
))
diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py
index 73c00844..7a44dea8 100644
--- a/openstackclient/tests/unit/volume/v1/test_volume.py
+++ b/openstackclient/tests/unit/volume/v1/test_volume.py
@@ -14,15 +14,14 @@
#
import argparse
-import copy
import mock
from mock import call
from osc_lib import exceptions
from osc_lib import utils
-from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes
+from openstackclient.tests.unit.image.v1 import fakes as image_fakes
from openstackclient.tests.unit import utils as tests_utils
from openstackclient.tests.unit.volume.v1 import fakes as volume_fakes
from openstackclient.volume.v1 import volume
@@ -58,10 +57,6 @@ class TestVolume(volume_fakes.TestVolumev1):
return volumes
-# TODO(dtroyer): The volume create tests are incomplete, only the minimal
-# options and the options that require additional processing
-# are implemented at this time.
-
class TestVolumeCreate(TestVolume):
project = identity_fakes.FakeProject.create_one_project()
@@ -321,19 +316,16 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(self.datalist, data)
def test_volume_create_image_id(self):
- self.images_mock.get.return_value = fakes.FakeResource(
- None,
- copy.deepcopy(volume_fakes.IMAGE),
- loaded=True,
- )
+ image = image_fakes.FakeImage.create_one_image()
+ self.images_mock.get.return_value = image
arglist = [
- '--image', volume_fakes.image_id,
+ '--image', image.id,
'--size', str(self.new_volume.size),
self.new_volume.display_name,
]
verifylist = [
- ('image', volume_fakes.image_id),
+ ('image', image.id),
('size', self.new_volume.size),
('name', self.new_volume.display_name),
]
@@ -360,26 +352,23 @@ class TestVolumeCreate(TestVolume):
None,
None,
None,
- volume_fakes.image_id,
+ image.id,
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, data)
def test_volume_create_image_name(self):
- self.images_mock.get.return_value = fakes.FakeResource(
- None,
- copy.deepcopy(volume_fakes.IMAGE),
- loaded=True,
- )
+ image = image_fakes.FakeImage.create_one_image()
+ self.images_mock.get.return_value = image
arglist = [
- '--image', volume_fakes.image_name,
+ '--image', image.name,
'--size', str(self.new_volume.size),
self.new_volume.display_name,
]
verifylist = [
- ('image', volume_fakes.image_name),
+ ('image', image.name),
('size', self.new_volume.size),
('name', self.new_volume.display_name),
]
@@ -406,7 +395,7 @@ class TestVolumeCreate(TestVolume):
None,
None,
None,
- volume_fakes.image_id,
+ image.id,
)
self.assertEqual(self.columns, columns)
@@ -739,6 +728,68 @@ class TestVolumeList(TestVolume):
self.cmd, arglist, verifylist)
+class TestVolumeMigrate(TestVolume):
+
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+
+ def setUp(self):
+ super(TestVolumeMigrate, self).setUp()
+
+ self.volumes_mock.get.return_value = self._volume
+ self.volumes_mock.migrate_volume.return_value = None
+ # Get the command object to test
+ self.cmd = volume.MigrateVolume(self.app, None)
+
+ def test_volume_migrate(self):
+ arglist = [
+ "--host", "host@backend-name#pool",
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", False),
+ ("host", "host@backend-name#pool"),
+ ("volume", self._volume.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.get.assert_called_once_with(self._volume.id)
+ self.volumes_mock.migrate_volume.assert_called_once_with(
+ self._volume.id, "host@backend-name#pool", False)
+ self.assertIsNone(result)
+
+ def test_volume_migrate_with_option(self):
+ arglist = [
+ "--force-host-copy",
+ "--host", "host@backend-name#pool",
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", True),
+ ("host", "host@backend-name#pool"),
+ ("volume", self._volume.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.get.assert_called_once_with(self._volume.id)
+ self.volumes_mock.migrate_volume.assert_called_once_with(
+ self._volume.id, "host@backend-name#pool", True)
+ self.assertIsNone(result)
+
+ def test_volume_migrate_without_host(self):
+ arglist = [
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", False),
+ ("volume", self._volume.id),
+ ]
+
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
+
class TestVolumeSet(TestVolume):
_volume = volume_fakes.FakeVolume.create_one_volume()
@@ -844,8 +895,7 @@ class TestVolumeSet(TestVolume):
)
self.assertIsNone(result)
- @mock.patch.object(volume.LOG, 'error')
- def test_volume_set_size_smaller(self, mock_log_error):
+ def test_volume_set_size_smaller(self):
self._volume.status = 'available'
arglist = [
'--size', '1',
@@ -860,15 +910,11 @@ class TestVolumeSet(TestVolume):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- result = self.cmd.take_action(parsed_args)
-
- mock_log_error.assert_called_with("New size must be greater "
- "than %s GB",
- self._volume.size)
- self.assertIsNone(result)
+ self.assertRaises(exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
- @mock.patch.object(volume.LOG, 'error')
- def test_volume_set_size_not_available(self, mock_log_error):
+ def test_volume_set_size_not_available(self):
self._volume.status = 'error'
arglist = [
'--size', '130',
@@ -883,12 +929,9 @@ class TestVolumeSet(TestVolume):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- result = self.cmd.take_action(parsed_args)
-
- mock_log_error.assert_called_with("Volume is in %s state, it must be "
- "available before size can be "
- "extended", 'error')
- self.assertIsNone(result)
+ self.assertRaises(exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
def test_volume_set_property(self):
arglist = [
@@ -896,6 +939,8 @@ class TestVolumeSet(TestVolume):
self._volume.display_name,
]
verifylist = [
+ ('read_only', False),
+ ('read_write', False),
('name', None),
('description', None),
('size', None),
@@ -916,6 +961,7 @@ class TestVolumeSet(TestVolume):
self._volume.id,
metadata
)
+ self.volumes_mock.update_readonly_flag.assert_not_called()
self.assertIsNone(result)
def test_volume_set_bootable(self):
@@ -943,6 +989,44 @@ class TestVolumeSet(TestVolume):
self.volumes_mock.set_bootable.assert_called_with(
self._volume.id, verifylist[index][0][1])
+ def test_volume_set_readonly(self):
+ arglist = [
+ '--read-only',
+ self._volume.id
+ ]
+ verifylist = [
+ ('read_only', True),
+ ('read_write', False),
+ ('volume', self._volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.update_readonly_flag.assert_called_once_with(
+ self._volume.id,
+ True)
+ self.assertIsNone(result)
+
+ def test_volume_set_read_write(self):
+ arglist = [
+ '--read-write',
+ self._volume.id
+ ]
+ verifylist = [
+ ('read_only', False),
+ ('read_write', True),
+ ('volume', self._volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.update_readonly_flag.assert_called_once_with(
+ self._volume.id,
+ False)
+ self.assertIsNone(result)
+
class TestVolumeShow(TestVolume):
diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py
index 5e1d16e1..3137bfb0 100644
--- a/openstackclient/tests/unit/volume/v2/fakes.py
+++ b/openstackclient/tests/unit/volume/v2/fakes.py
@@ -224,6 +224,8 @@ class FakeVolumeClient(object):
self.quota_classes.resource_class = fakes.FakeResource(None, {})
self.consistencygroups = mock.Mock()
self.consistencygroups.resource_class = fakes.FakeResource(None, {})
+ self.cgsnapshots = mock.Mock()
+ self.cgsnapshots.resource_class = fakes.FakeResource(None, {})
self.auth_token = kwargs['token']
self.management_url = kwargs['endpoint']
@@ -248,10 +250,7 @@ class TestVolume(utils.TestCommand):
class FakeVolume(object):
- """Fake one or more volumes.
-
- TODO(xiexs): Currently, only volume API v2 is supported by this class.
- """
+ """Fake one or more volumes."""
@staticmethod
def create_one_volume(attrs=None):
@@ -547,6 +546,106 @@ class FakeConsistencyGroup(object):
return consistency_groups
+ @staticmethod
+ def get_consistency_groups(consistency_groups=None, count=2):
+ """Note:
+
+ Get an iterable MagicMock object with a list of faked
+ consistency_groups.
+
+ If consistency_groups list is provided, then initialize
+ the Mock object with the list. Otherwise create one.
+
+ :param List consistency_groups:
+ A list of FakeResource objects faking consistency_groups
+ :param Integer count:
+ The number of consistency_groups to be faked
+ :return
+ An iterable Mock object with side_effect set to a list of faked
+ consistency_groups
+ """
+ if consistency_groups is None:
+ consistency_groups = (FakeConsistencyGroup.
+ create_consistency_groups(count))
+
+ return mock.Mock(side_effect=consistency_groups)
+
+
+class FakeConsistencyGroupSnapshot(object):
+ """Fake one or more consistency group snapshot."""
+
+ @staticmethod
+ def create_one_consistency_group_snapshot(attrs=None):
+ """Create a fake consistency group snapshot.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with id, name, description, etc.
+ """
+ attrs = attrs or {}
+
+ # Set default attributes.
+ consistency_group_snapshot_info = {
+ "id": 'id-' + uuid.uuid4().hex,
+ "name": 'backup-name-' + uuid.uuid4().hex,
+ "description": 'description-' + uuid.uuid4().hex,
+ "status": "error",
+ "consistencygroup_id": 'consistency-group-id' + uuid.uuid4().hex,
+ "created_at": 'time-' + uuid.uuid4().hex,
+ }
+
+ # Overwrite default attributes.
+ consistency_group_snapshot_info.update(attrs)
+
+ consistency_group_snapshot = fakes.FakeResource(
+ info=copy.deepcopy(consistency_group_snapshot_info),
+ loaded=True)
+ return consistency_group_snapshot
+
+ @staticmethod
+ def create_consistency_group_snapshots(attrs=None, count=2):
+ """Create multiple fake consistency group snapshots.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :param int count:
+ The number of consistency group snapshots to fake
+ :return:
+ A list of FakeResource objects faking the
+ consistency group snapshots
+ """
+ consistency_group_snapshots = []
+ for i in range(0, count):
+ consistency_group_snapshot = (
+ FakeConsistencyGroupSnapshot.
+ create_one_consistency_group_snapshot(attrs)
+ )
+ consistency_group_snapshots.append(consistency_group_snapshot)
+
+ return consistency_group_snapshots
+
+ @staticmethod
+ def get_consistency_group_snapshots(snapshots=None, count=2):
+ """Get an iterable MagicMock object with a list of faked cgsnapshots.
+
+ If consistenct group snapshots list is provided, then initialize
+ the Mock object with the list. Otherwise create one.
+
+ :param List snapshots:
+ A list of FakeResource objects faking consistency group snapshots
+ :param Integer count:
+ The number of consistency group snapshots to be faked
+ :return
+ An iterable Mock object with side_effect set to a list of faked
+ consistency groups
+ """
+ if snapshots is None:
+ snapshots = (FakeConsistencyGroupSnapshot.
+ create_consistency_group_snapshots(count))
+
+ return mock.Mock(side_effect=snapshots)
+
class FakeExtension(object):
"""Fake one or more extension."""
diff --git a/openstackclient/tests/unit/volume/v2/test_backup.py b/openstackclient/tests/unit/volume/v2/test_backup.py
index 306c9eb3..10e7aac5 100644
--- a/openstackclient/tests/unit/volume/v2/test_backup.py
+++ b/openstackclient/tests/unit/volume/v2/test_backup.py
@@ -280,26 +280,78 @@ class TestBackupList(TestBackup):
self.volumes_mock.list.return_value = [self.volume]
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
self.cmd = backup.ListVolumeBackup(self.app, None)
def test_backup_list_without_options(self):
arglist = []
- verifylist = [("long", False)]
+ verifylist = [
+ ("long", False),
+ ("name", None),
+ ("status", None),
+ ("volume", None),
+ ("marker", None),
+ ("limit", None),
+ ('all_projects', False),
+ ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
+ search_opts = {
+ "name": None,
+ "status": None,
+ "volume_id": None,
+ 'all_tenants': False,
+ }
+ 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.data, list(data))
def test_backup_list_with_options(self):
- arglist = ["--long"]
- verifylist = [("long", True)]
+ arglist = [
+ "--long",
+ "--name", self.backups[0].name,
+ "--status", "error",
+ "--volume", self.volume.id,
+ "--marker", self.backups[0].id,
+ "--all-projects",
+ "--limit", "3",
+ ]
+ verifylist = [
+ ("long", True),
+ ("name", self.backups[0].name),
+ ("status", "error"),
+ ("volume", self.volume.id),
+ ("marker", self.backups[0].id),
+ ('all_projects', True),
+ ("limit", 3),
+ ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
+ search_opts = {
+ "name": self.backups[0].name,
+ "status": "error",
+ "volume_id": self.volume.id,
+ 'all_tenants': True,
+ }
+ 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.data_long, list(data))
diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group.py b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
index 00e1b60e..5beb6ef2 100644
--- a/openstackclient/tests/unit/volume/v2/test_consistency_group.py
+++ b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
@@ -12,6 +12,10 @@
# under the License.
#
+import mock
+from mock import call
+
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
@@ -28,6 +32,235 @@ class TestConsistencyGroup(volume_fakes.TestVolume):
self.app.client_manager.volume.consistencygroups)
self.consistencygroups_mock.reset_mock()
+ self.types_mock = self.app.client_manager.volume.volume_types
+ self.types_mock.reset_mock()
+
+
+class TestConsistencyGroupCreate(TestConsistencyGroup):
+
+ volume_type = volume_fakes.FakeType.create_one_type()
+ new_consistency_group = (
+ volume_fakes.FakeConsistencyGroup.create_one_consistency_group())
+
+ columns = (
+ 'availability_zone',
+ 'created_at',
+ 'description',
+ 'id',
+ 'name',
+ 'status',
+ 'volume_types',
+ )
+ data = (
+ new_consistency_group.availability_zone,
+ new_consistency_group.created_at,
+ new_consistency_group.description,
+ new_consistency_group.id,
+ new_consistency_group.name,
+ new_consistency_group.status,
+ new_consistency_group.volume_types,
+ )
+
+ def setUp(self):
+ super(TestConsistencyGroupCreate, self).setUp()
+ self.consistencygroups_mock.create.return_value = (
+ self.new_consistency_group)
+ self.consistencygroups_mock.create_from_src.return_value = (
+ self.new_consistency_group)
+ self.consistencygroups_mock.get.return_value = (
+ self.new_consistency_group)
+ self.types_mock.get.return_value = self.volume_type
+
+ # Get the command object to test
+ self.cmd = consistency_group.CreateConsistencyGroup(self.app, None)
+
+ def test_consistency_group_create(self):
+ arglist = [
+ '--volume-type', self.volume_type.id,
+ '--description', self.new_consistency_group.description,
+ '--availability-zone',
+ self.new_consistency_group.availability_zone,
+ self.new_consistency_group.name,
+ ]
+ verifylist = [
+ ('volume_type', self.volume_type.id),
+ ('description', self.new_consistency_group.description),
+ ('availability_zone',
+ self.new_consistency_group.availability_zone),
+ ('name', self.new_consistency_group.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.types_mock.get.assert_called_once_with(
+ self.volume_type.id)
+ self.consistencygroups_mock.get.assert_not_called()
+ self.consistencygroups_mock.create.assert_called_once_with(
+ self.volume_type.id,
+ name=self.new_consistency_group.name,
+ description=self.new_consistency_group.description,
+ availability_zone=self.new_consistency_group.availability_zone,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+ def test_consistency_group_create_without_name(self):
+ arglist = [
+ '--volume-type', self.volume_type.id,
+ '--description', self.new_consistency_group.description,
+ '--availability-zone',
+ self.new_consistency_group.availability_zone,
+ ]
+ verifylist = [
+ ('volume_type', self.volume_type.id),
+ ('description', self.new_consistency_group.description),
+ ('availability_zone',
+ self.new_consistency_group.availability_zone),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.types_mock.get.assert_called_once_with(
+ self.volume_type.id)
+ self.consistencygroups_mock.get.assert_not_called()
+ self.consistencygroups_mock.create.assert_called_once_with(
+ self.volume_type.id,
+ name=None,
+ description=self.new_consistency_group.description,
+ availability_zone=self.new_consistency_group.availability_zone,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+ def test_consistency_group_create_from_source(self):
+ arglist = [
+ '--consistency-group-source', self.new_consistency_group.id,
+ '--description', self.new_consistency_group.description,
+ self.new_consistency_group.name,
+ ]
+ verifylist = [
+ ('consistency_group_source', self.new_consistency_group.id),
+ ('description', self.new_consistency_group.description),
+ ('name', self.new_consistency_group.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.types_mock.get.assert_not_called()
+ self.consistencygroups_mock.get.assert_called_once_with(
+ self.new_consistency_group.id)
+ self.consistencygroups_mock.create_from_src.assert_called_with(
+ None,
+ self.new_consistency_group.id,
+ name=self.new_consistency_group.name,
+ description=self.new_consistency_group.description,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+
+class TestConsistencyGroupDelete(TestConsistencyGroup):
+
+ consistency_groups =\
+ volume_fakes.FakeConsistencyGroup.create_consistency_groups(count=2)
+
+ def setUp(self):
+ super(TestConsistencyGroupDelete, self).setUp()
+
+ self.consistencygroups_mock.get = volume_fakes.FakeConsistencyGroup.\
+ get_consistency_groups(self.consistency_groups)
+ self.consistencygroups_mock.delete.return_value = None
+
+ # Get the command object to mock
+ self.cmd = consistency_group.DeleteConsistencyGroup(self.app, None)
+
+ def test_consistency_group_delete(self):
+ arglist = [
+ self.consistency_groups[0].id
+ ]
+ verifylist = [
+ ("consistency_groups", [self.consistency_groups[0].id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.consistencygroups_mock.delete.assert_called_with(
+ self.consistency_groups[0].id, False)
+ self.assertIsNone(result)
+
+ def test_consistency_group_delete_with_force(self):
+ arglist = [
+ '--force',
+ self.consistency_groups[0].id,
+ ]
+ verifylist = [
+ ('force', True),
+ ("consistency_groups", [self.consistency_groups[0].id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.consistencygroups_mock.delete.assert_called_with(
+ self.consistency_groups[0].id, True)
+ self.assertIsNone(result)
+
+ def test_delete_multiple_consistency_groups(self):
+ arglist = []
+ for b in self.consistency_groups:
+ arglist.append(b.id)
+ verifylist = [
+ ('consistency_groups', arglist),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for b in self.consistency_groups:
+ calls.append(call(b.id, False))
+ self.consistencygroups_mock.delete.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_delete_multiple_consistency_groups_with_exception(self):
+ arglist = [
+ self.consistency_groups[0].id,
+ 'unexist_consistency_group',
+ ]
+ verifylist = [
+ ('consistency_groups', arglist),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self.consistency_groups[0],
+ exceptions.CommandError]
+ with mock.patch.object(utils, 'find_resource',
+ side_effect=find_mock_result) as find_mock:
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 consistency groups failed to delete.',
+ str(e))
+
+ find_mock.assert_any_call(self.consistencygroups_mock,
+ self.consistency_groups[0].id)
+ find_mock.assert_any_call(self.consistencygroups_mock,
+ 'unexist_consistency_group')
+
+ self.assertEqual(2, find_mock.call_count)
+ self.consistencygroups_mock.delete.assert_called_once_with(
+ self.consistency_groups[0].id, False
+ )
+
class TestConsistencyGroupList(TestConsistencyGroup):
@@ -120,3 +353,46 @@ class TestConsistencyGroupList(TestConsistencyGroup):
detailed=True, search_opts={'all_tenants': False})
self.assertEqual(self.columns_long, columns)
self.assertEqual(self.data_long, list(data))
+
+
+class TestConsistencyGroupShow(TestConsistencyGroup):
+ columns = (
+ 'availability_zone',
+ 'created_at',
+ 'description',
+ 'id',
+ 'name',
+ 'status',
+ 'volume_types',
+ )
+
+ def setUp(self):
+ super(TestConsistencyGroupShow, self).setUp()
+
+ self.consistency_group = (
+ volume_fakes.FakeConsistencyGroup.create_one_consistency_group())
+ self.data = (
+ self.consistency_group.availability_zone,
+ self.consistency_group.created_at,
+ self.consistency_group.description,
+ self.consistency_group.id,
+ self.consistency_group.name,
+ self.consistency_group.status,
+ self.consistency_group.volume_types,
+ )
+ self.consistencygroups_mock.get.return_value = self.consistency_group
+ self.cmd = consistency_group.ShowConsistencyGroup(self.app, None)
+
+ def test_consistency_group_show(self):
+ arglist = [
+ self.consistency_group.id
+ ]
+ verifylist = [
+ ("consistency_group", self.consistency_group.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+ self.consistencygroups_mock.get.assert_called_once_with(
+ self.consistency_group.id)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py b/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py
new file mode 100644
index 00000000..3bfe93df
--- /dev/null
+++ b/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py
@@ -0,0 +1,351 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+from mock import call
+
+from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
+from openstackclient.volume.v2 import consistency_group_snapshot
+
+
+class TestConsistencyGroupSnapshot(volume_fakes.TestVolume):
+
+ def setUp(self):
+ super(TestConsistencyGroupSnapshot, self).setUp()
+
+ # Get a shortcut to the TransferManager Mock
+ self.cgsnapshots_mock = (
+ self.app.client_manager.volume.cgsnapshots)
+ self.cgsnapshots_mock.reset_mock()
+ self.consistencygroups_mock = (
+ self.app.client_manager.volume.consistencygroups)
+ self.consistencygroups_mock.reset_mock()
+
+
+class TestConsistencyGroupSnapshotCreate(TestConsistencyGroupSnapshot):
+
+ _consistency_group_snapshot = (
+ volume_fakes.
+ FakeConsistencyGroupSnapshot.
+ create_one_consistency_group_snapshot()
+ )
+ consistency_group = (
+ volume_fakes.FakeConsistencyGroup.create_one_consistency_group())
+
+ columns = (
+ 'consistencygroup_id',
+ 'created_at',
+ 'description',
+ 'id',
+ 'name',
+ 'status',
+ )
+ data = (
+ _consistency_group_snapshot.consistencygroup_id,
+ _consistency_group_snapshot.created_at,
+ _consistency_group_snapshot.description,
+ _consistency_group_snapshot.id,
+ _consistency_group_snapshot.name,
+ _consistency_group_snapshot.status,
+ )
+
+ def setUp(self):
+ super(TestConsistencyGroupSnapshotCreate, self).setUp()
+ self.cgsnapshots_mock.create.return_value = (
+ self._consistency_group_snapshot)
+ self.consistencygroups_mock.get.return_value = (
+ self.consistency_group)
+
+ # Get the command object to test
+ self.cmd = (consistency_group_snapshot.
+ CreateConsistencyGroupSnapshot(self.app, None))
+
+ def test_consistency_group_snapshot_create(self):
+ arglist = [
+ '--consistency-group', self.consistency_group.id,
+ '--description', self._consistency_group_snapshot.description,
+ self._consistency_group_snapshot.name,
+ ]
+ verifylist = [
+ ('consistency_group', self.consistency_group.id),
+ ('description', self._consistency_group_snapshot.description),
+ ('snapshot_name', self._consistency_group_snapshot.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.consistencygroups_mock.get.assert_called_once_with(
+ self.consistency_group.id)
+ self.cgsnapshots_mock.create.assert_called_once_with(
+ self.consistency_group.id,
+ name=self._consistency_group_snapshot.name,
+ description=self._consistency_group_snapshot.description,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+ def test_consistency_group_snapshot_create_no_consistency_group(self):
+ arglist = [
+ '--description', self._consistency_group_snapshot.description,
+ self._consistency_group_snapshot.name,
+ ]
+ verifylist = [
+ ('description', self._consistency_group_snapshot.description),
+ ('snapshot_name', self._consistency_group_snapshot.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.consistencygroups_mock.get.assert_called_once_with(
+ self._consistency_group_snapshot.name)
+ self.cgsnapshots_mock.create.assert_called_once_with(
+ self.consistency_group.id,
+ name=self._consistency_group_snapshot.name,
+ description=self._consistency_group_snapshot.description,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
+
+class TestConsistencyGroupSnapshotDelete(TestConsistencyGroupSnapshot):
+
+ consistency_group_snapshots = (
+ volume_fakes.FakeConsistencyGroupSnapshot.
+ create_consistency_group_snapshots(count=2)
+ )
+
+ def setUp(self):
+ super(TestConsistencyGroupSnapshotDelete, self).setUp()
+
+ self.cgsnapshots_mock.get = (
+ volume_fakes.FakeConsistencyGroupSnapshot.
+ get_consistency_group_snapshots(self.consistency_group_snapshots)
+ )
+ self.cgsnapshots_mock.delete.return_value = None
+
+ # Get the command object to mock
+ self.cmd = (consistency_group_snapshot.
+ DeleteConsistencyGroupSnapshot(self.app, None))
+
+ def test_consistency_group_snapshot_delete(self):
+ arglist = [
+ self.consistency_group_snapshots[0].id
+ ]
+ verifylist = [
+ ("consistency_group_snapshot",
+ [self.consistency_group_snapshots[0].id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.cgsnapshots_mock.delete.assert_called_once_with(
+ self.consistency_group_snapshots[0].id)
+ self.assertIsNone(result)
+
+ def test_multiple_consistency_group_snapshots_delete(self):
+ arglist = []
+ for c in self.consistency_group_snapshots:
+ arglist.append(c.id)
+ verifylist = [
+ ('consistency_group_snapshot', arglist),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for c in self.consistency_group_snapshots:
+ calls.append(call(c.id))
+ self.cgsnapshots_mock.delete.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+
+class TestConsistencyGroupSnapshotList(TestConsistencyGroupSnapshot):
+
+ consistency_group_snapshots = (
+ volume_fakes.FakeConsistencyGroupSnapshot.
+ create_consistency_group_snapshots(count=2)
+ )
+ consistency_group = (
+ volume_fakes.FakeConsistencyGroup.create_one_consistency_group()
+ )
+
+ columns = [
+ 'ID',
+ 'Status',
+ 'Name',
+ ]
+ columns_long = [
+ 'ID',
+ 'Status',
+ 'ConsistencyGroup ID',
+ 'Name',
+ 'Description',
+ 'Created At',
+ ]
+ data = []
+ for c in consistency_group_snapshots:
+ data.append((
+ c.id,
+ c.status,
+ c.name,
+ ))
+ data_long = []
+ for c in consistency_group_snapshots:
+ data_long.append((
+ c.id,
+ c.status,
+ c.consistencygroup_id,
+ c.name,
+ c.description,
+ c.created_at,
+ ))
+
+ def setUp(self):
+ super(TestConsistencyGroupSnapshotList, self).setUp()
+
+ self.cgsnapshots_mock.list.return_value = (
+ self.consistency_group_snapshots)
+ self.consistencygroups_mock.get.return_value = self.consistency_group
+ # Get the command to test
+ self.cmd = (
+ consistency_group_snapshot.
+ ListConsistencyGroupSnapshot(self.app, None)
+ )
+
+ def test_consistency_group_snapshot_list_without_options(self):
+ arglist = []
+ verifylist = [
+ ("all_projects", False),
+ ("long", False),
+ ("status", None),
+ ("consistency_group", None),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ search_opts = {
+ 'all_tenants': False,
+ 'status': None,
+ 'consistencygroup_id': None,
+ }
+ self.cgsnapshots_mock.list.assert_called_once_with(
+ detailed=True, search_opts=search_opts)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_consistency_group_snapshot_list_with_long(self):
+ arglist = [
+ "--long",
+ ]
+ verifylist = [
+ ("all_projects", False),
+ ("long", True),
+ ("status", None),
+ ("consistency_group", None),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ search_opts = {
+ 'all_tenants': False,
+ 'status': None,
+ 'consistencygroup_id': None,
+ }
+ self.cgsnapshots_mock.list.assert_called_once_with(
+ detailed=True, search_opts=search_opts)
+ self.assertEqual(self.columns_long, columns)
+ self.assertEqual(self.data_long, list(data))
+
+ def test_consistency_group_snapshot_list_with_options(self):
+ arglist = [
+ "--all-project",
+ "--status", self.consistency_group_snapshots[0].status,
+ "--consistency-group", self.consistency_group.id,
+ ]
+ verifylist = [
+ ("all_projects", True),
+ ("long", False),
+ ("status", self.consistency_group_snapshots[0].status),
+ ("consistency_group", self.consistency_group.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ search_opts = {
+ 'all_tenants': True,
+ 'status': self.consistency_group_snapshots[0].status,
+ 'consistencygroup_id': self.consistency_group.id,
+ }
+ self.consistencygroups_mock.get.assert_called_once_with(
+ self.consistency_group.id)
+ self.cgsnapshots_mock.list.assert_called_once_with(
+ detailed=True, search_opts=search_opts)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+
+class TestConsistencyGroupSnapshotShow(TestConsistencyGroupSnapshot):
+
+ _consistency_group_snapshot = (
+ volume_fakes.
+ FakeConsistencyGroupSnapshot.
+ create_one_consistency_group_snapshot()
+ )
+
+ columns = (
+ 'consistencygroup_id',
+ 'created_at',
+ 'description',
+ 'id',
+ 'name',
+ 'status',
+ )
+ data = (
+ _consistency_group_snapshot.consistencygroup_id,
+ _consistency_group_snapshot.created_at,
+ _consistency_group_snapshot.description,
+ _consistency_group_snapshot.id,
+ _consistency_group_snapshot.name,
+ _consistency_group_snapshot.status,
+ )
+
+ def setUp(self):
+ super(TestConsistencyGroupSnapshotShow, self).setUp()
+
+ self.cgsnapshots_mock.get.return_value = (
+ self._consistency_group_snapshot)
+ self.cmd = (consistency_group_snapshot.
+ ShowConsistencyGroupSnapshot(self.app, None))
+
+ def test_consistency_group_snapshot_show(self):
+ arglist = [
+ self._consistency_group_snapshot.id
+ ]
+ verifylist = [
+ ("consistency_group_snapshot", self._consistency_group_snapshot.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+ self.cgsnapshots_mock.get.assert_called_once_with(
+ self._consistency_group_snapshot.id)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
diff --git a/openstackclient/tests/unit/volume/v2/test_type.py b/openstackclient/tests/unit/volume/v2/test_type.py
index 84f87e3b..325872d7 100644
--- a/openstackclient/tests/unit/volume/v2/test_type.py
+++ b/openstackclient/tests/unit/volume/v2/test_type.py
@@ -165,7 +165,8 @@ class TestTypeList(TestType):
columns = [
"ID",
- "Name"
+ "Name",
+ "Is Public",
]
columns_long = columns + [
"Description",
@@ -177,12 +178,14 @@ class TestTypeList(TestType):
data.append((
t.id,
t.name,
+ t.is_public,
))
data_long = []
for t in volume_types:
data_long.append((
t.id,
t.name,
+ t.is_public,
t.description,
utils.format_dict(t.extra_specs),
))
diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py
index f4a7c142..41728342 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume.py
@@ -46,6 +46,9 @@ class TestVolume(volume_fakes.TestVolume):
self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
self.snapshots_mock.reset_mock()
+ self.types_mock = self.app.client_manager.volume.volume_types
+ self.types_mock.reset_mock()
+
self.consistencygroups_mock = (
self.app.client_manager.volume.consistencygroups)
self.consistencygroups_mock.reset_mock()
@@ -996,13 +999,106 @@ class TestVolumeList(TestVolume):
self.cmd, arglist, verifylist)
+class TestVolumeMigrate(TestVolume):
+
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+
+ def setUp(self):
+ super(TestVolumeMigrate, self).setUp()
+
+ self.volumes_mock.get.return_value = self._volume
+ self.volumes_mock.migrate_volume.return_value = None
+ # Get the command object to test
+ self.cmd = volume.MigrateVolume(self.app, None)
+
+ def test_volume_migrate(self):
+ arglist = [
+ "--host", "host@backend-name#pool",
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", False),
+ ("lock_volume", False),
+ ("unlock_volume", False),
+ ("host", "host@backend-name#pool"),
+ ("volume", self._volume.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.get.assert_called_once_with(self._volume.id)
+ self.volumes_mock.migrate_volume.assert_called_once_with(
+ self._volume.id, "host@backend-name#pool", False, False)
+ self.assertIsNone(result)
+
+ def test_volume_migrate_with_option(self):
+ arglist = [
+ "--force-host-copy",
+ "--lock-volume",
+ "--host", "host@backend-name#pool",
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", True),
+ ("lock_volume", True),
+ ("unlock_volume", False),
+ ("host", "host@backend-name#pool"),
+ ("volume", self._volume.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.get.assert_called_once_with(self._volume.id)
+ self.volumes_mock.migrate_volume.assert_called_once_with(
+ self._volume.id, "host@backend-name#pool", True, True)
+ self.assertIsNone(result)
+
+ def test_volume_migrate_with_unlock_volume(self):
+ arglist = [
+ "--unlock-volume",
+ "--host", "host@backend-name#pool",
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", False),
+ ("lock_volume", False),
+ ("unlock_volume", True),
+ ("host", "host@backend-name#pool"),
+ ("volume", self._volume.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.get.assert_called_once_with(self._volume.id)
+ self.volumes_mock.migrate_volume.assert_called_once_with(
+ self._volume.id, "host@backend-name#pool", False, False)
+ self.assertIsNone(result)
+
+ def test_volume_migrate_without_host(self):
+ arglist = [
+ self._volume.id,
+ ]
+ verifylist = [
+ ("force_host_copy", False),
+ ("lock_volume", False),
+ ("unlock_volume", False),
+ ("volume", self._volume.id),
+ ]
+
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
+
class TestVolumeSet(TestVolume):
+ volume_type = volume_fakes.FakeType.create_one_type()
+
def setUp(self):
super(TestVolumeSet, self).setUp()
self.new_volume = volume_fakes.FakeVolume.create_one_volume()
self.volumes_mock.get.return_value = self.new_volume
+ self.types_mock.get.return_value = self.volume_type
# Get the command object to test
self.cmd = volume.SetVolume(self.app, None)
@@ -1033,6 +1129,8 @@ class TestVolumeSet(TestVolume):
self.new_volume.id
]
verifylist = [
+ ('read_only', False),
+ ('read_write', False),
('state', 'error'),
('volume', self.new_volume.id)
]
@@ -1042,6 +1140,7 @@ class TestVolumeSet(TestVolume):
result = self.cmd.take_action(parsed_args)
self.volumes_mock.reset_state.assert_called_with(
self.new_volume.id, 'error')
+ self.volumes_mock.update_readonly_flag.assert_not_called()
self.assertIsNone(result)
def test_volume_set_state_failed(self):
@@ -1090,6 +1189,104 @@ class TestVolumeSet(TestVolume):
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, verifylist[index][0][1])
+ def test_volume_set_readonly(self):
+ arglist = [
+ '--read-only',
+ self.new_volume.id
+ ]
+ verifylist = [
+ ('read_only', True),
+ ('read_write', False),
+ ('volume', self.new_volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.update_readonly_flag.assert_called_once_with(
+ self.new_volume.id,
+ True)
+ self.assertIsNone(result)
+
+ def test_volume_set_read_write(self):
+ arglist = [
+ '--read-write',
+ self.new_volume.id
+ ]
+ verifylist = [
+ ('read_only', False),
+ ('read_write', True),
+ ('volume', self.new_volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.update_readonly_flag.assert_called_once_with(
+ self.new_volume.id,
+ False)
+ self.assertIsNone(result)
+
+ def test_volume_set_type(self):
+ arglist = [
+ '--type', self.volume_type.id,
+ self.new_volume.id
+ ]
+ verifylist = [
+ ('retype_policy', None),
+ ('type', self.volume_type.id),
+ ('volume', self.new_volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.retype.assert_called_once_with(
+ self.new_volume.id,
+ self.volume_type.id,
+ 'never')
+ self.assertIsNone(result)
+
+ def test_volume_set_type_with_policy(self):
+ arglist = [
+ '--retype-policy', 'on-demand',
+ '--type', self.volume_type.id,
+ self.new_volume.id
+ ]
+ verifylist = [
+ ('retype_policy', 'on-demand'),
+ ('type', self.volume_type.id),
+ ('volume', self.new_volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.retype.assert_called_once_with(
+ self.new_volume.id,
+ self.volume_type.id,
+ 'on-demand')
+ self.assertIsNone(result)
+
+ @mock.patch.object(volume.LOG, 'warning')
+ def test_volume_set_with_only_retype_policy(self, mock_warning):
+ arglist = [
+ '--retype-policy', 'on-demand',
+ self.new_volume.id
+ ]
+ verifylist = [
+ ('retype_policy', 'on-demand'),
+ ('volume', self.new_volume.id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.volumes_mock.retype.assert_not_called()
+ mock_warning.assert_called_with("'--retype-policy' option will "
+ "not work without '--type' option")
+ self.assertIsNone(result)
+
class TestVolumeShow(TestVolume):
diff --git a/openstackclient/volume/v1/backup.py b/openstackclient/volume/v1/backup.py
index c9d0ca0d..9ac1302a 100644
--- a/openstackclient/volume/v1/backup.py
+++ b/openstackclient/volume/v1/backup.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeBackup(command.ShowOne):
- """Create new volume backup"""
+ _description = _("Create new volume backup")
def get_parser(self, prog_name):
parser = super(CreateVolumeBackup, self).get_parser(prog_name)
@@ -73,7 +73,7 @@ class CreateVolumeBackup(command.ShowOne):
class CreateBackup(CreateVolumeBackup):
- """Create new backup"""
+ _description = _("Create new backup")
# TODO(Huanxuan Ao): Remove this class and ``backup create`` command
# two cycles after Newton.
@@ -90,7 +90,7 @@ class CreateBackup(CreateVolumeBackup):
class DeleteVolumeBackup(command.Command):
- """Delete volume backup(s)"""
+ _description = _("Delete volume backup(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeBackup, self).get_parser(prog_name)
@@ -125,7 +125,7 @@ class DeleteVolumeBackup(command.Command):
class DeleteBackup(DeleteVolumeBackup):
- """Delete backup(s)"""
+ _description = _("Delete backup(s)")
# TODO(Huanxuan Ao): Remove this class and ``backup delete`` command
# two cycles after Newton.
@@ -142,7 +142,7 @@ class DeleteBackup(DeleteVolumeBackup):
class ListVolumeBackup(command.Lister):
- """List volume backups"""
+ _description = _("List volume backups")
def get_parser(self, prog_name):
parser = super(ListVolumeBackup, self).get_parser(prog_name)
@@ -152,9 +152,36 @@ class ListVolumeBackup(command.Lister):
default=False,
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(
+ '--all-projects',
+ action='store_true',
+ default=False,
+ help=_('Include all projects (admin only)'),
+ )
return parser
def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
def _format_volume_id(volume_id):
"""Return a volume name if available
@@ -180,13 +207,25 @@ class ListVolumeBackup(command.Lister):
# Cache the volume list
volume_cache = {}
try:
- for s in self.app.client_manager.volume.volumes.list():
+ for s in volume_client.volumes.list():
volume_cache[s.id] = s
except Exception:
# Just forget it if there's any trouble
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,
+ 'all_tenants': parsed_args.all_projects,
+ }
+ data = volume_client.backups.list(
+ search_opts=search_opts,
+ )
return (column_headers,
(utils.get_item_properties(
@@ -196,7 +235,7 @@ class ListVolumeBackup(command.Lister):
class ListBackup(ListVolumeBackup):
- """List backups"""
+ _description = _("List backups")
# TODO(Huanxuan Ao): Remove this class and ``backup list`` command
# two cycles after Newton.
@@ -213,7 +252,7 @@ class ListBackup(ListVolumeBackup):
class RestoreVolumeBackup(command.Command):
- """Restore volume backup"""
+ _description = _("Restore volume backup")
def get_parser(self, prog_name):
parser = super(RestoreVolumeBackup, self).get_parser(prog_name)
@@ -240,7 +279,7 @@ class RestoreVolumeBackup(command.Command):
class RestoreBackup(RestoreVolumeBackup):
- """Restore backup"""
+ _description = _("Restore backup")
# TODO(Huanxuan Ao): Remove this class and ``backup restore`` command
# two cycles after Newton.
@@ -257,7 +296,7 @@ class RestoreBackup(RestoreVolumeBackup):
class ShowVolumeBackup(command.ShowOne):
- """Display volume backup details"""
+ _description = _("Display volume backup details")
def get_parser(self, prog_name):
parser = super(ShowVolumeBackup, self).get_parser(prog_name)
@@ -277,7 +316,7 @@ class ShowVolumeBackup(command.ShowOne):
class ShowBackup(ShowVolumeBackup):
- """Display backup details"""
+ _description = _("Display backup details")
# TODO(Huanxuan Ao): Remove this class and ``backup show`` command
# two cycles after Newton.
diff --git a/openstackclient/volume/v1/qos_specs.py b/openstackclient/volume/v1/qos_specs.py
index 93c24a21..b824b351 100644
--- a/openstackclient/volume/v1/qos_specs.py
+++ b/openstackclient/volume/v1/qos_specs.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class AssociateQos(command.Command):
- """Associate a QoS specification to a volume type"""
+ _description = _("Associate a QoS specification to a volume type")
def get_parser(self, prog_name):
parser = super(AssociateQos, self).get_parser(prog_name)
@@ -57,7 +57,7 @@ class AssociateQos(command.Command):
class CreateQos(command.ShowOne):
- """Create new QoS specification"""
+ _description = _("Create new QoS specification")
def get_parser(self, prog_name):
parser = super(CreateQos, self).get_parser(prog_name)
@@ -99,7 +99,7 @@ class CreateQos(command.ShowOne):
class DeleteQos(command.Command):
- """Delete QoS specification"""
+ _description = _("Delete QoS specification")
def get_parser(self, prog_name):
parser = super(DeleteQos, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class DeleteQos(command.Command):
class DisassociateQos(command.Command):
- """Disassociate a QoS specification from a volume type"""
+ _description = _("Disassociate a QoS specification from a volume type")
def get_parser(self, prog_name):
parser = super(DisassociateQos, self).get_parser(prog_name)
@@ -177,7 +177,7 @@ class DisassociateQos(command.Command):
class ListQos(command.Lister):
- """List QoS specifications"""
+ _description = _("List QoS specifications")
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
@@ -202,7 +202,7 @@ class ListQos(command.Lister):
class SetQos(command.Command):
- """Set QoS specification properties"""
+ _description = _("Set QoS specification properties")
def get_parser(self, prog_name):
parser = super(SetQos, self).get_parser(prog_name)
@@ -231,7 +231,7 @@ class SetQos(command.Command):
class ShowQos(command.ShowOne):
- """Display QoS specification details"""
+ _description = _("Display QoS specification details")
def get_parser(self, prog_name):
parser = super(ShowQos, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class ShowQos(command.ShowOne):
class UnsetQos(command.Command):
- """Unset QoS specification properties"""
+ _description = _("Unset QoS specification properties")
def get_parser(self, prog_name):
parser = super(UnsetQos, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/service.py b/openstackclient/volume/v1/service.py
index 867c4b9c..d468c6ff 100644
--- a/openstackclient/volume/v1/service.py
+++ b/openstackclient/volume/v1/service.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class ListService(command.Lister):
- """List service command"""
+ _description = _("List service command")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -76,7 +76,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set volume service properties"""
+ _description = _("Set volume service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py
index 1c0c0bc7..e9e3894b 100644
--- a/openstackclient/volume/v1/snapshot.py
+++ b/openstackclient/volume/v1/snapshot.py
@@ -37,7 +37,7 @@ LOG = logging.getLogger(__name__)
class CreateSnapshot(command.ShowOne):
- """Create new snapshot"""
+ _description = _("Create new snapshot")
def get_parser(self, prog_name):
parser = super(CreateSnapshot, self).get_parser(prog_name)
@@ -87,7 +87,7 @@ class CreateSnapshot(command.ShowOne):
class DeleteSnapshot(command.Command):
- """Delete snapshot(s)"""
+ _description = _("Delete snapshot(s)")
def get_parser(self, prog_name):
parser = super(DeleteSnapshot, self).get_parser(prog_name)
@@ -124,7 +124,7 @@ class DeleteSnapshot(command.Command):
class ListSnapshot(command.Lister):
- """List snapshots"""
+ _description = _("List snapshots")
def get_parser(self, prog_name):
parser = super(ListSnapshot, self).get_parser(prog_name)
@@ -197,7 +197,7 @@ class ListSnapshot(command.Lister):
class SetSnapshot(command.Command):
- """Set snapshot properties"""
+ _description = _("Set snapshot properties")
def get_parser(self, prog_name):
parser = super(SetSnapshot, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class SetSnapshot(command.Command):
class ShowSnapshot(command.ShowOne):
- """Display snapshot details"""
+ _description = _("Display snapshot details")
def get_parser(self, prog_name):
parser = super(ShowSnapshot, self).get_parser(prog_name)
@@ -286,7 +286,7 @@ class ShowSnapshot(command.ShowOne):
class UnsetSnapshot(command.Command):
- """Unset snapshot properties"""
+ _description = _("Unset snapshot properties")
def get_parser(self, prog_name):
parser = super(UnsetSnapshot, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index cafe8ce6..0087bad4 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -45,7 +45,7 @@ def _check_size_arg(args):
class CreateVolume(command.ShowOne):
- """Create new volume"""
+ _description = _("Create new volume")
def get_parser(self, prog_name):
parser = super(CreateVolume, self).get_parser(prog_name)
@@ -178,7 +178,7 @@ class CreateVolume(command.ShowOne):
class DeleteVolume(command.Command):
- """Delete volume(s)"""
+ _description = _("Delete volume(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolume, self).get_parser(prog_name)
@@ -223,7 +223,7 @@ class DeleteVolume(command.Command):
class ListVolume(command.Lister):
- """List volumes"""
+ _description = _("List volumes")
def get_parser(self, prog_name):
parser = super(ListVolume, self).get_parser(prog_name)
@@ -344,8 +344,39 @@ class ListVolume(command.Lister):
) for s in data))
+class MigrateVolume(command.Command):
+ _description = _("Migrate volume to a new host")
+
+ def get_parser(self, prog_name):
+ parser = super(MigrateVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar="<volume>",
+ help=_("Volume to migrate (name or ID)")
+ )
+ parser.add_argument(
+ '--host',
+ metavar="<host>",
+ required=True,
+ help=_("Destination host (takes the form: host@backend-name#pool)")
+ )
+ parser.add_argument(
+ '--force-host-copy',
+ action="store_true",
+ help=_("Enable generic host-based force-migration, "
+ "which bypasses driver optimizations")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ volume_client.volumes.migrate_volume(volume.id, parsed_args.host,
+ parsed_args.force_host_copy,)
+
+
class SetVolume(command.Command):
- """Set volume properties"""
+ _description = _("Set volume properties")
def get_parser(self, prog_name):
parser = super(SetVolume, self).get_parser(prog_name)
@@ -388,42 +419,82 @@ class SetVolume(command.Command):
action="store_true",
help=_("Mark volume as non-bootable")
)
+ 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")
+ )
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ result = 0
if parsed_args.size:
- if volume.status != 'available':
- LOG.error(_("Volume is in %s state, it must be available "
- "before size can be extended"), volume.status)
- return
- if parsed_args.size <= volume.size:
- LOG.error(_("New size must be greater than %s GB"),
- volume.size)
- return
- volume_client.volumes.extend(volume.id, parsed_args.size)
-
+ try:
+ if volume.status != 'available':
+ msg = (_("Volume is in %s state, it must be available "
+ "before size can be extended") % volume.status)
+ raise exceptions.CommandError(msg)
+ if parsed_args.size <= volume.size:
+ msg = (_("New size must be greater than %s GB")
+ % volume.size)
+ raise exceptions.CommandError(msg)
+ volume_client.volumes.extend(volume.id, parsed_args.size)
+ except Exception as e:
+ LOG.error(_("Failed to set volume size: %s"), e)
+ result += 1
if parsed_args.property:
- volume_client.volumes.set_metadata(volume.id, parsed_args.property)
+ try:
+ volume_client.volumes.set_metadata(
+ volume.id,
+ parsed_args.property)
+ except Exception as e:
+ LOG.error(_("Failed to set volume property: %s"), e)
+ result += 1
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)
+ result += 1
+ 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)
+ result += 1
kwargs = {}
if parsed_args.name:
kwargs['display_name'] = parsed_args.name
if parsed_args.description:
kwargs['display_description'] = parsed_args.description
if kwargs:
- volume_client.volumes.update(volume.id, **kwargs)
+ try:
+ volume_client.volumes.update(volume.id, **kwargs)
+ except Exception as e:
+ LOG.error(_("Failed to update volume display name "
+ "or display description: %s"), e)
+ result += 1
+
+ if result > 0:
+ raise exceptions.CommandError(_("One or more of the "
+ "set operations failed"))
class ShowVolume(command.ShowOne):
- """Show volume details"""
+ _description = _("Show volume details")
def get_parser(self, prog_name):
parser = super(ShowVolume, self).get_parser(prog_name)
@@ -453,7 +524,7 @@ class ShowVolume(command.ShowOne):
class UnsetVolume(command.Command):
- """Unset volume properties"""
+ _description = _("Unset volume properties")
def get_parser(self, prog_name):
parser = super(UnsetVolume, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume_transfer_request.py b/openstackclient/volume/v1/volume_transfer_request.py
index 4d6f2161..f24d5a56 100644
--- a/openstackclient/volume/v1/volume_transfer_request.py
+++ b/openstackclient/volume/v1/volume_transfer_request.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class AcceptTransferRequest(command.ShowOne):
- """Accept volume transfer request."""
+ _description = _("Accept volume transfer request.")
def get_parser(self, prog_name):
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
@@ -56,7 +56,7 @@ class AcceptTransferRequest(command.ShowOne):
class CreateTransferRequest(command.ShowOne):
- """Create volume transfer request."""
+ _description = _("Create volume transfer request.")
def get_parser(self, prog_name):
parser = super(CreateTransferRequest, self).get_parser(prog_name)
@@ -85,7 +85,7 @@ class CreateTransferRequest(command.ShowOne):
class DeleteTransferRequest(command.Command):
- """Delete volume transfer request(s)."""
+ _description = _("Delete volume transfer request(s).")
def get_parser(self, prog_name):
parser = super(DeleteTransferRequest, self).get_parser(prog_name)
@@ -120,7 +120,7 @@ class DeleteTransferRequest(command.Command):
class ListTransferRequest(command.Lister):
- """Lists all volume transfer requests."""
+ _description = _("Lists all volume transfer requests.")
def get_parser(self, prog_name):
parser = super(ListTransferRequest, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class ListTransferRequest(command.Lister):
class ShowTransferRequest(command.ShowOne):
- """Show volume transfer request details."""
+ _description = _("Show volume transfer request details.")
def get_parser(self, prog_name):
parser = super(ShowTransferRequest, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py
index 61e9f7fc..8adce322 100644
--- a/openstackclient/volume/v1/volume_type.py
+++ b/openstackclient/volume/v1/volume_type.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeType(command.ShowOne):
- """Create new volume type"""
+ _description = _("Create new volume type")
def get_parser(self, prog_name):
parser = super(CreateVolumeType, self).get_parser(prog_name)
@@ -61,7 +61,7 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type(s)"""
+ _description = _("Delete volume type(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
@@ -97,7 +97,7 @@ class DeleteVolumeType(command.Command):
class ListVolumeType(command.Lister):
- """List volume types"""
+ _description = _("List volume types")
def get_parser(self, prog_name):
parser = super(ListVolumeType, self).get_parser(prog_name)
@@ -111,10 +111,10 @@ class ListVolumeType(command.Lister):
def take_action(self, parsed_args):
if parsed_args.long:
- columns = ('ID', 'Name', 'Extra Specs')
- column_headers = ('ID', 'Name', 'Properties')
+ columns = ('ID', 'Name', 'Is Public', 'Extra Specs')
+ column_headers = ('ID', 'Name', 'Is Public', 'Properties')
else:
- columns = ('ID', 'Name')
+ columns = ('ID', 'Name', 'Is Public')
column_headers = columns
data = self.app.client_manager.volume.volume_types.list()
return (column_headers,
@@ -125,7 +125,7 @@ class ListVolumeType(command.Lister):
class SetVolumeType(command.Command):
- """Set volume type properties"""
+ _description = _("Set volume type properties")
def get_parser(self, prog_name):
parser = super(SetVolumeType, self).get_parser(prog_name)
@@ -153,7 +153,7 @@ class SetVolumeType(command.Command):
class ShowVolumeType(command.ShowOne):
- """Display volume type details"""
+ _description = _("Display volume type details")
def get_parser(self, prog_name):
parser = super(ShowVolumeType, self).get_parser(prog_name)
@@ -175,7 +175,7 @@ class ShowVolumeType(command.ShowOne):
class UnsetVolumeType(command.Command):
- """Unset volume type properties"""
+ _description = _("Unset volume type properties")
def get_parser(self, prog_name):
parser = super(UnsetVolumeType, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/backup.py b/openstackclient/volume/v2/backup.py
index 2ca35b24..00389fcb 100644
--- a/openstackclient/volume/v2/backup.py
+++ b/openstackclient/volume/v2/backup.py
@@ -17,6 +17,7 @@
import copy
import logging
+from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -29,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeBackup(command.ShowOne):
- """Create new volume backup"""
+ _description = _("Create new volume backup")
def get_parser(self, prog_name):
parser = super(CreateVolumeBackup, self).get_parser(prog_name)
@@ -94,7 +95,7 @@ class CreateVolumeBackup(command.ShowOne):
class CreateBackup(CreateVolumeBackup):
- """Create new backup"""
+ _description = _("Create new backup")
# TODO(Huanxuan Ao): Remove this class and ``backup create`` command
# two cycles after Newton.
@@ -111,7 +112,7 @@ class CreateBackup(CreateVolumeBackup):
class DeleteVolumeBackup(command.Command):
- """Delete volume backup(s)"""
+ _description = _("Delete volume backup(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeBackup, self).get_parser(prog_name)
@@ -152,7 +153,7 @@ class DeleteVolumeBackup(command.Command):
class DeleteBackup(DeleteVolumeBackup):
- """Delete backup(s)"""
+ _description = _("Delete backup(s)")
# TODO(Huanxuan Ao): Remove this class and ``backup delete`` command
# two cycles after Newton.
@@ -169,7 +170,7 @@ class DeleteBackup(DeleteVolumeBackup):
class ListVolumeBackup(command.Lister):
- """List volume backups"""
+ _description = _("List volume backups")
def get_parser(self, prog_name):
parser = super(ListVolumeBackup, self).get_parser(prog_name)
@@ -179,9 +180,48 @@ class ListVolumeBackup(command.Lister):
default=False,
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'),
+ )
+ parser.add_argument(
+ '--all-projects',
+ action='store_true',
+ default=False,
+ help=_('Include all projects (admin only)'),
+ )
return parser
def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
def _format_volume_id(volume_id):
"""Return a volume name if available
@@ -207,13 +247,31 @@ class ListVolumeBackup(command.Lister):
# Cache the volume list
volume_cache = {}
try:
- for s in self.app.client_manager.volume.volumes.list():
+ for s in volume_client.volumes.list():
volume_cache[s.id] = s
except Exception:
# Just forget it if there's any trouble
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,
+ 'all_tenants': parsed_args.all_projects,
+ }
+ data = volume_client.backups.list(
+ search_opts=search_opts,
+ marker=marker_backup_id,
+ limit=parsed_args.limit,
+ )
return (column_headers,
(utils.get_item_properties(
@@ -223,7 +281,7 @@ class ListVolumeBackup(command.Lister):
class ListBackup(ListVolumeBackup):
- """List backups"""
+ _description = _("List backups")
# TODO(Huanxuan Ao): Remove this class and ``backup list`` command
# two cycles after Newton.
@@ -240,7 +298,7 @@ class ListBackup(ListVolumeBackup):
class RestoreVolumeBackup(command.ShowOne):
- """Restore volume backup"""
+ _description = _("Restore volume backup")
def get_parser(self, prog_name):
parser = super(RestoreVolumeBackup, self).get_parser(prog_name)
@@ -265,7 +323,7 @@ class RestoreVolumeBackup(command.ShowOne):
class RestoreBackup(RestoreVolumeBackup):
- """Restore backup"""
+ _description = _("Restore backup")
# TODO(Huanxuan Ao): Remove this class and ``backup restore`` command
# two cycles after Newton.
@@ -282,7 +340,7 @@ class RestoreBackup(RestoreVolumeBackup):
class SetVolumeBackup(command.Command):
- """Set volume backup properties"""
+ _description = _("Set volume backup properties")
def get_parser(self, prog_name):
parser = super(SetVolumeBackup, self).get_parser(prog_name)
@@ -344,7 +402,7 @@ class SetVolumeBackup(command.Command):
class ShowVolumeBackup(command.ShowOne):
- """Display volume backup details"""
+ _description = _("Display volume backup details")
def get_parser(self, prog_name):
parser = super(ShowVolumeBackup, self).get_parser(prog_name)
@@ -364,7 +422,7 @@ class ShowVolumeBackup(command.ShowOne):
class ShowBackup(ShowVolumeBackup):
- """Display backup details"""
+ _description = _("Display backup details")
# TODO(Huanxuan Ao): Remove this class and ``backup show`` command
# two cycles after Newton.
diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py
index 39f2d577..661bcbe5 100644
--- a/openstackclient/volume/v2/consistency_group.py
+++ b/openstackclient/volume/v2/consistency_group.py
@@ -14,14 +14,137 @@
"""Volume v2 consistency group action implementations"""
+import logging
+
from osc_lib.command import command
+from osc_lib import exceptions
from osc_lib import utils
+import six
from openstackclient.i18n import _
+LOG = logging.getLogger(__name__)
+
+
+class DeleteConsistencyGroup(command.Command):
+ _description = _("Delete consistency group(s).")
+
+ def get_parser(self, prog_name):
+ parser = super(DeleteConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ 'consistency_groups',
+ metavar='<consistency-group>',
+ nargs="+",
+ help=_('Consistency group(s) to delete (name or ID)'),
+ )
+ parser.add_argument(
+ '--force',
+ action='store_true',
+ default=False,
+ help=_("Allow delete in state other than error or available"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ result = 0
+
+ for i in parsed_args.consistency_groups:
+ try:
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups, i).id
+ volume_client.consistencygroups.delete(
+ consistency_group_id, parsed_args.force)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete consistency group with "
+ "name or ID '%(consistency_group)s':%(e)s")
+ % {'consistency_group': i, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.consistency_groups)
+ msg = (_("%(result)s of %(total)s consistency groups failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateConsistencyGroup(command.ShowOne):
+ _description = _("Create new consistency group.")
+
+ def get_parser(self, prog_name):
+ parser = super(CreateConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ "name",
+ metavar="<name>",
+ nargs="?",
+ help=_("Name of new consistency group (default to None)")
+ )
+ exclusive_group = parser.add_mutually_exclusive_group(required=True)
+ exclusive_group.add_argument(
+ "--volume-type",
+ metavar="<volume-type>",
+ help=_("Volume type of this consistency group (name or ID)")
+ )
+ exclusive_group.add_argument(
+ "--consistency-group-source",
+ metavar="<consistency-group>",
+ help=_("Existing consistency group (name or ID)")
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help=_("Description of this consistency group")
+ )
+ parser.add_argument(
+ "--availability-zone",
+ metavar="<availability-zone>",
+ help=_("Availability zone for this consistency group "
+ "(not available if creating consistency group "
+ "from source)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ if parsed_args.volume_type:
+ volume_type_id = utils.find_resource(
+ volume_client.volume_types,
+ parsed_args.volume_type).id
+ consistency_group = volume_client.consistencygroups.create(
+ volume_type_id,
+ name=parsed_args.name,
+ description=parsed_args.description,
+ availability_zone=parsed_args.availability_zone
+ )
+ elif parsed_args.consistency_group_source:
+ if parsed_args.availability_zone:
+ msg = _("'--availability-zone' option will not work "
+ "if creating consistency group from source")
+ LOG.warning(msg)
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group_source).id
+ consistency_group_snapshot = None
+ # TODO(Huanxuan Ao): Support for creating from consistency group
+ # snapshot after adding "consistency_group_snapshot" resource
+ consistency_group = (
+ volume_client.consistencygroups.create_from_src(
+ consistency_group_snapshot,
+ consistency_group_id,
+ name=parsed_args.name,
+ description=parsed_args.description
+ )
+ )
+
+ return zip(*sorted(six.iteritems(consistency_group._info)))
+
+
class ListConsistencyGroup(command.Lister):
- """List consistency groups."""
+ _description = _("List consistency groups.")
def get_parser(self, prog_name):
parser = super(ListConsistencyGroup, self).get_parser(prog_name)
@@ -55,3 +178,23 @@ class ListConsistencyGroup(command.Lister):
s, columns,
formatters={'Volume Types': utils.format_list})
for s in consistency_groups))
+
+
+class ShowConsistencyGroup(command.ShowOne):
+ _description = _("Display consistency group details.")
+
+ def get_parser(self, prog_name):
+ parser = super(ShowConsistencyGroup, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group",
+ metavar="<consistency-group>",
+ help=_("Consistency group to display (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group)
+ return zip(*sorted(six.iteritems(consistency_group._info)))
diff --git a/openstackclient/volume/v2/consistency_group_snapshot.py b/openstackclient/volume/v2/consistency_group_snapshot.py
new file mode 100644
index 00000000..540deb01
--- /dev/null
+++ b/openstackclient/volume/v2/consistency_group_snapshot.py
@@ -0,0 +1,190 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+"""Volume v2 consistency group snapshot action implementations"""
+
+import logging
+
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateConsistencyGroupSnapshot(command.ShowOne):
+ _description = _("Create new consistency group snapshot.")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ CreateConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "snapshot_name",
+ metavar="<snapshot-name>",
+ nargs="?",
+ help=_("Name of new consistency group snapshot (default to None)")
+ )
+ parser.add_argument(
+ "--consistency-group",
+ metavar="<consistency-group>",
+ help=_("Consistency group to snapshot (name or ID) "
+ "(default to be the same as <snapshot-name>)")
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help=_("Description of this consistency group snapshot")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group = parsed_args.consistency_group
+ if not parsed_args.consistency_group:
+ # If "--consistency-group" not specified, then consistency_group
+ # will be the same as the new consistency group snapshot name
+ consistency_group = parsed_args.snapshot_name
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ consistency_group).id
+ consistency_group_snapshot = volume_client.cgsnapshots.create(
+ consistency_group_id,
+ name=parsed_args.snapshot_name,
+ description=parsed_args.description,
+ )
+
+ return zip(*sorted(six.iteritems(consistency_group_snapshot._info)))
+
+
+class DeleteConsistencyGroupSnapshot(command.Command):
+ _description = _("Delete consistency group snapshot(s).")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ DeleteConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group_snapshot",
+ metavar="<consistency-group-snapshot>",
+ nargs="+",
+ help=_("Consistency group snapshot(s) to delete (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ result = 0
+
+ for snapshot in parsed_args.consistency_group_snapshot:
+ try:
+ snapshot_id = utils.find_resource(volume_client.cgsnapshots,
+ snapshot).id
+
+ volume_client.cgsnapshots.delete(snapshot_id)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete consistency group snapshot "
+ "with name or ID '%(snapshot)s': %(e)s")
+ % {'snapshot': snapshot, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.consistency_group_snapshot)
+ msg = (_("%(result)s of %(total)s consistency group snapshots "
+ "failed to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
+
+
+class ListConsistencyGroupSnapshot(command.Lister):
+ _description = _("List consistency group snapshots.")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ ListConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ '--all-projects',
+ action="store_true",
+ help=_('Show detail for all projects (admin only) '
+ '(defaults to False)')
+ )
+ parser.add_argument(
+ '--long',
+ action="store_true",
+ help=_('List additional fields in output')
+ )
+ parser.add_argument(
+ '--status',
+ metavar="<status>",
+ choices=['available', 'error', 'creating', 'deleting',
+ 'error-deleting'],
+ help=_('Filters results by a status ("available", "error", '
+ '"creating", "deleting" or "error_deleting")')
+ )
+ parser.add_argument(
+ '--consistency-group',
+ metavar="<consistency-group>",
+ help=_('Filters results by a consistency group (name or ID)')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ if parsed_args.long:
+ columns = ['ID', 'Status', 'ConsistencyGroup ID',
+ 'Name', 'Description', 'Created At']
+ else:
+ columns = ['ID', 'Status', 'Name']
+ volume_client = self.app.client_manager.volume
+ consistency_group_id = None
+ if parsed_args.consistency_group:
+ consistency_group_id = utils.find_resource(
+ volume_client.consistencygroups,
+ parsed_args.consistency_group,
+ ).id
+ search_opts = {
+ 'all_tenants': parsed_args.all_projects,
+ 'status': parsed_args.status,
+ 'consistencygroup_id': consistency_group_id,
+ }
+ consistency_group_snapshots = volume_client.cgsnapshots.list(
+ detailed=True,
+ search_opts=search_opts,
+ )
+
+ return (columns, (
+ utils.get_item_properties(
+ s, columns)
+ for s in consistency_group_snapshots))
+
+
+class ShowConsistencyGroupSnapshot(command.ShowOne):
+ _description = _("Display consistency group snapshot details")
+
+ def get_parser(self, prog_name):
+ parser = super(
+ ShowConsistencyGroupSnapshot, self).get_parser(prog_name)
+ parser.add_argument(
+ "consistency_group_snapshot",
+ metavar="<consistency-group-snapshot>",
+ help=_("Consistency group snapshot to display (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ consistency_group_snapshot = utils.find_resource(
+ volume_client.cgsnapshots,
+ parsed_args.consistency_group_snapshot)
+ return zip(*sorted(six.iteritems(consistency_group_snapshot._info)))
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index 9797f1a6..b7f49eca 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class AssociateQos(command.Command):
- """Associate a QoS specification to a volume type"""
+ _description = _("Associate a QoS specification to a volume type")
def get_parser(self, prog_name):
parser = super(AssociateQos, self).get_parser(prog_name)
@@ -57,7 +57,7 @@ class AssociateQos(command.Command):
class CreateQos(command.ShowOne):
- """Create new QoS specification"""
+ _description = _("Create new QoS specification")
def get_parser(self, prog_name):
parser = super(CreateQos, self).get_parser(prog_name)
@@ -99,7 +99,7 @@ class CreateQos(command.ShowOne):
class DeleteQos(command.Command):
- """Delete QoS specification"""
+ _description = _("Delete QoS specification")
def get_parser(self, prog_name):
parser = super(DeleteQos, self).get_parser(prog_name)
@@ -139,7 +139,7 @@ class DeleteQos(command.Command):
class DisassociateQos(command.Command):
- """Disassociate a QoS specification from a volume type"""
+ _description = _("Disassociate a QoS specification from a volume type")
def get_parser(self, prog_name):
parser = super(DisassociateQos, self).get_parser(prog_name)
@@ -177,7 +177,7 @@ class DisassociateQos(command.Command):
class ListQos(command.Lister):
- """List QoS specifications"""
+ _description = _("List QoS specifications")
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
@@ -202,7 +202,7 @@ class ListQos(command.Lister):
class SetQos(command.Command):
- """Set QoS specification properties"""
+ _description = _("Set QoS specification properties")
def get_parser(self, prog_name):
parser = super(SetQos, self).get_parser(prog_name)
@@ -231,7 +231,7 @@ class SetQos(command.Command):
class ShowQos(command.ShowOne):
- """Display QoS specification details"""
+ _description = _("Display QoS specification details")
def get_parser(self, prog_name):
parser = super(ShowQos, self).get_parser(prog_name)
@@ -260,7 +260,7 @@ class ShowQos(command.ShowOne):
class UnsetQos(command.Command):
- """Unset QoS specification properties"""
+ _description = _("Unset QoS specification properties")
def get_parser(self, prog_name):
parser = super(UnsetQos, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/service.py b/openstackclient/volume/v2/service.py
index 867c4b9c..d468c6ff 100644
--- a/openstackclient/volume/v2/service.py
+++ b/openstackclient/volume/v2/service.py
@@ -22,7 +22,7 @@ from openstackclient.i18n import _
class ListService(command.Lister):
- """List service command"""
+ _description = _("List service command")
def get_parser(self, prog_name):
parser = super(ListService, self).get_parser(prog_name)
@@ -76,7 +76,7 @@ class ListService(command.Lister):
class SetService(command.Command):
- """Set volume service properties"""
+ _description = _("Set volume service properties")
def get_parser(self, prog_name):
parser = super(SetService, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/snapshot.py b/openstackclient/volume/v2/snapshot.py
index 2f3de211..a18887e3 100644
--- a/openstackclient/volume/v2/snapshot.py
+++ b/openstackclient/volume/v2/snapshot.py
@@ -36,7 +36,7 @@ LOG = logging.getLogger(__name__)
class CreateSnapshot(command.ShowOne):
- """Create new snapshot"""
+ _description = _("Create new snapshot")
def get_parser(self, prog_name):
parser = super(CreateSnapshot, self).get_parser(prog_name)
@@ -91,7 +91,7 @@ class CreateSnapshot(command.ShowOne):
class DeleteSnapshot(command.Command):
- """Delete volume snapshot(s)"""
+ _description = _("Delete volume snapshot(s)")
def get_parser(self, prog_name):
parser = super(DeleteSnapshot, self).get_parser(prog_name)
@@ -128,7 +128,7 @@ class DeleteSnapshot(command.Command):
class ListSnapshot(command.Lister):
- """List snapshots"""
+ _description = _("List snapshots")
def get_parser(self, prog_name):
parser = super(ListSnapshot, self).get_parser(prog_name)
@@ -211,7 +211,7 @@ class ListSnapshot(command.Lister):
class SetSnapshot(command.Command):
- """Set snapshot properties"""
+ _description = _("Set snapshot properties")
def get_parser(self, prog_name):
parser = super(SetSnapshot, self).get_parser(prog_name)
@@ -294,7 +294,7 @@ class SetSnapshot(command.Command):
class ShowSnapshot(command.ShowOne):
- """Display snapshot details"""
+ _description = _("Display snapshot details")
def get_parser(self, prog_name):
parser = super(ShowSnapshot, self).get_parser(prog_name)
@@ -318,7 +318,7 @@ class ShowSnapshot(command.ShowOne):
class UnsetSnapshot(command.Command):
- """Unset snapshot properties"""
+ _description = _("Unset snapshot properties")
def get_parser(self, prog_name):
parser = super(UnsetSnapshot, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index cb409711..80abfb55 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -45,7 +45,7 @@ def _check_size_arg(args):
class CreateVolume(command.ShowOne):
- """Create new volume"""
+ _description = _("Create new volume")
def get_parser(self, prog_name):
parser = super(CreateVolume, self).get_parser(prog_name)
@@ -211,7 +211,7 @@ class CreateVolume(command.ShowOne):
class DeleteVolume(command.Command):
- """Delete volume(s)"""
+ _description = _("Delete volume(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolume, self).get_parser(prog_name)
@@ -263,7 +263,7 @@ class DeleteVolume(command.Command):
class ListVolume(command.Lister):
- """List volumes"""
+ _description = _("List volumes")
def get_parser(self, prog_name):
parser = super(ListVolume, self).get_parser(prog_name)
@@ -409,8 +409,55 @@ class ListVolume(command.Lister):
) for s in data))
+class MigrateVolume(command.Command):
+ _description = _("Migrate volume to a new host")
+
+ def get_parser(self, prog_name):
+ parser = super(MigrateVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar="<volume>",
+ help=_("Volume to migrate (name or ID)")
+ )
+ parser.add_argument(
+ '--host',
+ metavar="<host>",
+ required=True,
+ help=_("Destination host (takes the form: host@backend-name#pool)")
+ )
+ parser.add_argument(
+ '--force-host-copy',
+ action="store_true",
+ help=_("Enable generic host-based force-migration, "
+ "which bypasses driver optimizations")
+ )
+ lock_group = parser.add_mutually_exclusive_group()
+ lock_group.add_argument(
+ '--lock-volume',
+ action="store_true",
+ help=_("If specified, the volume state will be locked "
+ "and will not allow a migration to be aborted "
+ "(possibly by another operation)")
+ )
+ lock_group.add_argument(
+ '--unlock-volume',
+ action="store_true",
+ help=_("If specified, the volume state will not be "
+ "locked and the a migration can be aborted "
+ "(default) (possibly by another operation)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+ volume_client.volumes.migrate_volume(volume.id, parsed_args.host,
+ parsed_args.force_host_copy,
+ parsed_args.lock_volume,)
+
+
class SetVolume(command.Command):
- """Set volume properties"""
+ _description = _("Set volume properties")
def get_parser(self, prog_name):
parser = super(SetVolume, self).get_parser(prog_name)
@@ -462,6 +509,19 @@ class SetVolume(command.Command):
'in the database with no regard to actual status, '
'exercise caution when using)'),
)
+ parser.add_argument(
+ '--type',
+ metavar='<volume-type>',
+ help=_('New volume type (name or ID)'),
+ )
+ parser.add_argument(
+ '--retype-policy',
+ metavar='<retype-policy>',
+ choices=['never', 'on-demand'],
+ help=_('Migration policy while re-typing volume '
+ '("never" or "on-demand", default is "never" ) '
+ '(available only when "--type" option is specified)'),
+ )
bootable_group = parser.add_mutually_exclusive_group()
bootable_group.add_argument(
"--bootable",
@@ -473,6 +533,17 @@ class SetVolume(command.Command):
action="store_true",
help=_("Mark volume as non-bootable")
)
+ 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")
+ )
return parser
def take_action(self, parsed_args):
@@ -523,6 +594,37 @@ class SetVolume(command.Command):
except Exception as e:
LOG.error(_("Failed to set volume bootable property: %s"), e)
result += 1
+ 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)
+ result += 1
+ if parsed_args.type:
+ # get the migration policy
+ migration_policy = 'never'
+ if parsed_args.retype_policy:
+ migration_policy = parsed_args.retype_policy
+ try:
+ # find the volume type
+ volume_type = utils.find_resource(
+ volume_client.volume_types,
+ parsed_args.type)
+ # reset to the new volume type
+ volume_client.volumes.retype(
+ volume.id,
+ volume_type.id,
+ migration_policy)
+ except Exception as e:
+ LOG.error(_("Failed to set volume type: %s"), e)
+ result += 1
+ elif parsed_args.retype_policy:
+ # If the "--retype-policy" is specified without "--type"
+ LOG.warning(_("'--retype-policy' option will not work "
+ "without '--type' option"))
kwargs = {}
if parsed_args.name:
@@ -543,7 +645,7 @@ class SetVolume(command.Command):
class ShowVolume(command.ShowOne):
- """Display volume details"""
+ _description = _("Display volume details")
def get_parser(self, prog_name):
parser = super(ShowVolume, self).get_parser(prog_name)
@@ -574,7 +676,7 @@ class ShowVolume(command.ShowOne):
class UnsetVolume(command.Command):
- """Unset volume properties"""
+ _description = _("Unset volume properties")
def get_parser(self, prog_name):
parser = super(UnsetVolume, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py
index 9008fe3c..aefe594a 100644
--- a/openstackclient/volume/v2/volume_transfer_request.py
+++ b/openstackclient/volume/v2/volume_transfer_request.py
@@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class AcceptTransferRequest(command.ShowOne):
- """Accept volume transfer request."""
+ _description = _("Accept volume transfer request.")
def get_parser(self, prog_name):
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
@@ -56,7 +56,7 @@ class AcceptTransferRequest(command.ShowOne):
class CreateTransferRequest(command.ShowOne):
- """Create volume transfer request."""
+ _description = _("Create volume transfer request.")
def get_parser(self, prog_name):
parser = super(CreateTransferRequest, self).get_parser(prog_name)
@@ -85,7 +85,7 @@ class CreateTransferRequest(command.ShowOne):
class DeleteTransferRequest(command.Command):
- """Delete volume transfer request(s)."""
+ _description = _("Delete volume transfer request(s).")
def get_parser(self, prog_name):
parser = super(DeleteTransferRequest, self).get_parser(prog_name)
@@ -120,7 +120,7 @@ class DeleteTransferRequest(command.Command):
class ListTransferRequest(command.Lister):
- """Lists all volume transfer requests."""
+ _description = _("Lists all volume transfer requests.")
def get_parser(self, prog_name):
parser = super(ListTransferRequest, self).get_parser(prog_name)
@@ -151,7 +151,7 @@ class ListTransferRequest(command.Lister):
class ShowTransferRequest(command.ShowOne):
- """Show volume transfer request details."""
+ _description = _("Show volume transfer request details.")
def get_parser(self, prog_name):
parser = super(ShowTransferRequest, self).get_parser(prog_name)
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 80a1f21b..42ebb53e 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -30,7 +30,7 @@ LOG = logging.getLogger(__name__)
class CreateVolumeType(command.ShowOne):
- """Create new volume type"""
+ _description = _("Create new volume type")
def get_parser(self, prog_name):
parser = super(CreateVolumeType, self).get_parser(prog_name)
@@ -116,7 +116,7 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type(s)"""
+ _description = _("Delete volume type(s)")
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
@@ -152,7 +152,7 @@ class DeleteVolumeType(command.Command):
class ListVolumeType(command.Lister):
- """List volume types"""
+ _description = _("List volume types")
def get_parser(self, prog_name):
parser = super(ListVolumeType, self).get_parser(prog_name)
@@ -176,10 +176,11 @@ class ListVolumeType(command.Lister):
def take_action(self, parsed_args):
if parsed_args.long:
- columns = ['ID', 'Name', 'Description', 'Extra Specs']
- column_headers = ['ID', 'Name', 'Description', 'Properties']
+ columns = ['ID', 'Name', 'Is Public', 'Description', 'Extra Specs']
+ column_headers = [
+ 'ID', 'Name', 'Is Public', 'Description', 'Properties']
else:
- columns = ['ID', 'Name']
+ columns = ['ID', 'Name', 'Is Public']
column_headers = columns
is_public = None
@@ -197,7 +198,7 @@ class ListVolumeType(command.Lister):
class SetVolumeType(command.Command):
- """Set volume type properties"""
+ _description = _("Set volume type properties")
def get_parser(self, prog_name):
parser = super(SetVolumeType, self).get_parser(prog_name)
@@ -213,7 +214,7 @@ class SetVolumeType(command.Command):
)
parser.add_argument(
'--description',
- metavar='<name>',
+ metavar='<description>',
help=_('Set volume type description'),
)
parser.add_argument(
@@ -286,7 +287,7 @@ class SetVolumeType(command.Command):
class ShowVolumeType(command.ShowOne):
- """Display volume type details"""
+ _description = _("Display volume type details")
def get_parser(self, prog_name):
parser = super(ShowVolumeType, self).get_parser(prog_name)
@@ -324,7 +325,7 @@ class ShowVolumeType(command.ShowOne):
class UnsetVolumeType(command.Command):
- """Unset volume type properties"""
+ _description = _("Unset volume type properties")
def get_parser(self, prog_name):
parser = super(UnsetVolumeType, self).get_parser(prog_name)