Cleanup manilaclient.utils module (part 1)

First part of manilaclient.utils module cleanup,
where usage of deleted functions replaced with functions
from common code.

Partially implements: blueprint use-common-code

Change-Id: Iefe7da601cdaf030787c6d7588dd0c1706e309cd
This commit is contained in:
vponomaryov 2014-07-15 15:04:31 +03:00 committed by Valeriy Ponomaryov
parent 1cc313e5cf
commit b11f5d78a2
6 changed files with 47 additions and 297 deletions

View File

@ -41,9 +41,9 @@ if not hasattr(urlparse, 'parse_qsl'):
import requests
from manilaclient import exceptions
from manilaclient.openstack.common import importutils
from manilaclient.openstack.common import jsonutils
from manilaclient import service_catalog
from manilaclient import utils
class HTTPClient(object):
@ -417,7 +417,7 @@ def get_client_class(version):
(version, ', '.join(version_map)))
raise exceptions.UnsupportedVersion(msg)
return utils.import_class(client_path)
return importutils.import_class(client_path)
def Client(version, *args, **kwargs):

View File

@ -36,6 +36,7 @@ import six
from manilaclient import client
from manilaclient import exceptions as exc
import manilaclient.extension
from manilaclient.openstack.common import cliutils
from manilaclient.openstack.common import strutils
from manilaclient import utils
from manilaclient.v1 import shell as shell_v1
@ -547,12 +548,12 @@ class OpenStackManilaShell(object):
if not service_type:
service_type = DEFAULT_MANILA_SERVICE_TYPE
service_type = utils.get_service_type(args.func) or service_type
service_type = cliutils.get_service_type(args.func) or service_type
# FIXME(usrleon): Here should be restrict for project id same as
# for os_username or os_password but for compatibility it is not.
if not utils.isunauthenticated(args.func):
if not cliutils.isunauthenticated(args.func):
if not os_username:
raise exc.CommandError(
"You must provide a username "
@ -591,7 +592,7 @@ class OpenStackManilaShell(object):
http_log_debug=args.debug,
cacert=cacert,
os_cache=os_cache)
if not utils.isunauthenticated(args.func):
if not cliutils.isunauthenticated(args.func):
helper = SecretsHelper(args, self.cs.client)
if os_reset_cache:
helper.reset()

View File

@ -14,12 +14,10 @@ from __future__ import print_function
import os
import sys
import uuid
import prettytable
import six
from manilaclient import exceptions
from manilaclient.openstack.common import strutils
@ -58,87 +56,6 @@ def add_arg(f, *args, **kwargs):
f.arguments.insert(0, (args, kwargs))
def add_resource_manager_extra_kwargs_hook(f, hook):
"""Adds hook to bind CLI arguments to ResourceManager calls.
The `do_foo` calls in shell.py will receive CLI args and then in turn pass
them through to the ResourceManager. Before passing through the args, the
hooks registered here will be called, giving us a chance to add extra
kwargs (taken from the command-line) to what's passed to the
ResourceManager.
"""
if not hasattr(f, 'resource_manager_kwargs_hooks'):
f.resource_manager_kwargs_hooks = []
names = [h.__name__ for h in f.resource_manager_kwargs_hooks]
if hook.__name__ not in names:
f.resource_manager_kwargs_hooks.append(hook)
def get_resource_manager_extra_kwargs(f, args, allow_conflicts=False):
"""Return extra_kwargs by calling resource manager kwargs hooks."""
hooks = getattr(f, "resource_manager_kwargs_hooks", [])
extra_kwargs = {}
for hook in hooks:
hook_name = hook.__name__
hook_kwargs = hook(args)
conflicting_keys = set(list(hook_kwargs)) & set(list(extra_kwargs))
if conflicting_keys and not allow_conflicts:
msg = ("Hook '%s' is attempting to redefine "
"attributes '%s'" % (hook_name, conflicting_keys))
raise Exception(msg)
extra_kwargs.update(hook_kwargs)
return extra_kwargs
def unauthenticated(f):
"""Adds 'unauthenticated' attribute to decorated function.
Usage:
@unauthenticated
def mymethod(f):
...
"""
f.unauthenticated = True
return f
def isunauthenticated(f):
"""Verifies whether function requires authentication or not.
Checks to see if the function is marked as not requiring authentication
with the @unauthenticated decorator.
Returns True if decorator is set to True, False otherwise.
"""
return getattr(f, 'unauthenticated', False)
def service_type(stype):
"""Adds 'service_type' attribute to decorated function.
Usage:
@service_type('share')
def mymethod(f):
...
"""
def inner(f):
f.service_type = stype
return f
return inner
def get_service_type(f):
"""Retrieves service type from function."""
return getattr(f, 'service_type', None)
def pretty_choice_list(l):
return ', '.join("'%s'" % i for i in l)
def _print(pt, order):
if sys.version_info >= (3, 0):
print(pt.get_string(sortby=order))
@ -146,6 +63,8 @@ def _print(pt, order):
print(strutils.safe_encode(pt.get_string(sortby=order)))
# NOTE(vponomaryov): replace function 'print_list' and 'print_dict'
# with functions from cliutils, when bug #1342050 is fixed
def print_list(objs, fields, formatters={}, order_by=None):
mixed_case_fields = ['serverId']
pt = prettytable.PrettyTable([f for f in fields], caching=False)
@ -178,70 +97,6 @@ def print_dict(d, property="Property"):
_print(pt, property)
def find_resource(manager, name_or_id):
"""Helper for the _find_* methods."""
# first try to get entity as integer id
try:
if isinstance(name_or_id, int) or name_or_id.isdigit():
return manager.get(int(name_or_id))
except exceptions.NotFound:
pass
if sys.version_info <= (3, 0):
name_or_id = strutils.safe_decode(name_or_id)
# now try to get entity as uuid
try:
uuid.UUID(name_or_id)
return manager.get(name_or_id)
except (ValueError, exceptions.NotFound):
pass
try:
try:
return manager.find(human_id=name_or_id)
except exceptions.NotFound:
pass
# finally try to find entity by name
try:
return manager.find(name=name_or_id)
except exceptions.NotFound:
try:
return manager.find(display_name=name_or_id)
except (UnicodeDecodeError, exceptions.NotFound):
try:
# Volumes does not have name, but display_name
return manager.find(display_name=name_or_id)
except exceptions.NotFound:
msg = ("No %s with a name or ID of '%s' exists." %
(manager.resource_class.__name__.lower(),
name_or_id))
raise exceptions.CommandError(msg)
except exceptions.NoUniqueMatch:
msg = ("Multiple %s matches found for '%s', use an ID to be more"
" specific." % (manager.resource_class.__name__.lower(),
name_or_id))
raise exceptions.CommandError(msg)
def find_share(cs, share):
"""Get a share by name or ID."""
return find_resource(cs.shares, share)
def _format_servers_list_networks(server):
output = []
for (network, addresses) in list(server.networks.items()):
if len(addresses) == 0:
continue
addresses_csv = ', '.join(addresses)
group = "%s=%s" % (network, addresses_csv)
output.append(group)
return '; '.join(output)
class HookableMixin(object):
"""Mixin so classes can register and run hooks."""
_hooks_map = {}
@ -270,25 +125,3 @@ def safe_issubclass(*args):
pass
return False
def import_class(import_str):
"""Returns a class from a string including module and class."""
mod_str, _sep, class_str = import_str.rpartition('.')
__import__(mod_str)
return getattr(sys.modules[mod_str], class_str)
def make_metadata_dict(metadata):
"""Converts cli key=value data to python dict as {'key': 'value'}."""
metadata_dict = {}
for item in metadata:
try:
key, value = item.split('=')
except ValueError:
msg = "Wrong argument format: '%s'" % item
raise exceptions.CommandError(msg)
if 'password' in key:
value = value.strip('"').strip("'")
metadata_dict[key] = value
return metadata_dict

View File

@ -15,6 +15,7 @@
from manilaclient import base
from manilaclient.openstack.common.apiclient import base as common_base
from manilaclient.openstack.common import cliutils
from manilaclient import utils
@ -38,7 +39,7 @@ class ListExtManager(base.Manager):
return self._list("/extensions", 'extensions')
@utils.service_type('share')
@cliutils.service_type('share')
def do_list_extensions(client, _args):
"""List all the os-api extensions that are available."""
extensions = client.list_extensions.show_all()

View File

@ -20,6 +20,7 @@ import sys
import time
from manilaclient import exceptions
from manilaclient.openstack.common import cliutils
from manilaclient import utils
from manilaclient.v1 import quotas
@ -56,7 +57,7 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
def _find_share(cs, share):
"""Get a share by ID."""
return utils.find_resource(cs.shares, share)
return cliutils.find_resource(cs.shares, share)
def _print_share(cs, share):
@ -66,7 +67,7 @@ def _print_share(cs, share):
def _find_share_snapshot(cs, snapshot):
"""Get a snapshot by ID."""
return utils.find_resource(cs.share_snapshots, snapshot)
return cliutils.find_resource(cs.share_snapshots, snapshot)
def _print_share_snapshot(cs, snapshot):
@ -77,7 +78,7 @@ def _print_share_snapshot(cs, snapshot):
def _find_share_network(cs, share_network):
"Get a share network by ID or name."
return utils.find_resource(cs.share_networks, share_network)
return cliutils.find_resource(cs.share_networks, share_network)
def _translate_keys(collection, convert):
@ -203,7 +204,7 @@ def do_quota_defaults(cs, args):
default=None,
help='Whether force update the quota even if the already used'
' and reserved exceeds the new quota')
@utils.service_type('share')
@cliutils.service_type('share')
def do_quota_update(cs, args):
"""Update the quotas for a tenant/user."""
@ -231,7 +232,7 @@ def do_quota_delete(cs, args):
@utils.arg('class_name',
metavar='<class>',
help='Name of quota class to list the quotas for.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_quota_class_show(cs, args):
"""List the quotas for a quota class."""
@ -257,14 +258,14 @@ def do_quota_class_show(cs, args):
metavar='<share-networks>',
type=int, default=None,
help='New value for the "share_networks" quota.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_quota_class_update(cs, args):
"""Update the quotas for a quota class."""
_quota_update(cs.quota_classes, args.class_name, args)
@utils.service_type('share')
@cliutils.service_type('share')
def do_absolute_limits(cs, args):
"""Print a list of absolute limits for a user."""
limits = cs.limits.get().absolute
@ -272,7 +273,7 @@ def do_absolute_limits(cs, args):
utils.print_list(limits, columns)
@utils.service_type('share')
@cliutils.service_type('share')
def do_rate_limits(cs, args):
"""Print a list of rate limits for a user."""
limits = cs.limits.get().rate
@ -321,7 +322,7 @@ def do_rate_limits(cs, args):
metavar='<volume-type>',
help='Optional volume type. (Default=None)',
default=None)
@utils.service_type('share')
@cliutils.service_type('share')
def do_create(cs, args):
"""Creates new NAS storage (NFS or CIFS)."""
@ -352,10 +353,10 @@ def do_create(cs, args):
nargs='+',
default=[],
help='Metadata to set/unset (only key is necessary on unset)')
@utils.service_type('share')
@cliutils.service_type('share')
def do_metadata(cs, args):
"""Set or Delete metadata on a share."""
share = utils.find_share(cs, args.share)
share = _find_share(cs, args.share)
metadata = _extract_metadata(args)
if args.action == 'set':
@ -366,10 +367,10 @@ def do_metadata(cs, args):
@utils.arg('share', metavar='<share>',
help='Name or ID of share')
@utils.service_type('share')
@cliutils.service_type('share')
def do_metadata_show(cs, args):
"""Show metadata of given share."""
share = utils.find_share(cs, args.share)
share = _find_share(cs, args.share)
metadata = cs.shares.get_metadata(share)._info
utils.print_dict(metadata, 'Metadata-property')
@ -382,10 +383,10 @@ def do_metadata_show(cs, args):
nargs='+',
default=[],
help='Metadata entry/entries to update.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_metadata_update_all(cs, args):
"""Update all metadata of a share."""
share = utils.find_share(cs, args.share)
share = _find_share(cs, args.share)
metadata = _extract_metadata(args)
metadata = share.update_all_metadata(metadata)._info['metadata']
utils.print_dict(metadata, 'Metadata-property')
@ -432,7 +433,7 @@ def do_force_delete(cs, args):
'share',
metavar='<share>',
help='Name or ID of the NAS share.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_show(cs, args):
"""Show details about a NAS share."""
share = _find_share(cs, args.share)
@ -452,7 +453,7 @@ def do_show(cs, args):
'access_to',
metavar='<access_to>',
help='Value that defines access')
@utils.service_type('share')
@cliutils.service_type('share')
def do_access_allow(cs, args):
"""Allow access to the share."""
share = _find_share(cs, args.share)
@ -468,7 +469,7 @@ def do_access_allow(cs, args):
'id',
metavar='<id>',
help='id of the access rule to be deleted.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_access_deny(cs, args):
"""Deny access to a share."""
share = _find_share(cs, args.share)
@ -479,7 +480,7 @@ def do_access_deny(cs, args):
'share',
metavar='<share>',
help='Name or ID of the share.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_access_list(cs, args):
"""Show access list for share."""
share = _find_share(cs, args.share)
@ -511,7 +512,7 @@ def do_access_list(cs, args):
metavar='<share_server_id>',
default=None,
help='Filter results by share-server id.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_list(cs, args):
"""List all NAS shares."""
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants))
@ -551,7 +552,7 @@ def do_list(cs, args):
metavar='<share-id>',
default=None,
help='Filter results by share-id')
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_list(cs, args):
"""List all the snapshots."""
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants))
@ -570,7 +571,7 @@ def do_snapshot_list(cs, args):
'snapshot',
metavar='<snapshot>',
help='Name or ID of the snapshot.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_show(cs, args):
"""Show details about a snapshot."""
snapshot = _find_share_snapshot(cs, args.snapshot)
@ -598,10 +599,10 @@ def do_snapshot_show(cs, args):
metavar='<description>',
default=None,
help='Optional snapshot description. (Default=None)')
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_create(cs, args):
"""Add a new snapshot."""
share = utils.find_share(cs, args.share)
share = _find_share(cs, args.share)
snapshot = cs.share_snapshots.create(share,
args.force,
args.name,
@ -619,7 +620,7 @@ def do_snapshot_create(cs, args):
@utils.arg('--description', metavar='<description>',
help='Optional share description. (Default=None)',
default=None)
@utils.service_type('share')
@cliutils.service_type('share')
def do_rename(cs, args):
"""Rename a share."""
kwargs = {}
@ -644,7 +645,7 @@ def do_rename(cs, args):
@utils.arg('--description', metavar='<description>',
help='Optional snapshot description. (Default=None)',
default=None)
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_rename(cs, args):
"""Rename a snapshot."""
kwargs = {}
@ -663,7 +664,7 @@ def do_snapshot_rename(cs, args):
'snapshot',
metavar='<snapshot>',
help='Name or ID of the snapshot to delete.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_delete(cs, args):
"""Remove a snapshot."""
snapshot = _find_share_snapshot(cs, args.snapshot)
@ -674,7 +675,7 @@ def do_snapshot_delete(cs, args):
'snapshot',
metavar='<snapshot>',
help='Name or ID of the snapshot to force delete.')
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_force_delete(cs, args):
"""Attempts force-delete of snapshot, regardless of state."""
snapshot = _find_share_snapshot(cs, args.snapshot)
@ -689,7 +690,7 @@ def do_snapshot_force_delete(cs, args):
'Options include available, error, creating, deleting, '
'error_deleting. If no state is provided, '
'available will be used.'))
@utils.service_type('share')
@cliutils.service_type('share')
def do_snapshot_reset_state(cs, args):
"""Explicitly update the state of a snapshot."""
snapshot = _find_share_snapshot(cs, args.snapshot)
@ -707,7 +708,7 @@ def do_snapshot_reset_state(cs, args):
help=('Indicate which state to assign the share. Options include '
'available, error, creating, deleting, error_deleting. If no '
'state is provided, available will be used.'))
@utils.service_type('share')
@cliutils.service_type('share')
def do_reset_state(cs, args):
"""Explicitly update the state of a share."""
share = _find_share(cs, args.share)
@ -1160,17 +1161,17 @@ def _print_type_and_extra_specs_list(vtypes):
def _find_volume_type(cs, vtype):
"""Get a volume type by name or ID."""
return utils.find_resource(cs.volume_types, vtype)
return cliutils.find_resource(cs.volume_types, vtype)
@utils.service_type('share')
@cliutils.service_type('share')
def do_type_list(cs, args):
"""Print a list of available 'volume types'."""
vtypes = cs.volume_types.list()
_print_volume_type_list(vtypes)
@utils.service_type('share')
@cliutils.service_type('share')
def do_extra_specs_list(cs, args):
"""Print a list of current 'volume types and extra specs' (Admin Only)."""
vtypes = cs.volume_types.list()
@ -1180,7 +1181,7 @@ def do_extra_specs_list(cs, args):
@utils.arg('name',
metavar='<name>',
help="Name of the new volume type")
@utils.service_type('share')
@cliutils.service_type('share')
def do_type_create(cs, args):
"""Create a new volume type."""
vtype = cs.volume_types.create(args.name)
@ -1190,7 +1191,7 @@ def do_type_create(cs, args):
@utils.arg('id',
metavar='<id>',
help="Name or ID of the volume type to delete")
@utils.service_type('share')
@cliutils.service_type('share')
def do_type_delete(cs, args):
"""Delete a specific volume type."""
volume_type = _find_volume_type(cs, args.id)
@ -1209,7 +1210,7 @@ def do_type_delete(cs, args):
nargs='*',
default=None,
help='Extra_specs to set/unset (only key is necessary on unset)')
@utils.service_type('share')
@cliutils.service_type('share')
def do_type_key(cs, args):
"""Set or unset extra_spec for a volume type."""
vtype = _find_volume_type(cs, args.vtype)

View File

@ -1,86 +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.
from manilaclient import base
from manilaclient import exceptions
from manilaclient import utils
from tests import utils as test_utils
UUID = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0'
class FakeResource(object):
def __init__(self, _id, properties):
self.id = _id
try:
self.name = properties['name']
except KeyError:
pass
try:
self.display_name = properties['display_name']
except KeyError:
pass
class FakeManager(base.ManagerWithFind):
resource_class = FakeResource
resources = [
FakeResource('1234', {'name': 'entity_one'}),
FakeResource(UUID, {'name': 'entity_two'}),
FakeResource('4242', {'display_name': 'entity_three'}),
FakeResource('5678', {'name': '9876'})
]
def get(self, resource_id):
for resource in self.resources:
if resource.id == str(resource_id):
return resource
raise exceptions.NotFound(resource_id)
def list(self):
return self.resources
class FindResourceTestCase(test_utils.TestCase):
def setUp(self):
super(FindResourceTestCase, self).setUp()
self.manager = FakeManager(None)
def test_find_none(self):
self.assertRaises(exceptions.CommandError,
utils.find_resource,
self.manager,
'asdf')
def test_find_by_integer_id(self):
output = utils.find_resource(self.manager, 1234)
self.assertEqual(output, self.manager.get('1234'))
def test_find_by_str_id(self):
output = utils.find_resource(self.manager, '1234')
self.assertEqual(output, self.manager.get('1234'))
def test_find_by_uuid(self):
output = utils.find_resource(self.manager, UUID)
self.assertEqual(output, self.manager.get(UUID))
def test_find_by_str_name(self):
output = utils.find_resource(self.manager, 'entity_one')
self.assertEqual(output, self.manager.get('1234'))
def test_find_by_str_displayname(self):
output = utils.find_resource(self.manager, 'entity_three')
self.assertEqual(output, self.manager.get('4242'))