summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/api/api.py23
-rw-r--r--openstackclient/api/auth.py51
-rw-r--r--openstackclient/api/auth_plugin.py25
-rw-r--r--openstackclient/api/object_store_v1.py3
-rw-r--r--openstackclient/common/availability_zone.py13
-rw-r--r--openstackclient/common/clientmanager.py4
-rw-r--r--openstackclient/common/command.py36
-rw-r--r--openstackclient/common/configuration.py7
-rw-r--r--openstackclient/common/exceptions.py108
-rw-r--r--openstackclient/common/extension.py21
-rw-r--r--openstackclient/common/limits.py23
-rw-r--r--openstackclient/common/logs.py188
-rw-r--r--openstackclient/common/module.py10
-rw-r--r--openstackclient/common/parseractions.py153
-rw-r--r--openstackclient/common/quota.py24
-rw-r--r--openstackclient/common/timing.py32
-rw-r--r--openstackclient/common/utils.py413
-rw-r--r--openstackclient/compute/client.py26
-rw-r--r--openstackclient/compute/v2/agent.py26
-rw-r--r--openstackclient/compute/v2/aggregate.py6
-rw-r--r--openstackclient/compute/v2/console.py9
-rw-r--r--openstackclient/compute/v2/fixedip.py4
-rw-r--r--openstackclient/compute/v2/flavor.py8
-rw-r--r--openstackclient/compute/v2/floatingip.py4
-rw-r--r--openstackclient/compute/v2/floatingippool.py4
-rw-r--r--openstackclient/compute/v2/host.py7
-rw-r--r--openstackclient/compute/v2/hypervisor.py7
-rw-r--r--openstackclient/compute/v2/hypervisor_stats.py2
-rw-r--r--openstackclient/compute/v2/keypair.py13
-rw-r--r--openstackclient/compute/v2/server.py12
-rw-r--r--openstackclient/compute/v2/server_backup.py6
-rw-r--r--openstackclient/compute/v2/server_group.py17
-rw-r--r--openstackclient/compute/v2/service.py96
-rw-r--r--openstackclient/compute/v2/usage.py4
-rw-r--r--openstackclient/identity/client.py10
-rw-r--r--openstackclient/identity/common.py38
-rw-r--r--openstackclient/identity/v2_0/catalog.py35
-rw-r--r--openstackclient/identity/v2_0/ec2creds.py4
-rw-r--r--openstackclient/identity/v2_0/endpoint.py9
-rw-r--r--openstackclient/identity/v2_0/project.py18
-rw-r--r--openstackclient/identity/v2_0/role.py36
-rw-r--r--openstackclient/identity/v2_0/service.py7
-rw-r--r--openstackclient/identity/v2_0/token.py21
-rw-r--r--openstackclient/identity/v2_0/user.py12
-rw-r--r--openstackclient/identity/v3/catalog.py35
-rw-r--r--openstackclient/identity/v3/consumer.py20
-rw-r--r--openstackclient/identity/v3/credential.py29
-rw-r--r--openstackclient/identity/v3/domain.py32
-rw-r--r--openstackclient/identity/v3/ec2creds.py16
-rw-r--r--openstackclient/identity/v3/endpoint.py48
-rw-r--r--openstackclient/identity/v3/federation_protocol.py50
-rw-r--r--openstackclient/identity/v3/group.py96
-rw-r--r--openstackclient/identity/v3/identity_provider.py43
-rw-r--r--openstackclient/identity/v3/mapping.py27
-rw-r--r--openstackclient/identity/v3/policy.py28
-rw-r--r--openstackclient/identity/v3/project.py61
-rw-r--r--openstackclient/identity/v3/region.py4
-rw-r--r--openstackclient/identity/v3/role.py57
-rw-r--r--openstackclient/identity/v3/role_assignment.py20
-rw-r--r--openstackclient/identity/v3/service.py41
-rw-r--r--openstackclient/identity/v3/service_provider.py45
-rw-r--r--openstackclient/identity/v3/token.py61
-rw-r--r--openstackclient/identity/v3/trust.py32
-rw-r--r--openstackclient/identity/v3/unscoped_saml.py16
-rw-r--r--openstackclient/identity/v3/user.py69
-rw-r--r--openstackclient/image/client.py3
-rw-r--r--openstackclient/image/v1/image.py9
-rw-r--r--openstackclient/image/v2/image.py36
-rw-r--r--openstackclient/locale/de/LC_MESSAGES/openstackclient.po117
-rw-r--r--openstackclient/locale/openstackclient.pot1410
-rw-r--r--openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po63
-rw-r--r--openstackclient/network/client.py3
-rw-r--r--openstackclient/network/common.py5
-rw-r--r--openstackclient/network/v2/address_scope.py14
-rw-r--r--openstackclient/network/v2/floating_ip.py21
-rw-r--r--openstackclient/network/v2/ip_availability.py112
-rw-r--r--openstackclient/network/v2/network.py18
-rw-r--r--openstackclient/network/v2/network_segment.py22
-rw-r--r--openstackclient/network/v2/port.py33
-rw-r--r--openstackclient/network/v2/router.py16
-rw-r--r--openstackclient/network/v2/security_group.py21
-rw-r--r--openstackclient/network/v2/security_group_rule.py25
-rw-r--r--openstackclient/network/v2/subnet.py13
-rw-r--r--openstackclient/network/v2/subnet_pool.py11
-rw-r--r--openstackclient/object/client.py3
-rw-r--r--openstackclient/object/v1/account.py7
-rw-r--r--openstackclient/object/v1/container.py7
-rw-r--r--openstackclient/object/v1/object.py7
-rw-r--r--openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml1
-rw-r--r--openstackclient/shell.py53
-rw-r--r--openstackclient/tests/api/test_api.py3
-rw-r--r--openstackclient/tests/common/test_clientmanager.py25
-rw-r--r--openstackclient/tests/common/test_command.py16
-rw-r--r--openstackclient/tests/common/test_extension.py156
-rw-r--r--openstackclient/tests/common/test_logs.py15
-rw-r--r--openstackclient/tests/common/test_parseractions.py20
-rw-r--r--openstackclient/tests/common/test_timing.py94
-rw-r--r--openstackclient/tests/common/test_utils.py400
-rw-r--r--openstackclient/tests/compute/v2/fakes.py75
-rw-r--r--openstackclient/tests/compute/v2/test_agent.py62
-rw-r--r--openstackclient/tests/compute/v2/test_flavor.py59
-rw-r--r--openstackclient/tests/compute/v2/test_hypervisor.py3
-rw-r--r--openstackclient/tests/compute/v2/test_server.py96
-rw-r--r--openstackclient/tests/compute/v2/test_server_backup.py5
-rw-r--r--openstackclient/tests/compute/v2/test_server_group.py5
-rw-r--r--openstackclient/tests/compute/v2/test_service.py140
-rw-r--r--openstackclient/tests/fakes.py17
-rw-r--r--openstackclient/tests/identity/v2_0/fakes.py96
-rw-r--r--openstackclient/tests/identity/v2_0/test_catalog.py29
-rw-r--r--openstackclient/tests/identity/v2_0/test_role.py66
-rw-r--r--openstackclient/tests/identity/v2_0/test_token.py35
-rw-r--r--openstackclient/tests/identity/v2_0/test_user.py4
-rw-r--r--openstackclient/tests/identity/v3/fakes.py34
-rw-r--r--openstackclient/tests/identity/v3/test_catalog.py19
-rw-r--r--openstackclient/tests/identity/v3/test_mappings.py3
-rw-r--r--openstackclient/tests/identity/v3/test_project.py7
-rw-r--r--openstackclient/tests/identity/v3/test_token.py49
-rw-r--r--openstackclient/tests/identity/v3/test_unscoped_saml.py3
-rw-r--r--openstackclient/tests/identity/v3/test_user.py6
-rw-r--r--openstackclient/tests/image/v1/test_image.py5
-rw-r--r--openstackclient/tests/image/v2/fakes.py5
-rw-r--r--openstackclient/tests/image/v2/test_image.py40
-rw-r--r--openstackclient/tests/network/v2/fakes.py136
-rw-r--r--openstackclient/tests/network/v2/test_address_scope.py11
-rw-r--r--openstackclient/tests/network/v2/test_floating_ip.py131
-rw-r--r--openstackclient/tests/network/v2/test_ip_availability.py184
-rw-r--r--openstackclient/tests/network/v2/test_network.py15
-rw-r--r--openstackclient/tests/network/v2/test_network_segment.py9
-rw-r--r--openstackclient/tests/network/v2/test_port.py92
-rw-r--r--openstackclient/tests/network/v2/test_router.py20
-rw-r--r--openstackclient/tests/network/v2/test_security_group.py139
-rw-r--r--openstackclient/tests/network/v2/test_security_group_rule.py130
-rw-r--r--openstackclient/tests/network/v2/test_subnet.py11
-rw-r--r--openstackclient/tests/network/v2/test_subnet_pool.py12
-rw-r--r--openstackclient/tests/test_shell.py2
-rw-r--r--openstackclient/tests/volume/test_find_resource.py4
-rw-r--r--openstackclient/tests/volume/v1/fakes.py55
-rw-r--r--openstackclient/tests/volume/v1/test_qos_specs.py3
-rw-r--r--openstackclient/tests/volume/v1/test_transfer_request.py114
-rw-r--r--openstackclient/tests/volume/v1/test_volume.py22
-rw-r--r--openstackclient/tests/volume/v2/fakes.py302
-rw-r--r--openstackclient/tests/volume/v2/test_qos_specs.py2
-rw-r--r--openstackclient/tests/volume/v2/test_snapshot.py3
-rw-r--r--openstackclient/tests/volume/v2/test_transfer_request.py114
-rw-r--r--openstackclient/tests/volume/v2/test_type.py9
-rw-r--r--openstackclient/tests/volume/v2/test_volume.py3
-rw-r--r--openstackclient/volume/client.py5
-rw-r--r--openstackclient/volume/v1/backup.py5
-rw-r--r--openstackclient/volume/v1/qos_specs.py10
-rw-r--r--openstackclient/volume/v1/service.py5
-rw-r--r--openstackclient/volume/v1/snapshot.py15
-rw-r--r--openstackclient/volume/v1/volume.py25
-rw-r--r--openstackclient/volume/v1/volume_transfer_request.py51
-rw-r--r--openstackclient/volume/v1/volume_type.py8
-rw-r--r--openstackclient/volume/v2/backup.py4
-rw-r--r--openstackclient/volume/v2/qos_specs.py10
-rw-r--r--openstackclient/volume/v2/service.py5
-rw-r--r--openstackclient/volume/v2/snapshot.py13
-rw-r--r--openstackclient/volume/v2/volume.py25
-rw-r--r--openstackclient/volume/v2/volume_transfer_request.py51
-rw-r--r--openstackclient/volume/v2/volume_type.py46
161 files changed, 3361 insertions, 4467 deletions
diff --git a/openstackclient/api/api.py b/openstackclient/api/api.py
index bd2abd88..04d88f31 100644
--- a/openstackclient/api/api.py
+++ b/openstackclient/api/api.py
@@ -17,8 +17,9 @@ import simplejson as json
from keystoneauth1 import exceptions as ks_exceptions
from keystoneauth1 import session as ks_session
+from osc_lib import exceptions
-from openstackclient.common import exceptions
+from openstackclient.i18n import _
class KeystoneSession(object):
@@ -255,9 +256,11 @@ class BaseAPI(KeystoneSession):
if len(data) == 1:
return data[0]
if len(data) > 1:
- msg = "Multiple %s exist with %s='%s'"
+ msg = _("Multiple %(resource)s exist with %(attr)s='%(value)s'")
raise exceptions.CommandError(
- msg % (resource, attr, value),
+ msg % {'resource': resource,
+ 'attr': attr,
+ 'value': value}
)
# Search by id
@@ -265,8 +268,12 @@ class BaseAPI(KeystoneSession):
data = getlist(kwargs)
if len(data) == 1:
return data[0]
- msg = "No %s with a %s or ID of '%s' found"
- raise exceptions.CommandError(msg % (resource, attr, value))
+ msg = _("No %(resource)s with a %(attr)s or ID of '%(value)s' found")
+ raise exceptions.CommandError(
+ msg % {'resource': resource,
+ 'attr': attr,
+ 'value': value}
+ )
def find_bulk(
self,
@@ -314,10 +321,10 @@ class BaseAPI(KeystoneSession):
bulk_list = self.find_bulk(path, **kwargs)
num_bulk = len(bulk_list)
if num_bulk == 0:
- msg = "none found"
+ msg = _("none found")
raise exceptions.NotFound(msg)
elif num_bulk > 1:
- msg = "many found"
+ msg = _("many found")
raise RuntimeError(msg)
return bulk_list[0]
@@ -344,7 +351,7 @@ class BaseAPI(KeystoneSession):
try:
ret = self.find_one("/%s/detail" % (path), **kwargs)
except ks_exceptions.NotFound:
- msg = "%s not found" % value
+ msg = _("%s not found") % value
raise exceptions.NotFound(msg)
return ret
diff --git a/openstackclient/api/auth.py b/openstackclient/api/auth.py
index c74e8005..b56035e4 100644
--- a/openstackclient/api/auth.py
+++ b/openstackclient/api/auth.py
@@ -16,15 +16,12 @@
import argparse
import logging
-import stevedore
+from keystoneauth1.loading import base
+from osc_lib import exceptions as exc
+from osc_lib import utils
-from keystoneclient.auth import base
-
-from openstackclient.common import exceptions as exc
-from openstackclient.common import utils
from openstackclient.i18n import _
-
LOG = logging.getLogger(__name__)
# Initialize the list of Authentication plugins early in order
@@ -37,15 +34,10 @@ OPTIONS_LIST = {}
def get_plugin_list():
"""Gather plugin list and cache it"""
-
global PLUGIN_LIST
if PLUGIN_LIST is None:
- PLUGIN_LIST = stevedore.ExtensionManager(
- base.PLUGIN_NAMESPACE,
- invoke_on_load=False,
- propagate_map_exceptions=True,
- )
+ PLUGIN_LIST = base.get_available_plugin_names()
return PLUGIN_LIST
@@ -55,8 +47,9 @@ def get_options_list():
global OPTIONS_LIST
if not OPTIONS_LIST:
- for plugin in get_plugin_list():
- for o in plugin.plugin.get_options():
+ for plugin_name in get_plugin_list():
+ plugin_options = base.get_plugin_options(plugin_name)
+ for o in plugin_options:
os_name = o.dest.lower().replace('_', '-')
os_env_name = 'OS_' + os_name.upper().replace('-', '_')
OPTIONS_LIST.setdefault(
@@ -66,7 +59,7 @@ def get_options_list():
# help texts if they vary from one auth plugin to another
# also the text rendering is ugly in the CLI ...
OPTIONS_LIST[os_name]['help'] += 'With %s: %s\n' % (
- plugin.name,
+ plugin_name,
o.help,
)
return OPTIONS_LIST
@@ -83,7 +76,7 @@ def select_auth_plugin(options):
if options.auth.get('url') and options.auth.get('token'):
# service token authentication
auth_plugin_name = 'token_endpoint'
- elif options.auth_type in [plugin.name for plugin in PLUGIN_LIST]:
+ elif options.auth_type in PLUGIN_LIST:
# A direct plugin name was given, use it
auth_plugin_name = options.auth_type
elif options.auth.get('username'):
@@ -115,7 +108,7 @@ def build_auth_params(auth_plugin_name, cmd_options):
auth_params = dict(cmd_options.auth)
if auth_plugin_name:
LOG.debug('auth_type: %s', auth_plugin_name)
- auth_plugin_class = base.get_plugin_class(auth_plugin_name)
+ auth_plugin_loader = base.get_plugin_loader(auth_plugin_name)
# grab tenant from project for v2.0 API compatibility
if auth_plugin_name.startswith("v2"):
if 'project_id' in auth_params:
@@ -127,12 +120,12 @@ def build_auth_params(auth_plugin_name, cmd_options):
else:
LOG.debug('no auth_type')
# delay the plugin choice, grab every option
- auth_plugin_class = None
+ auth_plugin_loader = None
plugin_options = set([o.replace('-', '_') for o in get_options_list()])
for option in plugin_options:
LOG.debug('fetching option %s', option)
auth_params[option] = getattr(cmd_options.auth, option, None)
- return (auth_plugin_class, auth_params)
+ return (auth_plugin_loader, auth_params)
def check_valid_auth_options(options, auth_plugin_name, required_scope=True):
@@ -178,7 +171,8 @@ def check_valid_auth_options(options, auth_plugin_name, required_scope=True):
'auth.url'))
if msgs:
- raise exc.CommandError('Missing parameter(s): \n%s' % '\n'.join(msgs))
+ raise exc.CommandError(
+ _('Missing parameter(s): \n%s') % '\n'.join(msgs))
def build_auth_plugins_option_parser(parser):
@@ -188,16 +182,15 @@ def build_auth_plugins_option_parser(parser):
authentication plugin.
"""
- available_plugins = [plugin.name for plugin in get_plugin_list()]
+ available_plugins = list(get_plugin_list())
parser.add_argument(
'--os-auth-type',
metavar='<auth-type>',
dest='auth_type',
default=utils.env('OS_AUTH_TYPE'),
- help='Select an authentication type. Available types: ' +
- ', '.join(available_plugins) +
- '. Default: selected based on --os-username/--os-token' +
- ' (Env: OS_AUTH_TYPE)',
+ help=_('Select an authentication type. Available types: %s.'
+ ' Default: selected based on --os-username/--os-token'
+ ' (Env: OS_AUTH_TYPE)') % ', '.join(available_plugins),
choices=available_plugins
)
# Maintain compatibility with old tenant env vars
@@ -222,10 +215,10 @@ def build_auth_plugins_option_parser(parser):
OPTIONS_LIST[o]['env'],
utils.env(OPTIONS_LIST[o]['env']),
),
- help='%s\n(Env: %s)' % (
- OPTIONS_LIST[o]['help'],
- OPTIONS_LIST[o]['env'],
- ),
+ help=_('%(help)s\n(Env: %(env)s)') % {
+ 'help': OPTIONS_LIST[o]['help'],
+ 'env': OPTIONS_LIST[o]['env'],
+ },
)
# add tenant-related options for compatibility
# this is deprecated but still used in some tempest tests...
diff --git a/openstackclient/api/auth_plugin.py b/openstackclient/api/auth_plugin.py
index cff0b75d..36dc5160 100644
--- a/openstackclient/api/auth_plugin.py
+++ b/openstackclient/api/auth_plugin.py
@@ -18,13 +18,15 @@ import logging
from oslo_config import cfg
from six.moves.urllib import parse as urlparse
-from keystoneclient.auth.identity.generic import password as ksc_password
-from keystoneclient.auth import token_endpoint
+from keystoneauth1.loading._plugins import admin_token as token_endpoint
+from keystoneauth1.loading._plugins.identity import generic as ksa_password
+
+from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class TokenEndpoint(token_endpoint.Token):
+class TokenEndpoint(token_endpoint.AdminToken):
"""Auth plugin to handle traditional token/endpoint usage
Implements the methods required to handle token authentication
@@ -36,36 +38,31 @@ class TokenEndpoint(token_endpoint.Token):
is for bootstrapping the Keystone database.
"""
- def __init__(self, url, token, **kwargs):
+ def load_from_options(self, url, token):
"""A plugin for static authentication with an existing token
:param string url: Service endpoint
:param string token: Existing token
"""
- super(TokenEndpoint, self).__init__(endpoint=url,
- token=token)
-
- def get_auth_ref(self, session, **kwargs):
- # Stub this method for compatibility
- return None
+ return super(TokenEndpoint, self).load_from_options(endpoint=url,
+ token=token)
- @classmethod
def get_options(self):
options = super(TokenEndpoint, self).get_options()
options.extend([
# Maintain name 'url' for compatibility
cfg.StrOpt('url',
- help='Specific service endpoint to use'),
+ help=_('Specific service endpoint to use')),
cfg.StrOpt('token',
secret=True,
- help='Authentication token to use'),
+ help=_('Authentication token to use')),
])
return options
-class OSCGenericPassword(ksc_password.Password):
+class OSCGenericPassword(ksa_password.Password):
"""Auth plugin hack to work around broken Keystone configurations
The default Keystone configuration uses http://localhost:xxxx in
diff --git a/openstackclient/api/object_store_v1.py b/openstackclient/api/object_store_v1.py
index 632e8b19..ae49922d 100644
--- a/openstackclient/api/object_store_v1.py
+++ b/openstackclient/api/object_store_v1.py
@@ -20,8 +20,9 @@ import os
import six
from six.moves import urllib
+from osc_lib import utils
+
from openstackclient.api import api
-from openstackclient.common import utils
class APIv1(api.BaseAPI):
diff --git a/openstackclient/common/availability_zone.py b/openstackclient/common/availability_zone.py
index 3b0270ad..af161d1f 100644
--- a/openstackclient/common/availability_zone.py
+++ b/openstackclient/common/availability_zone.py
@@ -16,10 +16,10 @@
import copy
from novaclient import exceptions as nova_exceptions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -92,17 +92,20 @@ class ListAvailabilityZone(command.Lister):
'--compute',
action='store_true',
default=False,
- help='List compute availability zones')
+ help=_('List compute availability zones'),
+ )
parser.add_argument(
'--network',
action='store_true',
default=False,
- help='List network availability zones')
+ help=_('List network availability zones'),
+ )
parser.add_argument(
'--volume',
action='store_true',
default=False,
- help='List volume availability zones')
+ help=_('List volume availability zones'),
+ )
parser.add_argument(
'--long',
action='store_true',
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index 9c2b320c..04f624d0 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -20,12 +20,12 @@ import logging
import pkg_resources
import sys
+from osc_lib import exceptions
from oslo_utils import strutils
import requests
import six
from openstackclient.api import auth
-from openstackclient.common import exceptions
from openstackclient.common import session as osc_session
from openstackclient.identity import client as identity_client
@@ -269,7 +269,7 @@ class ClientManager(object):
endpoint = self.auth_ref.service_catalog.url_for(
service_type=service_type,
region_name=region_name,
- endpoint_type=interface,
+ interface=interface,
)
else:
# Get the passed endpoint directly from the auth plugin
diff --git a/openstackclient/common/command.py b/openstackclient/common/command.py
index fee4559e..29c1534d 100644
--- a/openstackclient/common/command.py
+++ b/openstackclient/common/command.py
@@ -12,35 +12,15 @@
# License for the specific language governing permissions and limitations
# under the License.
-import abc
-import logging
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
-from cliff import command
-from cliff import lister
-from cliff import show
-import six
+import sys
+from osc_lib.command.command import * # noqa
-class CommandMeta(abc.ABCMeta):
- def __new__(mcs, name, bases, cls_dict):
- if 'log' not in cls_dict:
- cls_dict['log'] = logging.getLogger(
- cls_dict['__module__'] + '.' + name)
- return super(CommandMeta, mcs).__new__(mcs, name, bases, cls_dict)
-
-
-@six.add_metaclass(CommandMeta)
-class Command(command.Command):
-
- def run(self, parsed_args):
- self.log.debug('run(%s)', parsed_args)
- return super(Command, self).run(parsed_args)
-
-
-class Lister(Command, lister.Lister):
- pass
-
-
-class ShowOne(Command, show.ShowOne):
- pass
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.command.command\n" % __name__
+)
diff --git a/openstackclient/common/configuration.py b/openstackclient/common/configuration.py
index a70e4d14..d6e2ab45 100644
--- a/openstackclient/common/configuration.py
+++ b/openstackclient/common/configuration.py
@@ -13,9 +13,10 @@
"""Configuration action implementations"""
+from osc_lib.command import command
import six
-from openstackclient.common import command
+from openstackclient.i18n import _
REDACTED = "<redacted>"
@@ -31,13 +32,13 @@ class ShowConfiguration(command.ShowOne):
dest="mask",
action="store_true",
default=True,
- help="Attempt to mask passwords (default)",
+ help=_("Attempt to mask passwords (default)"),
)
mask_group.add_argument(
"--unmask",
dest="mask",
action="store_false",
- help="Show password in clear text",
+ help=_("Show password in clear text"),
)
return parser
diff --git a/openstackclient/common/exceptions.py b/openstackclient/common/exceptions.py
index bdc33ddb..7124074c 100644
--- a/openstackclient/common/exceptions.py
+++ b/openstackclient/common/exceptions.py
@@ -1,5 +1,3 @@
-# Copyright 2012-2013 OpenStack, LLC.
-#
# 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
@@ -13,105 +11,15 @@
# under the License.
#
-"""Exception definitions."""
-
-
-class CommandError(Exception):
- pass
-
-
-class AuthorizationFailure(Exception):
- pass
-
-
-class PluginAttributeError(Exception):
- """A plugin threw an AttributeError while being lazily loaded."""
- # This *must not* inherit from AttributeError;
- # that would defeat the whole purpose.
- pass
-
-
-class NoTokenLookupException(Exception):
- """This does not support looking up endpoints from an existing token."""
- pass
-
-
-class EndpointNotFound(Exception):
- """Could not find Service or Region in Service Catalog."""
- pass
-
-
-class UnsupportedVersion(Exception):
- """The user is trying to use an unsupported version of the API"""
- pass
-
-
-class ClientException(Exception):
- """The base exception class for all exceptions this library raises."""
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
- def __init__(self, code, message=None, details=None):
- self.code = code
- self.message = message or self.__class__.message
- self.details = details
+import sys
- def __str__(self):
- return "%s (HTTP %s)" % (self.message, self.code)
+from osc_lib.exceptions import * # noqa
-class BadRequest(ClientException):
- """HTTP 400 - Bad request: you sent some malformed data."""
- http_status = 400
- message = "Bad request"
-
-
-class Unauthorized(ClientException):
- """HTTP 401 - Unauthorized: bad credentials."""
- http_status = 401
- message = "Unauthorized"
-
-
-class Forbidden(ClientException):
- """HTTP 403 - Forbidden: not authorized to access to this resource."""
- http_status = 403
- message = "Forbidden"
-
-
-class NotFound(ClientException):
- """HTTP 404 - Not found"""
- http_status = 404
- message = "Not found"
-
-
-class Conflict(ClientException):
- """HTTP 409 - Conflict"""
- http_status = 409
- message = "Conflict"
-
-
-class OverLimit(ClientException):
- """HTTP 413 - Over limit: reached the API limits for this time period."""
- http_status = 413
- message = "Over limit"
-
-
-# NotImplemented is a python keyword.
-class HTTPNotImplemented(ClientException):
- """HTTP 501 - Not Implemented: server does not support this operation."""
- http_status = 501
- message = "Not Implemented"
-
-
-# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__()
-# so we can do this:
-# _code_map = dict((c.http_status, c)
-# for c in ClientException.__subclasses__())
-#
-# Instead, we have to hardcode it:
-_code_map = dict((c.http_status, c) for c in [
- BadRequest,
- Unauthorized,
- Forbidden,
- NotFound,
- OverLimit,
- HTTPNotImplemented
-])
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.exceptions\n" % __name__
+)
diff --git a/openstackclient/common/extension.py b/openstackclient/common/extension.py
index 8b556b4c..327fc223 100644
--- a/openstackclient/common/extension.py
+++ b/openstackclient/common/extension.py
@@ -17,8 +17,10 @@
import itertools
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
class ListExtension(command.Lister):
@@ -30,27 +32,32 @@ class ListExtension(command.Lister):
'--compute',
action='store_true',
default=False,
- help='List extensions for the Compute API')
+ help=_('List extensions for the Compute API'),
+ )
parser.add_argument(
'--identity',
action='store_true',
default=False,
- help='List extensions for the Identity API')
+ help=_('List extensions for the Identity API'),
+ )
parser.add_argument(
'--network',
action='store_true',
default=False,
- help='List extensions for the Network API')
+ help=_('List extensions for the Network API'),
+ )
parser.add_argument(
'--volume',
action='store_true',
default=False,
- help='List extensions for the Block Storage API')
+ help=_('List extensions for the Block Storage API'),
+ )
parser.add_argument(
'--long',
action='store_true',
default=False,
- help='List additional fields in output')
+ help=_('List additional fields in output'),
+ )
return parser
def take_action(self, parsed_args):
diff --git a/openstackclient/common/limits.py b/openstackclient/common/limits.py
index 1f87abf3..f7aa82f6 100644
--- a/openstackclient/common/limits.py
+++ b/openstackclient/common/limits.py
@@ -17,8 +17,10 @@
import itertools
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -33,30 +35,33 @@ class ShowLimits(command.Lister):
dest="is_absolute",
action="store_true",
default=False,
- help="Show absolute limits")
+ help=_("Show absolute limits"),
+ )
type_group.add_argument(
"--rate",
dest="is_rate",
action="store_true",
default=False,
- help="Show rate limits")
+ help=_("Show rate limits"),
+ )
parser.add_argument(
"--reserved",
dest="is_reserved",
action="store_true",
default=False,
- help="Include reservations count [only valid with --absolute]")
+ help=_("Include reservations count [only valid with --absolute]"),
+ )
parser.add_argument(
'--project',
metavar='<project>',
- help='Show limits for a specific project (name or ID)'
- ' [only valid with --absolute]',
+ help=_('Show limits for a specific project (name or ID)'
+ ' [only valid with --absolute]'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain the project belongs to (name or ID)'
- ' [only valid with --absolute]',
+ help=_('Domain the project belongs to (name or ID)'
+ ' [only valid with --absolute]'),
)
return parser
diff --git a/openstackclient/common/logs.py b/openstackclient/common/logs.py
index 221c5997..8aa97d5b 100644
--- a/openstackclient/common/logs.py
+++ b/openstackclient/common/logs.py
@@ -11,188 +11,16 @@
# under the License.
#
-"""Application logging"""
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
-import logging
import sys
-import warnings
+from osc_lib.logs import * # noqa
+from osc_lib.logs import _FileFormatter # noqa
-def get_loggers():
- loggers = {}
- for logkey in logging.Logger.manager.loggerDict.keys():
- loggers[logkey] = logging.getLevelName(logging.getLogger(logkey).level)
- return loggers
-
-def log_level_from_options(options):
- # if --debug, --quiet or --verbose is not specified,
- # the default logging level is warning
- log_level = logging.WARNING
- if options.verbose_level == 0:
- # --quiet
- log_level = logging.ERROR
- elif options.verbose_level == 2:
- # One --verbose
- log_level = logging.INFO
- elif options.verbose_level >= 3:
- # Two or more --verbose
- log_level = logging.DEBUG
- return log_level
-
-
-def log_level_from_string(level_string):
- log_level = {
- 'critical': logging.CRITICAL,
- 'error': logging.ERROR,
- 'warning': logging.WARNING,
- 'info': logging.INFO,
- 'debug': logging.DEBUG,
- }.get(level_string, logging.WARNING)
- return log_level
-
-
-def log_level_from_config(config):
- # Check the command line option
- verbose_level = config.get('verbose_level')
- if config.get('debug', False):
- verbose_level = 3
- if verbose_level == 0:
- verbose_level = 'error'
- elif verbose_level == 1:
- # If a command line option has not been specified, check the
- # configuration file
- verbose_level = config.get('log_level', 'warning')
- elif verbose_level == 2:
- verbose_level = 'info'
- else:
- verbose_level = 'debug'
- return log_level_from_string(verbose_level)
-
-
-def set_warning_filter(log_level):
- if log_level == logging.ERROR:
- warnings.simplefilter("ignore")
- elif log_level == logging.WARNING:
- warnings.simplefilter("ignore")
- elif log_level == logging.INFO:
- warnings.simplefilter("once")
-
-
-class _FileFormatter(logging.Formatter):
- """Customize the logging format for logging handler"""
- _LOG_MESSAGE_BEGIN = (
- '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s ')
- _LOG_MESSAGE_CONTEXT = '[%(cloud)s %(username)s %(project)s] '
- _LOG_MESSAGE_END = '%(message)s'
- _LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
-
- def __init__(self, options=None, config=None, **kwargs):
- context = {}
- if options:
- context = {
- 'cloud': getattr(options, 'cloud', ''),
- 'project': getattr(options, 'os_project_name', ''),
- 'username': getattr(options, 'username', ''),
- }
- elif config:
- context = {
- 'cloud': config.config.get('cloud', ''),
- 'project': config.auth.get('project_name', ''),
- 'username': config.auth.get('username', ''),
- }
- if context:
- self.fmt = (self._LOG_MESSAGE_BEGIN +
- (self._LOG_MESSAGE_CONTEXT % context) +
- self._LOG_MESSAGE_END)
- else:
- self.fmt = self._LOG_MESSAGE_BEGIN + self._LOG_MESSAGE_END
- logging.Formatter.__init__(self, self.fmt, self._LOG_DATE_FORMAT)
-
-
-class LogConfigurator(object):
-
- _CONSOLE_MESSAGE_FORMAT = '%(message)s'
-
- def __init__(self, options):
- self.root_logger = logging.getLogger('')
- self.root_logger.setLevel(logging.DEBUG)
-
- # Force verbose_level 3 on --debug
- self.dump_trace = False
- if options.debug:
- options.verbose_level = 3
- self.dump_trace = True
-
- # Always send higher-level messages to the console via stderr
- self.console_logger = logging.StreamHandler(sys.stderr)
- log_level = log_level_from_options(options)
- self.console_logger.setLevel(log_level)
- formatter = logging.Formatter(self._CONSOLE_MESSAGE_FORMAT)
- self.console_logger.setFormatter(formatter)
- self.root_logger.addHandler(self.console_logger)
-
- # Set the warning filter now
- set_warning_filter(log_level)
-
- # Set up logging to a file
- self.file_logger = None
- log_file = options.log_file
- if log_file:
- self.file_logger = logging.FileHandler(filename=log_file)
- self.file_logger.setFormatter(_FileFormatter(options=options))
- self.file_logger.setLevel(log_level)
- self.root_logger.addHandler(self.file_logger)
-
- # Requests logs some stuff at INFO that we don't want
- # unless we have DEBUG
- requests_log = logging.getLogger("requests")
-
- # Other modules we don't want DEBUG output for
- cliff_log = logging.getLogger('cliff')
- stevedore_log = logging.getLogger('stevedore')
- iso8601_log = logging.getLogger("iso8601")
-
- if options.debug:
- # --debug forces traceback
- requests_log.setLevel(logging.DEBUG)
- else:
- requests_log.setLevel(logging.ERROR)
-
- cliff_log.setLevel(logging.ERROR)
- stevedore_log.setLevel(logging.ERROR)
- iso8601_log.setLevel(logging.ERROR)
-
- def configure(self, cloud_config):
- log_level = log_level_from_config(cloud_config.config)
- set_warning_filter(log_level)
- self.dump_trace = cloud_config.config.get('debug', self.dump_trace)
- self.console_logger.setLevel(log_level)
-
- log_file = cloud_config.config.get('log_file')
- if log_file:
- if not self.file_logger:
- self.file_logger = logging.FileHandler(filename=log_file)
- formatter = _FileFormatter(cloud_config=cloud_config)
- self.file_logger.setFormatter(formatter)
- self.file_logger.setFormatter(_FileFormatter(config=cloud_config))
- self.file_logger.setLevel(log_level)
- self.root_logger.addHandler(self.file_logger)
-
- logconfig = cloud_config.config.get('logging')
- if logconfig:
- highest_level = logging.NOTSET
- for k in logconfig.keys():
- level = log_level_from_string(logconfig[k])
- logging.getLogger(k).setLevel(level)
- if (highest_level < level):
- highest_level = level
- self.console_logger.setLevel(highest_level)
- if self.file_logger:
- self.file_logger.setLevel(highest_level)
- # loggers that are not set will use the handler level, so we
- # need to set the global level for all the loggers
- for logkey in logging.Logger.manager.loggerDict.keys():
- logger = logging.getLogger(logkey)
- if logger.level == logging.NOTSET:
- logger.setLevel(log_level)
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.logs\n" % __name__
+)
diff --git a/openstackclient/common/module.py b/openstackclient/common/module.py
index 30c67c68..7c5fcd55 100644
--- a/openstackclient/common/module.py
+++ b/openstackclient/common/module.py
@@ -15,11 +15,13 @@
"""Module action implementation"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
class ListCommand(command.Lister):
@@ -61,7 +63,7 @@ class ListModule(command.ShowOne):
'--all',
action='store_true',
default=False,
- help='Show all modules that have version information',
+ help=_('Show all modules that have version information'),
)
return parser
diff --git a/openstackclient/common/parseractions.py b/openstackclient/common/parseractions.py
index 77798f90..fa5148ec 100644
--- a/openstackclient/common/parseractions.py
+++ b/openstackclient/common/parseractions.py
@@ -1,5 +1,3 @@
-# Copyright 2013 OpenStack Foundation
-#
# 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
@@ -13,150 +11,15 @@
# under the License.
#
-"""argparse Custom Actions"""
-
-import argparse
-
-from openstackclient.i18n import _
-
-
-class KeyValueAction(argparse.Action):
- """A custom action to parse arguments as key=value pairs
-
- Ensures that ``dest`` is a dict
- """
-
- def __call__(self, parser, namespace, values, option_string=None):
- # Make sure we have an empty dict rather than None
- if getattr(namespace, self.dest, None) is None:
- setattr(namespace, self.dest, {})
-
- # Add value if an assignment else remove it
- if '=' in values:
- getattr(namespace, self.dest, {}).update([values.split('=', 1)])
- else:
- getattr(namespace, self.dest, {}).pop(values, None)
-
-
-class MultiKeyValueAction(argparse.Action):
- """A custom action to parse arguments as key1=value1,key2=value2 pairs
-
- Ensure that ``dest`` is a list. The list will finally contain multiple
- dicts, with key=value pairs in them.
-
- NOTE: The arguments string should be a comma separated key-value pairs.
- And comma(',') and equal('=') may not be used in the key or value.
- """
-
- def __init__(self, option_strings, dest, nargs=None,
- required_keys=None, optional_keys=None, **kwargs):
- """Initialize the action object, and parse customized options
-
- Required keys and optional keys can be specified when initializing
- the action to enable the key validation. If none of them specified,
- the key validation will be skipped.
-
- :param required_keys: a list of required keys
- :param optional_keys: a list of optional keys
- """
- if nargs:
- raise ValueError("Parameter 'nargs' is not allowed, but got %s"
- % nargs)
-
- super(MultiKeyValueAction, self).__init__(option_strings,
- dest, **kwargs)
-
- # required_keys: A list of keys that is required. None by default.
- if required_keys and not isinstance(required_keys, list):
- raise TypeError("'required_keys' must be a list")
- self.required_keys = set(required_keys or [])
-
- # optional_keys: A list of keys that is optional. None by default.
- if optional_keys and not isinstance(optional_keys, list):
- raise TypeError("'optional_keys' must be a list")
- self.optional_keys = set(optional_keys or [])
-
- def __call__(self, parser, namespace, values, metavar=None):
- # Make sure we have an empty list rather than None
- if getattr(namespace, self.dest, None) is None:
- setattr(namespace, self.dest, [])
-
- params = {}
- for kv in values.split(','):
- # Add value if an assignment else raise ArgumentTypeError
- if '=' in kv:
- params.update([kv.split('=', 1)])
- else:
- msg = ("Expected key=value pairs separated by comma, "
- "but got: %s" % (str(kv)))
- raise argparse.ArgumentTypeError(msg)
-
- # Check key validation
- valid_keys = self.required_keys | self.optional_keys
- if valid_keys:
- invalid_keys = [k for k in params if k not in valid_keys]
- if invalid_keys:
- msg = _("Invalid keys %(invalid_keys)s specified.\n"
- "Valid keys are: %(valid_keys)s.")
- raise argparse.ArgumentTypeError(
- msg % {'invalid_keys': ', '.join(invalid_keys),
- 'valid_keys': ', '.join(valid_keys)}
- )
-
- if self.required_keys:
- missing_keys = [k for k in self.required_keys if k not in params]
- if missing_keys:
- msg = _("Missing required keys %(missing_keys)s.\n"
- "Required keys are: %(required_keys)s.")
- raise argparse.ArgumentTypeError(
- msg % {'missing_keys': ', '.join(missing_keys),
- 'required_keys': ', '.join(self.required_keys)}
- )
-
- # Update the dest dict
- getattr(namespace, self.dest, []).append(params)
-
-
-class RangeAction(argparse.Action):
- """A custom action to parse a single value or a range of values
-
- Parses single integer values or a range of integer values delimited
- by a colon and returns a tuple of integers:
- '4' sets ``dest`` to (4, 4)
- '6:9' sets ``dest`` to (6, 9)
- """
-
- def __call__(self, parser, namespace, values, option_string=None):
- range = values.split(':')
- if len(range) == 0:
- # Nothing passed, return a zero default
- setattr(namespace, self.dest, (0, 0))
- elif len(range) == 1:
- # Only a single value is present
- setattr(namespace, self.dest, (int(range[0]), int(range[0])))
- elif len(range) == 2:
- # Range of two values
- if int(range[0]) <= int(range[1]):
- setattr(namespace, self.dest, (int(range[0]), int(range[1])))
- else:
- msg = "Invalid range, %s is not less than %s" % \
- (range[0], range[1])
- raise argparse.ArgumentError(self, msg)
- else:
- # Too many values
- msg = "Invalid range, too many values"
- raise argparse.ArgumentError(self, msg)
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
+import sys
-class NonNegativeAction(argparse.Action):
- """A custom action to check whether the value is non-negative or not
+from osc_lib.cli.parseractions import * # noqa
- Ensures the value is >= 0.
- """
- def __call__(self, parser, namespace, values, option_string=None):
- if int(values) >= 0:
- setattr(namespace, self.dest, values)
- else:
- msg = "%s expected a non-negative integer" % (str(option_string))
- raise argparse.ArgumentTypeError(msg)
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.cli.parseractions\n" % __name__
+)
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index e177fbce..087d8ea3 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -16,11 +16,13 @@
"""Quota action implementations"""
import itertools
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
# List the quota items, map the internal argument name to the option
@@ -84,14 +86,14 @@ class SetQuota(command.Command):
parser.add_argument(
'project',
metavar='<project/class>',
- help='Set quotas for this project or class (name/ID)',
+ help=_('Set quotas for this project or class (name/ID)'),
)
parser.add_argument(
'--class',
dest='quota_class',
action='store_true',
default=False,
- help='Set quotas for <class>',
+ help=_('Set quotas for <class>'),
)
for k, v in self._build_options_list():
parser.add_argument(
@@ -99,12 +101,12 @@ class SetQuota(command.Command):
metavar='<%s>' % v,
dest=k,
type=int,
- help='New value for the %s quota' % v,
+ help=_('New value for the %s quota') % v,
)
parser.add_argument(
'--volume-type',
metavar='<volume-type>',
- help='Set quotas for a specific <volume-type>',
+ help=_('Set quotas for a specific <volume-type>'),
)
return parser
@@ -142,7 +144,7 @@ class SetQuota(command.Command):
if (compute_kwargs == {} and volume_kwargs == {}
and network_kwargs == {}):
- sys.stderr.write("No quotas updated")
+ sys.stderr.write("No quotas updated\n")
return
if parsed_args.project:
@@ -187,7 +189,7 @@ class ShowQuota(command.ShowOne):
'project',
metavar='<project/class>',
nargs='?',
- help='Show quotas for this project or class (name or ID)',
+ help=_('Show quotas for this project or class (name or ID)'),
)
type_group = parser.add_mutually_exclusive_group()
type_group.add_argument(
@@ -195,14 +197,14 @@ class ShowQuota(command.ShowOne):
dest='quota_class',
action='store_true',
default=False,
- help='Show quotas for <class>',
+ help=_('Show quotas for <class>'),
)
type_group.add_argument(
'--default',
dest='default',
action='store_true',
default=False,
- help='Show default quotas for <project>'
+ help=_('Show default quotas for <project>')
)
return parser
diff --git a/openstackclient/common/timing.py b/openstackclient/common/timing.py
index 71c2fec7..facbec35 100644
--- a/openstackclient/common/timing.py
+++ b/openstackclient/common/timing.py
@@ -11,31 +11,15 @@
# under the License.
#
-"""Timing Implementation"""
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
-from openstackclient.common import command
+import sys
+from osc_lib.command.timing import * # noqa
-class Timing(command.Lister):
- """Show timing data"""
- def take_action(self, parsed_args):
- column_headers = (
- 'URL',
- 'Seconds',
- )
-
- results = []
- total = 0.0
- for url, td in self.app.timing_data:
- # NOTE(dtroyer): Take the long way here because total_seconds()
- # was added in py27.
- sec = (td.microseconds + (td.seconds + td.days *
- 86400) * 1e6) / 1e6
- total += sec
- results.append((url, sec))
- results.append(('Total', total))
- return (
- column_headers,
- results,
- )
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.command.timing\n" % __name__
+)
diff --git a/openstackclient/common/utils.py b/openstackclient/common/utils.py
index daa65c25..73cd3dc9 100644
--- a/openstackclient/common/utils.py
+++ b/openstackclient/common/utils.py
@@ -1,5 +1,3 @@
-# Copyright 2012-2013 OpenStack Foundation
-#
# 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
@@ -13,410 +11,15 @@
# under the License.
#
-"""Common client utilities"""
-
-import getpass
-import logging
-import os
-import six
-import time
-
-from oslo_utils import importutils
-
-from openstackclient.common import exceptions
-
-
-def find_resource(manager, name_or_id, **kwargs):
- """Helper for the _find_* methods.
-
- :param manager: A client manager class
- :param name_or_id: The resource we are trying to find
- :param kwargs: To be used in calling .find()
- :rtype: The found resource
-
- This method will attempt to find a resource in a variety of ways.
- Primarily .get() methods will be called with `name_or_id` as an integer
- value, and tried again as a string value.
-
- If both fail, then a .find() is attempted, which is essentially calling
- a .list() function with a 'name' query parameter that is set to
- `name_or_id`.
-
- Lastly, if any kwargs are passed in, they will be treated as additional
- query parameters. This is particularly handy in the case of finding
- resources in a domain.
-
- """
-
- # Try to get entity as integer id
- try:
- if isinstance(name_or_id, int) or name_or_id.isdigit():
- return manager.get(int(name_or_id), **kwargs)
- # FIXME(dtroyer): The exception to catch here is dependent on which
- # client library the manager passed in belongs to.
- # Eventually this should be pulled from a common set
- # of client exceptions.
- except Exception as ex:
- if type(ex).__name__ == 'NotFound':
- pass
- else:
- raise
-
- # Try directly using the passed value
- try:
- return manager.get(name_or_id, **kwargs)
- except Exception:
- pass
-
- if len(kwargs) == 0:
- kwargs = {}
-
- try:
- # Prepare the kwargs for calling find
- if 'NAME_ATTR' in manager.resource_class.__dict__:
- # novaclient does this for oddball resources
- kwargs[manager.resource_class.NAME_ATTR] = name_or_id
- else:
- kwargs['name'] = name_or_id
- except Exception:
- pass
-
- # finally try to find entity by name
- try:
- return manager.find(**kwargs)
- # FIXME(dtroyer): The exception to catch here is dependent on which
- # client library the manager passed in belongs to.
- # Eventually this should be pulled from a common set
- # of client exceptions.
- except Exception as ex:
- if type(ex).__name__ == 'NotFound':
- msg = "No %s with a name or ID of '%s' exists." % \
- (manager.resource_class.__name__.lower(), name_or_id)
- raise exceptions.CommandError(msg)
- if type(ex).__name__ == 'NoUniqueMatch':
- msg = "More than one %s exists with the name '%s'." % \
- (manager.resource_class.__name__.lower(), name_or_id)
- raise exceptions.CommandError(msg)
- else:
- pass
-
- for resource in manager.list():
- # short circuit and return the first match
- if (resource.get('id') == name_or_id or
- resource.get('name') == name_or_id):
- return resource
- else:
- # we found no match, report back this error:
- msg = "Could not find resource %s" % name_or_id
- raise exceptions.CommandError(msg)
-
-
-def format_dict(data):
- """Return a formatted string of key value pairs
-
- :param data: a dict
- :rtype: a string formatted to key='value'
- """
-
- output = ""
- for s in sorted(data):
- output = output + s + "='" + six.text_type(data[s]) + "', "
- return output[:-2]
-
-
-def format_list(data, separator=', '):
- """Return a formatted strings
-
- :param data: a list of strings
- :param separator: the separator to use between strings (default: ', ')
- :rtype: a string formatted based on separator
- """
-
- return separator.join(sorted(data))
-
-
-def format_list_of_dicts(data):
- """Return a formatted string of key value pairs for each dict
-
- :param data: a list of dicts
- :rtype: a string formatted to key='value' with dicts separated by new line
- """
-
- return '\n'.join(format_dict(i) for i in data)
-
-
-def get_field(item, field):
- try:
- if isinstance(item, dict):
- return item[field]
- else:
- return getattr(item, field)
- except Exception:
- msg = "Resource doesn't have field %s" % field
- raise exceptions.CommandError(msg)
-
-
-def get_item_properties(item, fields, mixed_case_fields=None, formatters=None):
- """Return a tuple containing the item properties.
-
- :param item: a single item resource (e.g. Server, Project, etc)
- :param fields: tuple of strings with the desired field names
- :param mixed_case_fields: tuple of field names to preserve case
- :param formatters: dictionary mapping field names to callables
- to format the values
- """
- if mixed_case_fields is None:
- mixed_case_fields = []
- if formatters is None:
- formatters = {}
-
- row = []
-
- for field in fields:
- if field in mixed_case_fields:
- field_name = field.replace(' ', '_')
- else:
- field_name = field.lower().replace(' ', '_')
- data = getattr(item, field_name, '')
- if field in formatters:
- row.append(formatters[field](data))
- else:
- row.append(data)
- return tuple(row)
-
-
-def get_dict_properties(item, fields, mixed_case_fields=None, formatters=None):
- """Return a tuple containing the item properties.
-
- :param item: a single dict resource
- :param fields: tuple of strings with the desired field names
- :param mixed_case_fields: tuple of field names to preserve case
- :param formatters: dictionary mapping field names to callables
- to format the values
- """
- if mixed_case_fields is None:
- mixed_case_fields = []
- if formatters is None:
- formatters = {}
-
- row = []
-
- for field in fields:
- if field in mixed_case_fields:
- field_name = field.replace(' ', '_')
- else:
- field_name = field.lower().replace(' ', '_')
- data = item[field_name] if field_name in item else ''
- if field in formatters:
- row.append(formatters[field](data))
- else:
- row.append(data)
- return tuple(row)
-
-
-def sort_items(items, sort_str):
- """Sort items based on sort keys and sort directions given by sort_str.
-
- :param items: a list or generator object of items
- :param sort_str: a string defining the sort rules, the format is
- '<key1>:[direction1],<key2>:[direction2]...', direction can be 'asc'
- for ascending or 'desc' for descending, if direction is not given,
- it's ascending by default
- :return: sorted items
- """
- if not sort_str:
- return items
- # items may be a generator object, transform it to a list
- items = list(items)
- sort_keys = sort_str.strip().split(',')
- for sort_key in reversed(sort_keys):
- reverse = False
- if ':' in sort_key:
- sort_key, direction = sort_key.split(':', 1)
- if not sort_key:
- msg = "empty string is not a valid sort key"
- raise exceptions.CommandError(msg)
- if direction not in ['asc', 'desc']:
- if not direction:
- direction = "empty string"
- msg = ("%s is not a valid sort direction for sort key %s, "
- "use asc or desc instead" % (direction, sort_key))
- raise exceptions.CommandError(msg)
- if direction == 'desc':
- reverse = True
- items.sort(key=lambda item: get_field(item, sort_key),
- reverse=reverse)
- return items
-
-
-def env(*vars, **kwargs):
- """Search for the first defined of possibly many env vars
-
- Returns the first environment variable defined in vars, or
- returns the default defined in kwargs.
- """
- for v in vars:
- value = os.environ.get(v, None)
- if value:
- return value
- return kwargs.get('default', '')
-
-
-def get_client_class(api_name, version, version_map):
- """Returns the client class for the requested API version
-
- :param api_name: the name of the API, e.g. 'compute', 'image', etc
- :param version: the requested API version
- :param version_map: a dict of client classes keyed by version
- :rtype: a client class for the requested API version
- """
- try:
- client_path = version_map[str(version)]
- except (KeyError, ValueError):
- msg = "Invalid %s client version '%s'. must be one of: %s" % (
- (api_name, version, ', '.join(list(version_map.keys()))))
- raise exceptions.UnsupportedVersion(msg)
-
- return importutils.import_class(client_path)
-
-
-def wait_for_status(status_f,
- res_id,
- status_field='status',
- success_status=['active'],
- error_status=['error'],
- sleep_time=5,
- callback=None):
- """Wait for status change on a resource during a long-running operation
-
- :param status_f: a status function that takes a single id argument
- :param res_id: the resource id to watch
- :param status_field: the status attribute in the returned resource object
- :param success_status: a list of status strings for successful completion
- :param error_status: a list of status strings for error
- :param sleep_time: wait this long (seconds)
- :param callback: called per sleep cycle, useful to display progress
- :rtype: True on success
- """
- while True:
- res = status_f(res_id)
- status = getattr(res, status_field, '').lower()
- if status in success_status:
- retval = True
- break
- elif status in error_status:
- retval = False
- break
- if callback:
- progress = getattr(res, 'progress', None) or 0
- callback(progress)
- time.sleep(sleep_time)
- return retval
-
-
-def wait_for_delete(manager,
- res_id,
- status_field='status',
- error_status=['error'],
- exception_name=['NotFound'],
- sleep_time=5,
- timeout=300,
- callback=None):
- """Wait for resource deletion
-
- :param manager: the manager from which we can get the resource
- :param res_id: the resource id to watch
- :param status_field: the status attribute in the returned resource object,
- this is used to check for error states while the resource is being
- deleted
- :param error_status: a list of status strings for error
- :param exception_name: a list of exception strings for deleted case
- :param sleep_time: wait this long between checks (seconds)
- :param timeout: check until this long (seconds)
- :param callback: called per sleep cycle, useful to display progress; this
- function is passed a progress value during each iteration of the wait
- loop
- :rtype: True on success, False if the resource has gone to error state or
- the timeout has been reached
- """
- total_time = 0
- while total_time < timeout:
- try:
- # might not be a bad idea to re-use find_resource here if it was
- # a bit more friendly in the exceptions it raised so we could just
- # handle a NotFound exception here without parsing the message
- res = manager.get(res_id)
- except Exception as ex:
- if type(ex).__name__ in exception_name:
- return True
- raise
-
- status = getattr(res, status_field, '').lower()
- if status in error_status:
- return False
-
- if callback:
- progress = getattr(res, 'progress', None) or 0
- callback(progress)
- time.sleep(sleep_time)
- total_time += sleep_time
-
- # if we got this far we've timed out
- return False
-
-
-def get_effective_log_level():
- """Returns the lowest logging level considered by logging handlers
-
- Retrieve and return the smallest log level set among the root
- logger's handlers (in case of multiple handlers).
- """
- root_log = logging.getLogger()
- min_log_lvl = logging.CRITICAL
- for handler in root_log.handlers:
- min_log_lvl = min(min_log_lvl, handler.level)
- return min_log_lvl
-
-
-def get_password(stdin, prompt=None, confirm=True):
- message = prompt or "User Password:"
- if hasattr(stdin, 'isatty') and stdin.isatty():
- try:
- while True:
- first_pass = getpass.getpass(message)
- if not confirm:
- return first_pass
- second_pass = getpass.getpass("Repeat " + message)
- if first_pass == second_pass:
- return first_pass
- print("The passwords entered were not the same")
- except EOFError: # Ctl-D
- raise exceptions.CommandError("Error reading password.")
- raise exceptions.CommandError("There was a request to be prompted for a"
- " password and a terminal was not detected.")
-
-
-def read_blob_file_contents(blob_file):
- try:
- with open(blob_file) as file:
- blob = file.read().strip()
- return blob
- except IOError:
- msg = "Error occurred trying to read from file %s"
- raise exceptions.CommandError(msg % blob_file)
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
+import sys
-def build_kwargs_dict(arg_name, value):
- """Return a dictionary containing `arg_name` if `value` is set."""
- kwargs = {}
- if value:
- kwargs[arg_name] = value
- return kwargs
+from osc_lib.utils import * # noqa
-def is_ascii(string):
- try:
- string.decode('ascii')
- return True
- except UnicodeDecodeError:
- return False
+sys.stderr.write(
+ "WARNING: %s is deprecated and will be removed after Jun 2017. "
+ "Please use osc_lib.utils\n" % __name__
+)
diff --git a/openstackclient/compute/client.py b/openstackclient/compute/client.py
index 82f09cec..1583676a 100644
--- a/openstackclient/compute/client.py
+++ b/openstackclient/compute/client.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -15,8 +15,11 @@
import logging
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib import exceptions
+from osc_lib import utils
+
+from openstackclient.i18n import _
+
LOG = logging.getLogger(__name__)
@@ -82,9 +85,9 @@ def build_option_parser(parser):
'--os-compute-api-version',
metavar='<compute-api-version>',
default=utils.env('OS_COMPUTE_API_VERSION'),
- help='Compute API version, default=' +
- DEFAULT_API_VERSION +
- ' (Env: OS_COMPUTE_API_VERSION)')
+ help=_("Compute API version, default=%s "
+ "(Env: OS_COMPUTE_API_VERSION)") % DEFAULT_API_VERSION
+ )
return parser
@@ -118,10 +121,9 @@ def check_api_version(check_version):
novaclient.API_MIN_VERSION,
novaclient.API_MAX_VERSION,
):
- raise exceptions.CommandError(
- "versions supported by client: %s - %s" % (
- novaclient.API_MIN_VERSION.get_string(),
- novaclient.API_MAX_VERSION.get_string(),
- ),
- )
+ msg = _("versions supported by client: %(min)s - %(max)s") % {
+ "min": novaclient.API_MIN_VERSION.get_string(),
+ "max": novaclient.API_MAX_VERSION.get_string(),
+ }
+ raise exceptions.CommandError(msg)
return True
diff --git a/openstackclient/compute/v2/agent.py b/openstackclient/compute/v2/agent.py
index e358399d..ce6898c1 100644
--- a/openstackclient/compute/v2/agent.py
+++ b/openstackclient/compute/v2/agent.py
@@ -15,10 +15,11 @@
"""Agent action implementations"""
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -75,20 +76,35 @@ class CreateAgent(command.ShowOne):
class DeleteAgent(command.Command):
- """Delete compute agent command"""
+ """Delete compute agent(s)"""
def get_parser(self, prog_name):
parser = super(DeleteAgent, self).get_parser(prog_name)
parser.add_argument(
"id",
metavar="<id>",
- help=_("ID of agent to delete")
+ nargs='+',
+ help=_("ID of agent(s) to delete")
)
return parser
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
- compute_client.agents.delete(parsed_args.id)
+ result = 0
+ for id in parsed_args.id:
+ try:
+ compute_client.agents.delete(id)
+ except Exception as e:
+ result += 1
+ self.app.log.error(_("Failed to delete agent with "
+ "ID '%(id)s': %(e)s")
+ % {'id': id, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.id)
+ msg = (_("%(result)s of %(total)s agents failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListAgent(command.Lister):
diff --git a/openstackclient/compute/v2/aggregate.py b/openstackclient/compute/v2/aggregate.py
index 752e0fdf..8000c93a 100644
--- a/openstackclient/compute/v2/aggregate.py
+++ b/openstackclient/compute/v2/aggregate.py
@@ -16,11 +16,11 @@
"""Compute v2 Aggregate action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/console.py b/openstackclient/compute/v2/console.py
index 1165862c..97d3f318 100644
--- a/openstackclient/compute/v2/console.py
+++ b/openstackclient/compute/v2/console.py
@@ -15,12 +15,13 @@
"""Compute v2 Console action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/fixedip.py b/openstackclient/compute/v2/fixedip.py
index daac97d1..8bd72ca3 100644
--- a/openstackclient/compute/v2/fixedip.py
+++ b/openstackclient/compute/v2/fixedip.py
@@ -15,8 +15,8 @@
"""Fixed IP action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
class AddFixedIP(command.Command):
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index 87909a18..ab2bc85d 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -15,12 +15,12 @@
"""Flavor action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/compute/v2/floatingip.py b/openstackclient/compute/v2/floatingip.py
index fac4d2e3..98079fbc 100644
--- a/openstackclient/compute/v2/floatingip.py
+++ b/openstackclient/compute/v2/floatingip.py
@@ -15,8 +15,8 @@
"""Floating IP action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
class AddFloatingIP(command.Command):
diff --git a/openstackclient/compute/v2/floatingippool.py b/openstackclient/compute/v2/floatingippool.py
index 997e0324..0d46e32b 100644
--- a/openstackclient/compute/v2/floatingippool.py
+++ b/openstackclient/compute/v2/floatingippool.py
@@ -15,8 +15,8 @@
"""Floating IP Pool action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
class ListFloatingIPPool(command.Lister):
diff --git a/openstackclient/compute/v2/host.py b/openstackclient/compute/v2/host.py
index 73e2cdf9..764b22af 100644
--- a/openstackclient/compute/v2/host.py
+++ b/openstackclient/compute/v2/host.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -15,8 +15,9 @@
"""Host action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py
index 333a7dea..00625050 100644
--- a/openstackclient/compute/v2/hypervisor.py
+++ b/openstackclient/compute/v2/hypervisor.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -16,10 +16,11 @@
"""Hypervisor action implementations"""
import re
+
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/hypervisor_stats.py b/openstackclient/compute/v2/hypervisor_stats.py
index 290f5418..a70f0ce1 100644
--- a/openstackclient/compute/v2/hypervisor_stats.py
+++ b/openstackclient/compute/v2/hypervisor_stats.py
@@ -16,7 +16,7 @@
import six
-from openstackclient.common import command
+from osc_lib.command import command
class ShowHypervisorStats(command.ShowOne):
diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py
index 8a58e8f2..13c0a99c 100644
--- a/openstackclient/compute/v2/keypair.py
+++ b/openstackclient/compute/v2/keypair.py
@@ -17,12 +17,13 @@
import io
import os
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
+
from openstackclient.i18n import _
@@ -84,7 +85,7 @@ class DeleteKeypair(command.Command):
parser.add_argument(
'name',
metavar='<key>',
- help=_("Public key to delete")
+ help=_("Public key to delete (name only)")
)
return parser
@@ -118,7 +119,7 @@ class ShowKeypair(command.ShowOne):
parser.add_argument(
'name',
metavar='<key>',
- help=_("Public key to display")
+ help=_("Public key to display (name only)")
)
parser.add_argument(
'--public-key',
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index 16384074..42736d66 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -19,19 +19,19 @@ import argparse
import getpass
import io
import os
-import six
import sys
-from openstackclient.common import command
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
try:
from novaclient.v2 import servers
except ImportError:
from novaclient.v1_1 import servers
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -1390,7 +1390,7 @@ class ShowServer(command.ShowOne):
if parsed_args.diagnostics:
(resp, data) = server.diagnostics()
if not resp.status_code == 200:
- sys.stderr.write(_("Error retrieving diagnostics data"))
+ sys.stderr.write(_("Error retrieving diagnostics data\n"))
return ({}, {})
else:
data = _prep_server_detail(compute_client, server)
diff --git a/openstackclient/compute/v2/server_backup.py b/openstackclient/compute/v2/server_backup.py
index 24d71015..c0e2e5ee 100644
--- a/openstackclient/compute/v2/server_backup.py
+++ b/openstackclient/compute/v2/server_backup.py
@@ -17,12 +17,12 @@
import sys
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
from oslo_utils import importutils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py
index 7baa6fe7..955b147e 100644
--- a/openstackclient/compute/v2/server_group.py
+++ b/openstackclient/compute/v2/server_group.py
@@ -15,9 +15,10 @@
"""Compute v2 Server Group action implementations"""
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.i18n import _
@@ -129,15 +130,7 @@ class ListServerGroup(command.Lister):
data = compute_client.server_groups.list(parsed_args.all_projects)
if parsed_args.long:
- column_headers = (
- 'ID',
- 'Name',
- 'Policies',
- 'Members',
- 'Project Id',
- 'User Id',
- )
- columns = (
+ column_headers = columns = (
'ID',
'Name',
'Policies',
diff --git a/openstackclient/compute/v2/service.py b/openstackclient/compute/v2/service.py
index 6093b8ce..d10af2ca 100644
--- a/openstackclient/compute/v2/service.py
+++ b/openstackclient/compute/v2/service.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -15,9 +15,12 @@
"""Service action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.i18n import _
+from openstackclient.i18n import _LE
class DeleteService(command.Command):
@@ -105,28 +108,36 @@ class SetService(command.Command):
parser.add_argument(
"service",
metavar="<service>",
- help=_("Name of service")
+ help=_("Name of service (Binary name)")
)
enabled_group = parser.add_mutually_exclusive_group()
enabled_group.add_argument(
"--enable",
- dest="enabled",
- default=True,
action="store_true",
- help=_("Enable a service (default)")
+ help=_("Enable service")
)
enabled_group.add_argument(
"--disable",
- dest="enabled",
- action="store_false",
- help=_("Disable a service")
+ action="store_true",
+ help=_("Disable service")
)
parser.add_argument(
"--disable-reason",
default=None,
metavar="<reason>",
- help=_("Reason for disabling the service (in quotas). Note that "
- "when the service is enabled, this option is ignored.")
+ help=_("Reason for disabling the service (in quotas). "
+ "Should be used with --disable option.")
+ )
+ up_down_group = parser.add_mutually_exclusive_group()
+ up_down_group.add_argument(
+ '--up',
+ action='store_true',
+ help=_('Force up service'),
+ )
+ up_down_group.add_argument(
+ '--down',
+ action='store_true',
+ help=_('Force down service'),
)
return parser
@@ -134,16 +145,51 @@ class SetService(command.Command):
compute_client = self.app.client_manager.compute
cs = compute_client.services
- if not parsed_args.enabled:
- if parsed_args.disable_reason:
- cs.disable_log_reason(parsed_args.host,
- parsed_args.service,
- parsed_args.disable_reason)
- else:
- cs.disable(parsed_args.host, parsed_args.service)
- else:
- if parsed_args.disable_reason:
- msg = _("argument --disable-reason has been ignored")
- self.log.info(msg)
-
- cs.enable(parsed_args.host, parsed_args.service)
+ if (parsed_args.enable or not parsed_args.disable) and \
+ parsed_args.disable_reason:
+ msg = _("Cannot specify option --disable-reason without "
+ "--disable specified.")
+ raise exceptions.CommandError(msg)
+
+ result = 0
+ enabled = None
+ try:
+ if parsed_args.enable:
+ enabled = True
+ if parsed_args.disable:
+ enabled = False
+
+ if enabled is not None:
+ if enabled:
+ cs.enable(parsed_args.host, parsed_args.service)
+ else:
+ if parsed_args.disable_reason:
+ cs.disable_log_reason(parsed_args.host,
+ parsed_args.service,
+ parsed_args.disable_reason)
+ else:
+ cs.disable(parsed_args.host, parsed_args.service)
+ except Exception:
+ status = "enabled" if enabled else "disabled"
+ self.log.error(_LE("Failed to set service status to %s"), status)
+ result += 1
+
+ force_down = None
+ try:
+ if parsed_args.down:
+ force_down = True
+ if parsed_args.up:
+ force_down = False
+ if force_down is not None:
+ cs.force_down(parsed_args.host, parsed_args.service,
+ force_down=force_down)
+ except Exception:
+ state = "down" if force_down else "up"
+ self.log.error(_LE("Failed to set service state to %s"), state)
+ result += 1
+
+ if result > 0:
+ msg = _("Compute service %(service)s of host %(host)s failed to "
+ "set.") % {"service": parsed_args.service,
+ "host": parsed_args.host}
+ raise exceptions.CommandError(msg)
diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py
index b83bef13..2f35b01b 100644
--- a/openstackclient/compute/v2/usage.py
+++ b/openstackclient/compute/v2/usage.py
@@ -18,10 +18,10 @@
import datetime
import sys
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/identity/client.py b/openstackclient/identity/client.py
index c166e66a..be7b643f 100644
--- a/openstackclient/identity/client.py
+++ b/openstackclient/identity/client.py
@@ -16,8 +16,10 @@
import logging
from keystoneclient.v2_0 import client as identity_client_v2
+from osc_lib import utils
+
from openstackclient.api import auth
-from openstackclient.common import utils
+from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
@@ -64,9 +66,9 @@ def build_option_parser(parser):
'--os-identity-api-version',
metavar='<identity-api-version>',
default=utils.env('OS_IDENTITY_API_VERSION'),
- help='Identity API version, default=' +
- DEFAULT_API_VERSION +
- ' (Env: OS_IDENTITY_API_VERSION)')
+ help=_('Identity API version, default=%s '
+ '(Env: OS_IDENTITY_API_VERSION)') % DEFAULT_API_VERSION,
+ )
return auth.build_auth_plugins_option_parser(parser)
diff --git a/openstackclient/identity/common.py b/openstackclient/identity/common.py
index 2afa41fb..cd767d2f 100644
--- a/openstackclient/identity/common.py
+++ b/openstackclient/identity/common.py
@@ -20,9 +20,10 @@ from keystoneclient.v3 import domains
from keystoneclient.v3 import groups
from keystoneclient.v3 import projects
from keystoneclient.v3 import users
+from osc_lib import exceptions
+from osc_lib import utils
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from openstackclient.i18n import _
def find_service(identity_client, name_type_or_id):
@@ -38,14 +39,12 @@ def find_service(identity_client, name_type_or_id):
# FIXME(dtroyer): This exception should eventually come from
# common client exceptions
except identity_exc.NotFound:
- msg = ("No service with a type, name or ID of '%s' exists."
- % name_type_or_id)
- raise exceptions.CommandError(msg)
+ msg = _("No service with a type, name or ID of '%s' exists.")
+ raise exceptions.CommandError(msg % name_type_or_id)
except identity_exc.NoUniqueMatch:
- msg = ("Multiple service matches found for '%s', "
- "use an ID to be more specific."
- % name_type_or_id)
- raise exceptions.CommandError(msg)
+ msg = _("Multiple service matches found for '%s', "
+ "use an ID to be more specific.")
+ raise exceptions.CommandError(msg % name_type_or_id)
def _get_domain_id_if_requested(identity_client, domain_name_or_id):
@@ -132,9 +131,9 @@ def add_user_domain_option_to_parser(parser):
parser.add_argument(
'--user-domain',
metavar='<user-domain>',
- help=('Domain the user belongs to (name or ID). '
- 'This can be used in case collisions between user names '
- 'exist.')
+ help=_('Domain the user belongs to (name or ID). '
+ 'This can be used in case collisions between user names '
+ 'exist.'),
)
@@ -142,9 +141,9 @@ def add_group_domain_option_to_parser(parser):
parser.add_argument(
'--group-domain',
metavar='<group-domain>',
- help=('Domain the group belongs to (name or ID). '
- 'This can be used in case collisions between group names '
- 'exist.')
+ help=_('Domain the group belongs to (name or ID). '
+ 'This can be used in case collisions between group names '
+ 'exist.'),
)
@@ -152,9 +151,9 @@ def add_project_domain_option_to_parser(parser):
parser.add_argument(
'--project-domain',
metavar='<project-domain>',
- help=('Domain the project belongs to (name or ID). '
- 'This can be used in case collisions between project names '
- 'exist.')
+ help=_('Domain the project belongs to (name or ID). '
+ 'This can be used in case collisions between project names '
+ 'exist.'),
)
@@ -163,5 +162,6 @@ def add_inherited_option_to_parser(parser):
'--inherited',
action='store_true',
default=False,
- help=('Specifies if the role grant is inheritable to the sub projects')
+ help=_('Specifies if the role grant is inheritable to the sub '
+ 'projects'),
)
diff --git a/openstackclient/identity/v2_0/catalog.py b/openstackclient/identity/v2_0/catalog.py
index 53a6fe34..62e6b1f9 100644
--- a/openstackclient/identity/v2_0/catalog.py
+++ b/openstackclient/identity/v2_0/catalog.py
@@ -13,10 +13,11 @@
"""Identity v2 Service Catalog action implementations"""
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -41,13 +42,14 @@ class ListCatalog(command.Lister):
def take_action(self, parsed_args):
- # This is ugly because if auth hasn't happened yet we need
- # to trigger it here.
- sc = self.app.client_manager.session.auth.get_auth_ref(
- self.app.client_manager.session,
- ).service_catalog
+ # Trigger auth if it has not happened yet
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
+ raise exceptions.AuthorizationFailure(
+ "Only an authorized user may issue a new token."
+ )
- data = sc.get_data()
+ data = auth_ref.service_catalog.catalog
columns = ('Name', 'Type', 'Endpoints')
return (columns,
(utils.get_dict_properties(
@@ -72,14 +74,15 @@ class ShowCatalog(command.ShowOne):
def take_action(self, parsed_args):
- # This is ugly because if auth hasn't happened yet we need
- # to trigger it here.
- sc = self.app.client_manager.session.auth.get_auth_ref(
- self.app.client_manager.session,
- ).service_catalog
+ # Trigger auth if it has not happened yet
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
+ raise exceptions.AuthorizationFailure(
+ "Only an authorized user may issue a new token."
+ )
data = None
- for service in sc.get_data():
+ for service in auth_ref.service_catalog.catalog:
if (service.get('name') == parsed_args.service or
service.get('type') == parsed_args.service):
data = service
@@ -89,8 +92,8 @@ class ShowCatalog(command.ShowOne):
break
if not data:
- self.app.log.error('service %s not found\n' %
+ self.app.log.error(_('service %s not found\n') %
parsed_args.service)
- return ([], [])
+ return ((), ())
return zip(*sorted(six.iteritems(data)))
diff --git a/openstackclient/identity/v2_0/ec2creds.py b/openstackclient/identity/v2_0/ec2creds.py
index dfd67591..78f65824 100644
--- a/openstackclient/identity/v2_0/ec2creds.py
+++ b/openstackclient/identity/v2_0/ec2creds.py
@@ -16,10 +16,10 @@
"""Identity v2 EC2 Credentials action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py
index fcb82eb7..ee2bab6f 100644
--- a/openstackclient/identity/v2_0/endpoint.py
+++ b/openstackclient/identity/v2_0/endpoint.py
@@ -15,10 +15,10 @@
"""Endpoint action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -31,7 +31,7 @@ class CreateEndpoint(command.ShowOne):
parser.add_argument(
'service',
metavar='<service>',
- help=_('New endpoint service (name or ID)'),
+ help=_('Service to be associated with new endpoint (name or ID)'),
)
parser.add_argument(
'--publicurl',
@@ -81,7 +81,8 @@ class DeleteEndpoint(command.Command):
parser.add_argument(
'endpoint',
metavar='<endpoint-id>',
- help=_('Endpoint ID to delete'))
+ help=_('Endpoint to delete (ID only)'),
+ )
return parser
def take_action(self, parsed_args):
diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py
index d90162c9..8be482fe 100644
--- a/openstackclient/identity/v2_0/project.py
+++ b/openstackclient/identity/v2_0/project.py
@@ -15,13 +15,12 @@
"""Identity v2 Project action implementations"""
-import six
-
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -88,7 +87,7 @@ class CreateProject(command.ShowOne):
identity_client.tenants,
parsed_args.name,
)
- self.log.info('Returning existing project %s', project.name)
+ self.log.info(_('Returning existing project %s'), project.name)
else:
raise e
@@ -231,7 +230,8 @@ class ShowProject(command.ShowOne):
parser.add_argument(
'project',
metavar='<project>',
- help=_('Project to display (name or ID)'))
+ help=_('Project to display (name or ID)'),
+ )
return parser
def take_action(self, parsed_args):
@@ -295,9 +295,9 @@ class UnsetProject(command.Command):
metavar='<key>',
action='append',
default=[],
+ required=True,
help=_('Unset a project property '
'(repeat option to unset multiple properties)'),
- required=True,
)
return parser
@@ -308,7 +308,7 @@ class UnsetProject(command.Command):
parsed_args.project,
)
if not parsed_args.property:
- self.app.log.error("No changes requested\n")
+ self.app.log.error(_("No changes requested\n"))
else:
kwargs = project._info
for key in parsed_args.property:
diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py
index 1fcee15f..4c3fe6e2 100644
--- a/openstackclient/identity/v2_0/role.py
+++ b/openstackclient/identity/v2_0/role.py
@@ -15,13 +15,12 @@
"""Identity v2 Role action implementations"""
-import six
-
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -95,7 +94,7 @@ class CreateRole(command.ShowOne):
identity_client.roles,
parsed_args.role_name,
)
- self.log.info('Returning existing role %s', role.name)
+ self.log.info(_('Returning existing role %s'), role.name)
else:
raise e
@@ -136,12 +135,12 @@ class ListRole(command.Lister):
parser.add_argument(
'--project',
metavar='<project>',
- help='Filter roles by <project> (name or ID)',
+ help=_('Filter roles by <project> (name or ID)'),
)
parser.add_argument(
'--user',
metavar='<user>',
- help='Filter roles by <user> (name or ID)',
+ help=_('Filter roles by <user> (name or ID)'),
)
return parser
@@ -231,18 +230,19 @@ class ListUserRole(command.Lister):
# Project and user are required, if not included in command args
# default to the values used for authentication. For token-flow
# authentication they must be included on the command line.
+ if (not parsed_args.project and
+ self.app.client_manager.auth_ref.project_id):
+ parsed_args.project = auth_ref.project_id
if not parsed_args.project:
- if self.app.client_manager.auth_ref:
- parsed_args.project = auth_ref.project_id
- else:
- msg = _("Project must be specified")
- raise exceptions.CommandError(msg)
+ msg = _("Project must be specified")
+ raise exceptions.CommandError(msg)
+
+ if (not parsed_args.user and
+ self.app.client_manager.auth_ref.user_id):
+ parsed_args.user = auth_ref.user_id
if not parsed_args.user:
- if self.app.client_manager.auth_ref:
- parsed_args.user = auth_ref.user_id
- else:
- msg = _("User must be specified")
- raise exceptions.CommandError(msg)
+ msg = _("User must be specified")
+ raise exceptions.CommandError(msg)
project = utils.find_resource(
identity_client.tenants,
diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py
index 7fe66d91..947f361c 100644
--- a/openstackclient/identity/v2_0/service.py
+++ b/openstackclient/identity/v2_0/service.py
@@ -16,11 +16,12 @@
"""Service action implementations"""
import argparse
+
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v2_0/token.py b/openstackclient/identity/v2_0/token.py
index f435d7ce..56f920f3 100644
--- a/openstackclient/identity/v2_0/token.py
+++ b/openstackclient/identity/v2_0/token.py
@@ -15,9 +15,10 @@
"""Identity v2 Token action implementations"""
+from osc_lib.command import command
+from osc_lib import exceptions
import six
-from openstackclient.common import command
from openstackclient.i18n import _
@@ -32,11 +33,21 @@ class IssueToken(command.ShowOne):
return parser
def take_action(self, parsed_args):
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
+ raise exceptions.AuthorizationFailure(
+ "Only an authorized user may issue a new token.")
- token = self.app.client_manager.auth_ref.service_catalog.get_token()
- if 'tenant_id' in token:
- token['project_id'] = token.pop('tenant_id')
- return zip(*sorted(six.iteritems(token)))
+ data = {}
+ if auth_ref.auth_token:
+ data['id'] = auth_ref.auth_token
+ if auth_ref.expires:
+ data['expires'] = auth_ref.expires
+ if auth_ref.project_id:
+ data['project_id'] = auth_ref.project_id
+ if auth_ref.user_id:
+ data['user_id'] = auth_ref.user_id
+ return zip(*sorted(six.iteritems(data)))
class RevokeToken(command.Command):
diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py
index bc9bf837..7777bab8 100644
--- a/openstackclient/identity/v2_0/user.py
+++ b/openstackclient/identity/v2_0/user.py
@@ -15,12 +15,11 @@
"""Identity v2.0 User action implementations"""
-import six
-
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -104,7 +103,7 @@ class CreateUser(command.ShowOne):
identity_client.users,
parsed_args.name,
)
- self.log.info('Returning existing user %s', user.name)
+ self.log.info(_('Returning existing user %s'), user.name)
else:
raise e
@@ -159,7 +158,8 @@ class ListUser(command.Lister):
'--long',
action='store_true',
default=False,
- help=_('List additional fields in output'))
+ help=_('List additional fields in output'),
+ )
return parser
def take_action(self, parsed_args):
diff --git a/openstackclient/identity/v3/catalog.py b/openstackclient/identity/v3/catalog.py
index 78d71f59..a6e141c9 100644
--- a/openstackclient/identity/v3/catalog.py
+++ b/openstackclient/identity/v3/catalog.py
@@ -13,10 +13,11 @@
"""Identity v3 Service Catalog action implementations"""
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -36,13 +37,14 @@ class ListCatalog(command.Lister):
def take_action(self, parsed_args):
- # This is ugly because if auth hasn't happened yet we need
- # to trigger it here.
- sc = self.app.client_manager.session.auth.get_auth_ref(
- self.app.client_manager.session,
- ).service_catalog
+ # Trigger auth if it has not happened yet
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
+ raise exceptions.AuthorizationFailure(
+ "Only an authorized user may issue a new token."
+ )
- data = sc.get_data()
+ data = auth_ref.service_catalog.catalog
columns = ('Name', 'Type', 'Endpoints')
return (columns,
(utils.get_dict_properties(
@@ -67,14 +69,15 @@ class ShowCatalog(command.ShowOne):
def take_action(self, parsed_args):
- # This is ugly because if auth hasn't happened yet we need
- # to trigger it here.
- sc = self.app.client_manager.session.auth.get_auth_ref(
- self.app.client_manager.session,
- ).service_catalog
+ # Trigger auth if it has not happened yet
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
+ raise exceptions.AuthorizationFailure(
+ "Only an authorized user may issue a new token."
+ )
data = None
- for service in sc.get_data():
+ for service in auth_ref.service_catalog.catalog:
if (service.get('name') == parsed_args.service or
service.get('type') == parsed_args.service):
data = dict(service)
@@ -84,8 +87,8 @@ class ShowCatalog(command.ShowOne):
break
if not data:
- self.app.log.error('service %s not found\n' %
+ self.app.log.error(_('service %s not found\n') %
parsed_args.service)
- return ([], [])
+ return ((), ())
return zip(*sorted(six.iteritems(data)))
diff --git a/openstackclient/identity/v3/consumer.py b/openstackclient/identity/v3/consumer.py
index 0da4103d..a4620bf9 100644
--- a/openstackclient/identity/v3/consumer.py
+++ b/openstackclient/identity/v3/consumer.py
@@ -15,11 +15,13 @@
"""Identity v3 Consumer action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
class CreateConsumer(command.ShowOne):
@@ -30,7 +32,7 @@ class CreateConsumer(command.ShowOne):
parser.add_argument(
'--description',
metavar='<description>',
- help='New consumer description',
+ help=_('New consumer description'),
)
return parser
@@ -51,7 +53,7 @@ class DeleteConsumer(command.Command):
parser.add_argument(
'consumer',
metavar='<consumer>',
- help='Consumer to delete',
+ help=_('Consumer to delete'),
)
return parser
@@ -83,12 +85,12 @@ class SetConsumer(command.Command):
parser.add_argument(
'consumer',
metavar='<consumer>',
- help='Consumer to modify',
+ help=_('Consumer to modify'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New consumer description',
+ help=_('New consumer description'),
)
return parser
@@ -101,7 +103,7 @@ class SetConsumer(command.Command):
kwargs['description'] = parsed_args.description
if not len(kwargs):
- sys.stdout.write('Consumer not updated, no arguments present')
+ sys.stdout.write(_('Consumer not updated, no arguments present\n'))
return
consumer = identity_client.oauth1.consumers.update(
@@ -116,7 +118,7 @@ class ShowConsumer(command.ShowOne):
parser.add_argument(
'consumer',
metavar='<consumer>',
- help='Consumer to display',
+ help=_('Consumer to display'),
)
return parser
diff --git a/openstackclient/identity/v3/credential.py b/openstackclient/identity/v3/credential.py
index b0d2cafd..eeeddfa5 100644
--- a/openstackclient/identity/v3/credential.py
+++ b/openstackclient/identity/v3/credential.py
@@ -15,10 +15,11 @@
"""Identity v3 Credential action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
+from openstackclient.i18n import _
class CreateCredential(command.ShowOne):
@@ -29,24 +30,25 @@ class CreateCredential(command.ShowOne):
parser.add_argument(
'user',
metavar='<user>',
- help='Name or ID of user that owns the credential',
+ help=_('Name or ID of user that owns the credential'),
)
parser.add_argument(
'--type',
default="cert",
metavar='<type>',
choices=['ec2', 'cert'],
- help='New credential type',
+ help=_('New credential type'),
)
parser.add_argument(
'data',
metavar='<data>',
- help='New credential data',
+ help=_('New credential data'),
)
parser.add_argument(
'--project',
metavar='<project>',
- help='Project name or ID which limits the scope of the credential',
+ help=_('Project name or ID which limits the '
+ 'scope of the credential'),
)
return parser
@@ -77,7 +79,7 @@ class DeleteCredential(command.Command):
parser.add_argument(
'credential',
metavar='<credential-id>',
- help='ID of credential to delete',
+ help=_('ID of credential to delete'),
)
return parser
@@ -108,31 +110,32 @@ class SetCredential(command.Command):
parser.add_argument(
'credential',
metavar='<credential-id>',
- help='ID of credential to change',
+ help=_('ID of credential to change'),
)
parser.add_argument(
'--user',
metavar='<user>',
required=True,
- help='Name or ID of user that owns the credential',
+ help=_('Name or ID of user that owns the credential'),
)
parser.add_argument(
'--type',
metavar='<type>',
choices=['ec2', 'cert'],
required=True,
- help='New credential type',
+ help=_('New credential type'),
)
parser.add_argument(
'--data',
metavar='<data>',
required=True,
- help='New credential data',
+ help=_('New credential data'),
)
parser.add_argument(
'--project',
metavar='<project>',
- help='Project name or ID which limits the scope of the credential',
+ help=_('Project name or ID which limits the '
+ 'scope of the credential'),
)
return parser
@@ -163,7 +166,7 @@ class ShowCredential(command.ShowOne):
parser.add_argument(
'credential',
metavar='<credential-id>',
- help='ID of credential to display',
+ help=_('ID of credential to display'),
)
return parser
diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py
index 7fcab4f1..8eb7bc91 100644
--- a/openstackclient/identity/v3/domain.py
+++ b/openstackclient/identity/v3/domain.py
@@ -15,13 +15,13 @@
"""Identity v3 Domain action implementations"""
-import six
import sys
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -33,23 +33,23 @@ class CreateDomain(command.ShowOne):
parser.add_argument(
'name',
metavar='<domain-name>',
- help='New domain name',
+ help=_('New domain name'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New domain description',
+ help=_('New domain description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable domain (default)',
+ help=_('Enable domain (default)'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable domain',
+ help=_('Disable domain'),
)
parser.add_argument(
'--or-show',
@@ -75,7 +75,7 @@ class CreateDomain(command.ShowOne):
if parsed_args.or_show:
domain = utils.find_resource(identity_client.domains,
parsed_args.name)
- self.log.info('Returning existing domain %s', domain.name)
+ self.log.info(_('Returning existing domain %s'), domain.name)
else:
raise e
@@ -91,7 +91,7 @@ class DeleteDomain(command.Command):
parser.add_argument(
'domain',
metavar='<domain>',
- help='Domain to delete (name or ID)',
+ help=_('Domain to delete (name or ID)'),
)
return parser
@@ -123,28 +123,28 @@ class SetDomain(command.Command):
parser.add_argument(
'domain',
metavar='<domain>',
- help='Domain to modify (name or ID)',
+ help=_('Domain to modify (name or ID)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='New domain name',
+ help=_('New domain name'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New domain description',
+ help=_('New domain description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable domain',
+ help=_('Enable domain'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable domain',
+ help=_('Disable domain'),
)
return parser
@@ -164,7 +164,7 @@ class SetDomain(command.Command):
kwargs['enabled'] = False
if not kwargs:
- sys.stdout.write("Domain not updated, no arguments present")
+ sys.stdout.write(_("Domain not updated, no arguments present\n"))
return
identity_client.domains.update(domain.id, **kwargs)
@@ -177,7 +177,7 @@ class ShowDomain(command.ShowOne):
parser.add_argument(
'domain',
metavar='<domain>',
- help='Domain to display (name or ID)',
+ help=_('Domain to display (name or ID)'),
)
return parser
diff --git a/openstackclient/identity/v3/ec2creds.py b/openstackclient/identity/v3/ec2creds.py
index a12b2d3b..835fe96f 100644
--- a/openstackclient/identity/v3/ec2creds.py
+++ b/openstackclient/identity/v3/ec2creds.py
@@ -12,10 +12,10 @@
"""Identity v3 EC2 Credentials action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -56,18 +56,14 @@ class CreateEC2Creds(command.ShowOne):
parser.add_argument(
'--project',
metavar='<project>',
- help=_(
- 'Create credentials in project '
- '(name or ID; default: current authenticated project)'
- ),
+ help=_('Create credentials in project '
+ '(name or ID; default: current authenticated project)'),
)
parser.add_argument(
'--user',
metavar='<user>',
- help=_(
- 'Create credentials for user '
- '(name or ID; default: current authenticated user)'
- ),
+ help=_('Create credentials for user '
+ '(name or ID; default: current authenticated user)'),
)
common.add_user_domain_option_to_parser(parser)
common.add_project_domain_option_to_parser(parser)
diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py
index b03b78ce..2f1cc9f3 100644
--- a/openstackclient/identity/v3/endpoint.py
+++ b/openstackclient/identity/v3/endpoint.py
@@ -15,11 +15,13 @@
"""Identity v3 Endpoint action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
from openstackclient.identity import common
@@ -38,23 +40,23 @@ class CreateEndpoint(command.ShowOne):
parser.add_argument(
'service',
metavar='<service>',
- help='New endpoint service (name or ID)',
+ help=_('Service to be associated with new endpoint (name or ID)'),
)
parser.add_argument(
'interface',
metavar='<interface>',
choices=['admin', 'public', 'internal'],
- help='New endpoint interface type (admin, public or internal)',
+ help=_('New endpoint interface type (admin, public or internal)'),
)
parser.add_argument(
'url',
metavar='<url>',
- help='New endpoint URL',
+ help=_('New endpoint URL'),
)
parser.add_argument(
'--region',
metavar='<region-id>',
- help='New endpoint region ID',
+ help=_('New endpoint region ID'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
@@ -62,13 +64,13 @@ class CreateEndpoint(command.ShowOne):
dest='enabled',
action='store_true',
default=True,
- help='Enable endpoint (default)',
+ help=_('Enable endpoint (default)'),
)
enable_group.add_argument(
'--disable',
dest='enabled',
action='store_false',
- help='Disable endpoint',
+ help=_('Disable endpoint'),
)
return parser
@@ -100,7 +102,7 @@ class DeleteEndpoint(command.Command):
parser.add_argument(
'endpoint',
metavar='<endpoint-id>',
- help='Endpoint ID to delete',
+ help=_('Endpoint to delete (ID only)'),
)
return parser
@@ -119,18 +121,18 @@ class ListEndpoint(command.Lister):
parser.add_argument(
'--service',
metavar='<service>',
- help='Filter by service',
+ help=_('Filter by service (name or ID)'),
)
parser.add_argument(
'--interface',
metavar='<interface>',
choices=['admin', 'public', 'internal'],
- help='Filter by interface type (admin, public or internal)',
+ help=_('Filter by interface type (admin, public or internal)'),
)
parser.add_argument(
'--region',
metavar='<region-id>',
- help='Filter by region ID',
+ help=_('Filter by region ID'),
)
return parser
@@ -167,41 +169,41 @@ class SetEndpoint(command.Command):
parser.add_argument(
'endpoint',
metavar='<endpoint-id>',
- help='Endpoint ID to modify',
+ help=_('Endpoint to modify (ID only)'),
)
parser.add_argument(
'--region',
metavar='<region-id>',
- help='New endpoint region ID',
+ help=_('New endpoint region ID'),
)
parser.add_argument(
'--interface',
metavar='<interface>',
choices=['admin', 'public', 'internal'],
- help='New endpoint interface type (admin, public or internal)',
+ help=_('New endpoint interface type (admin, public or internal)'),
)
parser.add_argument(
'--url',
metavar='<url>',
- help='New endpoint URL',
+ help=_('New endpoint URL'),
)
parser.add_argument(
'--service',
metavar='<service>',
- help='New endpoint service (name or ID)',
+ help=_('New endpoint service (name or ID)'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
dest='enabled',
action='store_true',
- help='Enable endpoint',
+ help=_('Enable endpoint'),
)
enable_group.add_argument(
'--disable',
dest='disabled',
action='store_true',
- help='Disable endpoint',
+ help=_('Disable endpoint'),
)
return parser
@@ -213,7 +215,7 @@ class SetEndpoint(command.Command):
if (not parsed_args.interface and not parsed_args.url
and not parsed_args.service and not parsed_args.region
and not parsed_args.enabled and not parsed_args.disabled):
- sys.stdout.write("Endpoint not updated, no arguments present")
+ sys.stdout.write(_("Endpoint not updated, no arguments present\n"))
return
service_id = None
@@ -244,8 +246,8 @@ class ShowEndpoint(command.ShowOne):
parser.add_argument(
'endpoint',
metavar='<endpoint>',
- help='Endpoint to display (endpoint ID, service ID,'
- ' service name, service type)',
+ help=_('Endpoint to display (endpoint ID, service ID,'
+ ' service name, service type)'),
)
return parser
diff --git a/openstackclient/identity/v3/federation_protocol.py b/openstackclient/identity/v3/federation_protocol.py
index 27c837c5..377ddcce 100644
--- a/openstackclient/identity/v3/federation_protocol.py
+++ b/openstackclient/identity/v3/federation_protocol.py
@@ -14,10 +14,11 @@
"""Identity v3 Protocols actions implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
+from openstackclient.i18n import _
class CreateProtocol(command.ShowOne):
@@ -28,19 +29,22 @@ class CreateProtocol(command.ShowOne):
parser.add_argument(
'federation_protocol',
metavar='<name>',
- help='New federation protocol name (must be unique per identity '
- ' provider)')
+ help=_('New federation protocol name (must be unique '
+ 'per identity provider)'),
+ )
parser.add_argument(
'--identity-provider',
metavar='<identity-provider>',
required=True,
- help='Identity provider that will support the new federation '
- ' protocol (name or ID) (required)')
+ help=_('Identity provider that will support the new federation '
+ ' protocol (name or ID) (required)'),
+ )
parser.add_argument(
'--mapping',
metavar='<mapping>',
required=True,
- help='Mapping that is to be used (name or ID) (required)')
+ help=_('Mapping that is to be used (name or ID) (required)'),
+ )
return parser
@@ -69,13 +73,15 @@ class DeleteProtocol(command.Command):
parser.add_argument(
'federation_protocol',
metavar='<federation-protocol>',
- help='Federation protocol to delete (name or ID)')
+ help=_('Federation protocol to delete (name or ID)'),
+ )
parser.add_argument(
'--identity-provider',
metavar='<identity-provider>',
required=True,
- help='Identity provider that supports <federation-protocol> '
- '(name or ID) (required)')
+ help=_('Identity provider that supports <federation-protocol> '
+ '(name or ID) (required)'),
+ )
return parser
@@ -94,7 +100,8 @@ class ListProtocols(command.Lister):
'--identity-provider',
metavar='<identity-provider>',
required=True,
- help='Identity provider to list (name or ID) (required)')
+ help=_('Identity provider to list (name or ID) (required)'),
+ )
return parser
@@ -118,24 +125,27 @@ class SetProtocol(command.Command):
parser.add_argument(
'federation_protocol',
metavar='<name>',
- help='Federation protocol to modify (name or ID)')
+ help=_('Federation protocol to modify (name or ID)'),
+ )
parser.add_argument(
'--identity-provider',
metavar='<identity-provider>',
required=True,
- help='Identity provider that supports <federation-protocol> '
- '(name or ID) (required)')
+ help=_('Identity provider that supports <federation-protocol> '
+ '(name or ID) (required)'),
+ )
parser.add_argument(
'--mapping',
metavar='<mapping>',
- help='Mapping that is to be used (name or ID)')
+ help=_('Mapping that is to be used (name or ID)'),
+ )
return parser
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
if not parsed_args.mapping:
- self.app.log.error("No changes requested")
+ self.app.log.error(_("No changes requested"))
return
protocol = identity_client.federation.protocols.update(
@@ -159,13 +169,15 @@ class ShowProtocol(command.ShowOne):
parser.add_argument(
'federation_protocol',
metavar='<federation-protocol>',
- help='Federation protocol to display (name or ID)')
+ help=_('Federation protocol to display (name or ID)'),
+ )
parser.add_argument(
'--identity-provider',
metavar='<identity-provider>',
required=True,
- help=('Identity provider that supports <federation-protocol> '
- '(name or ID) (required)'))
+ help=_('Identity provider that supports <federation-protocol> '
+ '(name or ID) (required)'),
+ )
return parser
def take_action(self, parsed_args):
diff --git a/openstackclient/identity/v3/group.py b/openstackclient/identity/v3/group.py
index 3c243531..fb0a25b9 100644
--- a/openstackclient/identity/v3/group.py
+++ b/openstackclient/identity/v3/group.py
@@ -15,13 +15,13 @@
"""Group action implementations"""
-import six
import sys
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -34,12 +34,12 @@ class AddUserToGroup(command.Command):
parser.add_argument(
'group',
metavar='<group>',
- help='Group to contain <user> (name or ID)',
+ help=_('Group to contain <user> (name or ID)'),
)
parser.add_argument(
'user',
metavar='<user>',
- help='User to add to <group> (name or ID)',
+ help=_('User to add to <group> (name or ID)'),
)
common.add_group_domain_option_to_parser(parser)
common.add_user_domain_option_to_parser(parser)
@@ -58,11 +58,17 @@ class AddUserToGroup(command.Command):
try:
identity_client.users.add_to_group(user_id, group_id)
except Exception:
- sys.stderr.write("%s not added to group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s not added to group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stderr.write(msg)
else:
- sys.stdout.write("%s added to group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s added to group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stdout.write(msg)
class CheckUserInGroup(command.Command):
@@ -73,12 +79,12 @@ class CheckUserInGroup(command.Command):
parser.add_argument(
'group',
metavar='<group>',
- help='Group to check (name or ID)',
+ help=_('Group to check (name or ID)'),
)
parser.add_argument(
'user',
metavar='<user>',
- help='User to check (name or ID)',
+ help=_('User to check (name or ID)'),
)
common.add_group_domain_option_to_parser(parser)
common.add_user_domain_option_to_parser(parser)
@@ -97,11 +103,17 @@ class CheckUserInGroup(command.Command):
try:
identity_client.users.check_in_group(user_id, group_id)
except Exception:
- sys.stderr.write("%s not in group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s not in group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stderr.write(msg)
else:
- sys.stdout.write("%s in group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s in group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stdout.write(msg)
class CreateGroup(command.ShowOne):
@@ -112,17 +124,17 @@ class CreateGroup(command.ShowOne):
parser.add_argument(
'name',
metavar='<group-name>',
- help='New group name',
+ help=_('New group name'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain to contain new group (name or ID)',
+ help=_('Domain to contain new group (name or ID)'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New group description',
+ help=_('New group description'),
)
parser.add_argument(
'--or-show',
@@ -149,7 +161,7 @@ class CreateGroup(command.ShowOne):
group = utils.find_resource(identity_client.groups,
parsed_args.name,
domain_id=domain)
- self.log.info('Returning existing group %s', group.name)
+ self.log.info(_('Returning existing group %s'), group.name)
else:
raise e
@@ -166,11 +178,12 @@ class DeleteGroup(command.Command):
'groups',
metavar='<group>',
nargs="+",
- help='Group(s) to delete (name or ID)')
+ help=_('Group(s) to delete (name or ID)'),
+ )
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain containing group(s) (name or ID)',
+ help=_('Domain containing group(s) (name or ID)'),
)
return parser
@@ -192,19 +205,19 @@ class ListGroup(command.Lister):
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Filter group list by <domain> (name or ID)',
+ help=_('Filter group list by <domain> (name or ID)'),
)
parser.add_argument(
'--user',
metavar='<user>',
- help='Filter group list by <user> (name or ID)',
+ help=_('Filter group list by <user> (name or ID)'),
)
common.add_user_domain_option_to_parser(parser)
parser.add_argument(
'--long',
action='store_true',
default=False,
- help='List additional fields in output',
+ help=_('List additional fields in output'),
)
return parser
@@ -252,12 +265,12 @@ class RemoveUserFromGroup(command.Command):
parser.add_argument(
'group',
metavar='<group>',
- help='Group containing <user> (name or ID)',
+ help=_('Group containing <user> (name or ID)'),
)
parser.add_argument(
'user',
metavar='<user>',
- help='User to remove from <group> (name or ID)',
+ help=_('User to remove from <group> (name or ID)'),
)
common.add_group_domain_option_to_parser(parser)
common.add_user_domain_option_to_parser(parser)
@@ -276,11 +289,17 @@ class RemoveUserFromGroup(command.Command):
try:
identity_client.users.remove_from_group(user_id, group_id)
except Exception:
- sys.stderr.write("%s not removed from group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s not removed from group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stderr.write(msg)
else:
- sys.stdout.write("%s removed from group %s\n" %
- (parsed_args.user, parsed_args.group))
+ msg = _("%(user)s removed from group %(group)s\n") % {
+ 'user': parsed_args.user,
+ 'group': parsed_args.group,
+ }
+ sys.stdout.write(msg)
class SetGroup(command.Command):
@@ -291,20 +310,23 @@ class SetGroup(command.Command):
parser.add_argument(
'group',
metavar='<group>',
- help='Group to modify (name or ID)')
+ help=_('Group to modify (name or ID)'),
+ )
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain containing <group> (name or ID)',
+ help=_('Domain containing <group> (name or ID)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='New group name')
+ help=_('New group name'),
+ )
parser.add_argument(
'--description',
metavar='<description>',
- help='New group description')
+ help=_('New group description'),
+ )
return parser
def take_action(self, parsed_args):
@@ -318,7 +340,7 @@ class SetGroup(command.Command):
kwargs['description'] = parsed_args.description
if not len(kwargs):
- sys.stderr.write("Group not updated, no arguments present")
+ sys.stderr.write("Group not updated, no arguments present\n")
return
identity_client.groups.update(group.id, **kwargs)
@@ -331,12 +353,12 @@ class ShowGroup(command.ShowOne):
parser.add_argument(
'group',
metavar='<group>',
- help='Group to display (name or ID)',
+ help=_('Group to display (name or ID)'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain containing <group> (name or ID)',
+ help=_('Domain containing <group> (name or ID)'),
)
return parser
diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py
index 39f440f4..0b530a26 100644
--- a/openstackclient/identity/v3/identity_provider.py
+++ b/openstackclient/identity/v3/identity_provider.py
@@ -13,10 +13,11 @@
"""Identity v3 IdentityProvider action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
+from openstackclient.i18n import _
class CreateIdentityProvider(command.ShowOne):
@@ -27,26 +28,26 @@ class CreateIdentityProvider(command.ShowOne):
parser.add_argument(
'identity_provider_id',
metavar='<name>',
- help='New identity provider name (must be unique)'
+ help=_('New identity provider name (must be unique)'),
)
identity_remote_id_provider = parser.add_mutually_exclusive_group()
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
action='append',
- help='Remote IDs to associate with the Identity Provider '
- '(repeat option to provide multiple values)'
+ help=_('Remote IDs to associate with the Identity Provider '
+ '(repeat option to provide multiple values)'),
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
metavar='<file-name>',
- help='Name of a file that contains many remote IDs to associate '
- 'with the identity provider, one per line'
+ help=_('Name of a file that contains many remote IDs to associate '
+ 'with the identity provider, one per line'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New identity provider description',
+ help=_('New identity provider description'),
)
enable_identity_provider = parser.add_mutually_exclusive_group()
enable_identity_provider.add_argument(
@@ -54,13 +55,13 @@ class CreateIdentityProvider(command.ShowOne):
dest='enabled',
action='store_true',
default=True,
- help='Enable identity provider (default)',
+ help=_('Enable identity provider (default)'),
)
enable_identity_provider.add_argument(
'--disable',
dest='enabled',
action='store_false',
- help='Disable the identity provider',
+ help=_('Disable the identity provider'),
)
return parser
@@ -94,7 +95,7 @@ class DeleteIdentityProvider(command.Command):
parser.add_argument(
'identity_provider',
metavar='<identity-provider>',
- help='Identity provider to delete',
+ help=_('Identity provider to delete'),
)
return parser
@@ -126,37 +127,37 @@ class SetIdentityProvider(command.Command):
parser.add_argument(
'identity_provider',
metavar='<identity-provider>',
- help='Identity provider to modify',
+ help=_('Identity provider to modify'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='Set identity provider description',
+ help=_('Set identity provider description'),
)
identity_remote_id_provider = parser.add_mutually_exclusive_group()
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
action='append',
- help='Remote IDs to associate with the Identity Provider '
- '(repeat option to provide multiple values)'
+ help=_('Remote IDs to associate with the Identity Provider '
+ '(repeat option to provide multiple values)'),
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
metavar='<file-name>',
- help='Name of a file that contains many remote IDs to associate '
- 'with the identity provider, one per line'
+ help=_('Name of a file that contains many remote IDs to associate '
+ 'with the identity provider, one per line'),
)
enable_identity_provider = parser.add_mutually_exclusive_group()
enable_identity_provider.add_argument(
'--enable',
action='store_true',
- help='Enable the identity provider',
+ help=_('Enable the identity provider'),
)
enable_identity_provider.add_argument(
'--disable',
action='store_true',
- help='Disable the identity provider',
+ help=_('Disable the identity provider'),
)
return parser
@@ -168,7 +169,7 @@ class SetIdentityProvider(command.Command):
not parsed_args.remote_id and
not parsed_args.remote_id_file and
not parsed_args.description):
- self.log.error('No changes requested')
+ self.log.error(_('No changes requested'))
return (None, None)
# Always set remote_ids if either is passed in
@@ -206,7 +207,7 @@ class ShowIdentityProvider(command.ShowOne):
parser.add_argument(
'identity_provider',
metavar='<identity-provider>',
- help='Identity provider to display',
+ help=_('Identity provider to display'),
)
return parser
diff --git a/openstackclient/identity/v3/mapping.py b/openstackclient/identity/v3/mapping.py
index 3cdc8afc..5937474e 100644
--- a/openstackclient/identity/v3/mapping.py
+++ b/openstackclient/identity/v3/mapping.py
@@ -17,11 +17,12 @@
import json
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from openstackclient.i18n import _
class _RulesReader(object):
@@ -69,9 +70,9 @@ class _RulesReader(object):
try:
rules = json.loads(blob)
except ValueError as e:
- raise exceptions.CommandError(
- 'An error occurred when reading '
- 'rules from file %s: %s' % (path, e))
+ msg = _("An error occurred when reading rules from file "
+ "%(path)s: %(error)s") % {"path": path, "error": e}
+ raise exceptions.CommandError(msg)
else:
return rules
@@ -84,12 +85,12 @@ class CreateMapping(command.ShowOne, _RulesReader):
parser.add_argument(
'mapping',
metavar='<name>',
- help='New mapping name (must be unique)',
+ help=_('New mapping name (must be unique)'),
)
parser.add_argument(
'--rules',
metavar='<filename>', required=True,
- help='Filename that contains a set of mapping rules (required)',
+ help=_('Filename that contains a set of mapping rules (required)'),
)
return parser
@@ -113,7 +114,7 @@ class DeleteMapping(command.Command):
parser.add_argument(
'mapping',
metavar='<mapping>',
- help='Mapping to delete',
+ help=_('Mapping to delete'),
)
return parser
@@ -145,12 +146,12 @@ class SetMapping(command.Command, _RulesReader):
parser.add_argument(
'mapping',
metavar='<name>',
- help='Mapping to modify',
+ help=_('Mapping to modify'),
)
parser.add_argument(
'--rules',
metavar='<filename>',
- help='Filename that contains a new set of mapping rules',
+ help=_('Filename that contains a new set of mapping rules'),
)
return parser
@@ -158,7 +159,7 @@ class SetMapping(command.Command, _RulesReader):
identity_client = self.app.client_manager.identity
if not parsed_args.rules:
- self.app.log.error("No changes requested")
+ self.app.log.error(_("No changes requested"))
return
rules = self._read_rules(parsed_args.rules)
@@ -179,7 +180,7 @@ class ShowMapping(command.ShowOne):
parser.add_argument(
'mapping',
metavar='<mapping>',
- help='Mapping to display',
+ help=_('Mapping to display'),
)
return parser
diff --git a/openstackclient/identity/v3/policy.py b/openstackclient/identity/v3/policy.py
index 3c2d1a7c..68fb2738 100644
--- a/openstackclient/identity/v3/policy.py
+++ b/openstackclient/identity/v3/policy.py
@@ -15,11 +15,13 @@
"""Identity v3 Policy action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
class CreatePolicy(command.ShowOne):
@@ -31,13 +33,13 @@ class CreatePolicy(command.ShowOne):
'--type',
metavar='<type>',
default="application/json",
- help='New MIME type of the policy rules file '
- '(defaults to application/json)',
+ help=_('New MIME type of the policy rules file '
+ '(defaults to application/json)'),
)
parser.add_argument(
'rules',
metavar='<filename>',
- help='New serialized policy rules file',
+ help=_('New serialized policy rules file'),
)
return parser
@@ -62,7 +64,7 @@ class DeletePolicy(command.Command):
parser.add_argument(
'policy',
metavar='<policy>',
- help='Policy to delete',
+ help=_('Policy to delete'),
)
return parser
@@ -80,7 +82,7 @@ class ListPolicy(command.Lister):
'--long',
action='store_true',
default=False,
- help='List additional fields in output',
+ help=_('List additional fields in output'),
)
return parser
@@ -107,17 +109,17 @@ class SetPolicy(command.Command):
parser.add_argument(
'policy',
metavar='<policy>',
- help='Policy to modify',
+ help=_('Policy to modify'),
)
parser.add_argument(
'--type',
metavar='<type>',
- help='New MIME type of the policy rules file',
+ help=_('New MIME type of the policy rules file'),
)
parser.add_argument(
'--rules',
metavar='<filename>',
- help='New serialized policy rules file',
+ help=_('New serialized policy rules file'),
)
return parser
@@ -135,7 +137,7 @@ class SetPolicy(command.Command):
kwargs['type'] = parsed_args.type
if not kwargs:
- sys.stdout.write('Policy not updated, no arguments present \n')
+ sys.stdout.write(_('Policy not updated, no arguments present\n'))
return
identity_client.policies.update(parsed_args.policy, **kwargs)
@@ -148,7 +150,7 @@ class ShowPolicy(command.ShowOne):
parser.add_argument(
'policy',
metavar='<policy>',
- help='Policy to display',
+ help=_('Policy to display'),
)
return parser
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py
index 4990b1b9..6145dcf1 100644
--- a/openstackclient/identity/v3/project.py
+++ b/openstackclient/identity/v3/project.py
@@ -15,13 +15,12 @@
"""Project action implementations"""
-import six
-
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -34,40 +33,40 @@ class CreateProject(command.ShowOne):
parser.add_argument(
'name',
metavar='<project-name>',
- help='New project name',
+ help=_('New project name'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning the project (name or ID)',
+ help=_('Domain owning the project (name or ID)'),
)
parser.add_argument(
'--parent',
metavar='<project>',
- help='Parent of the project (name or ID)',
+ help=_('Parent of the project (name or ID)'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='Project description',
+ help=_('Project description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable project',
+ help=_('Enable project'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable project',
+ help=_('Disable project'),
)
parser.add_argument(
'--property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
- help='Add a property to <name> '
- '(repeat option to set multiple properties)',
+ help=_('Add a property to <name> '
+ '(repeat option to set multiple properties)'),
)
parser.add_argument(
'--or-show',
@@ -112,7 +111,7 @@ class CreateProject(command.ShowOne):
project = utils.find_resource(identity_client.projects,
parsed_args.name,
domain_id=domain)
- self.log.info('Returning existing project %s', project.name)
+ self.log.info(_('Returning existing project %s'), project.name)
else:
raise e
@@ -129,12 +128,12 @@ class DeleteProject(command.Command):
'projects',
metavar='<project>',
nargs="+",
- help='Project(s) to delete (name or ID)',
+ help=_('Project(s) to delete (name or ID)'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <project> (name or ID)',
+ help=_('Domain owning <project> (name or ID)'),
)
return parser
@@ -163,18 +162,18 @@ class ListProject(command.Lister):
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Filter projects by <domain> (name or ID)',
+ help=_('Filter projects by <domain> (name or ID)'),
)
parser.add_argument(
'--user',
metavar='<user>',
- help='Filter projects by <user> (name or ID)',
+ help=_('Filter projects by <user> (name or ID)'),
)
parser.add_argument(
'--long',
action='store_true',
default=False,
- help='List additional fields in output',
+ help=_('List additional fields in output'),
)
return parser
@@ -219,40 +218,40 @@ class SetProject(command.Command):
parser.add_argument(
'project',
metavar='<project>',
- help='Project to modify (name or ID)',
+ help=_('Project to modify (name or ID)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='Set project name',
+ help=_('Set project name'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <project> (name or ID)',
+ help=_('Domain owning <project> (name or ID)'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='Set project description',
+ help=_('Set project description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable project',
+ help=_('Enable project'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable project',
+ help=_('Disable project'),
)
parser.add_argument(
'--property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
- help='Set a property on <project> '
- '(repeat option to set multiple properties)',
+ help=_('Set a property on <project> '
+ '(repeat option to set multiple properties)'),
)
return parser
@@ -293,24 +292,24 @@ class ShowProject(command.ShowOne):
parser.add_argument(
'project',
metavar='<project>',
- help='Project to display (name or ID)',
+ help=_('Project to display (name or ID)'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <project> (name or ID)',
+ help=_('Domain owning <project> (name or ID)'),
)
parser.add_argument(
'--parents',
action='store_true',
default=False,
- help='Show the project\'s parents as a list',
+ help=_('Show the project\'s parents as a list'),
)
parser.add_argument(
'--children',
action='store_true',
default=False,
- help='Show project\'s subtree (children) as a list',
+ help=_('Show project\'s subtree (children) as a list'),
)
return parser
diff --git a/openstackclient/identity/v3/region.py b/openstackclient/identity/v3/region.py
index 053e4b31..b5e46a9a 100644
--- a/openstackclient/identity/v3/region.py
+++ b/openstackclient/identity/v3/region.py
@@ -13,10 +13,10 @@
"""Identity v3 Region action implementations"""
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py
index f93c9d80..1bb27585 100644
--- a/openstackclient/identity/v3/role.py
+++ b/openstackclient/identity/v3/role.py
@@ -15,13 +15,13 @@
"""Identity v3 Role action implementations"""
-import six
import sys
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -31,23 +31,23 @@ def _add_identity_and_resource_options_to_parser(parser):
domain_or_project.add_argument(
'--domain',
metavar='<domain>',
- help='Include <domain> (name or ID)',
+ help=_('Include <domain> (name or ID)'),
)
domain_or_project.add_argument(
'--project',
metavar='<project>',
- help='Include <project> (name or ID)',
+ help=_('Include <project> (name or ID)'),
)
user_or_group = parser.add_mutually_exclusive_group()
user_or_group.add_argument(
'--user',
metavar='<user>',
- help='Include <user> (name or ID)',
+ help=_('Include <user> (name or ID)'),
)
user_or_group.add_argument(
'--group',
metavar='<group>',
- help='Include <group> (name or ID)',
+ help=_('Include <group> (name or ID)'),
)
common.add_group_domain_option_to_parser(parser)
common.add_project_domain_option_to_parser(parser)
@@ -112,7 +112,7 @@ class AddRole(command.Command):
parser.add_argument(
'role',
metavar='<role>',
- help='Role to add to <user> (name or ID)',
+ help=_('Role to add to <user> (name or ID)'),
)
_add_identity_and_resource_options_to_parser(parser)
return parser
@@ -131,9 +131,9 @@ class AddRole(command.Command):
kwargs = _process_identity_and_resource_options(
parsed_args, self.app.client_manager.identity)
if not kwargs:
- sys.stderr.write("Role not added, incorrect set of arguments "
- "provided. See openstack --help for more "
- "details\n")
+ sys.stderr.write(_("Role not added, incorrect set of arguments "
+ "provided. See openstack --help for more "
+ "details\n"))
return
identity_client.roles.grant(role.id, **kwargs)
@@ -147,7 +147,7 @@ class CreateRole(command.ShowOne):
parser.add_argument(
'name',
metavar='<role-name>',
- help='New role name',
+ help=_('New role name'),
)
parser.add_argument(
'--or-show',
@@ -165,7 +165,7 @@ class CreateRole(command.ShowOne):
if parsed_args.or_show:
role = utils.find_resource(identity_client.roles,
parsed_args.name)
- self.log.info('Returning existing role %s', role.name)
+ self.log.info(_('Returning existing role %s'), role.name)
else:
raise e
@@ -182,7 +182,7 @@ class DeleteRole(command.Command):
'roles',
metavar='<role>',
nargs="+",
- help='Role(s) to delete (name or ID)',
+ help=_('Role(s) to delete (name or ID)'),
)
return parser
@@ -285,9 +285,9 @@ class ListRole(command.Lister):
group_role.group = group.name
group_role.project = project.name
else:
- sys.stderr.write("Error: If a user or group is specified, either "
- "--domain or --project must also be specified to "
- "list role grants.\n")
+ sys.stderr.write(_("Error: If a user or group is specified, "
+ "either --domain or --project must also be "
+ "specified to list role grants.\n"))
return ([], [])
return (columns,
@@ -305,7 +305,7 @@ class RemoveRole(command.Command):
parser.add_argument(
'role',
metavar='<role>',
- help='Role to remove (name or ID)',
+ help=_('Role to remove (name or ID)'),
)
_add_identity_and_resource_options_to_parser(parser)
return parser
@@ -315,9 +315,8 @@ class RemoveRole(command.Command):
if (not parsed_args.user and not parsed_args.domain
and not parsed_args.group and not parsed_args.project):
- sys.stderr.write("Incorrect set of arguments "
- "provided. See openstack --help for more "
- "details\n")
+ sys.stderr.write(_("Incorrect set of arguments provided. "
+ "See openstack --help for more details\n"))
return
role = utils.find_resource(
identity_client.roles,
@@ -327,8 +326,9 @@ class RemoveRole(command.Command):
kwargs = _process_identity_and_resource_options(
parsed_args, self.app.client_manager.identity)
if not kwargs:
- sys.stderr.write("Role not removed, incorrect set of arguments \
- provided. See openstack --help for more details\n")
+ sys.stderr.write(_("Role not removed, incorrect set of arguments "
+ "provided. See openstack --help for more "
+ "details\n"))
return
identity_client.roles.revoke(role.id, **kwargs)
@@ -341,12 +341,12 @@ class SetRole(command.Command):
parser.add_argument(
'role',
metavar='<role>',
- help='Role to modify (name or ID)',
+ help=_('Role to modify (name or ID)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='Set role name',
+ help=_('Set role name'),
)
return parser
@@ -354,9 +354,8 @@ class SetRole(command.Command):
identity_client = self.app.client_manager.identity
if not parsed_args.name:
- sys.stderr.write("Incorrect set of arguments "
- "provided. See openstack --help for more "
- "details\n")
+ sys.stderr.write(_("Incorrect set of arguments provided. "
+ "See openstack --help for more details\n"))
return
role = utils.find_resource(
identity_client.roles,
@@ -374,7 +373,7 @@ class ShowRole(command.ShowOne):
parser.add_argument(
'role',
metavar='<role>',
- help='Role to display (name or ID)',
+ help=_('Role to display (name or ID)'),
)
return parser
diff --git a/openstackclient/identity/v3/role_assignment.py b/openstackclient/identity/v3/role_assignment.py
index a1418a82..39e2336d 100644
--- a/openstackclient/identity/v3/role_assignment.py
+++ b/openstackclient/identity/v3/role_assignment.py
@@ -13,8 +13,10 @@
"""Identity v3 Assignment action implementations """
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
from openstackclient.identity import common
@@ -27,41 +29,41 @@ class ListRoleAssignment(command.Lister):
'--effective',
action="store_true",
default=False,
- help='Returns only effective role assignments',
+ help=_('Returns only effective role assignments'),
)
parser.add_argument(
'--role',
metavar='<role>',
- help='Role to filter (name or ID)',
+ help=_('Role to filter (name or ID)'),
)
parser.add_argument(
'--names',
action="store_true",
- help='Display names instead of IDs',
+ help=_('Display names instead of IDs'),
)
user_or_group = parser.add_mutually_exclusive_group()
user_or_group.add_argument(
'--user',
metavar='<user>',
- help='User to filter (name or ID)',
+ help=_('User to filter (name or ID)'),
)
common.add_user_domain_option_to_parser(parser)
user_or_group.add_argument(
'--group',
metavar='<group>',
- help='Group to filter (name or ID)',
+ help=_('Group to filter (name or ID)'),
)
common.add_group_domain_option_to_parser(parser)
domain_or_project = parser.add_mutually_exclusive_group()
domain_or_project.add_argument(
'--domain',
metavar='<domain>',
- help='Domain to filter (name or ID)',
+ help=_('Domain to filter (name or ID)'),
)
domain_or_project.add_argument(
'--project',
metavar='<project>',
- help='Project to filter (name or ID)',
+ help=_('Project to filter (name or ID)'),
)
common.add_project_domain_option_to_parser(parser)
common.add_inherited_option_to_parser(parser)
diff --git a/openstackclient/identity/v3/service.py b/openstackclient/identity/v3/service.py
index f43ada56..7beadc9d 100644
--- a/openstackclient/identity/v3/service.py
+++ b/openstackclient/identity/v3/service.py
@@ -15,11 +15,13 @@
"""Identity v3 Service action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
from openstackclient.identity import common
@@ -31,28 +33,28 @@ class CreateService(command.ShowOne):
parser.add_argument(
'type',
metavar='<type>',
- help='New service type (compute, image, identity, volume, etc)',
+ help=_('New service type (compute, image, identity, volume, etc)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='New service name',
+ help=_('New service name'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New service description',
+ help=_('New service description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable service (default)',
+ help=_('Enable service (default)'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable service',
+ help=_('Disable service'),
)
return parser
@@ -82,7 +84,7 @@ class DeleteService(command.Command):
parser.add_argument(
'service',
metavar='<service>',
- help='Service to delete (type, name or ID)',
+ help=_('Service to delete (type, name or ID)'),
)
return parser
@@ -103,7 +105,7 @@ class ListService(command.Lister):
'--long',
action='store_true',
default=False,
- help='List additional fields in output',
+ help=_('List additional fields in output'),
)
return parser
@@ -128,33 +130,33 @@ class SetService(command.Command):
parser.add_argument(
'service',
metavar='<service>',
- help='Service to update (type, name or ID)',
+ help=_('Service to update (type, name or ID)'),
)
parser.add_argument(
'--type',
metavar='<type>',
- help='New service type (compute, image, identity, volume, etc)',
+ help=_('New service type (compute, image, identity, volume, etc)'),
)
parser.add_argument(
'--name',
metavar='<service-name>',
- help='New service name',
+ help=_('New service name'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New service description',
+ help=_('New service description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable service',
+ help=_('Enable service'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable service',
+ help=_('Disable service'),
)
return parser
@@ -166,9 +168,8 @@ class SetService(command.Command):
and not parsed_args.description
and not parsed_args.enable
and not parsed_args.disable):
- sys.stderr.write("Incorrect set of arguments "
- "provided. See openstack --help for more "
- "details\n")
+ sys.stderr.write(_("Incorrect set of arguments provided. "
+ "See openstack --help for more details\n"))
return
service = common.find_service(identity_client,
parsed_args.service)
@@ -198,7 +199,7 @@ class ShowService(command.ShowOne):
parser.add_argument(
'service',
metavar='<service>',
- help='Service to display (type, name or ID)',
+ help=_('Service to display (type, name or ID)'),
)
return parser
diff --git a/openstackclient/identity/v3/service_provider.py b/openstackclient/identity/v3/service_provider.py
index 8b433b4d..0beea813 100644
--- a/openstackclient/identity/v3/service_provider.py
+++ b/openstackclient/identity/v3/service_provider.py
@@ -13,11 +13,13 @@
"""Service Provider action implementations"""
-import six
import sys
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
+from openstackclient.i18n import _
class CreateServiceProvider(command.ShowOne):
@@ -28,26 +30,26 @@ class CreateServiceProvider(command.ShowOne):
parser.add_argument(
'service_provider_id',
metavar='<name>',
- help='New service provider name (must be unique)'
+ help=_('New service provider name (must be unique)'),
)
parser.add_argument(
'--auth-url',
metavar='<auth-url>',
required=True,
- help='Authentication URL of remote federated service provider '
- '(required)',
+ help=_('Authentication URL of remote federated service provider '
+ '(required)'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New service provider description',
+ help=_('New service provider description'),
)
parser.add_argument(
'--service-provider-url',
metavar='<sp-url>',
required=True,
- help='A service URL where SAML assertions are being sent '
- '(required)',
+ help=_('A service URL where SAML assertions are being sent '
+ '(required)'),
)
enable_service_provider = parser.add_mutually_exclusive_group()
@@ -56,13 +58,13 @@ class CreateServiceProvider(command.ShowOne):
dest='enabled',
action='store_true',
default=True,
- help='Enable the service provider (default)',
+ help=_('Enable the service provider (default)'),
)
enable_service_provider.add_argument(
'--disable',
dest='enabled',
action='store_false',
- help='Disable the service provider',
+ help=_('Disable the service provider'),
)
return parser
@@ -88,7 +90,7 @@ class DeleteServiceProvider(command.Command):
parser.add_argument(
'service_provider',
metavar='<service-provider>',
- help='Service provider to delete',
+ help=_('Service provider to delete'),
)
return parser
@@ -121,34 +123,35 @@ class SetServiceProvider(command.Command):
parser.add_argument(
'service_provider',
metavar='<service-provider>',
- help='Service provider to modify',
+ help=_('Service provider to modify'),
)
parser.add_argument(
'--auth-url',
metavar='<auth-url>',
- help='New Authentication URL of remote federated service provider',
+ help=_('New Authentication URL of remote '
+ 'federated service provider'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='New service provider description',
+ help=_('New service provider description'),
)
parser.add_argument(
'--service-provider-url',
metavar='<sp-url>',
- help='New service provider URL, where SAML assertions are sent',
+ help=_('New service provider URL, where SAML assertions are sent'),
)
enable_service_provider = parser.add_mutually_exclusive_group()
enable_service_provider.add_argument(
'--enable',
action='store_true',
- help='Enable the service provider',
+ help=_('Enable the service provider'),
)
enable_service_provider.add_argument(
'--disable',
action='store_true',
- help='Disable the service provider',
+ help=_('Disable the service provider'),
)
return parser
@@ -164,8 +167,8 @@ class SetServiceProvider(command.Command):
if not any((enabled is not None, parsed_args.description,
parsed_args.service_provider_url,
parsed_args.auth_url)):
- sys.stdout.write("Service Provider not updated, no arguments "
- "present")
+ sys.stdout.write(_("Service Provider not updated, no arguments "
+ "present\n"))
return (None, None)
service_provider = federation_client.service_providers.update(
@@ -184,7 +187,7 @@ class ShowServiceProvider(command.ShowOne):
parser.add_argument(
'service_provider',
metavar='<service-provider>',
- help='Service provider to display',
+ help=_('Service provider to display'),
)
return parser
diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py
index bdc5e95f..ecf09693 100644
--- a/openstackclient/identity/v3/token.py
+++ b/openstackclient/identity/v3/token.py
@@ -15,11 +15,12 @@
"""Identity v3 Token action implementations"""
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from openstackclient.i18n import _
from openstackclient.identity import common
@@ -31,17 +32,17 @@ class AuthorizeRequestToken(command.ShowOne):
parser.add_argument(
'--request-key',
metavar='<request-key>',
- help='Request token to authorize (ID only) (required)',
- required=True
+ required=True,
+ help=_('Request token to authorize (ID only) (required)'),
)
parser.add_argument(
'--role',
metavar='<role>',
action='append',
default=[],
- help='Roles to authorize (name or ID) '
- '(repeat option to set multiple values, required)',
- required=True
+ required=True,
+ help=_('Roles to authorize (name or ID) '
+ '(repeat option to set multiple values, required)'),
)
return parser
@@ -72,31 +73,31 @@ class CreateAccessToken(command.ShowOne):
parser.add_argument(
'--consumer-key',
metavar='<consumer-key>',
- help='Consumer key (required)',
+ help=_('Consumer key (required)'),
required=True
)
parser.add_argument(
'--consumer-secret',
metavar='<consumer-secret>',
- help='Consumer secret (required)',
+ help=_('Consumer secret (required)'),
required=True
)
parser.add_argument(
'--request-key',
metavar='<request-key>',
- help='Request token to exchange for access token (required)',
+ help=_('Request token to exchange for access token (required)'),
required=True
)
parser.add_argument(
'--request-secret',
metavar='<request-secret>',
- help='Secret associated with <request-key> (required)',
+ help=_('Secret associated with <request-key> (required)'),
required=True
)
parser.add_argument(
'--verifier',
metavar='<verifier>',
- help='Verifier associated with <request-key> (required)',
+ help=_('Verifier associated with <request-key> (required)'),
required=True
)
return parser
@@ -118,26 +119,26 @@ class CreateRequestToken(command.ShowOne):
parser.add_argument(
'--consumer-key',
metavar='<consumer-key>',
- help='Consumer key (required)',
+ help=_('Consumer key (required)'),
required=True
)
parser.add_argument(
'--consumer-secret',
metavar='<consumer-secret>',
- help='Consumer secret (required)',
+ help=_('Consumer secret (required)'),
required=True
)
parser.add_argument(
'--project',
metavar='<project>',
- help='Project that consumer wants to access (name or ID)'
- ' (required)',
+ help=_('Project that consumer wants to access (name or ID)'
+ ' (required)'),
required=True
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <project> (name or ID)',
+ help=_('Domain owning <project> (name or ID)'),
)
return parser
@@ -173,13 +174,23 @@ class IssueToken(command.ShowOne):
return parser
def take_action(self, parsed_args):
- if not self.app.client_manager.auth_ref:
+ auth_ref = self.app.client_manager.auth_ref
+ if not auth_ref:
raise exceptions.AuthorizationFailure(
- "Only an authorized user may issue a new token.")
- token = self.app.client_manager.auth_ref.service_catalog.get_token()
- if 'tenant_id' in token:
- token['project_id'] = token.pop('tenant_id')
- return zip(*sorted(six.iteritems(token)))
+ _("Only an authorized user may issue a new token."))
+
+ data = {}
+ if auth_ref.auth_token:
+ data['id'] = auth_ref.auth_token
+ if auth_ref.expires:
+ data['expires'] = auth_ref.expires
+ if auth_ref.project_id:
+ data['project_id'] = auth_ref.project_id
+ if auth_ref.user_id:
+ data['user_id'] = auth_ref.user_id
+ if auth_ref.domain_id:
+ data['domain_id'] = auth_ref.domain_id
+ return zip(*sorted(six.iteritems(data)))
class RevokeToken(command.Command):
@@ -190,7 +201,7 @@ class RevokeToken(command.Command):
parser.add_argument(
'token',
metavar='<token>',
- help='Token to be deleted',
+ help=_('Token to be deleted'),
)
return parser
diff --git a/openstackclient/identity/v3/trust.py b/openstackclient/identity/v3/trust.py
index b6f5c6b4..bbc86adb 100644
--- a/openstackclient/identity/v3/trust.py
+++ b/openstackclient/identity/v3/trust.py
@@ -14,10 +14,12 @@
"""Identity v3 Trust action implementations"""
import datetime
+
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
+from openstackclient.i18n import _
from openstackclient.identity import common
@@ -29,26 +31,26 @@ class CreateTrust(command.ShowOne):
parser.add_argument(
'trustor',
metavar='<trustor-user>',
- help='User that is delegating authorization (name or ID)',
+ help=_('User that is delegating authorization (name or ID)'),
)
parser.add_argument(
'trustee',
metavar='<trustee-user>',
- help='User that is assuming authorization (name or ID)',
+ help=_('User that is assuming authorization (name or ID)'),
)
parser.add_argument(
'--project',
metavar='<project>',
required=True,
- help='Project being delegated (name or ID) (required)',
+ help=_('Project being delegated (name or ID) (required)'),
)
parser.add_argument(
'--role',
metavar='<role>',
action='append',
default=[],
- help='Roles to authorize (name or ID) '
- '(repeat option to set multiple values, required)',
+ help=_('Roles to authorize (name or ID) '
+ '(repeat option to set multiple values, required)'),
required=True
)
parser.add_argument(
@@ -56,25 +58,25 @@ class CreateTrust(command.ShowOne):
dest='impersonate',
action='store_true',
default=False,
- help='Tokens generated from the trust will represent <trustor>'
- ' (defaults to False)',
+ help=_('Tokens generated from the trust will represent <trustor>'
+ ' (defaults to False)'),
)
parser.add_argument(
'--expiration',
metavar='<expiration>',
- help='Sets an expiration date for the trust'
- ' (format of YYYY-mm-ddTHH:MM:SS)',
+ help=_('Sets an expiration date for the trust'
+ ' (format of YYYY-mm-ddTHH:MM:SS)'),
)
common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--trustor-domain',
metavar='<trustor-domain>',
- help='Domain that contains <trustor> (name or ID)',
+ help=_('Domain that contains <trustor> (name or ID)'),
)
parser.add_argument(
'--trustee-domain',
metavar='<trustee-domain>',
- help='Domain that contains <trustee> (name or ID)',
+ help=_('Domain that contains <trustee> (name or ID)'),
)
return parser
@@ -136,8 +138,8 @@ class DeleteTrust(command.Command):
parser.add_argument(
'trust',
metavar='<trust>',
- help='Trust(s) to delete',
nargs="+",
+ help=_('Trust(s) to delete'),
)
return parser
@@ -170,7 +172,7 @@ class ShowTrust(command.ShowOne):
parser.add_argument(
'trust',
metavar='<trust>',
- help='Trust to display',
+ help=_('Trust to display'),
)
return parser
diff --git a/openstackclient/identity/v3/unscoped_saml.py b/openstackclient/identity/v3/unscoped_saml.py
index 8e2616a6..f116174b 100644
--- a/openstackclient/identity/v3/unscoped_saml.py
+++ b/openstackclient/identity/v3/unscoped_saml.py
@@ -17,9 +17,11 @@ The first step of federated auth is to fetch an unscoped token. From there,
the user can list domains and projects they are allowed to access, and request
a scoped token."""
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
+from openstackclient.i18n import _
UNSCOPED_AUTH_PLUGINS = ['v3unscopedsaml', 'v3unscopedadfs', 'v3oidc']
@@ -33,10 +35,10 @@ def auth_with_unscoped_saml(func):
if auth_plugin_name in UNSCOPED_AUTH_PLUGINS:
return func(self, parsed_args)
else:
- msg = ('This command requires the use of an unscoped SAML '
- 'authentication plugin. Please use argument '
- '--os-auth-type with one of the following '
- 'plugins: ' + ', '.join(UNSCOPED_AUTH_PLUGINS))
+ msg = (_('This command requires the use of an unscoped SAML '
+ 'authentication plugin. Please use argument '
+ '--os-auth-type with one of the following '
+ 'plugins: %s') % ', '.join(UNSCOPED_AUTH_PLUGINS))
raise exceptions.CommandError(msg)
return _decorated
diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py
index 8bc4183b..39125e2c 100644
--- a/openstackclient/identity/v3/user.py
+++ b/openstackclient/identity/v3/user.py
@@ -16,13 +16,13 @@
"""Identity v3 User action implementations"""
import copy
-import six
import sys
from keystoneauth1 import exceptions as ks_exc
+from osc_lib.command import command
+from osc_lib import utils
+import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -35,50 +35,50 @@ class CreateUser(command.ShowOne):
parser.add_argument(
'name',
metavar='<name>',
- help='New user name',
+ help=_('New user name'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Default domain (name or ID)',
+ help=_('Default domain (name or ID)'),
)
parser.add_argument(
'--project',
metavar='<project>',
- help='Default project (name or ID)',
+ help=_('Default project (name or ID)'),
)
common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--password',
metavar='<password>',
- help='Set user password',
+ help=_('Set user password'),
)
parser.add_argument(
'--password-prompt',
dest="password_prompt",
action="store_true",
- help='Prompt interactively for password',
+ help=_('Prompt interactively for password'),
)
parser.add_argument(
'--email',
metavar='<email-address>',
- help='Set user email address',
+ help=_('Set user email address'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='User description',
+ help=_('User description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable user (default)',
+ help=_('Enable user (default)'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable user',
+ help=_('Disable user'),
)
parser.add_argument(
'--or-show',
@@ -122,7 +122,7 @@ class CreateUser(command.ShowOne):
user = utils.find_resource(identity_client.users,
parsed_args.name,
domain_id=domain_id)
- self.log.info('Returning existing user %s', user.name)
+ self.log.info(_('Returning existing user %s'), user.name)
else:
raise e
@@ -139,12 +139,12 @@ class DeleteUser(command.Command):
'users',
metavar='<user>',
nargs="+",
- help='User(s) to delete (name or ID)',
+ help=_('User(s) to delete (name or ID)'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <user> (name or ID)',
+ help=_('Domain owning <user> (name or ID)'),
)
return parser
@@ -173,24 +173,24 @@ class ListUser(command.Lister):
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Filter users by <domain> (name or ID)',
+ help=_('Filter users by <domain> (name or ID)'),
)
project_or_group = parser.add_mutually_exclusive_group()
project_or_group.add_argument(
'--group',
metavar='<group>',
- help='Filter users by <group> membership (name or ID)',
+ help=_('Filter users by <group> membership (name or ID)'),
)
project_or_group.add_argument(
'--project',
metavar='<project>',
- help='Filter users by <project> (name or ID)',
+ help=_('Filter users by <project> (name or ID)'),
)
parser.add_argument(
'--long',
action='store_true',
default=False,
- help='List additional fields in output',
+ help=_('List additional fields in output'),
)
return parser
@@ -273,50 +273,50 @@ class SetUser(command.Command):
parser.add_argument(
'user',
metavar='<user>',
- help='User to change (name or ID)',
+ help=_('User to change (name or ID)'),
)
parser.add_argument(
'--name',
metavar='<name>',
- help='Set user name',
+ help=_('Set user name'),
)
parser.add_argument(
'--project',
metavar='<project>',
- help='Set default project (name or ID)',
+ help=_('Set default project (name or ID)'),
)
common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--password',
metavar='<password>',
- help='Set user password',
+ help=_('Set user password'),
)
parser.add_argument(
'--password-prompt',
dest="password_prompt",
action="store_true",
- help='Prompt interactively for password',
+ help=_('Prompt interactively for password'),
)
parser.add_argument(
'--email',
metavar='<email-address>',
- help='Set user email address',
+ help=_('Set user email address'),
)
parser.add_argument(
'--description',
metavar='<description>',
- help='Set user description',
+ help=_('Set user description'),
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
- help='Enable user (default)',
+ help=_('Enable user (default)'),
)
enable_group.add_argument(
'--disable',
action='store_true',
- help='Disable user',
+ help=_('Disable user'),
)
return parser
@@ -334,9 +334,8 @@ class SetUser(command.Command):
and not parsed_args.description
and not parsed_args.enable
and not parsed_args.disable):
- sys.stderr.write("Incorrect set of arguments "
- "provided. See openstack --help for more "
- "details\n")
+ sys.stderr.write(_("Incorrect set of arguments provided. "
+ "See openstack --help for more details\n"))
return
user = utils.find_resource(
@@ -376,12 +375,12 @@ class SetPasswordUser(command.Command):
parser.add_argument(
'--password',
metavar='<new-password>',
- help='New user password'
+ help=_('New user password'),
)
parser.add_argument(
'--original-password',
metavar='<original-password>',
- help='Original user password'
+ help=_('Original user password'),
)
return parser
@@ -429,12 +428,12 @@ class ShowUser(command.ShowOne):
parser.add_argument(
'user',
metavar='<user>',
- help='User to display (name or ID)',
+ help=_('User to display (name or ID)'),
)
parser.add_argument(
'--domain',
metavar='<domain>',
- help='Domain owning <user> (name or ID)',
+ help=_('Domain owning <user> (name or ID)'),
)
return parser
diff --git a/openstackclient/image/client.py b/openstackclient/image/client.py
index 9c45a63f..0ef694f4 100644
--- a/openstackclient/image/client.py
+++ b/openstackclient/image/client.py
@@ -15,7 +15,8 @@
import logging
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.i18n import _
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index e2109fca..1644809d 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -18,7 +18,6 @@
import argparse
import io
import os
-import six
import sys
if os.name == "nt":
@@ -27,10 +26,12 @@ else:
msvcrt = None
from glanceclient.common import utils as gc_utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+import six
+
from openstackclient.api import utils as api_utils
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index a81f092c..d20fdba6 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -16,15 +16,15 @@
"""Image V2 Action Implementations"""
import argparse
-import six
from glanceclient.common import utils as gc_utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+import six
from openstackclient.api import utils as api_utils
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -372,13 +372,27 @@ class DeleteImage(command.Command):
return parser
def take_action(self, parsed_args):
+
+ del_result = 0
image_client = self.app.client_manager.image
for image in parsed_args.images:
- image_obj = utils.find_resource(
- image_client.images,
- image,
- )
- image_client.images.delete(image_obj.id)
+ try:
+ image_obj = utils.find_resource(
+ image_client.images,
+ image,
+ )
+ image_client.images.delete(image_obj.id)
+ except Exception as e:
+ del_result += 1
+ self.app.log.error(_("Failed to delete image with "
+ "name or ID '%(image)s': %(e)s")
+ % {'image': image, 'e': e})
+
+ total = len(parsed_args.images)
+ if (del_result > 0):
+ msg = (_("Failed to delete %(dresult)s of %(total)s images.")
+ % {'dresult': del_result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListImage(command.Lister):
@@ -933,7 +947,7 @@ class UnsetImage(command.Command):
'propret': propret, 'proptotal': proptotal})
raise exceptions.CommandError(msg)
elif tagret > 0:
- msg = (_("Failed to unset %(target)s of %(tagtotal)s tags.")
+ msg = (_("Failed to unset %(tagret)s of %(tagtotal)s tags.")
% {'tagret': tagret, 'tagtotal': tagtotal})
raise exceptions.CommandError(msg)
elif propret > 0:
diff --git a/openstackclient/locale/de/LC_MESSAGES/openstackclient.po b/openstackclient/locale/de/LC_MESSAGES/openstackclient.po
index f7445b1c..06f1c8d6 100644
--- a/openstackclient/locale/de/LC_MESSAGES/openstackclient.po
+++ b/openstackclient/locale/de/LC_MESSAGES/openstackclient.po
@@ -8,13 +8,13 @@
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: python-openstackclient 2.2.1.dev235\n"
+"Project-Id-Version: python-openstackclient 2.5.1.dev51\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
-"POT-Creation-Date: 2016-04-19 05:02+0000\n"
+"POT-Creation-Date: 2016-06-03 19:37+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2015-09-19 07:10+0000\n"
+"PO-Revision-Date: 2016-06-02 01:43+0000\n"
"Last-Translator: Andreas Jaeger <jaegerandi@gmail.com>\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -22,69 +22,6 @@ msgstr ""
"X-Generator: Zanata 3.7.3\n"
"Language-Team: German\n"
-msgid ""
-"\n"
-"Complete\n"
-msgstr ""
-"\n"
-"Fertig\n"
-
-msgid ""
-"\n"
-"Error creating server"
-msgstr ""
-"\n"
-"Fehler beim Erstellen des Servers"
-
-msgid ""
-"\n"
-"Error creating server snapshot"
-msgstr ""
-"\n"
-"Fehler beim Erstellen der Server-Schattenkopie"
-
-msgid ""
-"\n"
-"Error deleting server"
-msgstr ""
-"\n"
-"Fehler beim Löschen des Servers"
-
-msgid ""
-"\n"
-"Error migrating server"
-msgstr ""
-"\n"
-"Fehler beim Migrieren des Servers"
-
-msgid ""
-"\n"
-"Error rebooting server\n"
-msgstr ""
-"\n"
-"Fehler beim Neustarten des Servers\n"
-
-msgid ""
-"\n"
-"Error rebuilding server"
-msgstr ""
-"\n"
-"Fehler bei der Wiederherstellung des Servers"
-
-msgid ""
-"\n"
-"Error resizing server"
-msgstr ""
-"\n"
-"Fehler bei der Größenänderung des Servers"
-
-msgid ""
-"\n"
-"Reboot complete\n"
-msgstr ""
-"\n"
-"Neustart abgeschlossen\n"
-
msgid "Add a property to <name> (repeat option to set multiple properties)"
msgstr ""
"Fügen Sie eine Eigenschaft zu <Name> hinzu (wiederholen Sie die Option, um "
@@ -93,6 +30,9 @@ msgstr ""
msgid "Allow disk over-commit on the destination host"
msgstr "Festplattenüberladung auf dem Zielhost erlauben"
+msgid "Availability zone name"
+msgstr "Name der Verfügbarkeitszone"
+
msgid "Complete\n"
msgstr "Fertig\n"
@@ -138,6 +78,9 @@ msgstr "Anmeldedaten für Benutzer löschen (name or ID)"
msgid "Destination port (ssh -p option)"
msgstr "Zielport (ssh -p Option)"
+msgid "Disable a service"
+msgstr "Dienst deaktivieren"
+
msgid "Disable project"
msgstr "Projekt deaktivieren"
@@ -162,13 +105,19 @@ msgstr "Benutzer aktivieren (Standardeinstellung)"
msgid "Endpoint ID to delete"
msgstr "Zu löschende Endpunktkennung"
-msgid "Endpoint ID to display"
-msgstr "Anzuzeigende Endpunktkennung"
+msgid "Error creating server\n"
+msgstr "Fehler beim Erstellen des Servers\n"
+
+msgid "Error creating server snapshot\n"
+msgstr "Fehler beim Erstellen der Server-Schattenkopie\n"
#, python-format
msgid "Error creating server: %s"
msgstr "Fehler beim Erstellen des Servers: %s"
+msgid "Error deleting server\n"
+msgstr "Fehler beim Löschen des Servers\n"
+
#, python-format
msgid "Error deleting server: %s"
msgstr "Fehler beim Löschen des Servers: %s"
@@ -188,6 +137,9 @@ msgstr "Benutzer nach <project> filtern (Name oder Kennung)"
msgid "Filter users by project (name or ID)"
msgstr "Benutzer nach Projekt filtern (Name oder Kennung)"
+msgid "Floating IP address"
+msgstr "Bewegliche IP-Adresse"
+
msgid "Hints for the scheduler (optional extension)"
msgstr "Hinweise für den Planer (optionale Erweiterung)"
@@ -209,6 +161,9 @@ msgstr "Zusätzliche Felder in der Ausgabe auflisten"
msgid "Login name (ssh -l option)"
msgstr "Anmeldename (ssh -l Option)"
+msgid "MD5 hash"
+msgstr "MD5-Hashwert"
+
msgid ""
"Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> "
"(optional extension)"
@@ -442,27 +397,27 @@ msgstr ""
"OS_DOMAIN_NAME oder auth.domain_name."
msgid ""
-"Set a service AUTH_URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n"
+"Set a service AUTH_URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url"
msgstr ""
"Legen Sie eine Dienst-AUTH_URL mit --os-auth-url, OS_AUTH_URL oder auth."
-"auth_url fest\n"
+"auth_url fest"
-msgid "Set a service URL, with --os-url, OS_URL or auth.url\n"
-msgstr "Legen Sie eine Dienst-URL mit --os-url, OS_URL oder auth.url fest\n"
+msgid "Set a service URL, with --os-url, OS_URL or auth.url"
+msgstr "Legen Sie eine Dienst-URL mit --os-url, OS_URL oder auth.url fest"
-msgid "Set a token with --os-token, OS_TOKEN or auth.token\n"
-msgstr "Legen Sie einen Token mit --os-token, OS_TOKEN oder auth.token fest\n"
+msgid "Set a token with --os-token, OS_TOKEN or auth.token"
+msgstr "Legen Sie einen Token mit --os-token, OS_TOKEN oder auth.token fest"
-msgid "Set a username with --os-username, OS_USERNAME, or auth.username\n"
+msgid "Set a username with --os-username, OS_USERNAME, or auth.username"
msgstr ""
"Legen Sie einen Benutzernamen mit --os-username, OS_USERNAME oder auth."
-"username fest\n"
+"username fest"
msgid ""
-"Set an authentication URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n"
+"Set an authentication URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url"
msgstr ""
"Legen Sie eine Authentifizierungs-URL mit --os-auth-url, OS_AUTH_URL oder "
-"auth.auth_url fest\n"
+"auth.auth_url fest"
msgid "Set default project (name or ID)"
msgstr "Standardprojekt festlegen (Name oder Kennung)"
@@ -504,6 +459,9 @@ msgstr ""
msgid "Token to be deleted"
msgstr "Zu löschender Token"
+msgid "URL"
+msgstr "URL"
+
msgid "Use only IPv4 addresses"
msgstr "Nur IPv4-Adressen verwenden"
@@ -543,6 +501,9 @@ msgstr "Aufzulistender Benutzer (Name oder Kennung)"
msgid "User(s) to delete (name or ID)"
msgstr "Zu löschende(r) Benutzer (Name oder Kennung)"
+msgid "Version"
+msgstr "Version"
+
msgid "Volume to add (name or ID)"
msgstr "Zu hinzufügender Datenträger (Name oder Kennung)"
diff --git a/openstackclient/locale/openstackclient.pot b/openstackclient/locale/openstackclient.pot
deleted file mode 100644
index e197fa7b..00000000
--- a/openstackclient/locale/openstackclient.pot
+++ /dev/null
@@ -1,1410 +0,0 @@
-# Translations template for python-openstackclient.
-# Copyright (C) 2016 ORGANIZATION
-# This file is distributed under the same license as the
-# python-openstackclient project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: python-openstackclient 2.2.1.dev235\n"
-"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
-"POT-Creation-Date: 2016-04-19 06:14+0000\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.2.0\n"
-
-#: openstackclient/api/auth.py:148
-msgid "Set a username with --os-username, OS_USERNAME, or auth.username\n"
-msgstr ""
-
-#: openstackclient/api/auth.py:151
-msgid ""
-"Set an authentication URL, with --os-auth-url, OS_AUTH_URL or "
-"auth.auth_url\n"
-msgstr ""
-
-#: openstackclient/api/auth.py:160
-msgid ""
-"Set a scope, such as a project or domain, set a project scope with --os-"
-"project-name, OS_PROJECT_NAME or auth.project_name, set a domain scope "
-"with --os-domain-name, OS_DOMAIN_NAME or auth.domain_name"
-msgstr ""
-
-#: openstackclient/api/auth.py:166 openstackclient/api/auth.py:172
-msgid "Set a token with --os-token, OS_TOKEN or auth.token\n"
-msgstr ""
-
-#: openstackclient/api/auth.py:168
-msgid "Set a service AUTH_URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n"
-msgstr ""
-
-#: openstackclient/api/auth.py:174
-msgid "Set a service URL, with --os-url, OS_URL or auth.url\n"
-msgstr ""
-
-#: openstackclient/common/availability_zone.py:110
-#: openstackclient/compute/v2/server.py:757
-#: openstackclient/identity/v2_0/endpoint.py:101
-#: openstackclient/identity/v2_0/project.py:133
-#: openstackclient/identity/v2_0/service.py:115
-#: openstackclient/identity/v2_0/user.py:162
-#: openstackclient/network/v2/router.py:230
-#: openstackclient/network/v2/subnet.py:299
-#: openstackclient/network/v2/subnet_pool.py:165
-msgid "List additional fields in output"
-msgstr ""
-
-#: openstackclient/common/parseractions.py:99
-#, python-format
-msgid ""
-"Invalid keys %(invalid_keys)s specified.\n"
-"Valid keys are: %(valid_keys)s."
-msgstr ""
-
-#: openstackclient/common/parseractions.py:109
-#, python-format
-msgid ""
-"Missing required keys %(missing_keys)s.\n"
-"Required keys are: %(required_keys)s."
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:195
-#: openstackclient/compute/v2/server.py:227
-#: openstackclient/compute/v2/server.py:598
-#: openstackclient/compute/v2/server.py:937
-#: openstackclient/compute/v2/server.py:1039
-#: openstackclient/compute/v2/server.py:1091
-#: openstackclient/compute/v2/server.py:1177
-#: openstackclient/compute/v2/server.py:1213
-#: openstackclient/compute/v2/server.py:1236
-#: openstackclient/compute/v2/server.py:1343
-#: openstackclient/compute/v2/server.py:1421
-#: openstackclient/compute/v2/server.py:1455
-#: openstackclient/compute/v2/server.py:1712
-#: openstackclient/compute/v2/server.py:1733
-msgid "Server (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:200
-msgid "Security group to add (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:232
-msgid "Volume to add (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:237
-msgid "Server internal device name for volume"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:269
-#: openstackclient/compute/v2/server.py:1348
-msgid "New server name"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:277
-msgid "Create server from this image (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:282
-msgid "Create server from this volume (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:288
-msgid "Create server with this flavor (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:295
-msgid ""
-"Security group to assign to this server (name or ID) (repeat option to "
-"set multiple groups)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:301
-msgid "Keypair to inject into this server (optional extension)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:307
-msgid "Set a property on this server (repeat option to set multiple values)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:315
-msgid ""
-"File to inject into image before boot (repeat option to set multiple "
-"files)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:321
-msgid "User data file to serve from the metadata server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:326
-msgid "Select an availability zone for the server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:333
-msgid ""
-"Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> "
-"(optional extension)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:343
-msgid ""
-"Create a NIC on the server. Specify option multiple times to create "
-"multiple NICs. Either net-id or port-id must be provided, but not both. "
-"net-id: attach NIC to network with this UUID, port-id: attach NIC to port"
-" with this UUID, v4-fixed-ip: IPv4 fixed address for NIC (optional), v6"
-"-fixed-ip: IPv6 fixed address for NIC (optional)."
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:356
-msgid "Hints for the scheduler (optional extension)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:362
-msgid ""
-"Use specified volume as the config drive, or 'True' to use an ephemeral "
-"drive"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:370
-msgid "Minimum number of servers to launch (default=1)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:377
-msgid "Maximum number of servers to launch (default=1)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:382
-msgid "Wait for build to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:421
-msgid "min instances should be <= max instances"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:424
-msgid "min instances should be > 0"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:427
-msgid "max instances should be > 0"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:456
-msgid "Volume name or ID must be specified if --block-device-mapping is specified"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:468
-msgid "either net-id or port-id should be specified but not both"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:488
-msgid "can't create server with port specified since network endpoint not enabled"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:553
-#, python-format
-msgid "Error creating server: %s"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:555
-msgid ""
-"\n"
-"Error creating server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:577
-msgid "Server(s) to create dump file (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:603
-msgid "Name of new image (default is server name)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:608
-msgid "Wait for image create to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:637
-#, python-format
-msgid "Error creating snapshot of server: %s"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:639
-msgid ""
-"\n"
-"Error creating server snapshot"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:656
-msgid "Server(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:661
-msgid "Wait for delete to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:679
-#, python-format
-msgid "Error deleting server: %s"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:681
-msgid ""
-"\n"
-"Error deleting server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:693
-msgid "Only return instances that match the reservation"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:698
-msgid "Regular expression to match IP addresses"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:703
-msgid "Regular expression to match IPv6 addresses"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:708
-msgid "Regular expression to match names"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:713
-msgid "Regular expression to match instance name (admin only)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:719
-msgid "Search by server status"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:724
-msgid "Search by flavor (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:729
-msgid "Search by image (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:734
-msgid "Search by hostname"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:740
-msgid "Include all projects (admin only)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:750
-msgid "Search by user (admin only) (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:905
-msgid "Server(s) to lock (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:942
-msgid "Target hostname"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:950
-msgid "Perform a shared live migration (default)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:956
-msgid "Perform a block live migration"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:963
-msgid "Allow disk over-commit on the destination host"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:970
-msgid "Do not over-commit disk on the destination host (default)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:976
-#: openstackclient/compute/v2/server.py:1256
-msgid "Wait for resize to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1003
-#: openstackclient/compute/v2/server.py:1280
-msgid "Complete\n"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1005
-msgid ""
-"\n"
-"Error migrating server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1018
-msgid "Server(s) to pause (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1048
-msgid "Perform a hard reboot"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1056
-msgid "Perform a soft reboot"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1061
-msgid "Wait for reboot to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1077
-msgid ""
-"\n"
-"Reboot complete\n"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1079
-msgid ""
-"\n"
-"Error rebooting server\n"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1096
-msgid ""
-"Recreate server from the specified image (name or ID). Defaults to the "
-"currently used one."
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1107
-msgid "Wait for rebuild to complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1128
-msgid ""
-"\n"
-"Complete\n"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1130
-msgid ""
-"\n"
-"Error rebuilding server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1145
-msgid "Name or ID of server to use"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1150
-msgid "Name or ID of security group to remove from server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1182
-msgid "Volume to remove (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1241
-msgid "Resize server to specified flavor"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1246
-msgid "Confirm server resize is complete"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1251
-msgid "Restore server state before resize"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1282
-msgid ""
-"\n"
-"Error resizing server"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1299
-msgid "Server(s) to restore (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1321
-msgid "Server(s) to resume (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1353
-msgid "Set new root password (interactive only)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1359
-msgid ""
-"Property to add/change for this server (repeat option to set multiple "
-"properties)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1382
-msgid "New password: "
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1383
-msgid "Retype new password: "
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1387
-msgid "Passwords do not match, password unchanged"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1400
-msgid "Server(s) to shelve (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1427
-msgid "Display server diagnostics information"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1439
-msgid "Error retrieving diagnostics data"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1460
-msgid "Login name (ssh -l option)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1472
-msgid "Destination port (ssh -p option)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1484
-msgid "Private key file (ssh -i option)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1495
-msgid "Options in ssh_config(5) format (ssh -o option)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1509
-msgid "Use only IPv4 addresses"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1516
-msgid "Use only IPv6 addresses"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1525
-msgid "Use public IP address"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1533
-msgid "Use private IP address"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1540
-msgid "Use other IP address (public, private, etc)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1600
-msgid "Server(s) to start (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1622
-msgid "Server(s) to stop (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1644
-msgid "Server(s) to suspend (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1667
-msgid "Server(s) to unlock (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1690
-msgid "Server(s) to unpause (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1740
-msgid ""
-"Property key to remove from server (repeat option to remove multiple "
-"values)"
-msgstr ""
-
-#: openstackclient/compute/v2/server.py:1768
-msgid "Server(s) to unshelve (name or ID)"
-msgstr ""
-
-#: openstackclient/compute/v2/service.py:138
-msgid "argument --disable-reason has been ignored"
-msgstr ""
-
-#: openstackclient/identity/v2_0/catalog.py:67
-#: openstackclient/identity/v3/catalog.py:64
-msgid "Service to display (type or name)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:34
-#: openstackclient/identity/v3/ec2creds.py:59
-msgid ""
-"Create credentials in project (name or ID; default: current authenticated"
-" project)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:42
-#: openstackclient/identity/v3/ec2creds.py:67
-msgid ""
-"Create credentials for user (name or ID; default: current authenticated "
-"user)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:90
-#: openstackclient/identity/v2_0/ec2creds.py:157
-#: openstackclient/identity/v3/ec2creds.py:120
-#: openstackclient/identity/v3/ec2creds.py:172
-msgid "Credentials access key"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:95
-#: openstackclient/identity/v3/ec2creds.py:125
-msgid "Delete credentials for user (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:122
-#: openstackclient/identity/v3/ec2creds.py:144
-msgid "Filter list by user (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/ec2creds.py:162
-#: openstackclient/identity/v3/ec2creds.py:177
-msgid "Show credentials for user (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:34
-msgid "New endpoint service (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:40
-msgid "New endpoint public URL (required)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:45
-msgid "New endpoint admin URL"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:50
-msgid "New endpoint internal URL"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:55
-msgid "New endpoint region ID"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:84
-msgid "Endpoint ID to delete"
-msgstr ""
-
-#: openstackclient/identity/v2_0/endpoint.py:133
-msgid "Endpoint ID to display"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:36
-msgid "New project name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:41
-msgid "Project description"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:47
-msgid "Enable project (default)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:52
-#: openstackclient/identity/v2_0/project.py:179
-msgid "Disable project"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:58
-msgid "Add a property to <name> (repeat option to set multiple properties)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:64
-#: openstackclient/identity/v3/project.py:75
-msgid "Return existing project"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:109
-msgid "Project(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:158
-#: openstackclient/identity/v2_0/project.py:291
-msgid "Project to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:163
-msgid "Set project name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:168
-msgid "Set project description"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:174
-msgid "Enable project"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:185
-msgid "Set a project property (repeat option to set multiple properties)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:234
-msgid "Project to display (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/project.py:298
-msgid "Unset a project property (repeat option to unset multiple properties)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:36
-msgid "Role to add to <project>:<user> (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:42
-#: openstackclient/identity/v2_0/role.py:288
-msgid "Include <project> (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:48
-#: openstackclient/identity/v2_0/role.py:294
-msgid "Include <user> (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:79
-msgid "New role name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:84
-#: openstackclient/identity/v3/role.py:155
-msgid "Return existing role"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:116
-msgid "Role(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:178
-#: openstackclient/identity/v2_0/role.py:238
-msgid "Project must be specified"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:192
-#: openstackclient/identity/v2_0/role.py:244
-msgid "User must be specified"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:218
-msgid "User to list (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:223
-msgid "Filter users by <project> (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:282
-msgid "Role to remove (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/role.py:320
-msgid "Role to display (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:36
-msgid "New service type (compute, image, identity, volume, etc)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:47
-msgid "New service name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:52
-msgid "New service description"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:71
-msgid ""
-"The argument --type is deprecated, use service create --name <service-"
-"name> type instead."
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:96
-msgid "Service to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:140
-msgid "Service to display (type, name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:146
-msgid "Show service catalog information"
-msgstr ""
-
-#: openstackclient/identity/v2_0/service.py:163
-#, python-format
-msgid "No service catalog with a type, name or ID of '%s' exists."
-msgstr ""
-
-#: openstackclient/identity/v2_0/token.py:50
-msgid "Token to be deleted"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:35
-msgid "New user name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:40
-msgid "Default project (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:45
-#: openstackclient/identity/v2_0/user.py:258
-msgid "Set user password"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:51
-#: openstackclient/identity/v2_0/user.py:264
-msgid "Prompt interactively for password"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:56
-#: openstackclient/identity/v2_0/user.py:269
-msgid "Set user email address"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:62
-#: openstackclient/identity/v2_0/user.py:275
-msgid "Enable user (default)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:67
-#: openstackclient/identity/v2_0/user.py:280
-msgid "Disable user"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:72
-#: openstackclient/identity/v3/user.py:86
-msgid "Return existing user"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:133
-msgid "User(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:156
-msgid "Filter users by project (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:243
-msgid "User to change (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:248
-msgid "Set user name"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:253
-msgid "Set default project (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v2_0/user.py:342
-msgid "User to display (name or ID)"
-msgstr ""
-
-#: openstackclient/identity/v3/domain.py:57
-msgid "Return existing domain"
-msgstr ""
-
-#: openstackclient/identity/v3/group.py:130
-msgid "Return existing group"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:33
-msgid "New region ID"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:38
-msgid "Parent region ID"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:43
-#: openstackclient/identity/v3/region.py:128
-msgid "New region description"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:70
-msgid "Region ID to delete"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:88
-msgid "Filter by parent region ID"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:118
-msgid "Region to modify"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:123
-msgid "New parent region ID"
-msgstr ""
-
-#: openstackclient/identity/v3/region.py:154
-msgid "Region to display"
-msgstr ""
-
-#: openstackclient/image/v1/image.py:191 openstackclient/image/v1/image.py:609
-#: openstackclient/image/v2/image.py:283 openstackclient/image/v2/image.py:794
-msgid "The --owner option is deprecated, please use --project instead."
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:67
-msgid "Network to allocate floating IP from (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:75
-msgid "Subnet on which you want to create the floating IP (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:81
-msgid "Port to be associated with the floating IP (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:88
-msgid "Floating IP address"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:94
-msgid "Fixed IP address mapped to the floating IP"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:119
-msgid "Floating IP to delete (IP address or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/floating_ip.py:193
-msgid "Floating IP to display (IP address or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:114
-msgid "New network name"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:121
-#: openstackclient/network/v2/network.py:385
-msgid "Share the network between projects"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:126
-#: openstackclient/network/v2/network.py:390
-msgid "Do not share the network between projects"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:136
-msgid "Enable network (default)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:141
-#: openstackclient/network/v2/network.py:378
-msgid "Disable network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:146
-#: openstackclient/network/v2/port.py:246
-#: openstackclient/network/v2/router.py:174
-#: openstackclient/network/v2/security_group.py:116
-#: openstackclient/network/v2/security_group_rule.py:127
-#: openstackclient/network/v2/subnet.py:183
-#: openstackclient/network/v2/subnet_pool.py:114
-msgid "Owner's project (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:154
-msgid ""
-"Availability Zone in which to create this network (Network Availability "
-"Zone extension required, repeat option to set multiple availability "
-"zones)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:162
-#: openstackclient/network/v2/network.py:396
-msgid "Set this network as an external network (external-net extension required)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:168
-msgid "Set this network as an internal network (default)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:174
-msgid "Specify if this network should be used as the default external network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:180
-msgid "Do not use the network as the default external network. (default)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:188
-msgid ""
-"The physical mechanism by which the virtual network is implemented. The "
-"supported options are: flat, gre, local, vlan, vxlan"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:196
-msgid "Name of the physical network over which the virtual network is implemented"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:203
-msgid "VLAN ID for VLAN networks or Tunnel ID for GRE/VXLAN networks"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:212
-msgid "IPv4 subnet for fixed IPs (in CIDR notation)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:361
-msgid "Network to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:366
-msgid "Set network name"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:373
-msgid "Enable network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:402
-msgid "Set this network as an internal network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:408
-msgid "Set the network as the default external network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:413
-msgid "Do not use the network as the default external network"
-msgstr ""
-
-#: openstackclient/network/v2/network.py:436
-msgid "Network to display (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:73
-msgid "The --device-id option is deprecated, please use --device instead."
-msgstr ""
-
-#: openstackclient/network/v2/port.py:79
-msgid "The --host-id option is deprecated, please use --host instead."
-msgstr ""
-
-#: openstackclient/network/v2/port.py:161
-msgid "Port device ID"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:171
-msgid "Device owner of this port"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:178
-msgid ""
-"VNIC type for this port (direct | direct-physical | macvtap | normal | "
-"baremetal, default: normal)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:187
-msgid "Allocate port on host <host-id> (ID only)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:206
-msgid "Network this port belongs to (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:214
-#: openstackclient/network/v2/port.py:365
-msgid ""
-"Desired IP and/or subnet (name or ID) for this port: subnet=<subnet>,ip-"
-"address=<ip-address> (repeat option to set multiple fixed IP addresses)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:222
-#: openstackclient/network/v2/port.py:379
-msgid ""
-"Custom data to be passed as binding:profile: <key>=<value> (repeat option"
-" to set multiple binding:profile data)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:231
-msgid "Enable port (default)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:236
-#: openstackclient/network/v2/port.py:352
-msgid "Disable port"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:241
-msgid "MAC address of this port"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:280
-msgid "Port(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:301
-msgid "List only ports attached to this router (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:347
-msgid "Enable port"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:357
-msgid "Set port name"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:372
-msgid "Clear existing information of fixed IP addresses"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:386
-msgid "Clear existing information of binding:profile"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:391
-msgid "Port to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/port.py:429
-msgid "Port to display (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:99
-msgid "Router to which port will be added (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:104
-msgid "Port to be added (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:123
-msgid "Router to which subnet will be added (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:128
-msgid "Subnet to be added (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:150
-msgid "New router name"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:157
-msgid "Enable router (default)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:162
-#: openstackclient/network/v2/router.py:351
-msgid "Disable router"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:169
-msgid "Create a distributed router"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:182
-msgid ""
-"Availability Zone in which to create this router (Router Availability "
-"Zone extension required, repeat option to set multiple availability "
-"zones)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:210
-msgid "Router(s) to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:283
-msgid "Router from which port will be removed (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:288
-msgid "Port to be removed (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:307
-msgid "Router from which the subnet will be removed (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:312
-msgid "Subnet to be removed (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:334
-msgid "Router to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:339
-msgid "Set router name"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:346
-msgid "Enable router"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:357
-msgid "Set router to distributed mode (disabled router only)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:362
-msgid "Set router to centralized mode (disabled router only)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:372
-msgid ""
-"Routes associated with the router destination: destination subnet (in "
-"CIDR notation) gateway: nexthop IP address (repeat option to set multiple"
-" routes)"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:380
-msgid "Clear routes associated with the router"
-msgstr ""
-
-#: openstackclient/network/v2/router.py:412
-msgid "Router to display (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:103
-#: openstackclient/network/v2/security_group.py:249
-msgid "New security group name"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:108
-msgid "Security group description"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:173
-msgid "Security group to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:208
-msgid "Display information from all projects (admin only)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:244
-msgid "Security group to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:254
-msgid "New security group description"
-msgstr ""
-
-#: openstackclient/network/v2/security_group.py:299
-msgid "Security group to display (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:82
-msgid "IP protocol (icmp, tcp, udp; default: tcp)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:88
-msgid ""
-"Source IP address block (may use CIDR notation; default for IPv4 rule: "
-"0.0.0.0/0)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:94
-msgid "Source security group (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:101
-msgid ""
-"Destination port, may be a single port or port range: 137:139 (only "
-"required for IP protocols tcp and udp)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:111
-msgid "Rule applies to incoming network traffic (default)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:116
-msgid "Rule applies to outgoing network traffic"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:122
-msgid "Ethertype of network traffic (IPv4, IPv6; default: IPv4)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:221
-msgid "Security group rule to delete (ID only)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:241
-msgid "List all rules in this security group (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/security_group_rule.py:336
-msgid "Security group rule to display (ID only)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:54
-msgid ""
-"Allocation pool IP addresses for this subnet e.g.: "
-"start=192.168.199.2,end=192.168.199.254 (repeat option to add multiple IP"
-" addresses)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:63
-msgid "DNS server for this subnet (repeat option to set multiple DNS servers)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:72
-msgid ""
-"Additional route for this subnet e.g.: "
-"destination=10.10.0.0/16,gateway=192.168.71.254 destination: destination "
-"subnet (in CIDR notation) gateway: nexthop IP address (repeat option to "
-"add multiple routes)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:178
-msgid "New subnet name"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:190
-msgid "Subnet pool from which this subnet will obtain a CIDR (Name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:196
-msgid "Use default subnet pool for --ip-version"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:201
-msgid "Prefix length for subnet allocation from subnet pool"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:206
-msgid ""
-"Subnet range in CIDR notation (required if --subnet-pool is not "
-"specified, optional otherwise)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:215
-msgid "Enable DHCP (default)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:220
-#: openstackclient/network/v2/subnet.py:348
-msgid "Disable DHCP"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:226
-msgid ""
-"Specify a gateway for the subnet. The three options are: <ip-address>: "
-"Specific IP address to use as the gateway, 'auto': Gateway address should"
-" automatically be chosen from within the subnet itself, 'none': This "
-"subnet will not use a gateway, e.g.: --gateway 192.168.9.1, --gateway "
-"auto, --gateway none (default is 'auto')"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:238
-msgid ""
-"IP version (default is 4). Note that when subnet pool is specified, IP "
-"version is determined from the subnet pool and this option is ignored"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:245
-msgid ""
-"IPv6 RA (Router Advertisement) mode, valid modes: [dhcpv6-stateful, "
-"dhcpv6-stateless, slaac]"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:251
-msgid "IPv6 address mode, valid modes: [dhcpv6-stateful, dhcpv6-stateless, slaac]"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:258
-msgid "Network this subnet belongs to (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:280
-msgid "Subnet to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:331
-msgid "Subnet to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:336
-msgid "Updated name of the subnet"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:343
-msgid "Enable DHCP"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:353
-msgid ""
-"Specify a gateway for the subnet. The options are: <ip-address>: Specific"
-" IP address to use as the gateway, 'none': This subnet will not use a "
-"gateway, e.g.: --gateway 192.168.9.1, --gateway none"
-msgstr ""
-
-#: openstackclient/network/v2/subnet.py:387
-msgid "Subnet to display (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:77
-msgid ""
-"Set subnet pool prefixes (in CIDR notation) (repeat option to set "
-"multiple prefixes)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:84
-msgid "Set subnet pool default prefix length"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:90
-msgid "Set subnet pool minimum prefix length"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:96
-msgid "Set subnet pool maximum prefix length"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:108
-msgid "Name of the new subnet pool"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:120
-#: openstackclient/network/v2/subnet_pool.py:226
-msgid ""
-"Set address scope associated with the subnet pool (name or ID), prefixes "
-"must be unique across address scopes"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:146
-msgid "Subnet pool to delete (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:214
-msgid "Subnet pool to modify (name or ID)"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:219
-msgid "Set subnet pool name"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:233
-msgid "Remove address scope associated with the subnet pool"
-msgstr ""
-
-#: openstackclient/network/v2/subnet_pool.py:262
-msgid "Subnet pool to display (name or ID)"
-msgstr ""
-
diff --git a/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po b/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po
index a121acab..d9bbf6fe 100644
--- a/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po
+++ b/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po
@@ -7,9 +7,9 @@
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: python-openstackclient 2.2.1.dev235\n"
+"Project-Id-Version: python-openstackclient 2.5.1.dev51\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
-"POT-Creation-Date: 2016-04-19 05:02+0000\n"
+"POT-Creation-Date: 2016-06-03 19:37+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -21,62 +21,6 @@ msgstr ""
"X-Generator: Zanata 3.7.3\n"
"Language-Team: Chinese (Taiwan)\n"
-msgid ""
-"\n"
-"Complete\n"
-msgstr ""
-"\n"
-"完成\n"
-
-msgid ""
-"\n"
-"Error creating server"
-msgstr ""
-"\n"
-"新增雲實例時出錯"
-
-msgid ""
-"\n"
-"Error creating server snapshot"
-msgstr ""
-"\n"
-"新增雲實例即時存檔時出錯"
-
-msgid ""
-"\n"
-"Error migrating server"
-msgstr ""
-"\n"
-"轉移雲實例出錯"
-
-msgid ""
-"\n"
-"Error rebooting server\n"
-msgstr ""
-"\n"
-"重開雲實例出錯\n"
-
-msgid ""
-"\n"
-"Error rebuilding server"
-msgstr ""
-"\n"
-"重建雲實例出錯"
-
-msgid ""
-"\n"
-"Error resizing server"
-msgstr ""
-"\n"
-"調整雲實例容量時出錯"
-
-msgid ""
-"\n"
-"Reboot complete\n"
-msgstr ""
-"\n"
-"重開機完成\n"
-
msgid "Add a property to <name> (repeat option to set multiple properties)"
msgstr "加入屬性到 <name>(重復這選項來設定多個屬性)"
@@ -122,9 +66,6 @@ msgstr "啟用用戶(預設)"
msgid "Endpoint ID to delete"
msgstr "要刪除的端點識別號"
-msgid "Endpoint ID to display"
-msgstr "要顯示的端點識別號"
-
#, python-format
msgid "Error creating server: %s"
msgstr "新增雲實例時出錯:%s"
diff --git a/openstackclient/network/client.py b/openstackclient/network/client.py
index d711f4fc..d12987dd 100644
--- a/openstackclient/network/client.py
+++ b/openstackclient/network/client.py
@@ -15,8 +15,8 @@ import logging
from openstack import connection
from openstack import profile
+from osc_lib import utils
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -36,6 +36,7 @@ def make_client(instance):
prof = profile.Profile()
prof.set_region(API_NAME, instance._region_name)
prof.set_version(API_NAME, instance._api_version[API_NAME])
+ prof.set_interface(API_NAME, instance._interface)
conn = connection.Connection(authenticator=instance.session.auth,
verify=instance.session.verify,
cert=instance.session.cert,
diff --git a/openstackclient/network/common.py b/openstackclient/network/common.py
index 4028ac0d..16cc7379 100644
--- a/openstackclient/network/common.py
+++ b/openstackclient/network/common.py
@@ -12,10 +12,11 @@
#
import abc
+
+from osc_lib.command import command
+from osc_lib import exceptions
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
from openstackclient.i18n import _
diff --git a/openstackclient/network/v2/address_scope.py b/openstackclient/network/v2/address_scope.py
index dbc6865f..bc1a96c3 100644
--- a/openstackclient/network/v2/address_scope.py
+++ b/openstackclient/network/v2/address_scope.py
@@ -13,9 +13,10 @@
"""Address scope action implementations"""
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -94,7 +95,7 @@ class CreateAddressScope(command.ShowOne):
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
- return columns, data
+ return (columns, data)
class DeleteAddressScope(command.Command):
@@ -200,9 +201,6 @@ class SetAddressScope(command.Command):
attrs['shared'] = True
if parsed_args.no_share:
attrs['shared'] = False
- if attrs == {}:
- msg = _("Nothing specified to be set.")
- raise exceptions.CommandError(msg)
client.update_address_scope(obj, **attrs)
@@ -227,4 +225,4 @@ class ShowAddressScope(command.ShowOne):
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
- return columns, data
+ return (columns, data)
diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py
index 21f86599..8fbf049e 100644
--- a/openstackclient/network/v2/floating_ip.py
+++ b/openstackclient/network/v2/floating_ip.py
@@ -13,7 +13,8 @@
"""IP Floating action implementations"""
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.network import common
@@ -109,26 +110,28 @@ class CreateFloatingIP(common.NetworkAndComputeShowOne):
return (columns, data)
-class DeleteFloatingIP(common.NetworkAndComputeCommand):
- """Delete floating IP"""
+class DeleteFloatingIP(common.NetworkAndComputeDelete):
+ """Delete floating IP(s)"""
+
+ # Used by base class to find resources in parsed_args.
+ resource = 'floating_ip'
+ r = None
def update_parser_common(self, parser):
parser.add_argument(
'floating_ip',
metavar="<floating-ip>",
- help=_("Floating IP to delete (IP address or ID)")
+ nargs="+",
+ help=_("Floating IP(s) to delete (IP address or ID)")
)
return parser
def take_action_network(self, client, parsed_args):
- obj = client.find_ip(parsed_args.floating_ip)
+ obj = client.find_ip(self.r, ignore_missing=False)
client.delete_ip(obj)
def take_action_compute(self, client, parsed_args):
- obj = utils.find_resource(
- client.floating_ips,
- parsed_args.floating_ip,
- )
+ obj = utils.find_resource(client.floating_ips, self.r)
client.floating_ips.delete(obj.id)
diff --git a/openstackclient/network/v2/ip_availability.py b/openstackclient/network/v2/ip_availability.py
new file mode 100644
index 00000000..1d7b2aed
--- /dev/null
+++ b/openstackclient/network/v2/ip_availability.py
@@ -0,0 +1,112 @@
+# 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.
+#
+
+"""IP Availability Info implementations"""
+
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
+from openstackclient.identity import common as identity_common
+
+
+_formatters = {
+ 'subnet_ip_availability': utils.format_list_of_dicts,
+}
+
+
+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))
+
+
+class ListIPAvailability(command.Lister):
+ """List IP availability for network"""
+
+ def get_parser(self, prog_name):
+ parser = super(ListIPAvailability, self).get_parser(prog_name)
+ parser.add_argument(
+ '--ip-version',
+ type=int,
+ default=4,
+ choices=[4, 6],
+ metavar='<ip-version>',
+ dest='ip_version',
+ help=_("List IP availability of given IP version "
+ "networks (default is 4)"),
+ )
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help=_("List IP availability of given project (name or ID)"),
+ )
+ identity_common.add_project_domain_option_to_parser(parser)
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+
+ columns = (
+ 'network_id',
+ 'network_name',
+ 'total_ips',
+ 'used_ips',
+ )
+ column_headers = (
+ 'Network ID',
+ 'Network Name',
+ 'Total IPs',
+ 'Used IPs',
+ )
+
+ filters = {}
+ if parsed_args.ip_version:
+ filters['ip_version'] = parsed_args.ip_version
+
+ if parsed_args.project:
+ identity_client = self.app.client_manager.identity
+ project_id = identity_common.find_project(
+ identity_client,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ filters['tenant_id'] = project_id
+ data = client.network_ip_availabilities(**filters)
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ ) for s in data))
+
+
+class ShowIPAvailability(command.ShowOne):
+ """Show network IP availability details"""
+
+ def get_parser(self, prog_name):
+ parser = super(ShowIPAvailability, self).get_parser(prog_name)
+ parser.add_argument(
+ 'network',
+ metavar="<network>",
+ help=_("Show IP availability for a specific network (name or ID)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ obj = client.find_network_ip_availability(parsed_args.network,
+ ignore_missing=False)
+ columns = _get_columns(obj)
+ data = utils.get_item_properties(obj, columns, formatters=_formatters)
+ return (columns, data)
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index bf01e2ec..41735500 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -13,9 +13,9 @@
"""Network action implementations"""
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -104,11 +104,11 @@ def _add_additional_network_options(parser):
parser.add_argument(
'--provider-network-type',
metavar='<provider-network-type>',
- choices=['flat', 'gre', 'local',
+ choices=['flat', 'geneve', 'gre', 'local',
'vlan', 'vxlan'],
help=_("The physical mechanism by which the virtual network "
"is implemented. The supported options are: "
- "flat, gre, local, vlan, vxlan"))
+ "flat, geneve, gre, local, vlan, vxlan"))
parser.add_argument(
'--provider-physical-network',
metavar='<provider-physical-network>',
@@ -119,8 +119,8 @@ def _add_additional_network_options(parser):
'--provider-segment',
metavar='<provider-segment>',
dest='segmentation_id',
- help=_("VLAN ID for VLAN networks or Tunnel ID for GRE/VXLAN "
- "networks"))
+ help=_("VLAN ID for VLAN networks or Tunnel ID for "
+ "GENEVE/GRE/VXLAN networks"))
vlan_transparent_grp = parser.add_mutually_exclusive_group()
vlan_transparent_grp.add_argument(
@@ -434,10 +434,6 @@ class SetNetwork(command.Command):
obj = client.find_network(parsed_args.network, ignore_missing=False)
attrs = _get_attrs(self.app.client_manager, parsed_args)
- if attrs == {}:
- msg = _("Nothing specified to be set")
- raise exceptions.CommandError(msg)
-
client.update_network(obj, **attrs)
diff --git a/openstackclient/network/v2/network_segment.py b/openstackclient/network/v2/network_segment.py
index d8a91fd2..bedf15f7 100644
--- a/openstackclient/network/v2/network_segment.py
+++ b/openstackclient/network/v2/network_segment.py
@@ -15,9 +15,9 @@
# TODO(rtheis): Add description and name properties when support is available.
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
@@ -25,7 +25,7 @@ class ListNetworkSegment(command.Lister):
"""List network segments
(Caution: This is a beta command and subject to change.
- Use global option --enable-beta-commands to enable
+ Use global option --os-beta-command to enable
this command)
"""
@@ -46,11 +46,7 @@ class ListNetworkSegment(command.Lister):
return parser
def take_action(self, parsed_args):
- if not self.app.options.enable_beta_commands:
- msg = _('Caution: This is a beta command and subject to '
- 'change. Use global option --enable-beta-commands '
- 'to enable this command.')
- raise exceptions.CommandError(msg)
+ self.validate_os_beta_command_enabled()
network_client = self.app.client_manager.network
@@ -94,7 +90,7 @@ class ShowNetworkSegment(command.ShowOne):
"""Display network segment details
(Caution: This is a beta command and subject to change.
- Use global option --enable-beta-commands to enable
+ Use global option --os-beta-command to enable
this command)
"""
@@ -108,11 +104,7 @@ class ShowNetworkSegment(command.ShowOne):
return parser
def take_action(self, parsed_args):
- if not self.app.options.enable_beta_commands:
- msg = _('Caution: This is a beta command and subject to '
- 'change. Use global option --enable-beta-commands '
- 'to enable this command.')
- raise exceptions.CommandError(msg)
+ self.validate_os_beta_command_enabled()
client = self.app.client_manager.network
obj = client.find_segment(
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index ca02281f..1c5db706 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -16,10 +16,11 @@
import argparse
import logging
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -266,7 +267,7 @@ class CreatePort(command.ShowOne):
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return columns, data
+ return (columns, data)
class DeletePort(command.Command):
@@ -284,10 +285,23 @@ class DeletePort(command.Command):
def take_action(self, parsed_args):
client = self.app.client_manager.network
+ result = 0
for port in parsed_args.port:
- res = client.find_port(port)
- client.delete_port(res)
+ try:
+ obj = client.find_port(port, ignore_missing=False)
+ client.delete_port(obj)
+ except Exception as e:
+ result += 1
+ self.app.log.error(_("Failed to delete port with "
+ "name or ID '%(port)s': %(e)s")
+ % {'port': port, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.port)
+ msg = (_("%(result)s of %(total)s ports failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListPort(command.Lister):
@@ -413,9 +427,6 @@ class SetPort(command.Command):
elif parsed_args.no_fixed_ip:
attrs['fixed_ips'] = []
- if attrs == {}:
- msg = _("Nothing specified to be set")
- raise exceptions.CommandError(msg)
client.update_port(obj, **attrs)
@@ -436,4 +447,4 @@ class ShowPort(command.ShowOne):
obj = client.find_port(parsed_args.port, ignore_missing=False)
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return columns, data
+ return (columns, data)
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index a2f0df1d..92ecf84d 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -17,10 +17,10 @@ import argparse
import json
import logging
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -204,7 +204,7 @@ class CreateRouter(command.ShowOne):
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return columns, data
+ return (columns, data)
class DeleteRouter(command.Command):
@@ -426,10 +426,6 @@ class SetRouter(command.Command):
route['nexthop'] = route.pop('gateway')
attrs['routes'] = obj.routes + parsed_args.routes
- if attrs == {}:
- msg = _("Nothing specified to be set")
- raise exceptions.CommandError(msg)
-
client.update_router(obj, **attrs)
@@ -450,4 +446,4 @@ class ShowRouter(command.ShowOne):
obj = client.find_router(parsed_args.router, ignore_missing=False)
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
- return columns, data
+ return (columns, data)
diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py
index 1ef2754e..f832f721 100644
--- a/openstackclient/network/v2/security_group.py
+++ b/openstackclient/network/v2/security_group.py
@@ -14,9 +14,10 @@
"""Security Group action implementations"""
import argparse
+
+from osc_lib import utils
import six
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -163,26 +164,28 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne):
return (display_columns, data)
-class DeleteSecurityGroup(common.NetworkAndComputeCommand):
- """Delete a security group"""
+class DeleteSecurityGroup(common.NetworkAndComputeDelete):
+ """Delete security group(s)"""
+
+ # Used by base class to find resources in parsed_args.
+ resource = 'group'
+ r = None
def update_parser_common(self, parser):
parser.add_argument(
'group',
metavar='<group>',
- help=_("Security group to delete (name or ID)")
+ nargs="+",
+ help=_("Security group(s) to delete (name or ID)"),
)
return parser
def take_action_network(self, client, parsed_args):
- obj = client.find_security_group(parsed_args.group)
+ obj = client.find_security_group(self.r, ignore_missing=False)
client.delete_security_group(obj)
def take_action_compute(self, client, parsed_args):
- data = utils.find_resource(
- client.security_groups,
- parsed_args.group,
- )
+ data = utils.find_resource(client.security_groups, self.r)
client.security_groups.delete(data.id)
diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py
index 5abe9b9d..18863223 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -14,16 +14,17 @@
"""Security Group Rule action implementations"""
import argparse
-import six
try:
from novaclient.v2 import security_group_rules as compute_secgroup_rules
except ImportError:
from novaclient.v1_1 import security_group_rules as compute_secgroup_rules
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib import exceptions
+from osc_lib import utils
+import six
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -332,23 +333,29 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
return _format_security_group_rule_show(obj._info)
-class DeleteSecurityGroupRule(common.NetworkAndComputeCommand):
- """Delete a security group rule"""
+class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
+ """Delete security group rule(s)"""
+
+ # Used by base class to find resources in parsed_args.
+ resource = 'rule'
+ r = None
def update_parser_common(self, parser):
parser.add_argument(
'rule',
metavar='<rule>',
- help=_("Security group rule to delete (ID only)")
+ nargs="+",
+ help=_("Security group rule(s) to delete (ID only)")
)
return parser
def take_action_network(self, client, parsed_args):
- obj = client.find_security_group_rule(parsed_args.rule)
+ obj = client.find_security_group_rule(
+ self.r, ignore_missing=False)
client.delete_security_group_rule(obj)
def take_action_compute(self, client, parsed_args):
- client.security_group_rules.delete(parsed_args.rule)
+ client.security_group_rules.delete(self.r)
class ListSecurityGroupRule(common.NetworkAndComputeLister):
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index e7e1be99..ceb1cb14 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -12,12 +12,14 @@
#
"""Subnet action implementations"""
+
import copy
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -373,9 +375,6 @@ class SetSubnet(command.Command):
obj = client.find_subnet(parsed_args.subnet, ignore_missing=False)
attrs = _get_attrs(self.app.client_manager, parsed_args,
is_create=False)
- if not attrs:
- msg = "Nothing specified to be set"
- raise exceptions.CommandError(msg)
if 'dns_nameservers' in attrs:
attrs['dns_nameservers'] += obj.dns_nameservers
if 'host_routes' in attrs:
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index a1a94426..79f98fd9 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -13,10 +13,10 @@
"""Subnet pool action implementations"""
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -286,9 +286,6 @@ class SetSubnetPool(command.Command):
ignore_missing=False)
attrs = _get_attrs(self.app.client_manager, parsed_args)
- if attrs == {}:
- msg = _("Nothing specified to be set")
- raise exceptions.CommandError(msg)
# Existing prefixes must be a subset of the new prefixes.
if 'prefixes' in attrs:
diff --git a/openstackclient/object/client.py b/openstackclient/object/client.py
index 3af6f8a0..cb3ddc28 100644
--- a/openstackclient/object/client.py
+++ b/openstackclient/object/client.py
@@ -15,8 +15,9 @@
"""Object client"""
+from osc_lib import utils
+
from openstackclient.api import object_store_v1
-from openstackclient.common import utils
DEFAULT_API_VERSION = '1'
API_VERSION_OPTION = 'os_object_api_version'
diff --git a/openstackclient/object/v1/account.py b/openstackclient/object/v1/account.py
index 543ce4f3..801fe450 100644
--- a/openstackclient/object/v1/account.py
+++ b/openstackclient/object/v1/account.py
@@ -13,12 +13,11 @@
"""Account v1 action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
-
class SetAccount(command.Command):
"""Set account properties"""
diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py
index 80b84238..2b021ec2 100644
--- a/openstackclient/object/v1/container.py
+++ b/openstackclient/object/v1/container.py
@@ -16,12 +16,11 @@
"""Container v1 action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
-
class CreateContainer(command.Lister):
"""Create new container"""
diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py
index f9a55e9c..39dba3d5 100644
--- a/openstackclient/object/v1/object.py
+++ b/openstackclient/object/v1/object.py
@@ -16,12 +16,11 @@
"""Object v1 action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
-
class CreateObject(command.Lister):
"""Upload object to container"""
diff --git a/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml b/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml
index c783d013..98e037bc 100644
--- a/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml
+++ b/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml
@@ -3,4 +3,3 @@ fixes:
- Keystone V3 `user password set` is a self-service operation. It should
not required a scoped token as it is not considered a `scoped operation`.
[Bug `1543222 <https://bugs.launchpad.net/bugs/1543222>`_]
-
diff --git a/openstackclient/shell.py b/openstackclient/shell.py
index 9968d73f..12a63af2 100644
--- a/openstackclient/shell.py
+++ b/openstackclient/shell.py
@@ -26,16 +26,17 @@ from cliff import app
from cliff import command
from cliff import complete
from cliff import help
+from osc_lib.command import timing
+from osc_lib import exceptions as exc
+from osc_lib import logs
+from osc_lib import utils
from oslo_utils import importutils
from oslo_utils import strutils
import openstackclient
from openstackclient.common import clientmanager
from openstackclient.common import commandmanager
-from openstackclient.common import exceptions as exc
-from openstackclient.common import logs
-from openstackclient.common import timing
-from openstackclient.common import utils
+from openstackclient.i18n import _
from os_client_config import config as cloud_config
@@ -63,9 +64,8 @@ def prompt_for_password(prompt=None):
pass
# No password because we did't have a tty or nothing was entered
if not pw:
- raise exc.CommandError(
- "No password entered, or found via --os-password or OS_PASSWORD",
- )
+ raise exc.CommandError(_("No password entered, or found via"
+ " --os-password or OS_PASSWORD"),)
return pw
@@ -185,7 +185,7 @@ class OpenStackShell(app.App):
metavar='<cloud-config-name>',
dest='cloud',
default=utils.env('OS_CLOUD'),
- help='Cloud name in clouds.yaml (Env: OS_CLOUD)',
+ help=_('Cloud name in clouds.yaml (Env: OS_CLOUD)'),
)
# Global arguments
parser.add_argument(
@@ -193,37 +193,41 @@ class OpenStackShell(app.App):
metavar='<auth-region-name>',
dest='region_name',
default=utils.env('OS_REGION_NAME'),
- help='Authentication region name (Env: OS_REGION_NAME)')
+ help=_('Authentication region name (Env: OS_REGION_NAME)'),
+ )
parser.add_argument(
'--os-cacert',
metavar='<ca-bundle-file>',
dest='cacert',
default=utils.env('OS_CACERT'),
- help='CA certificate bundle file (Env: OS_CACERT)')
+ help=_('CA certificate bundle file (Env: OS_CACERT)'),
+ )
parser.add_argument(
'--os-cert',
metavar='<certificate-file>',
dest='cert',
default=utils.env('OS_CERT'),
- help='Client certificate bundle file (Env: OS_CERT)')
+ help=_('Client certificate bundle file (Env: OS_CERT)'),
+ )
parser.add_argument(
'--os-key',
metavar='<key-file>',
dest='key',
default=utils.env('OS_KEY'),
- help='Client certificate key file (Env: OS_KEY)')
+ help=_('Client certificate key file (Env: OS_KEY)'),
+ )
verify_group = parser.add_mutually_exclusive_group()
verify_group.add_argument(
'--verify',
action='store_true',
default=None,
- help='Verify server certificate (default)',
+ help=_('Verify server certificate (default)'),
)
verify_group.add_argument(
'--insecure',
action='store_true',
default=None,
- help='Disable server certificate verification',
+ help=_('Disable server certificate verification'),
)
parser.add_argument(
'--os-default-domain',
@@ -232,28 +236,29 @@ class OpenStackShell(app.App):
default=utils.env(
'OS_DEFAULT_DOMAIN',
default=DEFAULT_DOMAIN),
- help='Default domain ID, default=' +
- DEFAULT_DOMAIN +
- ' (Env: OS_DEFAULT_DOMAIN)')
+ help=_('Default domain ID, default=%s. '
+ '(Env: OS_DEFAULT_DOMAIN)') % DEFAULT_DOMAIN,
+ )
parser.add_argument(
'--os-interface',
metavar='<interface>',
dest='interface',
choices=['admin', 'public', 'internal'],
default=utils.env('OS_INTERFACE'),
- help='Select an interface type.'
- ' Valid interface types: [admin, public, internal].'
- ' (Env: OS_INTERFACE)')
+ help=_('Select an interface type.'
+ ' Valid interface types: [admin, public, internal].'
+ ' (Env: OS_INTERFACE)'),
+ )
parser.add_argument(
'--timing',
default=False,
action='store_true',
- help="Print API call timing info",
+ help=_("Print API call timing info"),
)
parser.add_argument(
- '--enable-beta-commands',
+ '--os-beta-command',
action='store_true',
- help="Enable beta commands which are subject to change",
+ help=_("Enable beta commands which are subject to change"),
)
# osprofiler HMAC key argument
@@ -262,7 +267,7 @@ class OpenStackShell(app.App):
'--os-profile',
metavar='hmac-key',
dest='profile',
- help='HMAC key for encrypting profiling context data',
+ help=_('HMAC key for encrypting profiling context data'),
)
# NOTE(dtroyer): This global option should have been named
# --os-profile as --profile interferes with at
diff --git a/openstackclient/tests/api/test_api.py b/openstackclient/tests/api/test_api.py
index 81197967..b444d9f1 100644
--- a/openstackclient/tests/api/test_api.py
+++ b/openstackclient/tests/api/test_api.py
@@ -13,8 +13,9 @@
"""Base API Library Tests"""
+from osc_lib import exceptions
+
from openstackclient.api import api
-from openstackclient.common import exceptions
from openstackclient.tests.api import fakes as api_fakes
diff --git a/openstackclient/tests/common/test_clientmanager.py b/openstackclient/tests/common/test_clientmanager.py
index fa6c3fcc..520cce13 100644
--- a/openstackclient/tests/common/test_clientmanager.py
+++ b/openstackclient/tests/common/test_clientmanager.py
@@ -15,21 +15,20 @@
import json as jsonutils
import mock
-from requests_mock.contrib import fixture
-from keystoneclient.auth.identity import v2 as auth_v2
-from keystoneclient import service_catalog
+from keystoneauth1.access import service_catalog
+from keystoneauth1.identity import v2 as auth_v2
+from keystoneauth1 import token_endpoint
+from osc_lib import exceptions as exc
+from requests_mock.contrib import fixture
from openstackclient.api import auth
-from openstackclient.api import auth_plugin
from openstackclient.common import clientmanager
-from openstackclient.common import exceptions as exc
from openstackclient.tests import fakes
from openstackclient.tests import utils
API_VERSION = {"identity": "2.0"}
-
AUTH_REF = {'version': 'v2.0'}
AUTH_REF.update(fakes.TEST_RESPONSE_DICT['access'])
SERVICE_CATALOG = service_catalog.ServiceCatalogV2(AUTH_REF)
@@ -126,7 +125,7 @@ class TestClientManager(utils.TestCase):
)
self.assertIsInstance(
client_manager.auth,
- auth_plugin.TokenEndpoint,
+ token_endpoint.Token,
)
self.assertFalse(client_manager._insecure)
self.assertTrue(client_manager._verify)
@@ -205,11 +204,14 @@ class TestClientManager(utils.TestCase):
)
self.assertTrue(client_manager._insecure)
self.assertFalse(client_manager._verify)
-
# These need to stick around until the old-style clients are gone
self.assertEqual(
- AUTH_REF,
- client_manager.auth_ref,
+ AUTH_REF.pop('version'),
+ client_manager.auth_ref.version,
+ )
+ self.assertEqual(
+ fakes.to_unicode_dict(AUTH_REF),
+ client_manager.auth_ref._data['access'],
)
self.assertEqual(
dir(SERVICE_CATALOG),
@@ -296,9 +298,10 @@ class TestClientManager(utils.TestCase):
def _select_auth_plugin(self, auth_params, api_version, auth_plugin_name):
auth_params['auth_type'] = auth_plugin_name
auth_params['identity_api_version'] = api_version
+
client_manager = clientmanager.ClientManager(
cli_options=FakeOptions(**auth_params),
- api_version=API_VERSION,
+ api_version={"identity": api_version},
verify=True
)
client_manager.setup_auth()
diff --git a/openstackclient/tests/common/test_command.py b/openstackclient/tests/common/test_command.py
index 7467d9eb..658bc895 100644
--- a/openstackclient/tests/common/test_command.py
+++ b/openstackclient/tests/common/test_command.py
@@ -14,7 +14,10 @@
import mock
+from osc_lib import exceptions
+
from openstackclient.common import command
+from openstackclient.tests import fakes as test_fakes
from openstackclient.tests import utils as test_utils
@@ -31,3 +34,16 @@ class TestCommand(test_utils.TestCase):
self.assertTrue(hasattr(cmd, 'log'))
self.assertEqual('openstackclient.tests.common.test_command.'
'FakeCommand', cmd.log.name)
+
+ def test_validate_os_beta_command_enabled(self):
+ cmd = FakeCommand(mock.Mock(), mock.Mock())
+ cmd.app = mock.Mock()
+ cmd.app.options = test_fakes.FakeOptions()
+
+ # No exception is raised when enabled.
+ cmd.app.options.os_beta_command = True
+ cmd.validate_os_beta_command_enabled()
+
+ cmd.app.options.os_beta_command = False
+ self.assertRaises(exceptions.CommandError,
+ cmd.validate_os_beta_command_enabled)
diff --git a/openstackclient/tests/common/test_extension.py b/openstackclient/tests/common/test_extension.py
index 0736a3e5..17a3b492 100644
--- a/openstackclient/tests/common/test_extension.py
+++ b/openstackclient/tests/common/test_extension.py
@@ -11,7 +11,6 @@
# under the License.
#
-import copy
import mock
from openstackclient.common import extension
@@ -29,26 +28,38 @@ class TestExtension(utils.TestCommand):
def setUp(self):
super(TestExtension, self).setUp()
- self.app.client_manager.identity = identity_fakes.FakeIdentityv2Client(
+ identity_client = identity_fakes.FakeIdentityv2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
- self.identity_extensions_mock = (
- self.app.client_manager.identity.extensions)
+ self.app.client_manager.identity = identity_client
+ self.identity_extensions_mock = identity_client.extensions
self.identity_extensions_mock.reset_mock()
- self.app.client_manager.compute = compute_fakes.FakeComputev2Client(
+ compute_client = compute_fakes.FakeComputev2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
+ self.app.client_manager.compute = compute_client
+ compute_client.list_extensions = mock.Mock()
+ self.compute_extensions_mock = compute_client.list_extensions
+ self.compute_extensions_mock.reset_mock()
- self.app.client_manager.volume = volume_fakes.FakeVolumeClient(
+ volume_client = volume_fakes.FakeVolumeClient(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
+ self.app.client_manager.volume = volume_client
+ volume_client.list_extensions = mock.Mock()
+ self.volume_extensions_mock = volume_client.list_extensions
+ self.volume_extensions_mock.reset_mock()
- network_client = network_fakes.FakeNetworkV2Client()
+ network_client = network_fakes.FakeNetworkV2Client(
+ endpoint=fakes.AUTH_URL,
+ token=fakes.AUTH_TOKEN,
+ )
self.app.client_manager.network = network_client
+ network_client.extensions = mock.Mock()
self.network_extensions_mock = network_client.extensions
self.network_extensions_mock.reset_mock()
@@ -59,38 +70,21 @@ class TestExtensionList(TestExtension):
long_columns = ('Name', 'Namespace', 'Description', 'Alias', 'Updated',
'Links')
+ volume_extension = volume_fakes.FakeExtension.create_one_extension()
+ identity_extension = identity_fakes.FakeExtension.create_one_extension()
+ compute_extension = compute_fakes.FakeExtension.create_one_extension()
+ network_extension = network_fakes.FakeExtension.create_one_extension()
+
def setUp(self):
super(TestExtensionList, self).setUp()
self.identity_extensions_mock.list.return_value = [
- fakes.FakeResource(
- None,
- copy.deepcopy(identity_fakes.EXTENSION),
- loaded=True,
- ),
- ]
-
- self.app.client_manager.compute.list_extensions = mock.Mock()
- self.compute_extensions_mock = (
- self.app.client_manager.compute.list_extensions)
+ self.identity_extension]
self.compute_extensions_mock.show_all.return_value = [
- fakes.FakeResource(
- None,
- copy.deepcopy(compute_fakes.EXTENSION),
- loaded=True,
- ),
- ]
-
- self.app.client_manager.volume.list_extensions = mock.Mock()
- self.volume_extensions_mock = (
- self.app.client_manager.volume.list_extensions)
+ self.compute_extension]
self.volume_extensions_mock.show_all.return_value = [
- fakes.FakeResource(
- None,
- copy.deepcopy(volume_fakes.EXTENSION),
- loaded=True,
- ),
- ]
+ self.volume_extension]
+ self.network_extensions_mock.return_value = [self.network_extension]
# Get the command object to test
self.cmd = extension.ListExtension(self.app, None)
@@ -115,24 +109,24 @@ class TestExtensionList(TestExtension):
verifylist = []
datalist = (
(
- identity_fakes.extension_name,
- identity_fakes.extension_alias,
- identity_fakes.extension_description,
+ self.identity_extension.name,
+ self.identity_extension.alias,
+ self.identity_extension.description,
),
(
- compute_fakes.extension_name,
- compute_fakes.extension_alias,
- compute_fakes.extension_description,
+ self.compute_extension.name,
+ self.compute_extension.alias,
+ self.compute_extension.description,
),
(
- volume_fakes.extension_name,
- volume_fakes.extension_alias,
- volume_fakes.extension_description,
+ self.volume_extension.name,
+ self.volume_extension.alias,
+ self.volume_extension.description,
),
(
- network_fakes.extension_name,
- network_fakes.extension_alias,
- network_fakes.extension_description,
+ self.network_extension.name,
+ self.network_extension.alias,
+ self.network_extension.description,
),
)
self._test_extension_list_helper(arglist, verifylist, datalist)
@@ -150,36 +144,36 @@ class TestExtensionList(TestExtension):
]
datalist = (
(
- identity_fakes.extension_name,
- identity_fakes.extension_namespace,
- identity_fakes.extension_description,
- identity_fakes.extension_alias,
- identity_fakes.extension_updated,
- identity_fakes.extension_links,
+ self.identity_extension.name,
+ self.identity_extension.namespace,
+ self.identity_extension.description,
+ self.identity_extension.alias,
+ self.identity_extension.updated,
+ self.identity_extension.links,
),
(
- compute_fakes.extension_name,
- compute_fakes.extension_namespace,
- compute_fakes.extension_description,
- compute_fakes.extension_alias,
- compute_fakes.extension_updated,
- compute_fakes.extension_links,
+ self.compute_extension.name,
+ self.compute_extension.namespace,
+ self.compute_extension.description,
+ self.compute_extension.alias,
+ self.compute_extension.updated,
+ self.compute_extension.links,
),
(
- volume_fakes.extension_name,
- volume_fakes.extension_namespace,
- volume_fakes.extension_description,
- volume_fakes.extension_alias,
- volume_fakes.extension_updated,
- volume_fakes.extension_links,
+ self.volume_extension.name,
+ self.volume_extension.namespace,
+ self.volume_extension.description,
+ self.volume_extension.alias,
+ self.volume_extension.updated,
+ self.volume_extension.links,
),
(
- network_fakes.extension_name,
- network_fakes.extension_namespace,
- network_fakes.extension_description,
- network_fakes.extension_alias,
- network_fakes.extension_updated,
- network_fakes.extension_links,
+ self.network_extension.name,
+ self.network_extension.namespace,
+ self.network_extension.description,
+ self.network_extension.alias,
+ self.network_extension.updated,
+ self.network_extension.links,
),
)
self._test_extension_list_helper(arglist, verifylist, datalist, True)
@@ -196,9 +190,9 @@ class TestExtensionList(TestExtension):
('identity', True),
]
datalist = ((
- identity_fakes.extension_name,
- identity_fakes.extension_alias,
- identity_fakes.extension_description,
+ self.identity_extension.name,
+ self.identity_extension.alias,
+ self.identity_extension.description,
), )
self._test_extension_list_helper(arglist, verifylist, datalist)
self.identity_extensions_mock.list.assert_called_with()
@@ -212,9 +206,9 @@ class TestExtensionList(TestExtension):
]
datalist = (
(
- network_fakes.extension_name,
- network_fakes.extension_alias,
- network_fakes.extension_description,
+ self.network_extension.name,
+ self.network_extension.alias,
+ self.network_extension.description,
),
)
self._test_extension_list_helper(arglist, verifylist, datalist)
@@ -228,9 +222,9 @@ class TestExtensionList(TestExtension):
('compute', True),
]
datalist = ((
- compute_fakes.extension_name,
- compute_fakes.extension_alias,
- compute_fakes.extension_description,
+ self.compute_extension.name,
+ self.compute_extension.alias,
+ self.compute_extension.description,
), )
self._test_extension_list_helper(arglist, verifylist, datalist)
self.compute_extensions_mock.show_all.assert_called_with()
@@ -243,9 +237,9 @@ class TestExtensionList(TestExtension):
('volume', True),
]
datalist = ((
- volume_fakes.extension_name,
- volume_fakes.extension_alias,
- volume_fakes.extension_description,
+ self.volume_extension.name,
+ self.volume_extension.alias,
+ self.volume_extension.description,
), )
self._test_extension_list_helper(arglist, verifylist, datalist)
self.volume_extensions_mock.show_all.assert_called_with()
diff --git a/openstackclient/tests/common/test_logs.py b/openstackclient/tests/common/test_logs.py
index 0386cdfd..5091510c 100644
--- a/openstackclient/tests/common/test_logs.py
+++ b/openstackclient/tests/common/test_logs.py
@@ -11,6 +11,9 @@
# under the License.
#
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
+
import logging
import mock
@@ -121,7 +124,7 @@ class TestLogConfigurator(utils.TestCase):
@mock.patch('logging.StreamHandler')
@mock.patch('logging.getLogger')
- @mock.patch('openstackclient.common.logs.set_warning_filter')
+ @mock.patch('osc_lib.logs.set_warning_filter')
def test_init(self, warning_filter, getLogger, handle):
getLogger.side_effect = self.loggers
console_logger = mock.Mock()
@@ -142,7 +145,7 @@ class TestLogConfigurator(utils.TestCase):
self.assertFalse(configurator.dump_trace)
@mock.patch('logging.getLogger')
- @mock.patch('openstackclient.common.logs.set_warning_filter')
+ @mock.patch('osc_lib.logs.set_warning_filter')
def test_init_no_debug(self, warning_filter, getLogger):
getLogger.side_effect = self.loggers
self.options.debug = True
@@ -155,8 +158,8 @@ class TestLogConfigurator(utils.TestCase):
@mock.patch('logging.FileHandler')
@mock.patch('logging.getLogger')
- @mock.patch('openstackclient.common.logs.set_warning_filter')
- @mock.patch('openstackclient.common.logs._FileFormatter')
+ @mock.patch('osc_lib.logs.set_warning_filter')
+ @mock.patch('osc_lib.logs._FileFormatter')
def test_init_log_file(self, formatter, warning_filter, getLogger, handle):
getLogger.side_effect = self.loggers
self.options.log_file = '/tmp/log_file'
@@ -176,8 +179,8 @@ class TestLogConfigurator(utils.TestCase):
@mock.patch('logging.FileHandler')
@mock.patch('logging.getLogger')
- @mock.patch('openstackclient.common.logs.set_warning_filter')
- @mock.patch('openstackclient.common.logs._FileFormatter')
+ @mock.patch('osc_lib.logs.set_warning_filter')
+ @mock.patch('osc_lib.logs._FileFormatter')
def test_configure(self, formatter, warning_filter, getLogger, handle):
getLogger.side_effect = self.loggers
configurator = logs.LogConfigurator(self.options)
diff --git a/openstackclient/tests/common/test_parseractions.py b/openstackclient/tests/common/test_parseractions.py
index 5c5ca3d3..60d4a8cf 100644
--- a/openstackclient/tests/common/test_parseractions.py
+++ b/openstackclient/tests/common/test_parseractions.py
@@ -13,6 +13,9 @@
# under the License.
#
+# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
+# or Jun 2017.
+
import argparse
from openstackclient.common import parseractions
@@ -49,16 +52,13 @@ class TestKeyValueAction(utils.TestCase):
self.assertDictEqual(expect, actual)
def test_error_values(self):
- results = self.parser.parse_args([
- '--property', 'red',
- '--property', 'green=100%',
- '--property', 'blue',
- ])
-
- actual = getattr(results, 'property', {})
- # There should be no red or blue
- expect = {'green': '100%', 'format': '#rgb'}
- self.assertDictEqual(expect, actual)
+ self.assertRaises(
+ argparse.ArgumentTypeError,
+ self.parser.parse_args,
+ [
+ '--property', 'red',
+ ]
+ )
class TestMultiKeyValueAction(utils.TestCase):
diff --git a/openstackclient/tests/common/test_timing.py b/openstackclient/tests/common/test_timing.py
deleted file mode 100644
index e33bb7ae..00000000
--- a/openstackclient/tests/common/test_timing.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# 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.
-#
-
-"""Test Timing pseudo-command"""
-
-import datetime
-
-from openstackclient.common import timing
-from openstackclient.tests import fakes
-from openstackclient.tests import utils
-
-
-timing_url = 'GET http://localhost:5000'
-timing_elapsed = 0.872809
-
-
-class FakeGenericClient(object):
-
- def __init__(self, **kwargs):
- self.auth_token = kwargs['token']
- self.management_url = kwargs['endpoint']
-
-
-class TestTiming(utils.TestCommand):
-
- columns = (
- 'URL',
- 'Seconds',
- )
-
- def setUp(self):
- super(TestTiming, self).setUp()
-
- self.app.timing_data = []
-
- self.app.client_manager.compute = FakeGenericClient(
- endpoint=fakes.AUTH_URL,
- token=fakes.AUTH_TOKEN,
- )
-
- self.app.client_manager.volume = FakeGenericClient(
- endpoint=fakes.AUTH_URL,
- token=fakes.AUTH_TOKEN,
- )
-
- # Get the command object to test
- self.cmd = timing.Timing(self.app, None)
-
- def test_timing_list_no_data(self):
- arglist = []
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- # In base command class Lister in cliff, abstract method take_action()
- # returns a tuple containing the column names and an iterable
- # containing the data to be listed.
- columns, data = self.cmd.take_action(parsed_args)
-
- self.assertEqual(self.columns, columns)
- datalist = [
- ('Total', 0.0,)
- ]
- self.assertEqual(datalist, data)
-
- def test_timing_list(self):
- self.app.timing_data = [(
- timing_url,
- datetime.timedelta(microseconds=timing_elapsed * 1000000),
- )]
-
- arglist = []
- verifylist = []
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- # In base command class Lister in cliff, abstract method take_action()
- # returns a tuple containing the column names and an iterable
- # containing the data to be listed.
- columns, data = self.cmd.take_action(parsed_args)
- self.assertEqual(self.columns, columns)
- datalist = [
- (timing_url, timing_elapsed),
- ('Total', timing_elapsed),
- ]
- self.assertEqual(datalist, data)
diff --git a/openstackclient/tests/common/test_utils.py b/openstackclient/tests/common/test_utils.py
deleted file mode 100644
index 2248d043..00000000
--- a/openstackclient/tests/common/test_utils.py
+++ /dev/null
@@ -1,400 +0,0 @@
-# Copyright 2012-2013 OpenStack, LLC.
-#
-# 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 time
-import uuid
-
-import mock
-
-from openstackclient.common import exceptions
-from openstackclient.common import utils
-from openstackclient.tests import fakes
-from openstackclient.tests import utils as test_utils
-
-PASSWORD = "Pa$$w0rd"
-WASSPORD = "Wa$$p0rd"
-DROWSSAP = "dr0w$$aP"
-
-
-class FakeOddballResource(fakes.FakeResource):
-
- def get(self, attr):
- """get() is needed for utils.find_resource()"""
- if attr == 'id':
- return self.id
- elif attr == 'name':
- return self.name
- else:
- return None
-
-
-class TestUtils(test_utils.TestCase):
-
- def test_get_password_good(self):
- with mock.patch("getpass.getpass", return_value=PASSWORD):
- mock_stdin = mock.Mock()
- mock_stdin.isatty = mock.Mock()
- mock_stdin.isatty.return_value = True
- self.assertEqual(PASSWORD, utils.get_password(mock_stdin))
-
- def test_get_password_bad_once(self):
- answers = [PASSWORD, WASSPORD, DROWSSAP, DROWSSAP]
- with mock.patch("getpass.getpass", side_effect=answers):
- mock_stdin = mock.Mock()
- mock_stdin.isatty = mock.Mock()
- mock_stdin.isatty.return_value = True
- self.assertEqual(DROWSSAP, utils.get_password(mock_stdin))
-
- def test_get_password_no_tty(self):
- mock_stdin = mock.Mock()
- mock_stdin.isatty = mock.Mock()
- mock_stdin.isatty.return_value = False
- self.assertRaises(exceptions.CommandError,
- utils.get_password,
- mock_stdin)
-
- def test_get_password_cntrl_d(self):
- with mock.patch("getpass.getpass", side_effect=EOFError()):
- mock_stdin = mock.Mock()
- mock_stdin.isatty = mock.Mock()
- mock_stdin.isatty.return_value = True
- self.assertRaises(exceptions.CommandError,
- utils.get_password,
- mock_stdin)
-
- def get_test_items(self):
- item1 = {'a': 1, 'b': 2}
- item2 = {'a': 1, 'b': 3}
- item3 = {'a': 2, 'b': 2}
- item4 = {'a': 2, 'b': 1}
- return [item1, item2, item3, item4]
-
- def test_sort_items_with_one_key(self):
- items = self.get_test_items()
- sort_str = 'b'
- expect_items = [items[3], items[0], items[2], items[1]]
- self.assertEqual(expect_items, utils.sort_items(items, sort_str))
-
- def test_sort_items_with_multiple_keys(self):
- items = self.get_test_items()
- sort_str = 'a,b'
- expect_items = [items[0], items[1], items[3], items[2]]
- self.assertEqual(expect_items, utils.sort_items(items, sort_str))
-
- def test_sort_items_all_with_direction(self):
- items = self.get_test_items()
- sort_str = 'a:desc,b:desc'
- expect_items = [items[2], items[3], items[1], items[0]]
- self.assertEqual(expect_items, utils.sort_items(items, sort_str))
-
- def test_sort_items_some_with_direction(self):
- items = self.get_test_items()
- sort_str = 'a,b:desc'
- expect_items = [items[1], items[0], items[2], items[3]]
- self.assertEqual(expect_items, utils.sort_items(items, sort_str))
-
- def test_sort_items_with_object(self):
- item1 = mock.Mock(a=1, b=2)
- item2 = mock.Mock(a=1, b=3)
- item3 = mock.Mock(a=2, b=2)
- item4 = mock.Mock(a=2, b=1)
- items = [item1, item2, item3, item4]
- sort_str = 'b,a'
- expect_items = [item4, item1, item3, item2]
- self.assertEqual(expect_items, utils.sort_items(items, sort_str))
-
- def test_sort_items_with_empty_key(self):
- items = self.get_test_items()
- sort_srt = ''
- self.assertEqual(items, utils.sort_items(items, sort_srt))
- sort_srt = None
- self.assertEqual(items, utils.sort_items(items, sort_srt))
-
- def test_sort_items_with_invalid_key(self):
- items = self.get_test_items()
- sort_str = 'c'
- self.assertRaises(exceptions.CommandError,
- utils.sort_items,
- items, sort_str)
-
- def test_sort_items_with_invalid_direction(self):
- items = self.get_test_items()
- sort_str = 'a:bad_dir'
- self.assertRaises(exceptions.CommandError,
- utils.sort_items,
- items, sort_str)
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_status_ok(self, mock_sleep):
- # Tests the normal flow that the resource is status=active
- resource = mock.MagicMock(status='ACTIVE')
- status_f = mock.Mock(return_value=resource)
- res_id = str(uuid.uuid4())
- self.assertTrue(utils.wait_for_status(status_f, res_id,))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_status_ok__with_overrides(self, mock_sleep):
- # Tests the normal flow that the resource is status=complete
- resource = mock.MagicMock(my_status='COMPLETE')
- status_f = mock.Mock(return_value=resource)
- res_id = str(uuid.uuid4())
- self.assertTrue(utils.wait_for_status(status_f, res_id,
- status_field='my_status',
- success_status=['complete']))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_status_error(self, mock_sleep):
- # Tests that we fail if the resource is status=error
- resource = mock.MagicMock(status='ERROR')
- status_f = mock.Mock(return_value=resource)
- res_id = str(uuid.uuid4())
- self.assertFalse(utils.wait_for_status(status_f, res_id))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_status_error_with_overrides(self, mock_sleep):
- # Tests that we fail if the resource is my_status=failed
- resource = mock.MagicMock(my_status='FAILED')
- status_f = mock.Mock(return_value=resource)
- res_id = str(uuid.uuid4())
- self.assertFalse(utils.wait_for_status(status_f, res_id,
- status_field='my_status',
- error_status=['failed']))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_delete_ok(self, mock_sleep):
- # Tests the normal flow that the resource is deleted with a 404 coming
- # back on the 2nd iteration of the wait loop.
- resource = mock.MagicMock(status='ACTIVE', progress=None)
- mock_get = mock.Mock(side_effect=[resource,
- exceptions.NotFound(404)])
- manager = mock.MagicMock(get=mock_get)
- res_id = str(uuid.uuid4())
- callback = mock.Mock()
- self.assertTrue(utils.wait_for_delete(manager, res_id,
- callback=callback))
- mock_sleep.assert_called_once_with(5)
- callback.assert_called_once_with(0)
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_delete_timeout(self, mock_sleep):
- # Tests that we fail if the resource is not deleted before the timeout.
- resource = mock.MagicMock(status='ACTIVE')
- mock_get = mock.Mock(return_value=resource)
- manager = mock.MagicMock(get=mock_get)
- res_id = str(uuid.uuid4())
- self.assertFalse(utils.wait_for_delete(manager, res_id, sleep_time=1,
- timeout=1))
- mock_sleep.assert_called_once_with(1)
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_delete_error(self, mock_sleep):
- # Tests that we fail if the resource goes to error state while waiting.
- resource = mock.MagicMock(status='ERROR')
- mock_get = mock.Mock(return_value=resource)
- manager = mock.MagicMock(get=mock_get)
- res_id = str(uuid.uuid4())
- self.assertFalse(utils.wait_for_delete(manager, res_id))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_delete_error_with_overrides(self, mock_sleep):
- # Tests that we fail if the resource is my_status=failed
- resource = mock.MagicMock(my_status='FAILED')
- mock_get = mock.Mock(return_value=resource)
- manager = mock.MagicMock(get=mock_get)
- res_id = str(uuid.uuid4())
- self.assertFalse(utils.wait_for_delete(manager, res_id,
- status_field='my_status',
- error_status=['failed']))
- mock_sleep.assert_not_called()
-
- @mock.patch.object(time, 'sleep')
- def test_wait_for_delete_error_with_overrides_exception(self, mock_sleep):
- # Tests that we succeed if the resource is specific exception
- mock_get = mock.Mock(side_effect=Exception)
- manager = mock.MagicMock(get=mock_get)
- res_id = str(uuid.uuid4())
- self.assertTrue(utils.wait_for_delete(manager, res_id,
- exception_name=['Exception']))
- mock_sleep.assert_not_called()
-
- def test_build_kwargs_dict_value_set(self):
- self.assertEqual({'arg_bla': 'bla'},
- utils.build_kwargs_dict('arg_bla', 'bla'))
-
- def test_build_kwargs_dict_value_None(self):
- self.assertEqual({}, utils.build_kwargs_dict('arg_bla', None))
-
- def test_build_kwargs_dict_value_empty_str(self):
- self.assertEqual({}, utils.build_kwargs_dict('arg_bla', ''))
-
-
-class NoUniqueMatch(Exception):
- pass
-
-
-class TestFindResource(test_utils.TestCase):
-
- def setUp(self):
- super(TestFindResource, self).setUp()
- self.name = 'legos'
- self.expected = mock.Mock()
- self.manager = mock.Mock()
- self.manager.resource_class = mock.Mock()
- self.manager.resource_class.__name__ = 'lego'
-
- def test_find_resource_get_int(self):
- self.manager.get = mock.Mock(return_value=self.expected)
- result = utils.find_resource(self.manager, 1)
- self.assertEqual(self.expected, result)
- self.manager.get.assert_called_with(1)
-
- def test_find_resource_get_int_string(self):
- self.manager.get = mock.Mock(return_value=self.expected)
- result = utils.find_resource(self.manager, "2")
- self.assertEqual(self.expected, result)
- self.manager.get.assert_called_with(2)
-
- def test_find_resource_get_uuid(self):
- uuid = '9a0dc2a0-ad0d-11e3-a5e2-0800200c9a66'
- self.manager.get = mock.Mock(return_value=self.expected)
- result = utils.find_resource(self.manager, uuid)
- self.assertEqual(self.expected, result)
- self.manager.get.assert_called_with(uuid)
-
- def test_find_resource_get_whatever(self):
- self.manager.get = mock.Mock(return_value=self.expected)
- result = utils.find_resource(self.manager, 'whatever')
- self.assertEqual(self.expected, result)
- self.manager.get.assert_called_with('whatever')
-
- def test_find_resource_find(self):
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(return_value=self.expected)
- result = utils.find_resource(self.manager, self.name)
- self.assertEqual(self.expected, result)
- self.manager.get.assert_called_with(self.name)
- self.manager.find.assert_called_with(name=self.name)
-
- def test_find_resource_find_not_found(self):
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(
- side_effect=exceptions.NotFound(404, "2")
- )
- result = self.assertRaises(exceptions.CommandError,
- utils.find_resource,
- self.manager,
- self.name)
- self.assertEqual("No lego with a name or ID of 'legos' exists.",
- str(result))
- self.manager.get.assert_called_with(self.name)
- self.manager.find.assert_called_with(name=self.name)
-
- def test_find_resource_list_forbidden(self):
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.list = mock.Mock(
- side_effect=exceptions.Forbidden(403)
- )
- self.assertRaises(exceptions.Forbidden,
- utils.find_resource,
- self.manager,
- self.name)
- self.manager.list.assert_called_with()
-
- def test_find_resource_find_no_unique(self):
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(side_effect=NoUniqueMatch())
- result = self.assertRaises(exceptions.CommandError,
- utils.find_resource,
- self.manager,
- self.name)
- self.assertEqual("More than one lego exists with the name 'legos'.",
- str(result))
- self.manager.get.assert_called_with(self.name)
- self.manager.find.assert_called_with(name=self.name)
-
- def test_find_resource_silly_resource(self):
- # We need a resource with no resource_class for this test, start fresh
- self.manager = mock.Mock()
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(
- side_effect=AttributeError(
- "'Controller' object has no attribute 'find'",
- )
- )
- silly_resource = FakeOddballResource(
- None,
- {'id': '12345', 'name': self.name},
- loaded=True,
- )
- self.manager.list = mock.Mock(
- return_value=[silly_resource, ],
- )
- result = utils.find_resource(self.manager, self.name)
- self.assertEqual(silly_resource, result)
- self.manager.get.assert_called_with(self.name)
- self.manager.find.assert_called_with(name=self.name)
-
- def test_find_resource_silly_resource_not_found(self):
- # We need a resource with no resource_class for this test, start fresh
- self.manager = mock.Mock()
- self.manager.get = mock.Mock(side_effect=Exception('Boom!'))
- self.manager.find = mock.Mock(
- side_effect=AttributeError(
- "'Controller' object has no attribute 'find'",
- )
- )
- self.manager.list = mock.Mock(return_value=[])
- result = self.assertRaises(exceptions.CommandError,
- utils.find_resource,
- self.manager,
- self.name)
- self.assertEqual("Could not find resource legos",
- str(result))
- self.manager.get.assert_called_with(self.name)
- self.manager.find.assert_called_with(name=self.name)
-
- def test_format_dict(self):
- expected = "a='b', c='d', e='f'"
- self.assertEqual(expected,
- utils.format_dict({'a': 'b', 'c': 'd', 'e': 'f'}))
- self.assertEqual(expected,
- utils.format_dict({'e': 'f', 'c': 'd', 'a': 'b'}))
-
- def test_format_list(self):
- expected = 'a, b, c'
- self.assertEqual(expected, utils.format_list(['a', 'b', 'c']))
- self.assertEqual(expected, utils.format_list(['c', 'b', 'a']))
-
- def test_format_list_of_dicts(self):
- expected = "a='b', c='d'\ne='f'"
- sorted_data = [{'a': 'b', 'c': 'd'}, {'e': 'f'}]
- unsorted_data = [{'c': 'd', 'a': 'b'}, {'e': 'f'}]
- self.assertEqual(expected, utils.format_list_of_dicts(sorted_data))
- self.assertEqual(expected, utils.format_list_of_dicts(unsorted_data))
- self.assertEqual('', utils.format_list_of_dicts([]))
- self.assertEqual('', utils.format_list_of_dicts([{}]))
-
- def test_format_list_separator(self):
- expected = 'a\nb\nc'
- actual_pre_sorted = utils.format_list(['a', 'b', 'c'], separator='\n')
- actual_unsorted = utils.format_list(['c', 'b', 'a'], separator='\n')
- self.assertEqual(expected, actual_pre_sorted)
- self.assertEqual(expected, actual_unsorted)
diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py
index c9e2025d..60abb8ef 100644
--- a/openstackclient/tests/compute/v2/fakes.py
+++ b/openstackclient/tests/compute/v2/fakes.py
@@ -24,26 +24,6 @@ from openstackclient.tests.network.v2 import fakes as network_fakes
from openstackclient.tests import utils
from openstackclient.tests.volume.v2 import fakes as volume_fakes
-
-extension_name = 'Multinic'
-extension_namespace = 'http://docs.openstack.org/compute/ext/'\
- 'multinic/api/v1.1'
-extension_description = 'Multiple network support'
-extension_updated = '2014-01-07T12:00:0-00:00'
-extension_alias = 'NMN'
-extension_links = '[{"href":'\
- '"https://github.com/openstack/compute-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,
-}
-
floating_ip_num = 100
fix_ip_num = 100
injected_file_num = 100
@@ -259,6 +239,42 @@ class FakeAgent(object):
return agents
+class FakeExtension(object):
+ """Fake one or more extension."""
+
+ @staticmethod
+ def create_one_extension(attrs=None):
+ """Create a fake extension.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with name, namespace, etc.
+ """
+ attrs = attrs or {}
+
+ # Set default attributes.
+ extension_info = {
+ 'name': 'name-' + uuid.uuid4().hex,
+ 'namespace': (
+ 'http://docs.openstack.org/compute/ext/multinic/api/v1.1'),
+ 'description': 'description-' + uuid.uuid4().hex,
+ 'updated': '2014-01-07T12:00:0-00:00',
+ 'alias': 'NMN',
+ 'links': ('[{"href":'
+ '"https://github.com/openstack/compute-api", "type":'
+ ' "text/html", "rel": "describedby"}]')
+ }
+
+ # Overwrite default attributes.
+ extension_info.update(attrs)
+
+ extension = fakes.FakeResource(
+ info=copy.deepcopy(extension_info),
+ loaded=True)
+ return extension
+
+
class FakeHypervisor(object):
"""Fake one or more hypervisor."""
@@ -436,6 +452,25 @@ class FakeSecurityGroup(object):
return security_groups
+ @staticmethod
+ def get_security_groups(security_groups=None, count=2):
+ """Get an iterable MagicMock object with a list of faked security groups.
+
+ If security groups list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List security groups:
+ A list of FakeResource objects faking security groups
+ :param int count:
+ The number of security groups to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ security groups
+ """
+ if security_groups is None:
+ security_groups = FakeSecurityGroup.create_security_groups(count)
+ return mock.MagicMock(side_effect=security_groups)
+
class FakeSecurityGroupRule(object):
"""Fake one or more security group rules."""
diff --git a/openstackclient/tests/compute/v2/test_agent.py b/openstackclient/tests/compute/v2/test_agent.py
index bdff8c5e..b9040ba9 100644
--- a/openstackclient/tests/compute/v2/test_agent.py
+++ b/openstackclient/tests/compute/v2/test_agent.py
@@ -13,6 +13,11 @@
# under the License.
#
+import mock
+
+from mock import call
+from osc_lib import exceptions
+
from openstackclient.compute.v2 import agent
from openstackclient.tests.compute.v2 import fakes as compute_fakes
@@ -89,26 +94,73 @@ class TestAgentCreate(TestAgent):
class TestAgentDelete(TestAgent):
+ fake_agents = compute_fakes.FakeAgent.create_agents(count=2)
+
def setUp(self):
super(TestAgentDelete, self).setUp()
- self.agents_mock.get.return_value = self.fake_agent
+ self.agents_mock.get.return_value = self.fake_agents
self.cmd = agent.DeleteAgent(self.app, None)
- def test_one_agent_delete(self):
+ def test_delete_one_agent(self):
arglist = [
- 'test'
+ self.fake_agents[0].agent_id
+ ]
+
+ verifylist = [
+ ('id', [self.fake_agents[0].agent_id]),
]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.agents_mock.delete.assert_called_with(
+ self.fake_agents[0].agent_id)
+ self.assertIsNone(result)
+
+ def test_delete_multiple_agents(self):
+ arglist = []
+ for n in self.fake_agents:
+ arglist.append(n.agent_id)
verifylist = [
- ('id', 'test'),
+ ('id', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.agents_mock.delete.assert_called_with(parsed_args.id)
+
+ calls = []
+ for n in self.fake_agents:
+ calls.append(call(n.agent_id))
+ self.agents_mock.delete.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_delete_multiple_agents_exception(self):
+ arglist = [
+ self.fake_agents[0].agent_id,
+ self.fake_agents[1].agent_id,
+ 'x-y-z',
+ ]
+ verifylist = [
+ ('id', arglist),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ret_delete = [
+ None,
+ None,
+ exceptions.NotFound('404')
+ ]
+ self.agents_mock.delete = mock.Mock(side_effect=ret_delete)
+
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+ calls = [
+ call(self.fake_agents[0].agent_id),
+ call(self.fake_agents[1].agent_id),
+ ]
+ self.agents_mock.delete.assert_has_calls(calls)
+
class TestAgentList(TestAgent):
diff --git a/openstackclient/tests/compute/v2/test_flavor.py b/openstackclient/tests/compute/v2/test_flavor.py
index 9d424890..4365a540 100644
--- a/openstackclient/tests/compute/v2/test_flavor.py
+++ b/openstackclient/tests/compute/v2/test_flavor.py
@@ -15,8 +15,9 @@
import copy
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.compute.v2 import flavor
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import fakes
@@ -468,6 +469,7 @@ class TestFlavorSet(TestFlavor):
result = self.cmd.take_action(parsed_args)
self.flavors_mock.find.assert_called_with(name=parsed_args.flavor,
is_public=None)
+ self.flavor.set_keys.assert_called_with({'FOO': '"B A R"'})
self.assertIsNone(result)
def test_flavor_set_project(self):
@@ -482,26 +484,27 @@ class TestFlavorSet(TestFlavor):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.assertIsNone(result)
+ self.flavors_mock.find.assert_called_with(name=parsed_args.flavor,
+ is_public=None)
self.flavor_access_mock.add_tenant_access.assert_called_with(
self.flavor.id,
identity_fakes.project_id,
)
+ self.flavor.set_keys.assert_not_called()
+ self.assertIsNone(result)
def test_flavor_set_no_project(self):
arglist = [
- '--project', '',
+ '--project',
self.flavor.id,
]
verifylist = [
- ('project', ''),
+ ('project', None),
('flavor', self.flavor.id),
]
-
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
def test_flavor_set_no_flavor(self):
arglist = [
@@ -510,12 +513,8 @@ class TestFlavorSet(TestFlavor):
verifylist = [
('project', identity_fakes.project_id),
]
-
- self.assertRaises(tests_utils.ParserException,
- self.check_parser,
- self.cmd,
- arglist,
- verifylist)
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
def test_flavor_set_with_unexist_flavor(self):
self.flavors_mock.get.side_effect = exceptions.NotFound(None)
@@ -542,7 +541,6 @@ class TestFlavorSet(TestFlavor):
verifylist = [
('flavor', self.flavor.id),
]
-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
@@ -646,6 +644,8 @@ class TestFlavorUnset(TestFlavor):
result = self.cmd.take_action(parsed_args)
self.flavors_mock.find.assert_called_with(name=parsed_args.flavor,
is_public=None)
+ self.flavor.unset_keys.assert_called_with(['property'])
+ self.flavor_access_mock.remove_tenant_access.assert_not_called()
self.assertIsNone(result)
def test_flavor_unset_project(self):
@@ -662,24 +662,26 @@ class TestFlavorUnset(TestFlavor):
result = self.cmd.take_action(parsed_args)
self.assertIsNone(result)
+ self.flavors_mock.find.assert_called_with(name=parsed_args.flavor,
+ is_public=None)
self.flavor_access_mock.remove_tenant_access.assert_called_with(
self.flavor.id,
identity_fakes.project_id,
)
+ self.flavor.unset_keys.assert_not_called()
+ self.assertIsNone(result)
def test_flavor_unset_no_project(self):
arglist = [
- '--project', '',
+ '--project',
self.flavor.id,
]
verifylist = [
- ('project', ''),
+ ('project', None),
('flavor', self.flavor.id),
]
-
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
def test_flavor_unset_no_flavor(self):
arglist = [
@@ -688,12 +690,8 @@ class TestFlavorUnset(TestFlavor):
verifylist = [
('project', identity_fakes.project_id),
]
-
- self.assertRaises(tests_utils.ParserException,
- self.check_parser,
- self.cmd,
- arglist,
- verifylist)
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
def test_flavor_unset_with_unexist_flavor(self):
self.flavors_mock.get.side_effect = exceptions.NotFound(None)
@@ -708,9 +706,7 @@ class TestFlavorUnset(TestFlavor):
('flavor', 'unexist_flavor'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- self.assertRaises(exceptions.CommandError,
- self.cmd.take_action,
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
def test_flavor_unset_nothing(self):
@@ -720,7 +716,6 @@ class TestFlavorUnset(TestFlavor):
verifylist = [
('flavor', self.flavor.id),
]
-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
diff --git a/openstackclient/tests/compute/v2/test_hypervisor.py b/openstackclient/tests/compute/v2/test_hypervisor.py
index 8d717ba7..ee0f40ed 100644
--- a/openstackclient/tests/compute/v2/test_hypervisor.py
+++ b/openstackclient/tests/compute/v2/test_hypervisor.py
@@ -15,7 +15,8 @@
import copy
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.compute.v2 import hypervisor
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import fakes
diff --git a/openstackclient/tests/compute/v2/test_server.py b/openstackclient/tests/compute/v2/test_server.py
index 01aa9fc1..0f155601 100644
--- a/openstackclient/tests/compute/v2/test_server.py
+++ b/openstackclient/tests/compute/v2/test_server.py
@@ -12,11 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
#
+import getpass
import mock
-
from mock import call
-from openstackclient.common import exceptions
-from openstackclient.common import utils as common_utils
+
+from osc_lib import exceptions
+from osc_lib import utils as common_utils
+
from openstackclient.compute.v2 import server
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
@@ -1129,6 +1131,53 @@ class TestServerSet(TestServer):
self.check_parser,
self.cmd, arglist, verifylist)
+ def test_server_set_with_name(self):
+ arglist = [
+ '--name', 'foo_name',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('name', 'foo_name'),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.fake_servers[0].update.assert_called_once_with(name='foo_name')
+ self.assertIsNone(result)
+
+ def test_server_set_with_property(self):
+ arglist = [
+ '--property', 'key1=value1',
+ '--property', 'key2=value2',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('property', {'key1': 'value1', 'key2': 'value2'}),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.servers_mock.set_meta.assert_called_once_with(
+ self.fake_servers[0], parsed_args.property)
+ self.assertIsNone(result)
+
+ @mock.patch.object(getpass, 'getpass',
+ return_value=mock.sentinel.fake_pass)
+ def test_server_set_with_root_password(self, mock_getpass):
+ arglist = [
+ '--root-password',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('root_password', True),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.fake_servers[0].change_password.assert_called_once_with(
+ mock.sentinel.fake_pass)
+ self.assertIsNone(result)
+
class TestServerShelve(TestServer):
@@ -1345,6 +1394,45 @@ class TestServerUnpause(TestServer):
self.run_method_with_servers('unpause', 3)
+class TestServerUnset(TestServer):
+
+ def setUp(self):
+ super(TestServerUnset, self).setUp()
+
+ self.fake_server = self.setup_servers_mock(1)[0]
+
+ # Get the command object to test
+ self.cmd = server.UnsetServer(self.app, None)
+
+ def test_server_unset_no_option(self):
+ arglist = [
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.assertNotCalled(self.servers_mock.delete_meta)
+ self.assertIsNone(result)
+
+ def test_server_unset_with_property(self):
+ arglist = [
+ '--property', 'key1',
+ '--property', 'key2',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('property', ['key1', 'key2']),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.servers_mock.delete_meta.assert_called_once_with(
+ self.fake_server, ['key1', 'key2'])
+ self.assertIsNone(result)
+
+
class TestServerUnshelve(TestServer):
def setUp(self):
@@ -1460,7 +1548,7 @@ class TestServerGeneral(TestServer):
(data_1, data_2, networks_format))
self.assertIn(networks_format, (data_1, data_2), msg)
- @mock.patch('openstackclient.common.utils.find_resource')
+ @mock.patch('osc_lib.utils.find_resource')
def test_prep_server_detail(self, find_resource):
# Setup mock method return value. utils.find_resource() will be called
# three times in _prep_server_detail():
diff --git a/openstackclient/tests/compute/v2/test_server_backup.py b/openstackclient/tests/compute/v2/test_server_backup.py
index b35f9f52..b6802ff0 100644
--- a/openstackclient/tests/compute/v2/test_server_backup.py
+++ b/openstackclient/tests/compute/v2/test_server_backup.py
@@ -13,8 +13,9 @@
import mock
-from openstackclient.common import exceptions
-from openstackclient.common import utils as common_utils
+from osc_lib import exceptions
+from osc_lib import utils as common_utils
+
from openstackclient.compute.v2 import server_backup
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
diff --git a/openstackclient/tests/compute/v2/test_server_group.py b/openstackclient/tests/compute/v2/test_server_group.py
index 70ff23f9..bd5f8471 100644
--- a/openstackclient/tests/compute/v2/test_server_group.py
+++ b/openstackclient/tests/compute/v2/test_server_group.py
@@ -15,8 +15,9 @@
import mock
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.compute.v2 import server_group
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import utils as tests_utils
diff --git a/openstackclient/tests/compute/v2/test_service.py b/openstackclient/tests/compute/v2/test_service.py
index 7a5a840f..b360c9dc 100644
--- a/openstackclient/tests/compute/v2/test_service.py
+++ b/openstackclient/tests/compute/v2/test_service.py
@@ -15,6 +15,8 @@
import mock
+from osc_lib import exceptions
+
from openstackclient.compute.v2 import service
from openstackclient.tests.compute.v2 import fakes as compute_fakes
@@ -128,6 +130,23 @@ class TestServiceSet(TestService):
self.cmd = service.SetService(self.app, None)
+ def test_set_nothing(self):
+ arglist = [
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ self.service_mock.enable.assert_not_called()
+ self.service_mock.disable.assert_not_called()
+ self.service_mock.disable_log_reason.assert_not_called()
+ self.assertIsNone(result)
+
def test_service_set_enable(self):
arglist = [
'--enable',
@@ -135,7 +154,7 @@ class TestServiceSet(TestService):
self.service.binary,
]
verifylist = [
- ('enabled', True),
+ ('enable', True),
('host', self.service.host),
('service', self.service.binary),
]
@@ -156,7 +175,7 @@ class TestServiceSet(TestService):
self.service.binary,
]
verifylist = [
- ('enabled', False),
+ ('disable', True),
('host', self.service.host),
('service', self.service.binary),
]
@@ -179,7 +198,7 @@ class TestServiceSet(TestService):
self.service.binary,
]
verifylist = [
- ('enabled', False),
+ ('disable', True),
('disable_reason', reason),
('host', self.service.host),
('service', self.service.binary),
@@ -203,24 +222,17 @@ class TestServiceSet(TestService):
self.service.binary,
]
verifylist = [
- ('enabled', True),
('disable_reason', reason),
('host', self.service.host),
('service', self.service.binary),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- with mock.patch.object(self.cmd.log, 'info') as mock_log:
- result = self.cmd.take_action(parsed_args)
-
- msg = "argument --disable-reason has been ignored"
- mock_log.assert_called_once_with(msg)
-
- self.service_mock.enable.assert_called_with(
- self.service.host,
- self.service.binary
- )
- self.assertIsNone(result)
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail("CommandError should be raised.")
+ except exceptions.CommandError as e:
+ self.assertEqual("Cannot specify option --disable-reason without "
+ "--disable specified.", str(e))
def test_service_set_enable_with_disable_reason(self):
reason = 'earthquake'
@@ -231,21 +243,99 @@ class TestServiceSet(TestService):
self.service.binary,
]
verifylist = [
- ('enabled', True),
+ ('enable', True),
('disable_reason', reason),
('host', self.service.host),
('service', self.service.binary),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail("CommandError should be raised.")
+ except exceptions.CommandError as e:
+ self.assertEqual("Cannot specify option --disable-reason without "
+ "--disable specified.", str(e))
+
+ def test_service_set_state_up(self):
+ arglist = [
+ '--up',
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('up', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.force_down.assert_called_once_with(
+ self.service.host, self.service.binary, force_down=False)
+ self.assertNotCalled(self.service_mock.enable)
+ self.assertNotCalled(self.service_mock.disable)
+ self.assertIsNone(result)
- with mock.patch.object(self.cmd.log, 'info') as mock_log:
- result = self.cmd.take_action(parsed_args)
-
- msg = "argument --disable-reason has been ignored"
- mock_log.assert_called_once_with(msg)
+ def test_service_set_state_down(self):
+ arglist = [
+ '--down',
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('down', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.force_down.assert_called_once_with(
+ self.service.host, self.service.binary, force_down=True)
+ self.assertNotCalled(self.service_mock.enable)
+ self.assertNotCalled(self.service_mock.disable)
+ self.assertIsNone(result)
- self.service_mock.enable.assert_called_with(
+ def test_service_set_enable_and_state_down(self):
+ arglist = [
+ '--enable',
+ '--down',
self.service.host,
- self.service.binary
- )
+ self.service.binary,
+ ]
+ verifylist = [
+ ('enable', True),
+ ('down', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.enable.assert_called_once_with(
+ self.service.host, self.service.binary)
+ self.service_mock.force_down.assert_called_once_with(
+ self.service.host, self.service.binary, force_down=True)
self.assertIsNone(result)
+
+ def test_service_set_enable_and_state_down_with_exception(self):
+ arglist = [
+ '--enable',
+ '--down',
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('enable', True),
+ ('down', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(self.cmd.log, 'error') as mock_log:
+ with mock.patch.object(self.service_mock, 'enable',
+ side_effect=Exception()):
+ self.assertRaises(exceptions.CommandError,
+ self.cmd.take_action, parsed_args)
+ mock_log.assert_called_once_with(
+ "Failed to set service status to %s", "enabled")
+ self.service_mock.force_down.assert_called_once_with(
+ self.service.host, self.service.binary, force_down=True)
diff --git a/openstackclient/tests/fakes.py b/openstackclient/tests/fakes.py
index 7fb1daa9..d0cab019 100644
--- a/openstackclient/tests/fakes.py
+++ b/openstackclient/tests/fakes.py
@@ -50,6 +50,21 @@ TEST_RESPONSE_DICT_V3.set_project_scope()
TEST_VERSIONS = fixture.DiscoveryList(href=AUTH_URL)
+def to_unicode_dict(catalog_dict):
+ """Converts dict to unicode dict
+
+ """
+ if isinstance(catalog_dict, dict):
+ return {to_unicode_dict(key): to_unicode_dict(value)
+ for key, value in catalog_dict.items()}
+ elif isinstance(catalog_dict, list):
+ return [to_unicode_dict(element) for element in catalog_dict]
+ elif isinstance(catalog_dict, str):
+ return catalog_dict + u""
+ else:
+ return catalog_dict
+
+
class FakeStdout(object):
def __init__(self):
@@ -99,7 +114,7 @@ class FakeApp(object):
class FakeOptions(object):
def __init__(self, **kwargs):
- self.enable_beta_commands = False
+ self.os_beta_command = False
class FakeClient(object):
diff --git a/openstackclient/tests/identity/v2_0/fakes.py b/openstackclient/tests/identity/v2_0/fakes.py
index b37bd9da..c613ad82 100644
--- a/openstackclient/tests/identity/v2_0/fakes.py
+++ b/openstackclient/tests/identity/v2_0/fakes.py
@@ -13,7 +13,12 @@
# under the License.
#
+import copy
import mock
+import uuid
+
+from keystoneauth1 import access
+from keystoneauth1 import fixture
from openstackclient.tests import fakes
from openstackclient.tests import utils
@@ -106,25 +111,42 @@ ENDPOINT = {
'service_id': endpoint_service_id,
}
-extension_name = 'OpenStack Keystone User CRUD'
-extension_namespace = 'http://docs.openstack.org/identity/'\
- 'api/ext/OS-KSCRUD/v1.0'
-extension_description = 'OpenStack extensions to Keystone v2.0 API'\
- ' enabling User Operations.'
-extension_updated = '2013-07-07T12:00:0-00:00'
-extension_alias = 'OS-KSCRUD'
-extension_links = '[{"href":'\
- '"https://github.com/openstack/identity-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,
-}
+
+def fake_auth_ref(fake_token, fake_service=None):
+ """Create an auth_ref using keystoneauth's fixtures"""
+ token_copy = copy.deepcopy(fake_token)
+ token_copy['token_id'] = token_copy.pop('id')
+ token = fixture.V2Token(**token_copy)
+ # An auth_ref is actually an access info object
+ auth_ref = access.create(body=token)
+
+ # Create a service catalog
+ if fake_service:
+ service = token.add_service(
+ fake_service['type'],
+ fake_service['name'],
+ )
+ # TODO(dtroyer): Add an 'id' element to KSA's _Service fixure
+ service['id'] = fake_service['id']
+ for e in fake_service['endpoints']:
+ # KSA's _Service fixture copies publicURL to internalURL and
+ # adminURL if they do not exist. Soooo helpful...
+ internal = e.get('internalURL', None)
+ admin = e.get('adminURL', None)
+ region = e.get('region_id') or e.get('region', '<none>')
+ endpoint = service.add_endpoint(
+ public=e['publicURL'],
+ internal=internal,
+ admin=admin,
+ region=region,
+ )
+ # ...so undo that helpfulness
+ if not internal:
+ endpoint['internalURL'] = None
+ if not admin:
+ endpoint['adminURL'] = None
+
+ return auth_ref
class FakeIdentityv2Client(object):
@@ -166,3 +188,39 @@ class TestIdentityv2(utils.TestCommand):
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
+
+
+class FakeExtension(object):
+ """Fake one or more extension."""
+
+ @staticmethod
+ def create_one_extension(attrs=None):
+ """Create a fake extension.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with name, namespace, etc.
+ """
+ attrs = attrs or {}
+
+ # Set default attributes.
+ extension_info = {
+ 'name': 'name-' + uuid.uuid4().hex,
+ 'namespace': ('http://docs.openstack.org/identity/'
+ 'api/ext/OS-KSCRUD/v1.0'),
+ 'description': 'description-' + uuid.uuid4().hex,
+ 'updated': '2013-07-07T12:00:0-00:00',
+ 'alias': 'OS-KSCRUD',
+ 'links': ('[{"href":'
+ '"https://github.com/openstack/identity-api", "type":'
+ ' "text/html", "rel": "describedby"}]')
+ }
+
+ # Overwrite default attributes.
+ extension_info.update(attrs)
+
+ extension = fakes.FakeResource(
+ info=copy.deepcopy(extension_info),
+ loaded=True)
+ return extension
diff --git a/openstackclient/tests/identity/v2_0/test_catalog.py b/openstackclient/tests/identity/v2_0/test_catalog.py
index d9ae6a80..2fdbafbe 100644
--- a/openstackclient/tests/identity/v2_0/test_catalog.py
+++ b/openstackclient/tests/identity/v2_0/test_catalog.py
@@ -14,6 +14,7 @@
import mock
from openstackclient.identity.v2_0 import catalog
+from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
from openstackclient.tests import utils
@@ -49,7 +50,7 @@ class TestCatalog(utils.TestCommand):
super(TestCatalog, self).setUp()
self.sc_mock = mock.MagicMock()
- self.sc_mock.service_catalog.get_data.return_value = [
+ self.sc_mock.service_catalog.catalog.return_value = [
self.fake_service,
]
@@ -74,6 +75,13 @@ class TestCatalogList(TestCatalog):
self.cmd = catalog.ListCatalog(self.app, None)
def test_catalog_list(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -82,7 +90,6 @@ class TestCatalogList(TestCatalog):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.service_catalog.get_data.assert_called_with()
self.assertEqual(self.columns, columns)
datalist = ((
@@ -117,9 +124,12 @@ class TestCatalogList(TestCatalog):
},
],
}
- self.sc_mock.service_catalog.get_data.return_value = [
- fake_service,
- ]
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN,
+ fake_service=fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
arglist = []
verifylist = []
@@ -129,7 +139,6 @@ class TestCatalogList(TestCatalog):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.service_catalog.get_data.assert_called_with()
self.assertEqual(self.columns, columns)
datalist = ((
@@ -151,6 +160,13 @@ class TestCatalogShow(TestCatalog):
self.cmd = catalog.ShowCatalog(self.app, None)
def test_catalog_show(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.UNSCOPED_TOKEN,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = [
'compute',
]
@@ -163,7 +179,6 @@ class TestCatalogShow(TestCatalog):
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.service_catalog.get_data.assert_called_with()
collist = ('endpoints', 'id', 'name', 'type')
self.assertEqual(collist, columns)
diff --git a/openstackclient/tests/identity/v2_0/test_role.py b/openstackclient/tests/identity/v2_0/test_role.py
index 3c4b79a4..7241c7bd 100644
--- a/openstackclient/tests/identity/v2_0/test_role.py
+++ b/openstackclient/tests/identity/v2_0/test_role.py
@@ -17,8 +17,8 @@ import copy
import mock
from keystoneauth1 import exceptions as ks_exc
+from osc_lib import exceptions
-from openstackclient.common import exceptions
from openstackclient.identity.v2_0 import role
from openstackclient.tests import fakes
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
@@ -26,6 +26,13 @@ from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
class TestRole(identity_fakes.TestIdentityv2):
+ fake_service = copy.deepcopy(identity_fakes.SERVICE)
+ fake_service['endpoints'] = [
+ {
+ 'publicURL': identity_fakes.ENDPOINT['publicurl'],
+ },
+ ]
+
def setUp(self):
super(TestRole, self).setUp()
@@ -41,6 +48,13 @@ class TestRole(identity_fakes.TestIdentityv2):
self.roles_mock = self.app.client_manager.identity.roles
self.roles_mock.reset_mock()
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
class TestRoleAdd(TestRole):
@@ -320,7 +334,14 @@ class TestUserRoleList(TestRole):
# Get the command object to test
self.cmd = role.ListUserRole(self.app, None)
- def test_user_role_list_no_options(self):
+ def test_user_role_list_no_options_unscoped_token(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.UNSCOPED_TOKEN,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -332,11 +353,7 @@ class TestUserRoleList(TestRole):
parsed_args,
)
- def test_user_role_list_no_options_def_creds(self):
- auth_ref = self.app.client_manager.auth_ref = mock.MagicMock()
- auth_ref.project_id.return_value = identity_fakes.project_id
- auth_ref.user_id.return_value = identity_fakes.user_id
-
+ def test_user_role_list_no_options_scoped_token(self):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -361,7 +378,14 @@ class TestUserRoleList(TestRole):
), )
self.assertEqual(datalist, tuple(data))
- def test_user_role_list_project(self):
+ def test_user_role_list_project_unscoped_token(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.UNSCOPED_TOKEN,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
self.projects_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(identity_fakes.PROJECT_2),
@@ -375,18 +399,26 @@ class TestUserRoleList(TestRole):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- # This argument combination should raise a CommandError
- self.assertRaises(
- exceptions.CommandError,
- self.cmd.take_action,
- parsed_args,
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.roles_mock.roles_for_user.assert_called_with(
+ identity_fakes.user_id,
+ identity_fakes.PROJECT_2['id'],
)
- def test_user_role_list_project_def_creds(self):
- auth_ref = self.app.client_manager.auth_ref = mock.MagicMock()
- auth_ref.project_id.return_value = identity_fakes.project_id
- auth_ref.user_id.return_value = identity_fakes.user_id
+ self.assertEqual(columns, columns)
+ datalist = ((
+ identity_fakes.role_id,
+ identity_fakes.role_name,
+ identity_fakes.PROJECT_2['name'],
+ identity_fakes.user_name,
+ ), )
+ self.assertEqual(datalist, tuple(data))
+ def test_user_role_list_project_scoped_token(self):
self.projects_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(identity_fakes.PROJECT_2),
diff --git a/openstackclient/tests/identity/v2_0/test_token.py b/openstackclient/tests/identity/v2_0/test_token.py
index 613139dd..96f08e87 100644
--- a/openstackclient/tests/identity/v2_0/test_token.py
+++ b/openstackclient/tests/identity/v2_0/test_token.py
@@ -24,10 +24,9 @@ class TestToken(identity_fakes.TestIdentityv2):
def setUp(self):
super(TestToken, self).setUp()
- # Get a shortcut to the Service Catalog Mock
- self.sc_mock = mock.Mock()
- self.app.client_manager.auth_ref = mock.Mock()
- self.app.client_manager.auth_ref.service_catalog = self.sc_mock
+ # Get a shortcut to the Auth Ref Mock
+ self.ar_mock = mock.PropertyMock()
+ type(self.app.client_manager).auth_ref = self.ar_mock
class TestTokenIssue(TestToken):
@@ -35,10 +34,15 @@ class TestTokenIssue(TestToken):
def setUp(self):
super(TestTokenIssue, self).setUp()
- self.sc_mock.get_token.return_value = identity_fakes.TOKEN
self.cmd = token.IssueToken(self.app, None)
def test_token_issue(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -48,12 +52,10 @@ class TestTokenIssue(TestToken):
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.get_token.assert_called_with()
-
collist = ('expires', 'id', 'project_id', 'user_id')
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.token_expires,
+ auth_ref.expires,
identity_fakes.token_id,
identity_fakes.project_id,
identity_fakes.user_id,
@@ -61,8 +63,11 @@ class TestTokenIssue(TestToken):
self.assertEqual(datalist, data)
def test_token_issue_with_unscoped_token(self):
- # make sure we return an unscoped token
- self.sc_mock.get_token.return_value = identity_fakes.UNSCOPED_TOKEN
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.UNSCOPED_TOKEN,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
arglist = []
verifylist = []
@@ -71,12 +76,14 @@ class TestTokenIssue(TestToken):
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.get_token.assert_called_with()
-
- collist = ('expires', 'id', 'user_id')
+ collist = (
+ 'expires',
+ 'id',
+ 'user_id',
+ )
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.token_expires,
+ auth_ref.expires,
identity_fakes.token_id,
identity_fakes.user_id,
)
diff --git a/openstackclient/tests/identity/v2_0/test_user.py b/openstackclient/tests/identity/v2_0/test_user.py
index 921e215d..caf38a6f 100644
--- a/openstackclient/tests/identity/v2_0/test_user.py
+++ b/openstackclient/tests/identity/v2_0/test_user.py
@@ -152,7 +152,7 @@ class TestUserCreate(TestUser):
# data to be shown.
mocker = mock.Mock()
mocker.return_value = 'abc123'
- with mock.patch("openstackclient.common.utils.get_password", mocker):
+ with mock.patch("osc_lib.utils.get_password", mocker):
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
@@ -638,7 +638,7 @@ class TestUserSet(TestUser):
mocker = mock.Mock()
mocker.return_value = 'abc123'
- with mock.patch("openstackclient.common.utils.get_password", mocker):
+ with mock.patch("osc_lib.utils.get_password", mocker):
result = self.cmd.take_action(parsed_args)
# UserManager.update_password(user, password)
diff --git a/openstackclient/tests/identity/v3/fakes.py b/openstackclient/tests/identity/v3/fakes.py
index 1422166a..cd1b4bd7 100644
--- a/openstackclient/tests/identity/v3/fakes.py
+++ b/openstackclient/tests/identity/v3/fakes.py
@@ -13,8 +13,12 @@
# under the License.
#
+import copy
import mock
+from keystoneauth1 import access
+from keystoneauth1 import fixture
+
from openstackclient.tests import fakes
from openstackclient.tests import utils
@@ -419,6 +423,36 @@ OAUTH_VERIFIER = {
}
+def fake_auth_ref(fake_token, fake_service=None):
+ """Create an auth_ref using keystoneauth's fixtures"""
+ token_copy = copy.deepcopy(fake_token)
+ token_id = token_copy.pop('id')
+ token = fixture.V3Token(**token_copy)
+ # An auth_ref is actually an access info object
+ auth_ref = access.create(
+ body=token,
+ auth_token=token_id,
+ )
+
+ # Create a service catalog
+ if fake_service:
+ service = token.add_service(
+ fake_service['type'],
+ fake_service['name'],
+ )
+ # TODO(dtroyer): Add an 'id' element to KSA's _Service fixure
+ service['id'] = fake_service['id']
+ for e in fake_service['endpoints']:
+ region = e.get('region_id') or e.get('region', '<none>')
+ service.add_endpoint(
+ e['interface'],
+ e['url'],
+ region=region,
+ )
+
+ return auth_ref
+
+
class FakeAuth(object):
def __init__(self, auth_method_class=None):
diff --git a/openstackclient/tests/identity/v3/test_catalog.py b/openstackclient/tests/identity/v3/test_catalog.py
index 1b8fa085..e3c5ed3d 100644
--- a/openstackclient/tests/identity/v3/test_catalog.py
+++ b/openstackclient/tests/identity/v3/test_catalog.py
@@ -14,6 +14,7 @@
import mock
from openstackclient.identity.v3 import catalog
+from openstackclient.tests.identity.v3 import fakes as identity_fakes
from openstackclient.tests import utils
@@ -50,7 +51,7 @@ class TestCatalog(utils.TestCommand):
super(TestCatalog, self).setUp()
self.sc_mock = mock.MagicMock()
- self.sc_mock.service_catalog.get_data.return_value = [
+ self.sc_mock.service_catalog.catalog.return_value = [
self.fake_service,
]
@@ -69,6 +70,13 @@ class TestCatalogList(TestCatalog):
self.cmd = catalog.ListCatalog(self.app, None)
def test_catalog_list(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN_WITH_PROJECT_ID,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -77,7 +85,6 @@ class TestCatalogList(TestCatalog):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.service_catalog.get_data.assert_called_with()
collist = ('Name', 'Type', 'Endpoints')
self.assertEqual(collist, columns)
@@ -101,6 +108,13 @@ class TestCatalogShow(TestCatalog):
self.cmd = catalog.ShowCatalog(self.app, None)
def test_catalog_show(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN_WITH_PROJECT_ID,
+ fake_service=self.fake_service,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = [
'compute',
]
@@ -113,7 +127,6 @@ class TestCatalogShow(TestCatalog):
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.service_catalog.get_data.assert_called_with()
collist = ('endpoints', 'id', 'name', 'type')
self.assertEqual(collist, columns)
diff --git a/openstackclient/tests/identity/v3/test_mappings.py b/openstackclient/tests/identity/v3/test_mappings.py
index b9e3b1d5..af7b135d 100644
--- a/openstackclient/tests/identity/v3/test_mappings.py
+++ b/openstackclient/tests/identity/v3/test_mappings.py
@@ -16,7 +16,8 @@ import copy
import mock
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.identity.v3 import mapping
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
diff --git a/openstackclient/tests/identity/v3/test_project.py b/openstackclient/tests/identity/v3/test_project.py
index 1e9d1c8b..8fcada6e 100644
--- a/openstackclient/tests/identity/v3/test_project.py
+++ b/openstackclient/tests/identity/v3/test_project.py
@@ -16,7 +16,8 @@
import copy
import mock
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.identity.v3 import project
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
@@ -201,7 +202,7 @@ class TestProjectCreate(TestProject):
mocker = mock.Mock()
mocker.return_value = None
- with mock.patch("openstackclient.common.utils.find_resource", mocker):
+ with mock.patch("osc_lib.utils.find_resource", mocker):
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
@@ -548,7 +549,7 @@ class TestProjectList(TestProject):
mocker = mock.Mock()
mocker.return_value = None
- with mock.patch("openstackclient.common.utils.find_resource", mocker):
+ with mock.patch("osc_lib.utils.find_resource", mocker):
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.list.assert_called_with(
diff --git a/openstackclient/tests/identity/v3/test_token.py b/openstackclient/tests/identity/v3/test_token.py
index b68bc242..9728c6e1 100644
--- a/openstackclient/tests/identity/v3/test_token.py
+++ b/openstackclient/tests/identity/v3/test_token.py
@@ -24,10 +24,9 @@ class TestToken(identity_fakes.TestIdentityv3):
def setUp(self):
super(TestToken, self).setUp()
- # Get a shortcut to the Service Catalog Mock
- self.sc_mock = mock.Mock()
- self.app.client_manager.auth_ref = mock.Mock()
- self.app.client_manager.auth_ref.service_catalog = self.sc_mock
+ # Get a shortcut to the Auth Ref Mock
+ self.ar_mock = mock.PropertyMock()
+ type(self.app.client_manager).auth_ref = self.ar_mock
class TestTokenIssue(TestToken):
@@ -38,23 +37,25 @@ class TestTokenIssue(TestToken):
self.cmd = token.IssueToken(self.app, None)
def test_token_issue_with_project_id(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN_WITH_PROJECT_ID,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.sc_mock.get_token.return_value = \
- identity_fakes.TOKEN_WITH_PROJECT_ID
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.get_token.assert_called_with()
-
collist = ('expires', 'id', 'project_id', 'user_id')
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.token_expires,
+ auth_ref.expires,
identity_fakes.token_id,
identity_fakes.project_id,
identity_fakes.user_id,
@@ -62,45 +63,53 @@ class TestTokenIssue(TestToken):
self.assertEqual(datalist, data)
def test_token_issue_with_domain_id(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.TOKEN_WITH_DOMAIN_ID,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.sc_mock.get_token.return_value = \
- identity_fakes.TOKEN_WITH_DOMAIN_ID
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.get_token.assert_called_with()
-
collist = ('domain_id', 'expires', 'id', 'user_id')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.domain_id,
- identity_fakes.token_expires,
+ auth_ref.expires,
identity_fakes.token_id,
identity_fakes.user_id,
)
self.assertEqual(datalist, data)
def test_token_issue_with_unscoped(self):
+ auth_ref = identity_fakes.fake_auth_ref(
+ identity_fakes.UNSCOPED_TOKEN,
+ )
+ self.ar_mock = mock.PropertyMock(return_value=auth_ref)
+ type(self.app.client_manager).auth_ref = self.ar_mock
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.sc_mock.get_token.return_value = \
- identity_fakes.UNSCOPED_TOKEN
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
- self.sc_mock.get_token.assert_called_with()
-
- collist = ('expires', 'id', 'user_id')
+ collist = (
+ 'expires',
+ 'id',
+ 'user_id',
+ )
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.token_expires,
+ auth_ref.expires,
identity_fakes.token_id,
identity_fakes.user_id,
)
diff --git a/openstackclient/tests/identity/v3/test_unscoped_saml.py b/openstackclient/tests/identity/v3/test_unscoped_saml.py
index d12cb454..62623902 100644
--- a/openstackclient/tests/identity/v3/test_unscoped_saml.py
+++ b/openstackclient/tests/identity/v3/test_unscoped_saml.py
@@ -12,7 +12,8 @@
import copy
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.identity.v3 import unscoped_saml
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
diff --git a/openstackclient/tests/identity/v3/test_user.py b/openstackclient/tests/identity/v3/test_user.py
index 5dafa772..85522e57 100644
--- a/openstackclient/tests/identity/v3/test_user.py
+++ b/openstackclient/tests/identity/v3/test_user.py
@@ -185,7 +185,7 @@ class TestUserCreate(TestUser):
# data to be shown.
mocker = mock.Mock()
mocker.return_value = 'abc123'
- with mock.patch("openstackclient.common.utils.get_password", mocker):
+ with mock.patch("osc_lib.utils.get_password", mocker):
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
@@ -841,7 +841,7 @@ class TestUserSet(TestUser):
mocker = mock.Mock()
mocker.return_value = 'abc123'
- with mock.patch("openstackclient.common.utils.get_password", mocker):
+ with mock.patch("osc_lib.utils.get_password", mocker):
result = self.cmd.take_action(parsed_args)
# Set expected values
@@ -1023,7 +1023,7 @@ class TestUserSetPassword(TestUser):
@contextlib.contextmanager
def _mock_get_password(*passwords):
mocker = mock.Mock(side_effect=passwords)
- with mock.patch("openstackclient.common.utils.get_password", mocker):
+ with mock.patch("osc_lib.utils.get_password", mocker):
yield
def test_user_password_change(self):
diff --git a/openstackclient/tests/image/v1/test_image.py b/openstackclient/tests/image/v1/test_image.py
index 018e1199..99c0b0ee 100644
--- a/openstackclient/tests/image/v1/test_image.py
+++ b/openstackclient/tests/image/v1/test_image.py
@@ -16,7 +16,8 @@
import copy
import mock
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.image.v1 import image
from openstackclient.tests import fakes
from openstackclient.tests.image.v1 import fakes as image_fakes
@@ -416,7 +417,7 @@ class TestImageList(TestImage):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
- @mock.patch('openstackclient.common.utils.sort_items')
+ @mock.patch('osc_lib.utils.sort_items')
def test_image_list_sort_option(self, si_mock):
si_mock.side_effect = [
[copy.deepcopy(image_fakes.IMAGE)], [],
diff --git a/openstackclient/tests/image/v2/fakes.py b/openstackclient/tests/image/v2/fakes.py
index 24aaec51..8e22fbb2 100644
--- a/openstackclient/tests/image/v2/fakes.py
+++ b/openstackclient/tests/image/v2/fakes.py
@@ -19,13 +19,12 @@ import random
import uuid
from glanceclient.v2 import schemas
+from osc_lib import utils as common_utils
import warlock
-from openstackclient.common import utils as common_utils
from openstackclient.tests import fakes
-from openstackclient.tests import utils
-
from openstackclient.tests.identity.v3 import fakes as identity_fakes
+from openstackclient.tests import utils
image_id = '0f41529e-7c12-4de8-be2d-181abb825b3c'
image_name = 'graven'
diff --git a/openstackclient/tests/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py
index ca20d83d..96e8734f 100644
--- a/openstackclient/tests/image/v2/test_image.py
+++ b/openstackclient/tests/image/v2/test_image.py
@@ -19,8 +19,9 @@ import mock
import warlock
from glanceclient.v2 import schemas
-from openstackclient.common import exceptions
-from openstackclient.common import utils as common_utils
+from osc_lib import exceptions
+from osc_lib import utils as common_utils
+
from openstackclient.image.v2 import image
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
@@ -473,6 +474,37 @@ class TestImageDelete(TestImage):
self.images_mock.delete.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_image_delete_multi_images_exception(self):
+
+ images = image_fakes.FakeImage.create_images(count=2)
+ arglist = [
+ images[0].id,
+ images[1].id,
+ 'x-y-x',
+ ]
+ verifylist = [
+ ('images', arglist)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # Fake exception in utils.find_resource()
+ # In image v2, we use utils.find_resource() to find a network.
+ # It calls get() several times, but find() only one time. So we
+ # choose to fake get() always raise exception, then pass through.
+ # And fake find() to find the real network or not.
+ ret_find = [
+ images[0],
+ images[1],
+ exceptions.NotFound('404'),
+ ]
+
+ self.images_mock.get = Exception()
+ self.images_mock.find.side_effect = ret_find
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+ calls = [mock.call(i.id) for i in images]
+ self.images_mock.delete.assert_has_calls(calls)
+
class TestImageList(TestImage):
@@ -660,7 +692,7 @@ class TestImageList(TestImage):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
- @mock.patch('openstackclient.common.utils.sort_items')
+ @mock.patch('osc_lib.utils.sort_items')
def test_image_list_sort_option(self, si_mock):
si_mock.return_value = [copy.deepcopy(self._image)]
@@ -697,7 +729,7 @@ class TestImageList(TestImage):
self.assertEqual(self.columns, columns)
self.assertEqual(len(self.datalist), len(tuple(data)))
- @mock.patch('openstackclient.common.utils.find_resource')
+ @mock.patch('osc_lib.utils.find_resource')
def test_image_list_marker_option(self, fr_mock):
# tangchen: Since image_fakes.IMAGE is a dict, it cannot offer a .id
# operation. Will fix this by using FakeImage class instead
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index 587fdc1a..6b09e297 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -19,12 +19,6 @@ import uuid
from openstackclient.tests import fakes
from openstackclient.tests import utils
-extension_name = 'Matrix'
-extension_namespace = 'http://docs.openstack.org/network/'
-extension_description = 'Simulated reality'
-extension_updated = '2013-07-09T12:00:0-00:00'
-extension_alias = 'Dystopian'
-extension_links = '[{"href":''"https://github.com/os/network", "type"}]'
QUOTA = {
"subnet": 10,
@@ -42,21 +36,11 @@ QUOTA = {
}
-def create_extension():
- extension = mock.Mock()
- extension.name = extension_name
- extension.namespace = extension_namespace
- extension.description = extension_description
- extension.updated = extension_updated
- extension.alias = extension_alias
- extension.links = extension_links
- return extension
-
-
class FakeNetworkV2Client(object):
def __init__(self, **kwargs):
- self.extensions = mock.Mock(return_value=[create_extension()])
+ self.extensions = mock.Mock()
+ self.extensions.resource_class = fakes.FakeResource(None, {})
class TestNetworkV2(utils.TestCommand):
@@ -196,6 +180,83 @@ class FakeAvailabilityZone(object):
return availability_zones
+class FakeIPAvailability(object):
+ """Fake one or more network ip availabilities."""
+
+ @staticmethod
+ def create_one_ip_availability():
+ """Create a fake list with ip availability stats of a network.
+
+ :return:
+ A FakeResource object with network_name, network_id, etc.
+ """
+
+ # Set default attributes.
+ network_ip_availability = {
+ 'network_id': 'network-id-' + uuid.uuid4().hex,
+ 'network_name': 'network-name-' + uuid.uuid4().hex,
+ 'tenant_id': '',
+ 'subnet_ip_availability': [],
+ 'total_ips': 254,
+ 'used_ips': 6,
+ }
+
+ network_ip_availability = fakes.FakeResource(
+ info=copy.deepcopy(network_ip_availability),
+ loaded=True)
+ return network_ip_availability
+
+ @staticmethod
+ def create_ip_availability(count=2):
+ """Create fake list of ip availability stats of multiple networks.
+
+ :param int count:
+ The number of networks to fake
+ :return:
+ A list of FakeResource objects faking network ip availability stats
+ """
+ network_ip_availabilities = []
+ for i in range(0, count):
+ network_ip_availability = \
+ FakeIPAvailability.create_one_ip_availability()
+ network_ip_availabilities.append(network_ip_availability)
+
+ return network_ip_availabilities
+
+
+class FakeExtension(object):
+ """Fake one or more extension."""
+
+ @staticmethod
+ def create_one_extension(attrs=None):
+ """Create a fake extension.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with name, namespace, etc.
+ """
+ attrs = attrs or {}
+
+ # Set default attributes.
+ extension_info = {
+ 'name': 'name-' + uuid.uuid4().hex,
+ 'namespace': 'http://docs.openstack.org/network/',
+ 'description': 'description-' + uuid.uuid4().hex,
+ 'updated': '2013-07-09T12:00:0-00:00',
+ 'alias': 'Dystopian',
+ 'links': '[{"href":''"https://github.com/os/network", "type"}]',
+ }
+
+ # Overwrite default attributes.
+ extension_info.update(attrs)
+
+ extension = fakes.FakeResource(
+ info=copy.deepcopy(extension_info),
+ loaded=True)
+ return extension
+
+
class FakeNetwork(object):
"""Fake one or more networks."""
@@ -550,6 +611,25 @@ class FakeSecurityGroup(object):
return security_groups
+ @staticmethod
+ def get_security_groups(security_groups=None, count=2):
+ """Get an iterable MagicMock object with a list of faked security groups.
+
+ If security groups list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List security groups:
+ A list of FakeResource objects faking security groups
+ :param int count:
+ The number of security groups to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ security groups
+ """
+ if security_groups is None:
+ security_groups = FakeSecurityGroup.create_security_groups(count)
+ return mock.MagicMock(side_effect=security_groups)
+
class FakeSecurityGroupRule(object):
"""Fake one or more security group rules."""
@@ -609,6 +689,26 @@ class FakeSecurityGroupRule(object):
return security_group_rules
+ @staticmethod
+ def get_security_group_rules(security_group_rules=None, count=2):
+ """Get an iterable MagicMock object with a list of faked security group rules.
+
+ If security group rules list is provided, then initialize the Mock
+ object with the list. Otherwise create one.
+
+ :param List security group rules:
+ A list of FakeResource objects faking security group rules
+ :param int count:
+ The number of security group rules to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ security group rules
+ """
+ if security_group_rules is None:
+ security_group_rules = (
+ FakeSecurityGroupRule.create_security_group_rules(count))
+ return mock.MagicMock(side_effect=security_group_rules)
+
class FakeSubnet(object):
"""Fake one or more subnets."""
diff --git a/openstackclient/tests/network/v2/test_address_scope.py b/openstackclient/tests/network/v2/test_address_scope.py
index b4f4fa88..722371f9 100644
--- a/openstackclient/tests/network/v2/test_address_scope.py
+++ b/openstackclient/tests/network/v2/test_address_scope.py
@@ -15,7 +15,8 @@ import copy
import mock
from mock import call
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.network.v2 import address_scope
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes_v3
@@ -313,8 +314,12 @@ class TestSetAddressScope(TestAddressScope):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {}
+ self.network.update_address_scope.assert_called_with(
+ self._address_scope, **attrs)
+ self.assertIsNone(result)
def test_set_name_and_share(self):
arglist = [
diff --git a/openstackclient/tests/network/v2/test_floating_ip.py b/openstackclient/tests/network/v2/test_floating_ip.py
index f9ccfe1c..5cd5279a 100644
--- a/openstackclient/tests/network/v2/test_floating_ip.py
+++ b/openstackclient/tests/network/v2/test_floating_ip.py
@@ -12,6 +12,9 @@
#
import mock
+from mock import call
+
+from osc_lib import exceptions
from openstackclient.network.v2 import floating_ip
from openstackclient.tests.compute.v2 import fakes as compute_fakes
@@ -140,33 +143,84 @@ class TestCreateFloatingIPNetwork(TestFloatingIPNetwork):
class TestDeleteFloatingIPNetwork(TestFloatingIPNetwork):
- # The floating ip to be deleted.
- floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip()
+ # The floating ips to be deleted.
+ floating_ips = network_fakes.FakeFloatingIP.create_floating_ips(count=2)
def setUp(self):
super(TestDeleteFloatingIPNetwork, self).setUp()
self.network.delete_ip = mock.Mock(return_value=None)
- self.network.find_ip = mock.Mock(return_value=self.floating_ip)
+ self.network.find_ip = (
+ network_fakes.FakeFloatingIP.get_floating_ips(self.floating_ips))
# Get the command object to test
self.cmd = floating_ip.DeleteFloatingIP(self.app, self.namespace)
def test_floating_ip_delete(self):
arglist = [
- self.floating_ip.id,
+ self.floating_ips[0].id,
]
verifylist = [
- ('floating_ip', self.floating_ip.id),
+ ('floating_ip', [self.floating_ips[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.network.find_ip.assert_called_once_with(self.floating_ip.id)
- self.network.delete_ip.assert_called_once_with(self.floating_ip)
+ self.network.find_ip.assert_called_once_with(
+ self.floating_ips[0].id, ignore_missing=False)
+ self.network.delete_ip.assert_called_once_with(self.floating_ips[0])
self.assertIsNone(result)
+ def test_multi_floating_ips_delete(self):
+ arglist = []
+ verifylist = []
+
+ for f in self.floating_ips:
+ arglist.append(f.id)
+ verifylist = [
+ ('floating_ip', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for f in self.floating_ips:
+ calls.append(call(f))
+ self.network.delete_ip.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_floating_ips_delete_with_exception(self):
+ arglist = [
+ self.floating_ips[0].id,
+ 'unexist_floating_ip',
+ ]
+ verifylist = [
+ ('floating_ip',
+ [self.floating_ips[0].id, 'unexist_floating_ip']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self.floating_ips[0], exceptions.CommandError]
+ self.network.find_ip = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 floating_ip failed to delete.', str(e))
+
+ self.network.find_ip.assert_any_call(
+ self.floating_ips[0].id, ignore_missing=False)
+ self.network.find_ip.assert_any_call(
+ 'unexist_floating_ip', ignore_missing=False)
+ self.network.delete_ip.assert_called_once_with(
+ self.floating_ips[0]
+ )
+
class TestListFloatingIPNetwork(TestFloatingIPNetwork):
@@ -335,8 +389,8 @@ class TestCreateFloatingIPCompute(TestFloatingIPCompute):
class TestDeleteFloatingIPCompute(TestFloatingIPCompute):
- # The floating ip to be deleted.
- floating_ip = compute_fakes.FakeFloatingIP.create_one_floating_ip()
+ # The floating ips to be deleted.
+ floating_ips = compute_fakes.FakeFloatingIP.create_floating_ips(count=2)
def setUp(self):
super(TestDeleteFloatingIPCompute, self).setUp()
@@ -346,27 +400,78 @@ class TestDeleteFloatingIPCompute(TestFloatingIPCompute):
self.compute.floating_ips.delete.return_value = None
# Return value of utils.find_resource()
- self.compute.floating_ips.get.return_value = self.floating_ip
+ self.compute.floating_ips.get = (
+ compute_fakes.FakeFloatingIP.get_floating_ips(self.floating_ips))
# Get the command object to test
self.cmd = floating_ip.DeleteFloatingIP(self.app, None)
def test_floating_ip_delete(self):
arglist = [
- self.floating_ip.id,
+ self.floating_ips[0].id,
]
verifylist = [
- ('floating_ip', self.floating_ip.id),
+ ('floating_ip', [self.floating_ips[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.compute.floating_ips.delete.assert_called_once_with(
- self.floating_ip.id
+ self.floating_ips[0].id
)
self.assertIsNone(result)
+ def test_multi_floating_ips_delete(self):
+ arglist = []
+ verifylist = []
+
+ for f in self.floating_ips:
+ arglist.append(f.id)
+ verifylist = [
+ ('floating_ip', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for f in self.floating_ips:
+ calls.append(call(f.id))
+ self.compute.floating_ips.delete.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_floating_ips_delete_with_exception(self):
+ arglist = [
+ self.floating_ips[0].id,
+ 'unexist_floating_ip',
+ ]
+ verifylist = [
+ ('floating_ip',
+ [self.floating_ips[0].id, 'unexist_floating_ip']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self.floating_ips[0], exceptions.CommandError]
+ self.compute.floating_ips.get = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+ self.compute.floating_ips.find.side_effect = exceptions.NotFound(None)
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 floating_ip failed to delete.', str(e))
+
+ self.compute.floating_ips.get.assert_any_call(
+ self.floating_ips[0].id)
+ self.compute.floating_ips.get.assert_any_call(
+ 'unexist_floating_ip')
+ self.compute.floating_ips.delete.assert_called_once_with(
+ self.floating_ips[0].id
+ )
+
class TestListFloatingIPCompute(TestFloatingIPCompute):
diff --git a/openstackclient/tests/network/v2/test_ip_availability.py b/openstackclient/tests/network/v2/test_ip_availability.py
new file mode 100644
index 00000000..c6ec2b0b
--- /dev/null
+++ b/openstackclient/tests/network/v2/test_ip_availability.py
@@ -0,0 +1,184 @@
+# 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 copy
+import mock
+
+from osc_lib import utils as common_utils
+
+from openstackclient.network.v2 import ip_availability
+from openstackclient.tests import fakes
+from openstackclient.tests.identity.v3 import fakes as identity_fakes
+from openstackclient.tests.network.v2 import fakes as network_fakes
+from openstackclient.tests import utils as tests_utils
+
+
+class TestIPAvailability(network_fakes.TestNetworkV2):
+
+ def setUp(self):
+ super(TestIPAvailability, self).setUp()
+
+ # Get a shortcut to the network client
+ self.network = self.app.client_manager.network
+
+ # Set identity client v3. And get a shortcut to Identity client.
+ identity_client = identity_fakes.FakeIdentityv3Client(
+ endpoint=fakes.AUTH_URL,
+ token=fakes.AUTH_TOKEN,
+ )
+ self.app.client_manager.identity = identity_client
+ self.identity = self.app.client_manager.identity
+
+ # Get a shortcut to the ProjectManager Mock
+ self.projects_mock = self.identity.projects
+ self.projects_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ )
+
+
+class TestListIPAvailability(TestIPAvailability):
+
+ _ip_availability = \
+ network_fakes.FakeIPAvailability.create_ip_availability(count=3)
+ columns = (
+ 'Network ID',
+ 'Network Name',
+ 'Total IPs',
+ 'Used IPs',
+ )
+ data = []
+ for net in _ip_availability:
+ data.append((
+ net.network_id,
+ net.network_name,
+ net.total_ips,
+ net.used_ips,
+ ))
+
+ def setUp(self):
+ super(TestListIPAvailability, self).setUp()
+
+ self.cmd = ip_availability.ListIPAvailability(
+ self.app, self.namespace)
+ self.network.network_ip_availabilities = mock.Mock(
+ return_value=self._ip_availability)
+
+ def test_list_no_options(self):
+ arglist = []
+ verifylist = []
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ filters = {'ip_version': 4}
+
+ self.network.network_ip_availabilities.assert_called_once_with(
+ **filters)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_list_ip_version(self):
+ arglist = [
+ '--ip-version', str(4),
+ ]
+ verifylist = [
+ ('ip_version', 4)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ filters = {'ip_version': 4}
+
+ self.network.network_ip_availabilities.assert_called_once_with(
+ **filters)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+ def test_list_project(self):
+ arglist = [
+ '--project', identity_fakes.project_name
+ ]
+ verifylist = [
+ ('project', identity_fakes.project_name)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ filters = {'tenant_id': identity_fakes.project_id,
+ 'ip_version': 4}
+
+ self.network.network_ip_availabilities.assert_called_once_with(
+ **filters)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, list(data))
+
+
+class TestShowIPAvailability(TestIPAvailability):
+
+ _ip_availability = \
+ network_fakes.FakeIPAvailability.create_one_ip_availability()
+
+ columns = (
+ 'network_id',
+ 'network_name',
+ 'project_id',
+ 'subnet_ip_availability',
+ 'total_ips',
+ 'used_ips',
+ )
+ data = (
+ _ip_availability.network_id,
+ _ip_availability.network_name,
+ _ip_availability.tenant_id,
+ common_utils.format_list(
+ _ip_availability.subnet_ip_availability),
+ _ip_availability.total_ips,
+ _ip_availability.used_ips,
+ )
+
+ def setUp(self):
+ super(TestShowIPAvailability, self).setUp()
+
+ self.network.find_network_ip_availability = mock.Mock(
+ return_value=self._ip_availability)
+
+ # Get the command object to test
+ self.cmd = ip_availability.ShowIPAvailability(
+ self.app, self.namespace)
+
+ def test_show_no_option(self):
+ arglist = []
+ verifylist = []
+
+ self.assertRaises(tests_utils.ParserException,
+ self.check_parser, self.cmd, arglist, verifylist)
+
+ def test_show_all_options(self):
+ arglist = [
+ self._ip_availability.network_name,
+ ]
+ verifylist = [
+ ('network', self._ip_availability.network_name)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+ self.network.find_network_ip_availability.assert_called_once_with(
+ self._ip_availability.network_name,
+ ignore_missing=False)
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
diff --git a/openstackclient/tests/network/v2/test_network.py b/openstackclient/tests/network/v2/test_network.py
index ba810f16..8fc9dadf 100644
--- a/openstackclient/tests/network/v2/test_network.py
+++ b/openstackclient/tests/network/v2/test_network.py
@@ -13,10 +13,11 @@
import copy
import mock
-
from mock import call
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.network.v2 import network
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import fakes
@@ -609,8 +610,12 @@ class TestSetNetwork(TestNetwork):
verifylist = [('network', self._network.name), ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {}
+ self.network.update_network.assert_called_once_with(
+ self._network, **attrs)
+ self.assertIsNone(result)
class TestShowNetwork(TestNetwork):
diff --git a/openstackclient/tests/network/v2/test_network_segment.py b/openstackclient/tests/network/v2/test_network_segment.py
index 2822581c..a635d845 100644
--- a/openstackclient/tests/network/v2/test_network_segment.py
+++ b/openstackclient/tests/network/v2/test_network_segment.py
@@ -13,7 +13,8 @@
import mock
-from openstackclient.common import exceptions
+from osc_lib import exceptions
+
from openstackclient.network.v2 import network_segment
from openstackclient.tests.network.v2 import fakes as network_fakes
from openstackclient.tests import utils as tests_utils
@@ -25,7 +26,7 @@ class TestNetworkSegment(network_fakes.TestNetworkV2):
super(TestNetworkSegment, self).setUp()
# Enable beta commands.
- self.app.options.enable_beta_commands = True
+ self.app.options.os_beta_command = True
# Get a shortcut to the network client
self.network = self.app.client_manager.network
@@ -89,7 +90,7 @@ class TestListNetworkSegment(TestNetworkSegment):
self.assertEqual(self.data, list(data))
def test_list_no_beta_commands(self):
- self.app.options.enable_beta_commands = False
+ self.app.options.os_beta_command = False
parsed_args = self.check_parser(self.cmd, [], [])
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
@@ -174,7 +175,7 @@ class TestShowNetworkSegment(TestNetworkSegment):
verifylist = [
('network_segment', self._network_segment.id),
]
- self.app.options.enable_beta_commands = False
+ self.app.options.os_beta_command = False
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
diff --git a/openstackclient/tests/network/v2/test_port.py b/openstackclient/tests/network/v2/test_port.py
index f2aa26cf..779dca05 100644
--- a/openstackclient/tests/network/v2/test_port.py
+++ b/openstackclient/tests/network/v2/test_port.py
@@ -13,7 +13,10 @@
import mock
-from openstackclient.common import utils
+from mock import call
+from osc_lib import exceptions
+from osc_lib import utils
+
from openstackclient.network.v2 import port
from openstackclient.tests.network.v2 import fakes as network_fakes
from openstackclient.tests import utils as tests_utils
@@ -174,30 +177,82 @@ class TestCreatePort(TestPort):
class TestDeletePort(TestPort):
- # The port to delete.
- _port = network_fakes.FakePort.create_one_port()
+ # Ports to delete.
+ _ports = network_fakes.FakePort.create_ports(count=2)
def setUp(self):
super(TestDeletePort, self).setUp()
self.network.delete_port = mock.Mock(return_value=None)
- self.network.find_port = mock.Mock(return_value=self._port)
+ self.network.find_port = network_fakes.FakePort.get_ports(
+ ports=self._ports)
# Get the command object to test
self.cmd = port.DeletePort(self.app, self.namespace)
- def test_delete(self):
+ def test_port_delete(self):
arglist = [
- self._port.name,
+ self._ports[0].name,
]
verifylist = [
- ('port', [self._port.name]),
+ ('port', [self._ports[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.network.delete_port.assert_called_once_with(self._port)
+ self.network.find_port.assert_called_once_with(
+ self._ports[0].name, ignore_missing=False)
+ self.network.delete_port.assert_called_once_with(self._ports[0])
self.assertIsNone(result)
+ def test_multi_ports_delete(self):
+ arglist = []
+ verifylist = []
+
+ for p in self._ports:
+ arglist.append(p.name)
+ verifylist = [
+ ('port', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for p in self._ports:
+ calls.append(call(p))
+ self.network.delete_port.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_ports_delete_with_exception(self):
+ arglist = [
+ self._ports[0].name,
+ 'unexist_port',
+ ]
+ verifylist = [
+ ('port',
+ [self._ports[0].name, 'unexist_port']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._ports[0], exceptions.CommandError]
+ self.network.find_port = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 ports failed to delete.', str(e))
+
+ self.network.find_port.assert_any_call(
+ self._ports[0].name, ignore_missing=False)
+ self.network.find_port.assert_any_call(
+ 'unexist_port', ignore_missing=False)
+ self.network.delete_port.assert_called_once_with(
+ self._ports[0]
+ )
+
class TestListPort(TestPort):
@@ -283,6 +338,7 @@ class TestSetPort(TestPort):
]
verifylist = [
('fixed_ip', [{'ip-address': '10.0.0.11'}]),
+ ('port', self._port.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -304,6 +360,7 @@ class TestSetPort(TestPort):
]
verifylist = [
('fixed_ip', [{'ip-address': '10.0.0.12'}]),
+ ('port', _testport.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
@@ -325,6 +382,7 @@ class TestSetPort(TestPort):
('disable', True),
('no_binding_profile', True),
('no_fixed_ip', True),
+ ('port', self._port.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -352,7 +410,8 @@ class TestSetPort(TestPort):
('vnic_type', 'macvtap'),
('binding_profile', {'foo': 'bar'}),
('host', 'binding-host-id-xxxx'),
- ('name', 'newName')
+ ('name', 'newName'),
+ ('port', self._port.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -368,6 +427,21 @@ class TestSetPort(TestPort):
self.network.update_port.assert_called_once_with(self._port, **attrs)
self.assertIsNone(result)
+ def test_set_nothing(self):
+ arglist = [
+ self._port.name,
+ ]
+ verifylist = [
+ ('port', self._port.name),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {}
+ self.network.update_port.assert_called_once_with(self._port, **attrs)
+ self.assertIsNone(result)
+
class TestShowPort(TestPort):
diff --git a/openstackclient/tests/network/v2/test_router.py b/openstackclient/tests/network/v2/test_router.py
index 99b41d2d..16296139 100644
--- a/openstackclient/tests/network/v2/test_router.py
+++ b/openstackclient/tests/network/v2/test_router.py
@@ -13,8 +13,8 @@
import mock
-from openstackclient.common import exceptions
-from openstackclient.common import utils as osc_utils
+from osc_lib import utils as osc_utils
+
from openstackclient.network.v2 import router
from openstackclient.tests.network.v2 import fakes as network_fakes
from openstackclient.tests import utils as tests_utils
@@ -568,12 +568,20 @@ class TestSetRouter(TestRouter):
self.cmd, arglist, verifylist)
def test_set_nothing(self):
- arglist = [self._router.name, ]
- verifylist = [('router', self._router.name), ]
+ arglist = [
+ self._router.name,
+ ]
+ verifylist = [
+ ('router', self._router.name),
+ ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {}
+ self.network.update_router.assert_called_once_with(
+ self._router, **attrs)
+ self.assertIsNone(result)
class TestShowRouter(TestRouter):
diff --git a/openstackclient/tests/network/v2/test_security_group.py b/openstackclient/tests/network/v2/test_security_group.py
index 213367a4..b0c14985 100644
--- a/openstackclient/tests/network/v2/test_security_group.py
+++ b/openstackclient/tests/network/v2/test_security_group.py
@@ -13,6 +13,9 @@
import copy
import mock
+from mock import call
+
+from osc_lib import exceptions
from openstackclient.network.v2 import security_group
from openstackclient.tests.compute.v2 import fakes as compute_fakes
@@ -227,42 +230,93 @@ class TestCreateSecurityGroupCompute(TestSecurityGroupCompute):
class TestDeleteSecurityGroupNetwork(TestSecurityGroupNetwork):
- # The security group to be deleted.
- _security_group = \
- network_fakes.FakeSecurityGroup.create_one_security_group()
+ # The security groups to be deleted.
+ _security_groups = \
+ network_fakes.FakeSecurityGroup.create_security_groups()
def setUp(self):
super(TestDeleteSecurityGroupNetwork, self).setUp()
self.network.delete_security_group = mock.Mock(return_value=None)
- self.network.find_security_group = mock.Mock(
- return_value=self._security_group)
+ self.network.find_security_group = (
+ network_fakes.FakeSecurityGroup.get_security_groups(
+ self._security_groups)
+ )
# Get the command object to test
self.cmd = security_group.DeleteSecurityGroup(self.app, self.namespace)
def test_security_group_delete(self):
arglist = [
- self._security_group.name,
+ self._security_groups[0].name,
]
verifylist = [
- ('group', self._security_group.name),
+ ('group', [self._security_groups[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.delete_security_group.assert_called_once_with(
- self._security_group)
+ self._security_groups[0])
+ self.assertIsNone(result)
+
+ def test_multi_security_groups_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._security_groups:
+ arglist.append(s.name)
+ verifylist = [
+ ('group', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._security_groups:
+ calls.append(call(s))
+ self.network.delete_security_group.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_multi_security_groups_delete_with_exception(self):
+ arglist = [
+ self._security_groups[0].name,
+ 'unexist_security_group',
+ ]
+ verifylist = [
+ ('group',
+ [self._security_groups[0].name, 'unexist_security_group']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._security_groups[0], exceptions.CommandError]
+ self.network.find_security_group = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 group failed to delete.', str(e))
+
+ self.network.find_security_group.assert_any_call(
+ self._security_groups[0].name, ignore_missing=False)
+ self.network.find_security_group.assert_any_call(
+ 'unexist_security_group', ignore_missing=False)
+ self.network.delete_security_group.assert_called_once_with(
+ self._security_groups[0]
+ )
+
class TestDeleteSecurityGroupCompute(TestSecurityGroupCompute):
- # The security group to be deleted.
- _security_group = \
- compute_fakes.FakeSecurityGroup.create_one_security_group()
+ # The security groups to be deleted.
+ _security_groups = \
+ compute_fakes.FakeSecurityGroup.create_security_groups()
def setUp(self):
super(TestDeleteSecurityGroupCompute, self).setUp()
@@ -271,27 +325,80 @@ class TestDeleteSecurityGroupCompute(TestSecurityGroupCompute):
self.compute.security_groups.delete = mock.Mock(return_value=None)
- self.compute.security_groups.get = mock.Mock(
- return_value=self._security_group)
+ self.compute.security_groups.get = (
+ compute_fakes.FakeSecurityGroup.get_security_groups(
+ self._security_groups)
+ )
# Get the command object to test
self.cmd = security_group.DeleteSecurityGroup(self.app, None)
def test_security_group_delete(self):
arglist = [
- self._security_group.name,
+ self._security_groups[0].id,
]
verifylist = [
- ('group', self._security_group.name),
+ ('group', [self._security_groups[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.compute.security_groups.delete.assert_called_once_with(
- self._security_group.id)
+ self._security_groups[0].id)
+ self.assertIsNone(result)
+
+ def test_multi_security_groups_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._security_groups:
+ arglist.append(s.id)
+ verifylist = [
+ ('group', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._security_groups:
+ calls.append(call(s.id))
+ self.compute.security_groups.delete.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_multi_security_groups_delete_with_exception(self):
+ arglist = [
+ self._security_groups[0].id,
+ 'unexist_security_group',
+ ]
+ verifylist = [
+ ('group',
+ [self._security_groups[0].id, 'unexist_security_group']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._security_groups[0], exceptions.CommandError]
+ self.compute.security_groups.get = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+ self.compute.security_groups.find.side_effect = (
+ exceptions.NotFound(None))
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 group failed to delete.', str(e))
+
+ self.compute.security_groups.get.assert_any_call(
+ self._security_groups[0].id)
+ self.compute.security_groups.get.assert_any_call(
+ 'unexist_security_group')
+ self.compute.security_groups.delete.assert_called_once_with(
+ self._security_groups[0].id
+ )
+
class TestListSecurityGroupNetwork(TestSecurityGroupNetwork):
diff --git a/openstackclient/tests/network/v2/test_security_group_rule.py b/openstackclient/tests/network/v2/test_security_group_rule.py
index 2a64b884..b2862679 100644
--- a/openstackclient/tests/network/v2/test_security_group_rule.py
+++ b/openstackclient/tests/network/v2/test_security_group_rule.py
@@ -13,8 +13,10 @@
import copy
import mock
+from mock import call
+
+from osc_lib import exceptions
-from openstackclient.common import exceptions
from openstackclient.network import utils as network_utils
from openstackclient.network.v2 import security_group_rule
from openstackclient.tests.compute.v2 import fakes as compute_fakes
@@ -667,17 +669,20 @@ class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
class TestDeleteSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
- # The security group rule to be deleted.
- _security_group_rule = \
- network_fakes.FakeSecurityGroupRule.create_one_security_group_rule()
+ # The security group rules to be deleted.
+ _security_group_rules = \
+ network_fakes.FakeSecurityGroupRule.create_security_group_rules(
+ count=2)
def setUp(self):
super(TestDeleteSecurityGroupRuleNetwork, self).setUp()
self.network.delete_security_group_rule = mock.Mock(return_value=None)
- self.network.find_security_group_rule = mock.Mock(
- return_value=self._security_group_rule)
+ self.network.find_security_group_rule = (
+ network_fakes.FakeSecurityGroupRule.get_security_group_rules(
+ self._security_group_rules)
+ )
# Get the command object to test
self.cmd = security_group_rule.DeleteSecurityGroupRule(
@@ -685,25 +690,76 @@ class TestDeleteSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def test_security_group_rule_delete(self):
arglist = [
- self._security_group_rule.id,
+ self._security_group_rules[0].id,
]
verifylist = [
- ('rule', self._security_group_rule.id),
+ ('rule', [self._security_group_rules[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.delete_security_group_rule.assert_called_once_with(
- self._security_group_rule)
+ self._security_group_rules[0])
self.assertIsNone(result)
+ def test_multi_security_group_rules_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._security_group_rules:
+ arglist.append(s.id)
+ verifylist = [
+ ('rule', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._security_group_rules:
+ calls.append(call(s))
+ self.network.delete_security_group_rule.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_security_group_rules_delete_with_exception(self):
+ arglist = [
+ self._security_group_rules[0].id,
+ 'unexist_rule',
+ ]
+ verifylist = [
+ ('rule',
+ [self._security_group_rules[0].id, 'unexist_rule']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [
+ self._security_group_rules[0], exceptions.CommandError]
+ self.network.find_security_group_rule = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 rule failed to delete.', str(e))
+
+ self.network.find_security_group_rule.assert_any_call(
+ self._security_group_rules[0].id, ignore_missing=False)
+ self.network.find_security_group_rule.assert_any_call(
+ 'unexist_rule', ignore_missing=False)
+ self.network.delete_security_group_rule.assert_called_once_with(
+ self._security_group_rules[0]
+ )
+
class TestDeleteSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
# The security group rule to be deleted.
- _security_group_rule = \
- compute_fakes.FakeSecurityGroupRule.create_one_security_group_rule()
+ _security_group_rules = \
+ compute_fakes.FakeSecurityGroupRule.create_security_group_rules(
+ count=2)
def setUp(self):
super(TestDeleteSecurityGroupRuleCompute, self).setUp()
@@ -715,19 +771,65 @@ class TestDeleteSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
def test_security_group_rule_delete(self):
arglist = [
- self._security_group_rule.id,
+ self._security_group_rules[0].id,
]
verifylist = [
- ('rule', self._security_group_rule.id),
+ ('rule', [self._security_group_rules[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.compute.security_group_rules.delete.assert_called_once_with(
- self._security_group_rule.id)
+ self._security_group_rules[0].id)
+ self.assertIsNone(result)
+
+ def test_multi_security_group_rules_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._security_group_rules:
+ arglist.append(s.id)
+ verifylist = [
+ ('rule', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._security_group_rules:
+ calls.append(call(s.id))
+ self.compute.security_group_rules.delete.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_multi_security_group_rules_delete_with_exception(self):
+ arglist = [
+ self._security_group_rules[0].id,
+ 'unexist_rule',
+ ]
+ verifylist = [
+ ('rule',
+ [self._security_group_rules[0].id, 'unexist_rule']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [None, exceptions.CommandError]
+ self.compute.security_group_rules.delete = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 rule failed to delete.', str(e))
+
+ self.compute.security_group_rules.delete.assert_any_call(
+ self._security_group_rules[0].id)
+ self.compute.security_group_rules.delete.assert_any_call(
+ 'unexist_rule')
+
class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
diff --git a/openstackclient/tests/network/v2/test_subnet.py b/openstackclient/tests/network/v2/test_subnet.py
index 22c288f9..de7e1821 100644
--- a/openstackclient/tests/network/v2/test_subnet.py
+++ b/openstackclient/tests/network/v2/test_subnet.py
@@ -14,8 +14,8 @@
import copy
import mock
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.network.v2 import subnet as subnet_v2
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes_v3
@@ -549,8 +549,11 @@ class TestSetSubnet(TestSubnet):
verifylist = [('subnet', self._subnet.name)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {}
+ self.network.update_subnet.assert_called_with(self._subnet, **attrs)
+ self.assertIsNone(result)
def test_append_options(self):
_testsubnet = network_fakes.FakeSubnet.create_one_subnet(
diff --git a/openstackclient/tests/network/v2/test_subnet_pool.py b/openstackclient/tests/network/v2/test_subnet_pool.py
index de12c9e9..10ef76d8 100644
--- a/openstackclient/tests/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/network/v2/test_subnet_pool.py
@@ -15,8 +15,8 @@ import argparse
import copy
import mock
-from openstackclient.common import exceptions
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.network.v2 import subnet_pool
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes_v3
@@ -443,10 +443,14 @@ class TestSetSubnetPool(TestSubnetPool):
def test_set_nothing(self):
arglist = [self._subnet_pool.name, ]
verifylist = [('subnet_pool', self._subnet_pool.name), ]
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ attrs = {}
+ self.network.update_subnet_pool.assert_called_once_with(
+ self._subnet_pool, **attrs)
+ self.assertIsNone(result)
def test_set_len_negative(self):
arglist = [
diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py
index 90454fc2..7d0bbd12 100644
--- a/openstackclient/tests/test_shell.py
+++ b/openstackclient/tests/test_shell.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
diff --git a/openstackclient/tests/volume/test_find_resource.py b/openstackclient/tests/volume/test_find_resource.py
index 00cc46a6..227d6ca7 100644
--- a/openstackclient/tests/volume/test_find_resource.py
+++ b/openstackclient/tests/volume/test_find_resource.py
@@ -17,9 +17,9 @@ import mock
from cinderclient.v1 import volume_snapshots
from cinderclient.v1 import volumes
+from osc_lib import exceptions
+from osc_lib import utils
-from openstackclient.common import exceptions
-from openstackclient.common import utils
from openstackclient.tests import utils as test_utils
from openstackclient.volume import client # noqa
diff --git a/openstackclient/tests/volume/v1/fakes.py b/openstackclient/tests/volume/v1/fakes.py
index d6c46439..6c349866 100644
--- a/openstackclient/tests/volume/v1/fakes.py
+++ b/openstackclient/tests/volume/v1/fakes.py
@@ -129,6 +129,57 @@ QOS_WITH_ASSOCIATIONS = {
}
+class FakeTransferClient(object):
+
+ def __init__(self, **kwargs):
+
+ self.transfers = mock.Mock()
+ self.transfers.resource_class = fakes.FakeResource(None, {})
+
+
+class TestTransfer(utils.TestCommand):
+
+ def setUp(self):
+ super(TestTransfer, self).setUp()
+
+ self.app.client_manager.volume = FakeTransferClient(
+ endpoint=fakes.AUTH_URL,
+ token=fakes.AUTH_TOKEN
+ )
+
+
+class FakeTransfer(object):
+ """Fake one or more Transfer."""
+
+ @staticmethod
+ def create_one_transfer(attrs=None):
+ """Create a fake transfer.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes of Transfer Request
+ :retrun:
+ A FakeResource object with volume_id, name, id.
+ """
+ # Set default attribute
+ transfer_info = {
+ 'volume_id': 'ce26708d-a7f8-4b4b-9861-4a80256615a7',
+ 'name': 'fake_transfer_name',
+ 'id': '731a7f53-aa92-4fbd-9de3-6f7d729c926b'
+ }
+
+ # Overwrite default attributes if there are some attributes set
+ attrs = attrs or {}
+
+ transfer_info.update(attrs)
+
+ transfer = fakes.FakeResource(
+ None,
+ transfer_info,
+ loaded=True)
+
+ return transfer
+
+
class FakeServiceClient(object):
def __init__(self, **kwargs):
@@ -171,8 +222,8 @@ class FakeService(object):
}
# Overwrite default attributes if there are some attributes set
- if attrs is None:
- attrs = {}
+ attrs = attrs or {}
+
service_info.update(attrs)
service = fakes.FakeResource(
diff --git a/openstackclient/tests/volume/v1/test_qos_specs.py b/openstackclient/tests/volume/v1/test_qos_specs.py
index 4943f5df..392017c6 100644
--- a/openstackclient/tests/volume/v1/test_qos_specs.py
+++ b/openstackclient/tests/volume/v1/test_qos_specs.py
@@ -15,7 +15,8 @@
import copy
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.tests import fakes
from openstackclient.tests.volume.v1 import fakes as volume_fakes
from openstackclient.volume.v1 import qos_specs
diff --git a/openstackclient/tests/volume/v1/test_transfer_request.py b/openstackclient/tests/volume/v1/test_transfer_request.py
new file mode 100644
index 00000000..94e02d62
--- /dev/null
+++ b/openstackclient/tests/volume/v1/test_transfer_request.py
@@ -0,0 +1,114 @@
+#
+# 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.volume.v1 import fakes as transfer_fakes
+from openstackclient.volume.v1 import volume_transfer_request
+
+
+class TestTransfer(transfer_fakes.TestTransfer):
+
+ def setUp(self):
+ super(TestTransfer, self).setUp()
+
+ # Get a shortcut to the TransferManager Mock
+ self.transfer_mock = self.app.client_manager.volume.transfers
+ self.transfer_mock.reset_mock()
+
+
+class TestTransferList(TestTransfer):
+
+ # The Transfers to be listed
+ volume_transfers = transfer_fakes.FakeTransfer.create_one_transfer()
+
+ def setUp(self):
+ super(TestTransferList, self).setUp()
+
+ self.transfer_mock.list.return_value = [self.volume_transfers]
+
+ # Get the command object to test
+ self.cmd = volume_transfer_request.ListTransferRequests(self.app, None)
+
+ def test_transfer_list_without_argument(self):
+ arglist = []
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ expected_columns = [
+ 'ID',
+ 'Volume',
+ 'Name',
+ ]
+
+ # confirming if all expected columns are present in the result.
+ self.assertEqual(expected_columns, columns)
+
+ datalist = ((
+ self.volume_transfers.id,
+ self.volume_transfers.volume_id,
+ self.volume_transfers.name,
+ ), )
+
+ # confirming if all expected values are present in the result.
+ self.assertEqual(datalist, tuple(data))
+
+ # checking if proper call was made to list volume_transfers
+ self.transfer_mock.list.assert_called_with(
+ detailed=True,
+ search_opts={'all_tenants': 0}
+ )
+
+ def test_transfer_list_with_argument(self):
+ arglist = [
+ "--all-projects"
+ ]
+ verifylist = [
+ ("all_projects", True)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ expected_columns = [
+ 'ID',
+ 'Volume',
+ 'Name',
+ ]
+
+ # confirming if all expected columns are present in the result.
+ self.assertEqual(expected_columns, columns)
+
+ datalist = ((
+ self.volume_transfers.id,
+ self.volume_transfers.volume_id,
+ self.volume_transfers.name,
+ ), )
+
+ # confirming if all expected values are present in the result.
+ self.assertEqual(datalist, tuple(data))
+
+ # checking if proper call was made to list volume_transfers
+ self.transfer_mock.list.assert_called_with(
+ detailed=True,
+ search_opts={'all_tenants': 1}
+ )
diff --git a/openstackclient/tests/volume/v1/test_volume.py b/openstackclient/tests/volume/v1/test_volume.py
index e0fd1c08..380bc632 100644
--- a/openstackclient/tests/volume/v1/test_volume.py
+++ b/openstackclient/tests/volume/v1/test_volume.py
@@ -14,6 +14,7 @@
#
import copy
+import mock
from openstackclient.tests import fakes
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
@@ -578,9 +579,6 @@ class TestVolumeSet(TestVolume):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
-
- self.assertEqual("No changes requested\n",
- self.app.log.messages.get('error'))
self.assertIsNone(result)
def test_volume_set_name(self):
@@ -659,7 +657,8 @@ class TestVolumeSet(TestVolume):
)
self.assertIsNone(result)
- def test_volume_set_size_smaller(self):
+ @mock.patch.object(volume.LOG, 'error')
+ def test_volume_set_size_smaller(self, mock_log_error):
arglist = [
'--size', '100',
volume_fakes.volume_name,
@@ -675,12 +674,13 @@ class TestVolumeSet(TestVolume):
result = self.cmd.take_action(parsed_args)
- self.assertEqual("New size must be greater than %s GB" %
- volume_fakes.volume_size,
- self.app.log.messages.get('error'))
+ mock_log_error.assert_called_with("New size must be greater "
+ "than %s GB",
+ volume_fakes.volume_size)
self.assertIsNone(result)
- def test_volume_set_size_not_available(self):
+ @mock.patch.object(volume.LOG, 'error')
+ def test_volume_set_size_not_available(self, mock_log_error):
self.volumes_mock.get.return_value.status = 'error'
arglist = [
'--size', '130',
@@ -697,9 +697,9 @@ class TestVolumeSet(TestVolume):
result = self.cmd.take_action(parsed_args)
- self.assertEqual("Volume is in %s state, it must be available before "
- "size can be extended" % 'error',
- self.app.log.messages.get('error'))
+ mock_log_error.assert_called_with("Volume is in %s state, it must be "
+ "available before size can be "
+ "extended", 'error')
self.assertIsNone(result)
def test_volume_set_property(self):
diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py
index 158ab0ab..1cbbf68a 100644
--- a/openstackclient/tests/volume/v2/fakes.py
+++ b/openstackclient/tests/volume/v2/fakes.py
@@ -17,219 +17,63 @@ import mock
import random
import uuid
-from openstackclient.common import utils as common_utils
+from osc_lib import utils as common_utils
+
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
from openstackclient.tests import utils
-volume_attachment_server = {
- 'device': '/dev/ice',
- 'server_id': '1233',
-}
-
-volume_id = "ce26708d-a7f8-4b4b-9861-4a80256615a6"
-volume_name = "fake_volume"
-volume_description = "fake description"
-volume_status = "available"
-volume_size = 20
-volume_type = "fake_lvmdriver-1"
-volume_metadata = {
- 'Alpha': 'a',
- 'Beta': 'b',
- 'Gamma': 'g',
-}
-volume_metadata_str = "Alpha='a', Beta='b', Gamma='g'"
-volume_snapshot_id = 1
-volume_availability_zone = "nova"
-volume_attachments = [volume_attachment_server]
-
-VOLUME = {
- "id": volume_id,
- "name": volume_name,
- "description": volume_description,
- "status": volume_status,
- "size": volume_size,
- "volume_type": volume_type,
- "metadata": volume_metadata,
- "snapshot_id": volume_snapshot_id,
- "availability_zone": volume_availability_zone,
- "attachments": volume_attachments
-}
-
-VOLUME_columns = (
- "attachments",
- "availability_zone",
- "description",
- "id",
- "name",
- "properties",
- "size",
- "snapshot_id",
- "status",
- "type"
-)
-
-VOLUME_data = (
- volume_attachments,
- volume_availability_zone,
- volume_description,
- volume_id,
- volume_name,
- common_utils.format_dict(volume_metadata),
- volume_size,
- volume_snapshot_id,
- volume_status,
- volume_type
-)
-
-
-snapshot_id = "cb2d364e-4d1c-451a-8c68-b5bbcb340fb2"
-snapshot_name = "fake_snapshot"
-snapshot_description = "fake description"
-snapshot_size = 10
-snapshot_metadata = {
- "foo": "bar"
-}
-snapshot_volume_id = "bdbae8dc-e6ca-43c0-8076-951cc1b093a4"
-
-SNAPSHOT = {
- "id": snapshot_id,
- "name": snapshot_name,
- "description": snapshot_description,
- "size": snapshot_size,
- "status": "available",
- "metadata": snapshot_metadata,
- "created_at": "2015-06-03T18:49:19.000000",
- "volume_id": volume_name
-}
-EXPECTED_SNAPSHOT = copy.deepcopy(SNAPSHOT)
-EXPECTED_SNAPSHOT.pop("metadata")
-EXPECTED_SNAPSHOT['properties'] = "foo='bar'"
-SNAPSHOT_columns = tuple(sorted(EXPECTED_SNAPSHOT))
-SNAPSHOT_data = tuple((EXPECTED_SNAPSHOT[x]
- for x in sorted(EXPECTED_SNAPSHOT)))
-
-
-type_id = "5520dc9e-6f9b-4378-a719-729911c0f407"
-type_description = "fake description"
-type_name = "fake-lvmdriver-1"
-type_extra_specs = {
- "foo": "bar"
-}
-
-TYPE = {
- 'id': type_id,
- 'name': type_name,
- 'description': type_description,
- 'extra_specs': type_extra_specs
-}
-
-TYPE_columns = tuple(sorted(TYPE))
-TYPE_data = tuple((TYPE[x] for x in sorted(TYPE)))
-
-formatted_type_properties = "foo='bar'"
-TYPE_FORMATTED = {
- 'id': type_id,
- 'name': type_name,
- 'description': type_description,
- 'properties': formatted_type_properties
-}
-TYPE_FORMATTED_columns = tuple(sorted(TYPE_FORMATTED))
-TYPE_FORMATTED_data = tuple((TYPE_FORMATTED[x] for x in
- sorted(TYPE_FORMATTED)))
-
-backup_id = "3c409fe6-4d03-4a06-aeab-18bdcdf3c8f4"
-backup_volume_id = "bdbae8dc-e6ca-43c0-8076-951cc1b093a4"
-backup_name = "fake_backup"
-backup_description = "fake description"
-backup_object_count = None
-backup_container = None
-backup_size = 10
-backup_status = "error"
-
-BACKUP = {
- "id": backup_id,
- "name": backup_name,
- "volume_id": backup_volume_id,
- "description": backup_description,
- "object_count": backup_object_count,
- "container": backup_container,
- "size": backup_size,
- "status": backup_status,
- "availability_zone": volume_availability_zone,
-}
-
-BACKUP_columns = tuple(sorted(BACKUP))
-BACKUP_data = tuple((BACKUP[x] for x in sorted(BACKUP)))
-
-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]
-}
-
-image_id = 'im1'
-image_name = 'graven'
-IMAGE = {
- 'id': image_id,
- 'name': image_name
-}
-
-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 = '2013-04-18T00:00:00+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,
-}
+
+class FakeTransferClient(object):
+
+ def __init__(self, **kwargs):
+
+ self.transfers = mock.Mock()
+ self.transfers.resource_class = fakes.FakeResource(None, {})
+
+
+class TestTransfer(utils.TestCommand):
+
+ def setUp(self):
+ super(TestTransfer, self).setUp()
+
+ self.app.client_manager.volume = FakeTransferClient(
+ endpoint=fakes.AUTH_URL,
+ token=fakes.AUTH_TOKEN
+ )
+
+
+class FakeTransfer(object):
+ """Fake one or more Transfer."""
+
+ @staticmethod
+ def create_one_transfer(attrs=None):
+ """Create a fake transfer.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes of Transfer Request
+ :retrun:
+ A FakeResource object with volume_id, name, id.
+ """
+ # Set default attribute
+ transfer_info = {
+ 'volume_id': 'ce26708d-a7f8-4b4b-9861-4a80256615a7',
+ 'name': 'fake_transfer_name',
+ 'id': '731a7f53-aa92-4fbd-9de3-6f7d729c926b'
+ }
+
+ # Overwrite default attributes if there are some attributes set
+ attrs = attrs or {}
+
+ transfer_info.update(attrs)
+
+ transfer = fakes.FakeResource(
+ None,
+ transfer_info,
+ loaded=True)
+
+ return transfer
class FakeServiceClient(object):
@@ -274,8 +118,8 @@ class FakeService(object):
}
# Overwrite default attributes if there are some attributes set
- if attrs is None:
- attrs = {}
+ attrs = attrs or {}
+
service_info.update(attrs)
service = fakes.FakeResource(
@@ -328,6 +172,8 @@ class FakeVolumeClient(object):
def __init__(self, **kwargs):
self.volumes = mock.Mock()
self.volumes.resource_class = fakes.FakeResource(None, {})
+ self.extensions = mock.Mock()
+ self.extensions.resource_class = fakes.FakeResource(None, {})
self.volume_snapshots = mock.Mock()
self.volume_snapshots.resource_class = fakes.FakeResource(None, {})
self.backups = mock.Mock()
@@ -592,6 +438,42 @@ class FakeBackup(object):
return backups
+class FakeExtension(object):
+ """Fake one or more extension."""
+
+ @staticmethod
+ def create_one_extension(attrs=None):
+ """Create a fake extension.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with name, namespace, etc.
+ """
+ attrs = attrs or {}
+
+ # Set default attributes.
+ extension_info = {
+ 'name': 'name-' + uuid.uuid4().hex,
+ 'namespace': ('http://docs.openstack.org/'
+ 'block-service/ext/scheduler-hints/api/v2'),
+ 'description': 'description-' + uuid.uuid4().hex,
+ 'updated': '2013-04-18T00:00:00+00:00',
+ 'alias': 'OS-SCH-HNT',
+ 'links': ('[{"href":'
+ '"https://github.com/openstack/block-api", "type":'
+ ' "text/html", "rel": "describedby"}]'),
+ }
+
+ # Overwrite default attributes.
+ extension_info.update(attrs)
+
+ extension = fakes.FakeResource(
+ info=copy.deepcopy(extension_info),
+ loaded=True)
+ return extension
+
+
class FakeQos(object):
"""Fake one or more Qos specification."""
diff --git a/openstackclient/tests/volume/v2/test_qos_specs.py b/openstackclient/tests/volume/v2/test_qos_specs.py
index 741f4e70..11047535 100644
--- a/openstackclient/tests/volume/v2/test_qos_specs.py
+++ b/openstackclient/tests/volume/v2/test_qos_specs.py
@@ -13,9 +13,9 @@
# under the License.
#
-from openstackclient.common import utils
from openstackclient.tests.volume.v2 import fakes as volume_fakes
from openstackclient.volume.v2 import qos_specs
+from osc_lib import utils
class TestQos(volume_fakes.TestVolume):
diff --git a/openstackclient/tests/volume/v2/test_snapshot.py b/openstackclient/tests/volume/v2/test_snapshot.py
index fe6fbb52..ef199cbc 100644
--- a/openstackclient/tests/volume/v2/test_snapshot.py
+++ b/openstackclient/tests/volume/v2/test_snapshot.py
@@ -12,7 +12,8 @@
# under the License.
#
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.tests.volume.v2 import fakes as volume_fakes
from openstackclient.volume.v2 import snapshot
diff --git a/openstackclient/tests/volume/v2/test_transfer_request.py b/openstackclient/tests/volume/v2/test_transfer_request.py
new file mode 100644
index 00000000..945833c9
--- /dev/null
+++ b/openstackclient/tests/volume/v2/test_transfer_request.py
@@ -0,0 +1,114 @@
+#
+# 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.volume.v2 import fakes as transfer_fakes
+from openstackclient.volume.v2 import volume_transfer_request
+
+
+class TestTransfer(transfer_fakes.TestTransfer):
+
+ def setUp(self):
+ super(TestTransfer, self).setUp()
+
+ # Get a shortcut to the TransferManager Mock
+ self.transfer_mock = self.app.client_manager.volume.transfers
+ self.transfer_mock.reset_mock()
+
+
+class TestTransferList(TestTransfer):
+
+ # The Transfers to be listed
+ volume_transfers = transfer_fakes.FakeTransfer.create_one_transfer()
+
+ def setUp(self):
+ super(TestTransferList, self).setUp()
+
+ self.transfer_mock.list.return_value = [self.volume_transfers]
+
+ # Get the command object to test
+ self.cmd = volume_transfer_request.ListTransferRequests(self.app, None)
+
+ def test_transfer_list_without_argument(self):
+ arglist = []
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ expected_columns = [
+ 'ID',
+ 'Volume',
+ 'Name',
+ ]
+
+ # confirming if all expected columns are present in the result.
+ self.assertEqual(expected_columns, columns)
+
+ datalist = ((
+ self.volume_transfers.id,
+ self.volume_transfers.volume_id,
+ self.volume_transfers.name,
+ ), )
+
+ # confirming if all expected values are present in the result.
+ self.assertEqual(datalist, tuple(data))
+
+ # checking if proper call was made to list volume_transfers
+ self.transfer_mock.list.assert_called_with(
+ detailed=True,
+ search_opts={'all_tenants': 0}
+ )
+
+ def test_transfer_list_with_argument(self):
+ arglist = [
+ "--all-projects"
+ ]
+ verifylist = [
+ ("all_projects", True)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ expected_columns = [
+ 'ID',
+ 'Volume',
+ 'Name',
+ ]
+
+ # confirming if all expected columns are present in the result.
+ self.assertEqual(expected_columns, columns)
+
+ datalist = ((
+ self.volume_transfers.id,
+ self.volume_transfers.volume_id,
+ self.volume_transfers.name,
+ ), )
+
+ # confirming if all expected values are present in the result.
+ self.assertEqual(datalist, tuple(data))
+
+ # checking if proper call was made to list volume_transfers
+ self.transfer_mock.list.assert_called_with(
+ detailed=True,
+ search_opts={'all_tenants': 1}
+ )
diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py
index 872b4ae9..7eea1c3c 100644
--- a/openstackclient/tests/volume/v2/test_type.py
+++ b/openstackclient/tests/volume/v2/test_type.py
@@ -14,7 +14,8 @@
import copy
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
from openstackclient.tests import utils as tests_utils
@@ -397,17 +398,19 @@ class TestTypeUnset(TestType):
def test_type_unset(self):
arglist = [
'--property', 'property',
+ '--property', 'multi_property',
self.volume_type.id,
]
verifylist = [
- ('property', 'property'),
+ ('property', ['property', 'multi_property']),
('volume_type', self.volume_type.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.volume_type.unset_keys.assert_called_once_with('property')
+ self.volume_type.unset_keys.assert_called_once_with(
+ ['property', 'multi_property'])
self.assertIsNone(result)
def test_type_unset_project_access(self):
diff --git a/openstackclient/tests/volume/v2/test_volume.py b/openstackclient/tests/volume/v2/test_volume.py
index fb48d8ac..68158df0 100644
--- a/openstackclient/tests/volume/v2/test_volume.py
+++ b/openstackclient/tests/volume/v2/test_volume.py
@@ -16,7 +16,8 @@ import copy
from mock import call
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
diff --git a/openstackclient/volume/client.py b/openstackclient/volume/client.py
index a60f4b0e..ea0c441c 100644
--- a/openstackclient/volume/client.py
+++ b/openstackclient/volume/client.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -15,7 +15,8 @@
import logging
-from openstackclient.common import utils
+from osc_lib import utils
+
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/volume/v1/backup.py b/openstackclient/volume/v1/backup.py
index 607b5211..212c74ef 100644
--- a/openstackclient/volume/v1/backup.py
+++ b/openstackclient/volume/v1/backup.py
@@ -16,10 +16,11 @@
"""Volume v1 Backup action implementations"""
import copy
+
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v1/qos_specs.py b/openstackclient/volume/v1/qos_specs.py
index b9eb8752..56a96256 100644
--- a/openstackclient/volume/v1/qos_specs.py
+++ b/openstackclient/volume/v1/qos_specs.py
@@ -15,11 +15,11 @@
"""Volume v1 QoS action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -202,8 +202,6 @@ class SetQos(command.Command):
if parsed_args.property:
volume_client.qos_specs.set_keys(qos_spec.id,
parsed_args.property)
- else:
- self.app.log.error(_("No changes requested\n"))
class ShowQos(command.ShowOne):
@@ -263,5 +261,3 @@ class UnsetQos(command.Command):
if parsed_args.property:
volume_client.qos_specs.unset_keys(qos_spec.id,
parsed_args.property)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v1/service.py b/openstackclient/volume/v1/service.py
index 023dda98..2df38573 100644
--- a/openstackclient/volume/v1/service.py
+++ b/openstackclient/volume/v1/service.py
@@ -14,8 +14,9 @@
"""Service action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py
index bf5bf264..bb3a1fc3 100644
--- a/openstackclient/volume/v1/snapshot.py
+++ b/openstackclient/volume/v1/snapshot.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2013 OpenStack, LLC.
+# Copyright 2012-2013 OpenStack Foundation
#
# 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
@@ -16,11 +16,12 @@
"""Volume v1 Snapshot action implementations"""
import copy
+
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -208,10 +209,6 @@ class SetSnapshot(command.Command):
if parsed_args.description:
kwargs['display_description'] = parsed_args.description
- if not kwargs and not parsed_args.property:
- self.app.log.error(_("No changes requested\n"))
- return
-
snapshot.update(**kwargs)
@@ -270,5 +267,3 @@ class UnsetSnapshot(command.Command):
snapshot.id,
parsed_args.property,
)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index 11e42f83..e11aa1a7 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -16,14 +16,19 @@
"""Volume v1 Volume action implementations"""
import argparse
+import logging
+
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
+LOG = logging.getLogger(__name__)
+
+
class CreateVolume(command.ShowOne):
"""Create new volume"""
@@ -342,13 +347,12 @@ class SetVolume(command.Command):
if parsed_args.size:
if volume.status != 'available':
- self.app.log.error(_("Volume is in %s state, it must be "
- "available before size can be extended") %
- volume.status)
+ 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:
- self.app.log.error(_("New size must be greater than %s GB") %
- volume.size)
+ LOG.error(_("New size must be greater than %s GB"),
+ volume.size)
return
volume_client.volumes.extend(volume.id, parsed_args.size)
@@ -363,9 +367,6 @@ class SetVolume(command.Command):
if kwargs:
volume_client.volumes.update(volume.id, **kwargs)
- if not kwargs and not parsed_args.property and not parsed_args.size:
- self.app.log.error(_("No changes requested\n"))
-
class ShowVolume(command.ShowOne):
"""Show volume details"""
@@ -428,5 +429,3 @@ class UnsetVolume(command.Command):
volume.id,
parsed_args.property,
)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v1/volume_transfer_request.py b/openstackclient/volume/v1/volume_transfer_request.py
new file mode 100644
index 00000000..5d8ff683
--- /dev/null
+++ b/openstackclient/volume/v1/volume_transfer_request.py
@@ -0,0 +1,51 @@
+#
+# 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 transfer action implementations"""
+
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
+
+
+class ListTransferRequests(command.Lister):
+ """Lists all volume transfer requests."""
+
+ def get_parser(self, prog_name):
+ parser = super(ListTransferRequests, self).get_parser(prog_name)
+ parser.add_argument(
+ '--all-projects',
+ dest='all_projects',
+ action="store_true",
+ default=False,
+ help=_('Shows detail for all projects. Admin only. '
+ '(defaults to False)')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ columns = ['ID', 'Volume ID', 'Name']
+ column_headers = ['ID', 'Volume', 'Name']
+
+ volume_client = self.app.client_manager.volume
+
+ volume_transfer_result = volume_client.transfers.list(
+ detailed=True,
+ search_opts={'all_tenants': parsed_args.all_projects}
+ )
+
+ return (column_headers, (
+ utils.get_item_properties(s, columns)
+ for s in volume_transfer_result))
diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py
index 73927022..289966e5 100644
--- a/openstackclient/volume/v1/volume_type.py
+++ b/openstackclient/volume/v1/volume_type.py
@@ -15,11 +15,11 @@
"""Volume v1 Type action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -181,5 +181,3 @@ class UnsetVolumeType(command.Command):
if parsed_args.property:
volume_type.unset_keys(parsed_args.property)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v2/backup.py b/openstackclient/volume/v2/backup.py
index e6fbe78d..6a44e30c 100644
--- a/openstackclient/volume/v2/backup.py
+++ b/openstackclient/volume/v2/backup.py
@@ -16,10 +16,10 @@
import copy
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import utils
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index 3cea3303..7ec272b3 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -15,11 +15,11 @@
"""Volume v2 QoS action implementations"""
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -202,8 +202,6 @@ class SetQos(command.Command):
if parsed_args.property:
volume_client.qos_specs.set_keys(qos_spec.id,
parsed_args.property)
- else:
- self.app.log.error(_("No changes requested\n"))
class ShowQos(command.ShowOne):
@@ -263,5 +261,3 @@ class UnsetQos(command.Command):
if parsed_args.property:
volume_client.qos_specs.unset_keys(qos_spec.id,
parsed_args.property)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v2/service.py b/openstackclient/volume/v2/service.py
index 023dda98..2df38573 100644
--- a/openstackclient/volume/v2/service.py
+++ b/openstackclient/volume/v2/service.py
@@ -14,8 +14,9 @@
"""Service action implementations"""
-from openstackclient.common import command
-from openstackclient.common import utils
+from osc_lib.command import command
+from osc_lib import utils
+
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/snapshot.py b/openstackclient/volume/v2/snapshot.py
index 2886aaef..439904e7 100644
--- a/openstackclient/volume/v2/snapshot.py
+++ b/openstackclient/volume/v2/snapshot.py
@@ -16,11 +16,11 @@
import copy
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
@@ -205,11 +205,6 @@ class SetSnapshot(command.Command):
if parsed_args.description:
kwargs['description'] = parsed_args.description
- if (not kwargs and not parsed_args.property and not
- parsed_args.state):
- self.app.log.error(_("No changes requested\n"))
- return
-
if parsed_args.property:
volume_client.volume_snapshots.set_metadata(snapshot.id,
parsed_args.property)
@@ -271,5 +266,3 @@ class UnsetSnapshot(command.Command):
snapshot.id,
parsed_args.property,
)
- else:
- self.app.log.error(_("No changes requested\n"))
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index 0e07aa78..e54395fa 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -15,16 +15,20 @@
"""Volume V2 Volume action implementations"""
import copy
+import logging
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
class CreateVolume(command.ShowOne):
"""Create new volume"""
@@ -361,13 +365,12 @@ class SetVolume(command.Command):
if parsed_args.size:
if volume.status != 'available':
- self.app.log.error(_("Volume is in %s state, it must be "
- "available before size can be extended") %
- volume.status)
+ 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:
- self.app.log.error(_("New size must be greater than %s GB") %
- volume.size)
+ LOG.error(_("New size must be greater than %s GB"),
+ volume.size)
return
volume_client.volumes.extend(volume.id, parsed_args.size)
@@ -385,10 +388,6 @@ class SetVolume(command.Command):
if kwargs:
volume_client.volumes.update(volume.id, **kwargs)
- if (not kwargs and not parsed_args.property
- and not parsed_args.image_property and not parsed_args.size):
- self.app.log.error(_("No changes requested\n"))
-
class ShowVolume(command.ShowOne):
"""Display volume details"""
@@ -460,4 +459,4 @@ class UnsetVolume(command.Command):
volume.id, parsed_args.image_property)
if (not parsed_args.image_property and not parsed_args.property):
- self.app.log.error(_("No changes requested\n"))
+ LOG.error(_("No changes requested"))
diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py
new file mode 100644
index 00000000..5d8ff683
--- /dev/null
+++ b/openstackclient/volume/v2/volume_transfer_request.py
@@ -0,0 +1,51 @@
+#
+# 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 transfer action implementations"""
+
+from osc_lib.command import command
+from osc_lib import utils
+
+from openstackclient.i18n import _
+
+
+class ListTransferRequests(command.Lister):
+ """Lists all volume transfer requests."""
+
+ def get_parser(self, prog_name):
+ parser = super(ListTransferRequests, self).get_parser(prog_name)
+ parser.add_argument(
+ '--all-projects',
+ dest='all_projects',
+ action="store_true",
+ default=False,
+ help=_('Shows detail for all projects. Admin only. '
+ '(defaults to False)')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ columns = ['ID', 'Volume ID', 'Name']
+ column_headers = ['ID', 'Volume', 'Name']
+
+ volume_client = self.app.client_manager.volume
+
+ volume_transfer_result = volume_client.transfers.list(
+ detailed=True,
+ search_opts={'all_tenants': parsed_args.all_projects}
+ )
+
+ return (column_headers, (
+ utils.get_item_properties(s, columns)
+ for s in volume_transfer_result))
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 96f13c83..5e9faa1d 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -14,16 +14,21 @@
"""Volume v2 Type action implementations"""
+import logging
+
+from osc_lib.cli import parseractions
+from osc_lib.command import command
+from osc_lib import exceptions
+from osc_lib import utils
import six
-from openstackclient.common import command
-from openstackclient.common import exceptions
-from openstackclient.common import parseractions
-from openstackclient.common import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
class CreateVolumeType(command.ShowOne):
"""Create new volume type"""
@@ -176,13 +181,6 @@ class SetVolumeType(command.Command):
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
- if (not parsed_args.name
- and not parsed_args.description
- and not parsed_args.property
- and not parsed_args.project):
- self.app.log.error(_("No changes requested\n"))
- return
-
result = 0
kwargs = {}
if parsed_args.name:
@@ -197,16 +195,15 @@ class SetVolumeType(command.Command):
**kwargs
)
except Exception as e:
- self.app.log.error(_("Failed to update volume type name or"
- " description: %s") % str(e))
+ LOG.error(_("Failed to update volume type name or"
+ " description: %s"), e)
result += 1
if parsed_args.property:
try:
volume_type.set_keys(parsed_args.property)
except Exception as e:
- self.app.log.error(_("Failed to set volume type property: ") +
- str(e))
+ LOG.error(_("Failed to set volume type property: %s"), e)
result += 1
if parsed_args.project:
@@ -220,13 +217,13 @@ class SetVolumeType(command.Command):
volume_client.volume_type_access.add_project_access(
volume_type.id, project_info.id)
except Exception as e:
- self.app.log.error(_("Failed to set volume type access to"
- " project: %s") % str(e))
+ LOG.error(_("Failed to set volume type access to "
+ "project: %s"), e)
result += 1
if result > 0:
raise exceptions.CommandError(_("Command Failed: One or more of"
- " the operations failed"))
+ " the operations failed"))
class ShowVolumeType(command.ShowOne):
@@ -263,6 +260,7 @@ class UnsetVolumeType(command.Command):
parser.add_argument(
'--property',
metavar='<key>',
+ action='append',
help=_('Remove a property from this volume type '
'(repeat option to remove multiple properties)'),
)
@@ -285,18 +283,12 @@ class UnsetVolumeType(command.Command):
parsed_args.volume_type,
)
- if (not parsed_args.property
- and not parsed_args.project):
- self.app.log.error(_("No changes requested\n"))
- return
-
result = 0
if parsed_args.property:
try:
volume_type.unset_keys(parsed_args.property)
except Exception as e:
- self.app.log.error(_("Failed to unset volume type property: %s"
- ) % str(e))
+ LOG.error(_("Failed to unset volume type property: %s"), e)
result += 1
if parsed_args.project:
@@ -310,8 +302,8 @@ class UnsetVolumeType(command.Command):
volume_client.volume_type_access.remove_project_access(
volume_type.id, project_info.id)
except Exception as e:
- self.app.log.error(_("Failed to remove volume type access from"
- " project: %s") % str(e))
+ LOG.error(_("Failed to remove volume type access from "
+ "project: %s"), e)
result += 1
if result > 0: