diff --git a/novaclient/base.py b/novaclient/base.py index 173eda085..7f54d9363 100644 --- a/novaclient/base.py +++ b/novaclient/base.py @@ -26,7 +26,6 @@ import six from novaclient import exceptions from novaclient.openstack.common.apiclient import base -from novaclient import utils Resource = base.Resource @@ -42,7 +41,7 @@ def getid(obj): return obj -class Manager(utils.HookableMixin): +class Manager(base.HookableMixin): """ Managers interact with a particular type of API (servers, flavors, images, etc.) and provide CRUD operations for them. diff --git a/novaclient/client.py b/novaclient/client.py index b0d9aea10..5cd2d8f02 100644 --- a/novaclient/client.py +++ b/novaclient/client.py @@ -31,6 +31,7 @@ import re import time from keystoneclient import adapter +from oslo.utils import importutils from oslo.utils import netutils import requests from requests import adapters @@ -757,7 +758,7 @@ def get_client_class(version): 'keys': ', '.join(version_map.keys())} raise exceptions.UnsupportedVersion(msg) - return utils.import_class(client_path) + return importutils.import_class(client_path) def Client(version, *args, **kwargs): diff --git a/novaclient/extension.py b/novaclient/extension.py index ac105070a..9cfcc13d9 100644 --- a/novaclient/extension.py +++ b/novaclient/extension.py @@ -14,10 +14,11 @@ # under the License. from novaclient import base +from novaclient.openstack.common.apiclient import base as common_base from novaclient import utils -class Extension(utils.HookableMixin): +class Extension(common_base.HookableMixin): """Extension descriptor.""" SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') diff --git a/novaclient/shell.py b/novaclient/shell.py index 6623b7fbf..d0d183b23 100644 --- a/novaclient/shell.py +++ b/novaclient/shell.py @@ -601,7 +601,7 @@ class OpenStackComputeShell(object): except KeyError: service_type = DEFAULT_NOVA_SERVICE_TYPE_MAP[ DEFAULT_OS_COMPUTE_API_VERSION] - service_type = utils.get_service_type(args.func) or service_type + service_type = cliutils.get_service_type(args.func) or service_type # If we have an auth token but no management_url, we must auth anyway. # Expired tokens are handled by client.py:_cs_request diff --git a/novaclient/tests/test_utils.py b/novaclient/tests/test_utils.py index 69e5d6188..b8960b57c 100644 --- a/novaclient/tests/test_utils.py +++ b/novaclient/tests/test_utils.py @@ -267,15 +267,6 @@ class FlattenTestCase(test_utils.TestCase): 'a3': ('t',)}, squashed) - def test_pretty_choice_list(self): - l = [] - r = utils.pretty_choice_list(l) - self.assertEqual("", r) - - l = ["v1", "v2", "v3"] - r = utils.pretty_choice_list(l) - self.assertEqual("'v1', 'v2', 'v3'", r) - def test_pretty_choice_dict(self): d = {} r = utils.pretty_choice_dict(d) diff --git a/novaclient/utils.py b/novaclient/utils.py index d6068ba0c..3f4be4398 100644 --- a/novaclient/utils.py +++ b/novaclient/utils.py @@ -13,7 +13,6 @@ import json import re -import sys import textwrap import uuid @@ -71,34 +70,10 @@ def get_resource_manager_extra_kwargs(f, args, allow_conflicts=False): return extra_kwargs -def service_type(stype): - """ - Adds 'service_type' attribute to decorated function. - Usage: - @service_type('volume') - 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 pretty_choice_dict(d): """Returns a formatted dict as 'key=value'.""" - return pretty_choice_list(['%s=%s' % (k, d[k]) for k in sorted(d.keys())]) + return cliutils.pretty_choice_list( + ['%s=%s' % (k, d[k]) for k in sorted(d.keys())]) def print_list(objs, fields, formatters={}, sortby_index=None): @@ -313,24 +288,6 @@ def _make_field_formatter(attr, filters=None): return name, formatter -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - def safe_issubclass(*args): """Like issubclass, but will just return False if not a class.""" @@ -343,13 +300,6 @@ def safe_issubclass(*args): 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 _load_entry_point(ep_name, name=None): """Try to load the entry point ep_name that matches name.""" for ep in pkg_resources.iter_entry_points(ep_name, name=name): diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index 457ebc1a1..b7e8a74ed 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -34,6 +34,7 @@ from oslo.utils import timeutils import six from novaclient import exceptions +from novaclient.openstack.common import cliutils from novaclient.openstack.common.gettextutils import _ from novaclient.openstack.common import uuidutils from novaclient import utils @@ -1767,7 +1768,7 @@ def _translate_availability_zone_keys(collection): type=int, const=1, help=argparse.SUPPRESS) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_list(cs, args): """List all the volumes.""" search_opts = {'all_tenants': args.all_tenants} @@ -1783,7 +1784,7 @@ def do_volume_list(cs, args): @utils.arg('volume', metavar='', help=_('Name or ID of the volume.')) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_show(cs, args): """Show details about a volume.""" volume = _find_volume(cs, args.volume) @@ -1825,7 +1826,7 @@ def do_volume_show(cs, args): @utils.arg('--availability-zone', metavar='', help=_('Optional Availability Zone for volume. (Default=None)'), default=None) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_create(cs, args): """Add a new volume.""" volume = cs.volumes.create(args.size, @@ -1841,7 +1842,7 @@ def do_volume_create(cs, args): @utils.arg('volume', metavar='', nargs='+', help=_('Name or ID of the volume(s) to delete.')) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_delete(cs, args): """Remove volume(s).""" for volume in args.volume: @@ -1900,7 +1901,7 @@ def do_volume_detach(cs, args): args.attachment_id) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_snapshot_list(cs, _args): """List all the snapshots.""" snapshots = cs.volume_snapshots.list() @@ -1912,7 +1913,7 @@ def do_volume_snapshot_list(cs, _args): @utils.arg('snapshot', metavar='', help=_('Name or ID of the snapshot.')) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_snapshot_show(cs, args): """Show details about a snapshot.""" snapshot = _find_volume_snapshot(cs, args.snapshot) @@ -1939,7 +1940,7 @@ def do_volume_snapshot_show(cs, args): help=_('Optional snapshot description. (Default=None)')) @utils.arg('--display_description', help=argparse.SUPPRESS) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_snapshot_create(cs, args): """Add a new snapshot.""" snapshot = cs.volume_snapshots.create(args.volume_id, @@ -1952,7 +1953,7 @@ def do_volume_snapshot_create(cs, args): @utils.arg('snapshot', metavar='', help=_('Name or ID of the snapshot to delete.')) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_snapshot_delete(cs, args): """Remove a snapshot.""" snapshot = _find_volume_snapshot(cs, args.snapshot) @@ -1963,7 +1964,7 @@ def _print_volume_type_list(vtypes): utils.print_list(vtypes, ['ID', 'Name']) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_type_list(cs, args): """Print a list of available 'volume types'.""" vtypes = cs.volume_types.list() @@ -1973,7 +1974,7 @@ def do_volume_type_list(cs, args): @utils.arg('name', metavar='', help=_("Name of the new volume type")) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_type_create(cs, args): """Create a new volume type.""" vtype = cs.volume_types.create(args.name) @@ -1983,7 +1984,7 @@ def do_volume_type_create(cs, args): @utils.arg('id', metavar='', help=_("Unique ID of the volume type to delete")) -@utils.service_type('volume') +@cliutils.service_type('volume') def do_volume_type_delete(cs, args): """Delete a specific volume type.""" cs.volume_types.delete(args.id) @@ -2966,7 +2967,7 @@ def _print_aggregate_details(aggregate): return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) def parser_hosts(fields): - return utils.pretty_choice_list(getattr(fields, 'hosts', [])) + return cliutils.pretty_choice_list(getattr(fields, 'hosts', [])) formatters = { 'Metadata': parser_metadata, @@ -3783,7 +3784,7 @@ def _treeizeAvailabilityZone(zone): return result -@utils.service_type('compute') +@cliutils.service_type('compute') def do_availability_zone_list(cs, _args): """List all the availability zones.""" try: diff --git a/novaclient/v3/shell.py b/novaclient/v3/shell.py index 3d17e2890..1a5eb9ef3 100644 --- a/novaclient/v3/shell.py +++ b/novaclient/v3/shell.py @@ -32,6 +32,7 @@ from oslo.utils import timeutils import six from novaclient import exceptions +from novaclient.openstack.common import cliutils from novaclient.openstack.common.gettextutils import _ from novaclient.openstack.common import uuidutils from novaclient import utils @@ -778,7 +779,7 @@ def do_network_create(cs, args): dest="limit", metavar="", help='Number of images to return per request.') -@utils.service_type('image') +@cliutils.service_type('image') def do_image_list(cs, _args): """Print a list of available images to boot from.""" limit = _args.limit @@ -867,7 +868,7 @@ def _print_flavor(flavor): @utils.arg('image', metavar='', help="Name or ID of image") -@utils.service_type('image') +@cliutils.service_type('image') def do_image_show(cs, args): """Show details about the given image.""" image = _find_image(cs, args.image) @@ -2363,7 +2364,7 @@ def _print_aggregate_details(aggregate): return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) def parser_hosts(fields): - return utils.pretty_choice_list(getattr(fields, 'hosts', [])) + return cliutils.pretty_choice_list(getattr(fields, 'hosts', [])) formatters = { 'Metadata': parser_metadata,