summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/api/api.py22
-rw-r--r--openstackclient/api/auth.py18
-rw-r--r--openstackclient/api/auth_plugin.py6
-rw-r--r--openstackclient/common/command.py46
-rw-r--r--openstackclient/common/timing.py32
-rw-r--r--openstackclient/compute/client.py2
-rw-r--r--openstackclient/compute/v2/host.py2
-rw-r--r--openstackclient/compute/v2/hypervisor.py2
-rw-r--r--openstackclient/compute/v2/server.py74
-rw-r--r--openstackclient/compute/v2/server_image.py111
-rw-r--r--openstackclient/compute/v2/service.py71
-rw-r--r--openstackclient/identity/v2_0/endpoint.py4
-rw-r--r--openstackclient/identity/v3/endpoint.py8
-rw-r--r--openstackclient/image/v2/image.py24
-rw-r--r--openstackclient/network/client.py1
-rw-r--r--openstackclient/network/v2/floating_ip.py18
-rw-r--r--openstackclient/network/v2/ip_availability.py6
-rw-r--r--openstackclient/network/v2/network.py8
-rw-r--r--openstackclient/network/v2/security_group.py18
-rw-r--r--openstackclient/network/v2/security_group_rule.py16
-rw-r--r--openstackclient/network/v2/subnet.py28
-rw-r--r--openstackclient/network/v2/subnet_pool.py30
-rw-r--r--openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml6
-rw-r--r--openstackclient/shell.py45
-rw-r--r--openstackclient/tests/common/test_command.py2
-rw-r--r--openstackclient/tests/common/test_timing.py94
-rw-r--r--openstackclient/tests/compute/v2/fakes.py19
-rw-r--r--openstackclient/tests/compute/v2/test_flavor.py29
-rw-r--r--openstackclient/tests/compute/v2/test_server.py144
-rw-r--r--openstackclient/tests/compute/v2/test_server_image.py227
-rw-r--r--openstackclient/tests/compute/v2/test_service.py102
-rw-r--r--openstackclient/tests/image/v2/test_image.py31
-rw-r--r--openstackclient/tests/network/v2/fakes.py77
-rw-r--r--openstackclient/tests/network/v2/test_floating_ip.py131
-rw-r--r--openstackclient/tests/network/v2/test_ip_availability.py7
-rw-r--r--openstackclient/tests/network/v2/test_security_group.py139
-rw-r--r--openstackclient/tests/network/v2/test_security_group_rule.py127
-rw-r--r--openstackclient/tests/network/v2/test_subnet.py66
-rw-r--r--openstackclient/tests/network/v2/test_subnet_pool.py67
-rw-r--r--openstackclient/tests/test_shell.py2
-rw-r--r--openstackclient/tests/volume/v1/test_volume.py19
-rw-r--r--openstackclient/volume/client.py2
-rw-r--r--openstackclient/volume/v1/snapshot.py2
-rw-r--r--openstackclient/volume/v1/volume.py13
-rw-r--r--openstackclient/volume/v2/volume.py15
-rw-r--r--openstackclient/volume/v2/volume_type.py25
46 files changed, 1348 insertions, 590 deletions
diff --git a/openstackclient/api/api.py b/openstackclient/api/api.py
index 0b00ff50..04d88f31 100644
--- a/openstackclient/api/api.py
+++ b/openstackclient/api/api.py
@@ -19,6 +19,8 @@ from keystoneauth1 import exceptions as ks_exceptions
from keystoneauth1 import session as ks_session
from osc_lib import exceptions
+from openstackclient.i18n import _
+
class KeystoneSession(object):
"""Wrapper for the Keystone Session
@@ -254,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
@@ -264,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,
@@ -313,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]
@@ -343,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 a55af293..b56035e4 100644
--- a/openstackclient/api/auth.py
+++ b/openstackclient/api/auth.py
@@ -171,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):
@@ -187,10 +188,9 @@ def build_auth_plugins_option_parser(parser):
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
@@ -215,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 44d3b38e..36dc5160 100644
--- a/openstackclient/api/auth_plugin.py
+++ b/openstackclient/api/auth_plugin.py
@@ -21,6 +21,8 @@ from six.moves.urllib import parse as urlparse
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__)
@@ -51,10 +53,10 @@ class TokenEndpoint(token_endpoint.AdminToken):
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
diff --git a/openstackclient/common/command.py b/openstackclient/common/command.py
index adf984fa..29c1534d 100644
--- a/openstackclient/common/command.py
+++ b/openstackclient/common/command.py
@@ -12,45 +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
-from osc_lib import exceptions
-import six
+import sys
-from openstackclient.i18n import _
+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)
-
- def validate_os_beta_command_enabled(self):
- if not self.app.options.os_beta_command:
- msg = _('Caution: This is a beta command and subject to '
- 'change. Use global option --os-beta-command '
- 'to enable this command.')
- raise exceptions.CommandError(msg)
-
-
-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/timing.py b/openstackclient/common/timing.py
index dd2aeb83..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 osc_lib.command 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/compute/client.py b/openstackclient/compute/client.py
index a83700db..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
diff --git a/openstackclient/compute/v2/host.py b/openstackclient/compute/v2/host.py
index 620b4abb..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
diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py
index a34f2e1d..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
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index eb954c36..42736d66 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -164,23 +164,6 @@ def _prep_server_detail(compute_client, server):
return info
-def _prep_image_detail(image_client, image_id):
- """Prepare the detailed image dict for printing
-
- :param image_client: an image client instance
- :param image_id: id of image created
- :rtype: a dict of image details
- """
-
- info = utils.find_resource(
- image_client.images,
- image_id,
- )
- # Glance client V2 doesn't have _info attribute
- # The following condition deals with it.
- return getattr(info, "_info", info)
-
-
def _show_progress(progress):
if progress:
sys.stdout.write('\rProgress: %s' % progress)
@@ -597,63 +580,6 @@ class CreateServerDump(command.Command):
).trigger_crash_dump()
-class CreateServerImage(command.ShowOne):
- """Create a new disk image from a running server"""
-
- def get_parser(self, prog_name):
- parser = super(CreateServerImage, self).get_parser(prog_name)
- parser.add_argument(
- 'server',
- metavar='<server>',
- help=_('Server (name or ID)'),
- )
- parser.add_argument(
- '--name',
- metavar='<image-name>',
- help=_('Name of new image (default is server name)'),
- )
- parser.add_argument(
- '--wait',
- action='store_true',
- help=_('Wait for image create to complete'),
- )
- return parser
-
- def take_action(self, parsed_args):
- compute_client = self.app.client_manager.compute
- image_client = self.app.client_manager.image
- server = utils.find_resource(
- compute_client.servers,
- parsed_args.server,
- )
- if parsed_args.name:
- name = parsed_args.name
- else:
- name = server.name
-
- image_id = compute_client.servers.create_image(
- server,
- name,
- )
-
- if parsed_args.wait:
- if utils.wait_for_status(
- image_client.images.get,
- image_id,
- callback=_show_progress,
- ):
- sys.stdout.write('\n')
- else:
- self.log.error(_('Error creating snapshot of server: %s'),
- parsed_args.server)
- sys.stdout.write(_('Error creating server snapshot\n'))
- raise SystemExit
-
- image = _prep_image_detail(image_client, image_id)
-
- return zip(*sorted(six.iteritems(image)))
-
-
class DeleteServer(command.Command):
"""Delete server(s)"""
diff --git a/openstackclient/compute/v2/server_image.py b/openstackclient/compute/v2/server_image.py
new file mode 100644
index 00000000..85ee7f2d
--- /dev/null
+++ b/openstackclient/compute/v2/server_image.py
@@ -0,0 +1,111 @@
+# 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
+#
+# 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.
+#
+
+"""Compute v2 Server action implementations"""
+
+import sys
+
+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 _
+
+
+def _show_progress(progress):
+ if progress:
+ sys.stdout.write('\rProgress: %s' % progress)
+ sys.stdout.flush()
+
+
+class CreateServerImage(command.ShowOne):
+ """Create a new server disk image from an existing server"""
+
+ IMAGE_API_VERSIONS = {
+ "1": "openstackclient.image.v1.image",
+ "2": "openstackclient.image.v2.image",
+ }
+
+ def get_parser(self, prog_name):
+ parser = super(CreateServerImage, self).get_parser(prog_name)
+ parser.add_argument(
+ 'server',
+ metavar='<server>',
+ help=_('Server to create image (name or ID)'),
+ )
+ parser.add_argument(
+ '--name',
+ metavar='<image-name>',
+ help=_('Name of new disk image (default: server name)'),
+ )
+ parser.add_argument(
+ '--wait',
+ action='store_true',
+ help=_('Wait for operation to complete'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ compute_client = self.app.client_manager.compute
+
+ server = utils.find_resource(
+ compute_client.servers,
+ parsed_args.server,
+ )
+ if parsed_args.name:
+ image_name = parsed_args.name
+ else:
+ image_name = server.name
+
+ image_id = compute_client.servers.create_image(
+ server.id,
+ image_name,
+ )
+
+ image_client = self.app.client_manager.image
+ image = utils.find_resource(
+ image_client.images,
+ image_id,
+ )
+
+ if parsed_args.wait:
+ if utils.wait_for_status(
+ image_client.images.get,
+ image_id,
+ callback=_show_progress,
+ ):
+ sys.stdout.write('\n')
+ else:
+ self.log.error(
+ _('Error creating server image: %s') %
+ parsed_args.server,
+ )
+ raise exceptions.CommandError
+
+ if self.app.client_manager._api_version['image'] == '1':
+ info = {}
+ info.update(image._info)
+ info['properties'] = utils.format_dict(info.get('properties', {}))
+ else:
+ # Get the right image module to format the output
+ image_module = importutils.import_module(
+ self.IMAGE_API_VERSIONS[
+ self.app.client_manager._api_version['image']
+ ]
+ )
+ info = image_module._format_image(image)
+ return zip(*sorted(six.iteritems(info)))
diff --git a/openstackclient/compute/v2/service.py b/openstackclient/compute/v2/service.py
index 30465783..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
@@ -20,6 +20,7 @@ from osc_lib import exceptions
from osc_lib import utils
from openstackclient.i18n import _
+from openstackclient.i18n import _LE
class DeleteService(command.Command):
@@ -127,6 +128,17 @@ class SetService(command.Command):
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
def take_action(self, parsed_args):
@@ -139,20 +151,45 @@ class SetService(command.Command):
"--disable specified.")
raise exceptions.CommandError(msg)
+ result = 0
enabled = None
- if parsed_args.enable:
- enabled = True
- if parsed_args.disable:
- enabled = False
-
- if enabled is None:
- return
- elif 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)
+ 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/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py
index 4ffa363e..ee2bab6f 100644
--- a/openstackclient/identity/v2_0/endpoint.py
+++ b/openstackclient/identity/v2_0/endpoint.py
@@ -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,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
diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py
index 367b4e7b..2f1cc9f3 100644
--- a/openstackclient/identity/v3/endpoint.py
+++ b/openstackclient/identity/v3/endpoint.py
@@ -40,7 +40,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(
'interface',
@@ -102,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
@@ -121,7 +121,7 @@ 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',
@@ -169,7 +169,7 @@ 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',
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 47ba6493..53f9530b 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -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):
diff --git a/openstackclient/network/client.py b/openstackclient/network/client.py
index c81b7d87..d12987dd 100644
--- a/openstackclient/network/client.py
+++ b/openstackclient/network/client.py
@@ -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/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py
index c734c2ed..8fbf049e 100644
--- a/openstackclient/network/v2/floating_ip.py
+++ b/openstackclient/network/v2/floating_ip.py
@@ -110,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
index d429e86c..1d7b2aed 100644
--- a/openstackclient/network/v2/ip_availability.py
+++ b/openstackclient/network/v2/ip_availability.py
@@ -41,15 +41,17 @@ class ListIPAvailability(command.Lister):
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"),
+ 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"),
+ help=_("List IP availability of given project (name or ID)"),
)
identity_common.add_project_domain_option_to_parser(parser)
return parser
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 4d01accd..41735500 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -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(
diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py
index 95971800..f832f721 100644
--- a/openstackclient/network/v2/security_group.py
+++ b/openstackclient/network/v2/security_group.py
@@ -164,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 7c810786..18863223 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -333,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 ceb1cb14..a2e32622 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -14,6 +14,7 @@
"""Subnet action implementations"""
import copy
+import logging
from osc_lib.cli import parseractions
from osc_lib.command import command
@@ -24,6 +25,9 @@ from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
def _format_allocation_pools(data):
pool_formatted = ['%s-%s' % (pool.get('start', ''), pool.get('end', ''))
for pool in data]
@@ -270,21 +274,37 @@ class CreateSubnet(command.ShowOne):
class DeleteSubnet(command.Command):
- """Delete subnet"""
+ """Delete subnet(s)"""
def get_parser(self, prog_name):
parser = super(DeleteSubnet, self).get_parser(prog_name)
parser.add_argument(
'subnet',
metavar="<subnet>",
- help=_("Subnet to delete (name or ID)")
+ nargs='+',
+ help=_("Subnet(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
- client.delete_subnet(
- client.find_subnet(parsed_args.subnet))
+ result = 0
+
+ for subnet in parsed_args.subnet:
+ try:
+ obj = client.find_subnet(subnet, ignore_missing=False)
+ client.delete_subnet(obj)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete subnet with "
+ "name or ID '%(subnet)s': %(e)s")
+ % {'subnet': subnet, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.subnet)
+ msg = (_("%(result)s of %(total)s subnets failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListSubnet(command.Lister):
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index 79f98fd9..55dfed83 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -13,14 +13,20 @@
"""Subnet pool 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
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
def _get_columns(item):
columns = list(item.keys())
if 'tenant_id' in columns:
@@ -176,21 +182,37 @@ class CreateSubnetPool(command.ShowOne):
class DeleteSubnetPool(command.Command):
- """Delete subnet pool"""
+ """Delete subnet pool(s)"""
def get_parser(self, prog_name):
parser = super(DeleteSubnetPool, self).get_parser(prog_name)
parser.add_argument(
'subnet_pool',
metavar='<subnet-pool>',
- help=_("Subnet pool to delete (name or ID)")
+ nargs='+',
+ help=_("Subnet pool(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
- obj = client.find_subnet_pool(parsed_args.subnet_pool)
- client.delete_subnet_pool(obj)
+ result = 0
+
+ for pool in parsed_args.subnet_pool:
+ try:
+ obj = client.find_subnet_pool(pool, ignore_missing=False)
+ client.delete_subnet_pool(obj)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete subnet pool with "
+ "name or ID '%(pool)s': %(e)s")
+ % {'pool': pool, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.subnet_pool)
+ msg = (_("%(result)s of %(total)s subnet pools failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListSubnetPool(command.Lister):
diff --git a/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml b/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml
deleted file mode 100644
index c783d013..00000000
--- a/openstackclient/releasenotes/notes/bug-1543222-6f8579344ff5c958.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-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 3e899cb5..12a63af2 100644
--- a/openstackclient/shell.py
+++ b/openstackclient/shell.py
@@ -26,6 +26,7 @@ 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
@@ -35,7 +36,7 @@ from oslo_utils import strutils
import openstackclient
from openstackclient.common import clientmanager
from openstackclient.common import commandmanager
-from openstackclient.common import timing
+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(
'--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/common/test_command.py b/openstackclient/tests/common/test_command.py
index a8bcf6a8..658bc895 100644
--- a/openstackclient/tests/common/test_command.py
+++ b/openstackclient/tests/common/test_command.py
@@ -14,9 +14,9 @@
import mock
-from osc_lib.command import command
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
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/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py
index 9682eec4..60abb8ef 100644
--- a/openstackclient/tests/compute/v2/fakes.py
+++ b/openstackclient/tests/compute/v2/fakes.py
@@ -452,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_flavor.py b/openstackclient/tests/compute/v2/test_flavor.py
index 27b53bbf..4365a540 100644
--- a/openstackclient/tests/compute/v2/test_flavor.py
+++ b/openstackclient/tests/compute/v2/test_flavor.py
@@ -469,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):
@@ -483,12 +484,15 @@ 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 = [
@@ -496,7 +500,7 @@ class TestFlavorSet(TestFlavor):
self.flavor.id,
]
verifylist = [
- ('project', ''),
+ ('project', None),
('flavor', self.flavor.id),
]
self.assertRaises(tests_utils.ParserException, self.check_parser,
@@ -509,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)
@@ -541,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)
@@ -672,6 +671,18 @@ class TestFlavorUnset(TestFlavor):
self.flavor.unset_keys.assert_not_called()
self.assertIsNone(result)
+ def test_flavor_unset_no_project(self):
+ arglist = [
+ '--project',
+ self.flavor.id,
+ ]
+ verifylist = [
+ ('project', None),
+ ('flavor', self.flavor.id),
+ ]
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
def test_flavor_unset_no_flavor(self):
arglist = [
'--project', identity_fakes.project_id,
diff --git a/openstackclient/tests/compute/v2/test_server.py b/openstackclient/tests/compute/v2/test_server.py
index e10f43a1..0f155601 100644
--- a/openstackclient/tests/compute/v2/test_server.py
+++ b/openstackclient/tests/compute/v2/test_server.py
@@ -511,150 +511,6 @@ class TestServerDumpCreate(TestServer):
self.run_method_with_servers('trigger_crash_dump', 3)
-class TestServerImageCreate(TestServer):
-
- columns = (
- 'id',
- 'name',
- 'owner',
- 'protected',
- 'tags',
- 'visibility',
- )
-
- def datalist(self):
- datalist = (
- self.image.id,
- self.image.name,
- self.image.owner,
- self.image.protected,
- self.image.tags,
- self.image.visibility,
- )
- return datalist
-
- def setUp(self):
- super(TestServerImageCreate, self).setUp()
-
- self.server = compute_fakes.FakeServer.create_one_server()
-
- # This is the return value for utils.find_resource()
- self.servers_mock.get.return_value = self.server
-
- self.image = image_fakes.FakeImage.create_one_image()
- self.images_mock.get.return_value = self.image
- self.servers_mock.create_image.return_value = self.image.id
-
- # Get the command object to test
- self.cmd = server.CreateServerImage(self.app, None)
-
- def test_server_image_create_no_options(self):
- arglist = [
- self.server.id,
- ]
- verifylist = [
- ('server', self.server.id),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- # 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)
-
- # ServerManager.create_image(server, image_name, metadata=)
- self.servers_mock.create_image.assert_called_with(
- self.servers_mock.get.return_value,
- self.server.name,
- )
-
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist(), data)
-
- def test_server_image_create_name(self):
- arglist = [
- '--name', 'img-nam',
- self.server.id,
- ]
- verifylist = [
- ('name', 'img-nam'),
- ('server', self.server.id),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- # 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)
-
- # ServerManager.create_image(server, image_name, metadata=)
- self.servers_mock.create_image.assert_called_with(
- self.servers_mock.get.return_value,
- 'img-nam',
- )
-
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist(), data)
-
- @mock.patch.object(common_utils, 'wait_for_status', return_value=False)
- def test_server_create_image_with_wait_fails(self, mock_wait_for_status):
- arglist = [
- '--wait',
- self.server.id,
- ]
- verifylist = [
- ('wait', True),
- ('server', self.server.id),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- self.assertRaises(SystemExit, self.cmd.take_action, parsed_args)
-
- mock_wait_for_status.assert_called_once_with(
- self.images_mock.get,
- self.image.id,
- callback=server._show_progress
- )
-
- # ServerManager.create_image(server, image_name, metadata=)
- self.servers_mock.create_image.assert_called_with(
- self.servers_mock.get.return_value,
- self.server.name,
- )
-
- @mock.patch.object(common_utils, 'wait_for_status', return_value=True)
- def test_server_create_image_with_wait_ok(self, mock_wait_for_status):
- arglist = [
- '--wait',
- self.server.id,
- ]
- verifylist = [
- ('wait', True),
- ('server', self.server.id),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- # 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)
-
- # ServerManager.create_image(server, image_name, metadata=)
- self.servers_mock.create_image.assert_called_with(
- self.servers_mock.get.return_value,
- self.server.name,
- )
-
- mock_wait_for_status.assert_called_once_with(
- self.images_mock.get,
- self.image.id,
- callback=server._show_progress
- )
-
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist(), data)
-
-
class TestServerList(TestServer):
# Columns to be listed up.
diff --git a/openstackclient/tests/compute/v2/test_server_image.py b/openstackclient/tests/compute/v2/test_server_image.py
new file mode 100644
index 00000000..660e9817
--- /dev/null
+++ b/openstackclient/tests/compute/v2/test_server_image.py
@@ -0,0 +1,227 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+import mock
+
+from openstackclient.common import exceptions
+from openstackclient.common import utils as common_utils
+from openstackclient.compute.v2 import server_image
+from openstackclient.tests.compute.v2 import fakes as compute_fakes
+from openstackclient.tests.image.v2 import fakes as image_fakes
+
+
+class TestServerImage(compute_fakes.TestComputev2):
+
+ def setUp(self):
+ super(TestServerImage, self).setUp()
+
+ # Get a shortcut to the compute client ServerManager Mock
+ self.servers_mock = self.app.client_manager.compute.servers
+ self.servers_mock.reset_mock()
+
+ # Get a shortcut to the image client ImageManager Mock
+ self.images_mock = self.app.client_manager.image.images
+ self.images_mock.reset_mock()
+
+ # Set object attributes to be tested. Could be overwriten in subclass.
+ self.attrs = {}
+
+ # Set object methods to be tested. Could be overwriten in subclass.
+ self.methods = {}
+
+ def setup_servers_mock(self, count):
+ servers = compute_fakes.FakeServer.create_servers(
+ attrs=self.attrs,
+ methods=self.methods,
+ count=count,
+ )
+
+ # This is the return value for utils.find_resource()
+ self.servers_mock.get = compute_fakes.FakeServer.get_servers(
+ servers,
+ 0,
+ )
+ return servers
+
+
+class TestServerImageCreate(TestServerImage):
+
+ def image_columns(self, image):
+ columnlist = tuple(sorted(image.keys()))
+ return columnlist
+
+ def image_data(self, image):
+ datalist = (
+ image['id'],
+ image['name'],
+ image['owner'],
+ image['protected'],
+ 'active',
+ common_utils.format_list(image.get('tags')),
+ image['visibility'],
+ )
+ return datalist
+
+ def setUp(self):
+ super(TestServerImageCreate, self).setUp()
+
+ # Get the command object to test
+ self.cmd = server_image.CreateServerImage(self.app, None)
+
+ self.methods = {
+ 'create_image': None,
+ }
+
+ def setup_images_mock(self, count, servers=None):
+ if servers:
+ images = image_fakes.FakeImage.create_images(
+ attrs={
+ 'name': servers[0].name,
+ 'status': 'active',
+ },
+ count=count,
+ )
+ else:
+ images = image_fakes.FakeImage.create_images(
+ attrs={
+ 'status': 'active',
+ },
+ count=count,
+ )
+
+ self.images_mock.get = mock.MagicMock(side_effect=images)
+ self.servers_mock.create_image = mock.MagicMock(
+ return_value=images[0].id,
+ )
+ return images
+
+ def test_server_image_create_defaults(self):
+ servers = self.setup_servers_mock(count=1)
+ images = self.setup_images_mock(count=1, servers=servers)
+
+ arglist = [
+ servers[0].id,
+ ]
+ verifylist = [
+ ('server', servers[0].id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # 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)
+
+ # ServerManager.create_image(server, image_name, metadata=)
+ self.servers_mock.create_image.assert_called_with(
+ servers[0].id,
+ servers[0].name,
+ )
+
+ self.assertEqual(self.image_columns(images[0]), columns)
+ self.assertEqual(self.image_data(images[0]), data)
+
+ def test_server_image_create_options(self):
+ servers = self.setup_servers_mock(count=1)
+ images = self.setup_images_mock(count=1, servers=servers)
+
+ arglist = [
+ '--name', 'img-nam',
+ servers[0].id,
+ ]
+ verifylist = [
+ ('name', 'img-nam'),
+ ('server', servers[0].id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # 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)
+
+ # ServerManager.create_image(server, image_name, metadata=)
+ self.servers_mock.create_image.assert_called_with(
+ servers[0].id,
+ 'img-nam',
+ )
+
+ self.assertEqual(self.image_columns(images[0]), columns)
+ self.assertEqual(self.image_data(images[0]), data)
+
+ @mock.patch.object(common_utils, 'wait_for_status', return_value=False)
+ def test_server_create_image_wait_fail(self, mock_wait_for_status):
+ servers = self.setup_servers_mock(count=1)
+ images = self.setup_images_mock(count=1, servers=servers)
+
+ arglist = [
+ '--wait',
+ servers[0].id,
+ ]
+ verifylist = [
+ ('wait', True),
+ ('server', servers[0].id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
+ # ServerManager.create_image(server, image_name, metadata=)
+ self.servers_mock.create_image.assert_called_with(
+ servers[0].id,
+ servers[0].name,
+ )
+
+ mock_wait_for_status.assert_called_once_with(
+ self.images_mock.get,
+ images[0].id,
+ callback=mock.ANY
+ )
+
+ @mock.patch.object(common_utils, 'wait_for_status', return_value=True)
+ def test_server_create_image_wait_ok(self, mock_wait_for_status):
+ servers = self.setup_servers_mock(count=1)
+ images = self.setup_images_mock(count=1, servers=servers)
+
+ arglist = [
+ '--wait',
+ servers[0].id,
+ ]
+ verifylist = [
+ ('wait', True),
+ ('server', servers[0].id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # 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)
+
+ # ServerManager.create_image(server, image_name, metadata=)
+ self.servers_mock.create_image.assert_called_with(
+ servers[0].id,
+ servers[0].name,
+ )
+
+ mock_wait_for_status.assert_called_once_with(
+ self.images_mock.get,
+ images[0].id,
+ callback=mock.ANY
+ )
+
+ self.assertEqual(self.image_columns(images[0]), columns)
+ self.assertEqual(self.image_data(images[0]), data)
diff --git a/openstackclient/tests/compute/v2/test_service.py b/openstackclient/tests/compute/v2/test_service.py
index 3f741340..b360c9dc 100644
--- a/openstackclient/tests/compute/v2/test_service.py
+++ b/openstackclient/tests/compute/v2/test_service.py
@@ -13,6 +13,8 @@
# under the License.
#
+import mock
+
from osc_lib import exceptions
from openstackclient.compute.v2 import service
@@ -225,8 +227,12 @@ class TestServiceSet(TestService):
('service', self.service.binary),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ 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'
@@ -243,5 +249,93 @@ class TestServiceSet(TestService):
('service', self.service.binary),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.assertRaises(exceptions.CommandError, self.cmd.take_action,
- parsed_args)
+ 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)
+
+ 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)
+
+ def test_service_set_enable_and_state_down(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)
+ 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/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py
index 3dbf504a..592def21 100644
--- a/openstackclient/tests/image/v2/test_image.py
+++ b/openstackclient/tests/image/v2/test_image.py
@@ -474,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):
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index 9efbe8c6..a23efc2d 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -611,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."""
@@ -670,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."""
@@ -732,6 +771,25 @@ class FakeSubnet(object):
return subnets
+ @staticmethod
+ def get_subnets(subnets=None, count=2):
+ """Get an iterable MagicMock object with a list of faked subnets.
+
+ If subnets list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List subnets:
+ A list of FakeResource objects faking subnets
+ :param int count:
+ The number of subnets to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ subnets
+ """
+ if subnets is None:
+ subnets = FakeSubnet.create_subnets(count)
+ return mock.MagicMock(side_effect=subnets)
+
class FakeFloatingIP(object):
"""Fake one or more floating ip."""
@@ -871,3 +929,22 @@ class FakeSubnetPool(object):
)
return subnet_pools
+
+ @staticmethod
+ def get_subnet_pools(subnet_pools=None, count=2):
+ """Get an iterable MagicMock object with a list of faked subnet pools.
+
+ If subnet_pools list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List subnet pools:
+ A list of FakeResource objects faking subnet pools
+ :param int count:
+ The number of subnet pools to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ subnet pools
+ """
+ if subnet_pools is None:
+ subnet_pools = FakeSubnetPool.create_subnet_pools(count)
+ return mock.MagicMock(side_effect=subnet_pools)
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
index 39e11cd5..c6ec2b0b 100644
--- a/openstackclient/tests/network/v2/test_ip_availability.py
+++ b/openstackclient/tests/network/v2/test_ip_availability.py
@@ -82,8 +82,10 @@ class TestListIPAvailability(TestIPAvailability):
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()
+ self.network.network_ip_availabilities.assert_called_once_with(
+ **filters)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
@@ -116,7 +118,8 @@ class TestListIPAvailability(TestIPAvailability):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- filters = {'tenant_id': identity_fakes.project_id}
+ filters = {'tenant_id': identity_fakes.project_id,
+ 'ip_version': 4}
self.network.network_ip_availabilities.assert_called_once_with(
**filters)
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 b1f2209d..b2862679 100644
--- a/openstackclient/tests/network/v2/test_security_group_rule.py
+++ b/openstackclient/tests/network/v2/test_security_group_rule.py
@@ -13,6 +13,7 @@
import copy
import mock
+from mock import call
from osc_lib import exceptions
@@ -668,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(
@@ -686,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()
@@ -716,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 de7e1821..a57a0308 100644
--- a/openstackclient/tests/network/v2/test_subnet.py
+++ b/openstackclient/tests/network/v2/test_subnet.py
@@ -13,7 +13,9 @@
import copy
import mock
+from mock import call
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.network.v2 import subnet as subnet_v2
@@ -361,32 +363,82 @@ class TestCreateSubnet(TestSubnet):
class TestDeleteSubnet(TestSubnet):
- # The subnet to delete.
- _subnet = network_fakes.FakeSubnet.create_one_subnet()
+ # The subnets to delete.
+ _subnets = network_fakes.FakeSubnet.create_subnets(count=2)
def setUp(self):
super(TestDeleteSubnet, self).setUp()
self.network.delete_subnet = mock.Mock(return_value=None)
- self.network.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network.find_subnet = (
+ network_fakes.FakeSubnet.get_subnets(self._subnets))
# Get the command object to test
self.cmd = subnet_v2.DeleteSubnet(self.app, self.namespace)
- def test_delete(self):
+ def test_subnet_delete(self):
arglist = [
- self._subnet.name,
+ self._subnets[0].name,
]
verifylist = [
- ('subnet', self._subnet.name),
+ ('subnet', [self._subnets[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.network.delete_subnet.assert_called_once_with(self._subnet)
+ self.network.delete_subnet.assert_called_once_with(self._subnets[0])
self.assertIsNone(result)
+ def test_multi_subnets_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._subnets:
+ arglist.append(s.name)
+ verifylist = [
+ ('subnet', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._subnets:
+ calls.append(call(s))
+ self.network.delete_subnet.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_subnets_delete_with_exception(self):
+ arglist = [
+ self._subnets[0].name,
+ 'unexist_subnet',
+ ]
+ verifylist = [
+ ('subnet',
+ [self._subnets[0].name, 'unexist_subnet']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._subnets[0], exceptions.CommandError]
+ self.network.find_subnet = (
+ 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 subnets failed to delete.', str(e))
+
+ self.network.find_subnet.assert_any_call(
+ self._subnets[0].name, ignore_missing=False)
+ self.network.find_subnet.assert_any_call(
+ 'unexist_subnet', ignore_missing=False)
+ self.network.delete_subnet.assert_called_once_with(
+ self._subnets[0]
+ )
+
class TestListSubnet(TestSubnet):
# The subnets going to be listed up.
diff --git a/openstackclient/tests/network/v2/test_subnet_pool.py b/openstackclient/tests/network/v2/test_subnet_pool.py
index 10ef76d8..7a96b30f 100644
--- a/openstackclient/tests/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/network/v2/test_subnet_pool.py
@@ -14,7 +14,9 @@
import argparse
import copy
import mock
+from mock import call
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.network.v2 import subnet_pool
@@ -263,36 +265,85 @@ class TestCreateSubnetPool(TestSubnetPool):
class TestDeleteSubnetPool(TestSubnetPool):
- # The subnet pool to delete.
- _subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
+ # The subnet pools to delete.
+ _subnet_pools = network_fakes.FakeSubnetPool.create_subnet_pools(count=2)
def setUp(self):
super(TestDeleteSubnetPool, self).setUp()
self.network.delete_subnet_pool = mock.Mock(return_value=None)
- self.network.find_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
+ self.network.find_subnet_pool = (
+ network_fakes.FakeSubnetPool.get_subnet_pools(self._subnet_pools)
)
# Get the command object to test
self.cmd = subnet_pool.DeleteSubnetPool(self.app, self.namespace)
- def test_delete(self):
+ def test_subnet_pool_delete(self):
arglist = [
- self._subnet_pool.name,
+ self._subnet_pools[0].name,
]
verifylist = [
- ('subnet_pool', self._subnet_pool.name),
+ ('subnet_pool', [self._subnet_pools[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.delete_subnet_pool.assert_called_once_with(
- self._subnet_pool)
+ self._subnet_pools[0])
+ self.assertIsNone(result)
+
+ def test_multi_subnet_pools_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._subnet_pools:
+ arglist.append(s.name)
+ verifylist = [
+ ('subnet_pool', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._subnet_pools:
+ calls.append(call(s))
+ self.network.delete_subnet_pool.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_multi_subnet_pools_delete_with_exception(self):
+ arglist = [
+ self._subnet_pools[0].name,
+ 'unexist_subnet_pool',
+ ]
+ verifylist = [
+ ('subnet_pool',
+ [self._subnet_pools[0].name, 'unexist_subnet_pool']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._subnet_pools[0], exceptions.CommandError]
+ self.network.find_subnet_pool = (
+ 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 subnet pools failed to delete.', str(e))
+
+ self.network.find_subnet_pool.assert_any_call(
+ self._subnet_pools[0].name, ignore_missing=False)
+ self.network.find_subnet_pool.assert_any_call(
+ 'unexist_subnet_pool', ignore_missing=False)
+ self.network.delete_subnet_pool.assert_called_once_with(
+ self._subnet_pools[0]
+ )
+
class TestListSubnetPool(TestSubnetPool):
# The subnet pools going to be listed up.
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/v1/test_volume.py b/openstackclient/tests/volume/v1/test_volume.py
index e4f51bb5..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
@@ -656,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,
@@ -672,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',
@@ -694,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/volume/client.py b/openstackclient/volume/client.py
index cc195460..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
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py
index 41127af5..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
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index 7a3bfb97..e11aa1a7 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -16,6 +16,7 @@
"""Volume v1 Volume action implementations"""
import argparse
+import logging
from osc_lib.cli import parseractions
from osc_lib.command import command
@@ -25,6 +26,9 @@ import six
from openstackclient.i18n import _
+LOG = logging.getLogger(__name__)
+
+
class CreateVolume(command.ShowOne):
"""Create new volume"""
@@ -343,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)
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index b1a3af2e..e54395fa 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -15,6 +15,7 @@
"""Volume V2 Volume action implementations"""
import copy
+import logging
from osc_lib.cli import parseractions
from osc_lib.command import command
@@ -25,6 +26,9 @@ 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)
@@ -456,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_type.py b/openstackclient/volume/v2/volume_type.py
index dc6b4f9b..5e9faa1d 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -14,6 +14,8 @@
"""Volume v2 Type action implementations"""
+import logging
+
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -24,6 +26,9 @@ from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
class CreateVolumeType(command.ShowOne):
"""Create new volume type"""
@@ -190,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: %s") % str(e))
+ LOG.error(_("Failed to set volume type property: %s"), e)
result += 1
if parsed_args.project:
@@ -213,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):
@@ -284,8 +288,7 @@ class UnsetVolumeType(command.Command):
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:
@@ -299,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: