Deprecate v1.1 and remove v3
Module novaclient.v1_1 is already deprecated, so it's time to stop using it inside novaclient. Since support of v3 nova is undocumented feature, which uses v2 implementation, we can remove code related to it. Also, this patch removes redundant check for compute api version != 1.0. Change-Id: I06b349f704d5ae2c592d8d286da268870f2a69e9
This commit is contained in:
parent
5eab1430f2
commit
61ef35fe79
|
@ -24,8 +24,10 @@ import copy
|
||||||
import functools
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
|
import pkgutil
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
import warnings
|
||||||
|
|
||||||
from keystoneclient import adapter
|
from keystoneclient import adapter
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
@ -41,11 +43,15 @@ except ImportError:
|
||||||
from six.moves.urllib import parse
|
from six.moves.urllib import parse
|
||||||
|
|
||||||
from novaclient import exceptions
|
from novaclient import exceptions
|
||||||
from novaclient.i18n import _
|
from novaclient.i18n import _, _LW
|
||||||
from novaclient import service_catalog
|
from novaclient import service_catalog
|
||||||
from novaclient import utils
|
from novaclient import utils
|
||||||
|
|
||||||
|
|
||||||
|
# key is a deprecated version and value is an alternative version.
|
||||||
|
DEPRECATED_VERSIONS = {"1.1": "2"}
|
||||||
|
|
||||||
|
|
||||||
class TCPKeepAliveAdapter(adapters.HTTPAdapter):
|
class TCPKeepAliveAdapter(adapters.HTTPAdapter):
|
||||||
"""The custom adapter used to set TCP Keep-Alive on all connections."""
|
"""The custom adapter used to set TCP Keep-Alive on all connections."""
|
||||||
def init_poolmanager(self, *args, **kwargs):
|
def init_poolmanager(self, *args, **kwargs):
|
||||||
|
@ -712,21 +718,30 @@ def _construct_http_client(username=None, password=None, project_id=None,
|
||||||
|
|
||||||
|
|
||||||
def get_client_class(version):
|
def get_client_class(version):
|
||||||
version_map = {
|
version = str(version)
|
||||||
'1.1': 'novaclient.v2.client.Client',
|
if version in DEPRECATED_VERSIONS:
|
||||||
'2': 'novaclient.v2.client.Client',
|
warnings.warn(_LW(
|
||||||
'3': 'novaclient.v2.client.Client',
|
"Version %(deprecated_version)s is deprecated, using "
|
||||||
}
|
"alternative version %(alternative)s instead.") %
|
||||||
|
{"deprecated_version": version,
|
||||||
|
"alternative": DEPRECATED_VERSIONS[version]})
|
||||||
|
version = DEPRECATED_VERSIONS[version]
|
||||||
try:
|
try:
|
||||||
client_path = version_map[str(version)]
|
return importutils.import_class(
|
||||||
except (KeyError, ValueError):
|
"novaclient.v%s.client.Client" % version)
|
||||||
|
except ImportError:
|
||||||
|
# NOTE(andreykurilin): available clients version should not be
|
||||||
|
# hardcoded, so let's discover them.
|
||||||
|
matcher = re.compile(r"v[0-9_]*$")
|
||||||
|
submodules = pkgutil.iter_modules(['novaclient'])
|
||||||
|
available_versions = [
|
||||||
|
name[1:].replace("_", ".") for loader, name, ispkg in submodules
|
||||||
|
if matcher.search(name)]
|
||||||
msg = _("Invalid client version '%(version)s'. must be one of: "
|
msg = _("Invalid client version '%(version)s'. must be one of: "
|
||||||
"%(keys)s") % {'version': version,
|
"%(keys)s") % {'version': version,
|
||||||
'keys': ', '.join(version_map.keys())}
|
'keys': ', '.join(available_versions)}
|
||||||
raise exceptions.UnsupportedVersion(msg)
|
raise exceptions.UnsupportedVersion(msg)
|
||||||
|
|
||||||
return importutils.import_class(client_path)
|
|
||||||
|
|
||||||
|
|
||||||
def Client(version, *args, **kwargs):
|
def Client(version, *args, **kwargs):
|
||||||
client_class = get_client_class(version)
|
client_class = get_client_class(version)
|
||||||
|
|
|
@ -58,13 +58,7 @@ from novaclient.v2 import shell as shell_v2
|
||||||
|
|
||||||
DEFAULT_OS_COMPUTE_API_VERSION = "2"
|
DEFAULT_OS_COMPUTE_API_VERSION = "2"
|
||||||
DEFAULT_NOVA_ENDPOINT_TYPE = 'publicURL'
|
DEFAULT_NOVA_ENDPOINT_TYPE = 'publicURL'
|
||||||
# NOTE(cyeoh): Having the service type dependent on the API version
|
DEFAULT_NOVA_SERVICE_TYPE = "compute"
|
||||||
# is pretty ugly, but we have to do this because traditionally the
|
|
||||||
# catalog entry for compute points directly to the V2 API rather than
|
|
||||||
# the root, and then doing version discovery.
|
|
||||||
DEFAULT_NOVA_SERVICE_TYPE_MAP = {'1.1': 'compute',
|
|
||||||
'2': 'compute',
|
|
||||||
'3': 'computev3'}
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -414,7 +408,7 @@ class OpenStackComputeShell(object):
|
||||||
metavar='<compute-api-ver>',
|
metavar='<compute-api-ver>',
|
||||||
default=cliutils.env('OS_COMPUTE_API_VERSION',
|
default=cliutils.env('OS_COMPUTE_API_VERSION',
|
||||||
default=DEFAULT_OS_COMPUTE_API_VERSION),
|
default=DEFAULT_OS_COMPUTE_API_VERSION),
|
||||||
help=_('Accepts 1.1 or 3, '
|
help=_('Accepts number of API version, '
|
||||||
'defaults to env[OS_COMPUTE_API_VERSION].'))
|
'defaults to env[OS_COMPUTE_API_VERSION].'))
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--os_compute_api_version',
|
'--os_compute_api_version',
|
||||||
|
@ -490,9 +484,9 @@ class OpenStackComputeShell(object):
|
||||||
def _discover_via_contrib_path(self, version):
|
def _discover_via_contrib_path(self, version):
|
||||||
module_path = os.path.dirname(os.path.abspath(__file__))
|
module_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
version_str = "v%s" % version.replace('.', '_')
|
version_str = "v%s" % version.replace('.', '_')
|
||||||
# NOTE(akurilin): v1.1, v2 and v3 have one implementation, so
|
# NOTE(andreykurilin): v1.1 uses implementation of v2, so we should
|
||||||
# we should discover contrib modules in one place.
|
# discover contrib modules in novaclient.v2 dir.
|
||||||
if version_str in ["v1_1", "v3"]:
|
if version_str == "v1_1":
|
||||||
version_str = "v2"
|
version_str = "v2"
|
||||||
ext_path = os.path.join(module_path, version_str, 'contrib')
|
ext_path = os.path.join(module_path, version_str, 'contrib')
|
||||||
ext_glob = os.path.join(ext_path, "*.py")
|
ext_glob = os.path.join(ext_path, "*.py")
|
||||||
|
@ -656,15 +650,8 @@ class OpenStackComputeShell(object):
|
||||||
endpoint_type += 'URL'
|
endpoint_type += 'URL'
|
||||||
|
|
||||||
if not service_type:
|
if not service_type:
|
||||||
os_compute_api_version = (options.os_compute_api_version or
|
service_type = (cliutils.get_service_type(args.func) or
|
||||||
DEFAULT_OS_COMPUTE_API_VERSION)
|
DEFAULT_NOVA_SERVICE_TYPE)
|
||||||
try:
|
|
||||||
service_type = DEFAULT_NOVA_SERVICE_TYPE_MAP[
|
|
||||||
os_compute_api_version]
|
|
||||||
except KeyError:
|
|
||||||
service_type = DEFAULT_NOVA_SERVICE_TYPE_MAP[
|
|
||||||
DEFAULT_OS_COMPUTE_API_VERSION]
|
|
||||||
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.
|
# If we have an auth token but no management_url, we must auth anyway.
|
||||||
# Expired tokens are handled by client.py:_cs_request
|
# Expired tokens are handled by client.py:_cs_request
|
||||||
|
@ -734,8 +721,7 @@ class OpenStackComputeShell(object):
|
||||||
project_domain_id=args.os_project_domain_id,
|
project_domain_id=args.os_project_domain_id,
|
||||||
project_domain_name=args.os_project_domain_name)
|
project_domain_name=args.os_project_domain_name)
|
||||||
|
|
||||||
if (options.os_compute_api_version and
|
if options.os_compute_api_version:
|
||||||
options.os_compute_api_version != '1.0'):
|
|
||||||
if not any([args.os_tenant_id, args.os_tenant_name,
|
if not any([args.os_tenant_id, args.os_tenant_name,
|
||||||
args.os_project_id, args.os_project_name]):
|
args.os_project_id, args.os_project_name]):
|
||||||
raise exc.CommandError(_("You must provide a project name or"
|
raise exc.CommandError(_("You must provide a project name or"
|
||||||
|
@ -806,32 +792,6 @@ class OpenStackComputeShell(object):
|
||||||
except exc.AuthorizationFailure:
|
except exc.AuthorizationFailure:
|
||||||
raise exc.CommandError(_("Unable to authorize user"))
|
raise exc.CommandError(_("Unable to authorize user"))
|
||||||
|
|
||||||
if options.os_compute_api_version == "3" and service_type != 'image':
|
|
||||||
# NOTE(cyeoh): create an image based client because the
|
|
||||||
# images api is no longer proxied by the V3 API and we
|
|
||||||
# sometimes need to be able to look up images information
|
|
||||||
# via glance when connected to the nova api.
|
|
||||||
image_service_type = 'image'
|
|
||||||
# NOTE(hdd): the password is needed again because creating a new
|
|
||||||
# Client without specifying bypass_url will force authentication.
|
|
||||||
# We can't reuse self.cs's bypass_url, because that's the URL for
|
|
||||||
# the nova service; we need to get glance's URL for this Client
|
|
||||||
if not os_password:
|
|
||||||
os_password = helper.password
|
|
||||||
self.cs.image_cs = client.Client(
|
|
||||||
options.os_compute_api_version, os_username,
|
|
||||||
os_password, os_tenant_name, tenant_id=os_tenant_id,
|
|
||||||
auth_url=os_auth_url, insecure=insecure,
|
|
||||||
region_name=os_region_name, endpoint_type=endpoint_type,
|
|
||||||
extensions=self.extensions, service_type=image_service_type,
|
|
||||||
service_name=service_name, auth_system=os_auth_system,
|
|
||||||
auth_plugin=auth_plugin,
|
|
||||||
volume_service_name=volume_service_name,
|
|
||||||
timings=args.timings, bypass_url=bypass_url,
|
|
||||||
os_cache=os_cache, http_log_debug=options.debug,
|
|
||||||
session=keystone_session, auth=keystone_auth,
|
|
||||||
cacert=cacert, timeout=timeout)
|
|
||||||
|
|
||||||
args.func(self.cs, args)
|
args.func(self.cs, args)
|
||||||
|
|
||||||
if args.timings:
|
if args.timings:
|
||||||
|
|
|
@ -161,10 +161,6 @@ class ClientTest(utils.TestCase):
|
||||||
self._check_version_url('http://foo.com/nova/v2/%s',
|
self._check_version_url('http://foo.com/nova/v2/%s',
|
||||||
'http://foo.com/nova/')
|
'http://foo.com/nova/')
|
||||||
|
|
||||||
def test_get_client_class_v3(self):
|
|
||||||
output = novaclient.client.get_client_class('3')
|
|
||||||
self.assertEqual(output, novaclient.v2.client.Client)
|
|
||||||
|
|
||||||
def test_get_client_class_v2(self):
|
def test_get_client_class_v2(self):
|
||||||
output = novaclient.client.get_client_class('2')
|
output = novaclient.client.get_client_class('2')
|
||||||
self.assertEqual(output, novaclient.v2.client.Client)
|
self.assertEqual(output, novaclient.v2.client.Client)
|
||||||
|
|
|
@ -342,10 +342,6 @@ class ShellTest(utils.TestCase):
|
||||||
def test_v2_service_type(self, mock_client):
|
def test_v2_service_type(self, mock_client):
|
||||||
self._test_service_type('2', 'compute', mock_client)
|
self._test_service_type('2', 'compute', mock_client)
|
||||||
|
|
||||||
@mock.patch('novaclient.client.Client')
|
|
||||||
def test_v3_service_type(self, mock_client):
|
|
||||||
self._test_service_type('3', 'computev3', mock_client)
|
|
||||||
|
|
||||||
@mock.patch('novaclient.client.Client')
|
@mock.patch('novaclient.client.Client')
|
||||||
def test_v_unknown_service_type(self, mock_client):
|
def test_v_unknown_service_type(self, mock_client):
|
||||||
self._test_service_type('unknown', 'compute', mock_client)
|
self._test_service_type('unknown', 'compute', mock_client)
|
||||||
|
|
|
@ -2374,17 +2374,6 @@ class ShellTestV11(ShellTest):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ShellTestV3(ShellTest):
|
|
||||||
FAKE_ENV = {
|
|
||||||
'NOVA_USERNAME': 'username',
|
|
||||||
'NOVA_PASSWORD': 'password',
|
|
||||||
'NOVA_PROJECT_ID': 'project_id',
|
|
||||||
'OS_COMPUTE_API_VERSION': '3',
|
|
||||||
'NOVA_URL': 'http://no.where',
|
|
||||||
'OS_AUTH_URL': 'http://no.where/v2.0',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ShellWithSessionClientTest(ShellTest):
|
class ShellWithSessionClientTest(ShellTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Reference in New Issue