Adopts keystoneauth with glance client.
Migrate Glance client to Keystonesuth to make it consistent with Cinder and Neutron clients. Note: We still use the api_servers variable, rather than fetching endpoints from the service catalog. This change is needed to enable the use of service token with Glance client. Related to blueprint use-service-tokens-pike Change-Id: I02be31bbe2de54c69210934b234ed380daca4fda Co-Authored-By: Pushkar Umaranikar <pushkar.umaranikar@intel.com>
This commit is contained in:
parent
3d84232d7b
commit
b277b10df6
@ -60,7 +60,6 @@ from nova.conf import service
|
||||
from nova.conf import service_token
|
||||
from nova.conf import servicegroup
|
||||
from nova.conf import spice
|
||||
from nova.conf import ssl
|
||||
from nova.conf import upgrade_levels
|
||||
from nova.conf import vendordata
|
||||
from nova.conf import vmware
|
||||
@ -112,7 +111,6 @@ service.register_opts(CONF)
|
||||
service_token.register_opts(CONF)
|
||||
servicegroup.register_opts(CONF)
|
||||
spice.register_opts(CONF)
|
||||
ssl.register_opts(CONF)
|
||||
upgrade_levels.register_opts(CONF)
|
||||
vendordata.register_opts(CONF)
|
||||
vmware.register_opts(CONF)
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystoneauth1 import loading as ks_loading
|
||||
from oslo_config import cfg
|
||||
|
||||
glance_group = cfg.OptGroup(
|
||||
@ -34,14 +35,6 @@ Possible values:
|
||||
|
||||
* A list of any fully qualified url of the form "scheme://hostname:port[/path]"
|
||||
(i.e. "http://10.0.1.0:9292" or "https://my.glance.server/image").
|
||||
"""),
|
||||
cfg.BoolOpt('api_insecure',
|
||||
default=False,
|
||||
help="""
|
||||
Enable insecure SSL (https) requests to glance.
|
||||
|
||||
This setting can be used to turn off verification of the glance server
|
||||
certificate against the certificate authorities.
|
||||
"""),
|
||||
cfg.IntOpt('num_retries',
|
||||
default=0,
|
||||
@ -142,6 +135,23 @@ def register_opts(conf):
|
||||
conf.register_group(glance_group)
|
||||
conf.register_opts(glance_opts, group=glance_group)
|
||||
|
||||
deprecated = {
|
||||
'insecure': [cfg.DeprecatedOpt('api_insecure',
|
||||
group=glance_group.name)],
|
||||
'cafile': [cfg.DeprecatedOpt('ca_file',
|
||||
group="ssl")],
|
||||
'certfile': [cfg.DeprecatedOpt('cert_file',
|
||||
group="ssl")],
|
||||
'keyfile': [cfg.DeprecatedOpt('key_file',
|
||||
group="ssl")],
|
||||
}
|
||||
ks_loading.register_session_conf_options(conf, glance_group.name,
|
||||
deprecated)
|
||||
|
||||
|
||||
def list_opts():
|
||||
return {glance_group: glance_opts}
|
||||
return {
|
||||
glance_group: (
|
||||
glance_opts +
|
||||
ks_loading.get_session_conf_options())
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
# Copyright 2016 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_service import sslutils
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
sslutils.register_opts(conf)
|
||||
|
||||
|
||||
def list_opts():
|
||||
# The oslo_cache library returns a list of tuples
|
||||
return dict(sslutils.list_opts())
|
@ -31,9 +31,9 @@ from cursive import signature_utils
|
||||
import glanceclient
|
||||
import glanceclient.exc
|
||||
from glanceclient.v2 import schemas
|
||||
from keystoneauth1 import loading as ks_loading
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_service import sslutils
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
@ -50,6 +50,24 @@ from nova.objects import fields
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
_SESSION = None
|
||||
|
||||
|
||||
def _glanceclient_from_endpoint(context, endpoint, version):
|
||||
global _SESSION
|
||||
|
||||
if not _SESSION:
|
||||
_SESSION = ks_loading.load_session_from_conf_options(
|
||||
CONF, nova.conf.glance.glance_group.name)
|
||||
|
||||
auth = context.get_auth_plugin()
|
||||
|
||||
# TODO(johngarbutt) eventually we should default to getting the
|
||||
# endpoint URL from the service catalog.
|
||||
return glanceclient.Client(version, session=_SESSION, auth=auth,
|
||||
endpoint_override=endpoint,
|
||||
global_request_id=context.global_id)
|
||||
|
||||
|
||||
def generate_glance_url():
|
||||
"""Return a random glance url from the api servers we know about."""
|
||||
@ -85,27 +103,6 @@ def generate_identity_headers(context, status='Confirmed'):
|
||||
}
|
||||
|
||||
|
||||
def _glanceclient_from_endpoint(context, endpoint, version):
|
||||
"""Instantiate a new glanceclient.Client object."""
|
||||
params = {}
|
||||
# NOTE(sdague): even if we aren't using keystone, it doesn't
|
||||
# hurt to send these headers.
|
||||
params['identity_headers'] = generate_identity_headers(context)
|
||||
params['global_request_id'] = context.global_id
|
||||
if endpoint.startswith('https://'):
|
||||
# https specific params
|
||||
params['insecure'] = CONF.glance.api_insecure
|
||||
params['ssl_compression'] = False
|
||||
sslutils.is_enabled(CONF)
|
||||
if CONF.ssl.cert_file:
|
||||
params['cert_file'] = CONF.ssl.cert_file
|
||||
if CONF.ssl.key_file:
|
||||
params['key_file'] = CONF.ssl.key_file
|
||||
if CONF.ssl.ca_file:
|
||||
params['cacert'] = CONF.ssl.ca_file
|
||||
return glanceclient.Client(str(version), endpoint, **params)
|
||||
|
||||
|
||||
def get_api_servers():
|
||||
"""Shuffle a list of CONF.glance.api_servers and return an iterator
|
||||
that will cycle through the list, looping around to the beginning
|
||||
|
@ -22,6 +22,7 @@ from cursive import exception as cursive_exception
|
||||
import glanceclient.exc
|
||||
from glanceclient.v1 import images
|
||||
import glanceclient.v2.schemas as schemas
|
||||
from keystoneauth1 import loading as ks_loading
|
||||
import mock
|
||||
import six
|
||||
from six.moves import StringIO
|
||||
@ -340,52 +341,51 @@ class TestGetImageService(test.NoDBTestCase):
|
||||
|
||||
|
||||
class TestCreateGlanceClient(test.NoDBTestCase):
|
||||
|
||||
@mock.patch.object(context.RequestContext, 'get_auth_plugin')
|
||||
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
||||
@mock.patch('glanceclient.Client')
|
||||
def test_headers_passed_glanceclient(self, init_mock):
|
||||
self.flags(auth_strategy='keystone', group='api')
|
||||
auth_token = 'token'
|
||||
ctx = context.RequestContext('fake', 'fake', auth_token=auth_token)
|
||||
def test_glanceclient_with_ks_session(self, mock_client, mock_load,
|
||||
mock_get_auth):
|
||||
session = "fake_session"
|
||||
mock_load.return_value = session
|
||||
auth = "fake_auth"
|
||||
mock_get_auth.return_value = auth
|
||||
ctx = context.RequestContext('fake', 'fake', global_request_id='reqid')
|
||||
endpoint = "fake_endpoint"
|
||||
mock_client.side_effect = ["a", "b"]
|
||||
|
||||
expected_endpoint = 'http://host4:9295'
|
||||
expected_params = {
|
||||
'identity_headers': {
|
||||
'X-Auth-Token': 'token',
|
||||
'X-User-Id': 'fake',
|
||||
'X-Roles': '',
|
||||
'X-Tenant-Id': 'fake',
|
||||
'X-Identity-Status': 'Confirmed',
|
||||
},
|
||||
'global_request_id': mock.ANY
|
||||
# Reset the cache, so we know its empty before we start
|
||||
glance._SESSION = None
|
||||
|
||||
result1 = glance._glanceclient_from_endpoint(ctx, endpoint, 2)
|
||||
result2 = glance._glanceclient_from_endpoint(ctx, endpoint, 2)
|
||||
|
||||
# Ensure that session is only loaded once.
|
||||
mock_load.assert_called_once_with(glance.CONF, "glance")
|
||||
self.assertEqual(session, glance._SESSION)
|
||||
# Ensure new client created every time
|
||||
client_call = mock.call(2, auth="fake_auth",
|
||||
endpoint_override=endpoint, session=session,
|
||||
global_request_id='reqid')
|
||||
mock_client.assert_has_calls([client_call, client_call])
|
||||
self.assertEqual("a", result1)
|
||||
self.assertEqual("b", result2)
|
||||
|
||||
def test_generate_identity_headers(self):
|
||||
ctx = context.RequestContext('user', 'tenant',
|
||||
auth_token='token', roles=["a", "b"])
|
||||
|
||||
result = glance.generate_identity_headers(ctx, 'test')
|
||||
|
||||
expected = {
|
||||
'X-Auth-Token': 'token',
|
||||
'X-User-Id': 'user',
|
||||
'X-Tenant-Id': 'tenant',
|
||||
'X-Roles': 'a,b',
|
||||
'X-Identity-Status': 'test',
|
||||
}
|
||||
glance._glanceclient_from_endpoint(ctx, expected_endpoint, 2)
|
||||
init_mock.assert_called_once_with('2', expected_endpoint,
|
||||
**expected_params)
|
||||
|
||||
# Test the version is properly passed to glanceclient.
|
||||
init_mock.reset_mock()
|
||||
|
||||
expected_endpoint = 'http://host4:9295'
|
||||
expected_params = {
|
||||
'identity_headers': {
|
||||
'X-Auth-Token': 'token',
|
||||
'X-User-Id': 'fake',
|
||||
'X-Roles': '',
|
||||
'X-Tenant-Id': 'fake',
|
||||
'X-Identity-Status': 'Confirmed',
|
||||
},
|
||||
'global_request_id': mock.ANY
|
||||
}
|
||||
glance._glanceclient_from_endpoint(ctx, expected_endpoint, 2)
|
||||
init_mock.assert_called_once_with('2', expected_endpoint,
|
||||
**expected_params)
|
||||
|
||||
# Test that the IPv6 bracketization adapts the endpoint properly.
|
||||
init_mock.reset_mock()
|
||||
|
||||
expected_endpoint = 'http://[host4]:9295'
|
||||
glance._glanceclient_from_endpoint(ctx, expected_endpoint, 2)
|
||||
init_mock.assert_called_once_with('2', expected_endpoint,
|
||||
**expected_params)
|
||||
self.assertDictEqual(expected, result)
|
||||
|
||||
|
||||
class TestGlanceClientWrapperRetries(test.NoDBTestCase):
|
||||
@ -505,23 +505,6 @@ class TestGlanceClientWrapperRetries(test.NoDBTestCase):
|
||||
create_client_mock.return_value = client_mock
|
||||
|
||||
|
||||
class TestGlanceClientWrapper(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('oslo_service.sslutils.is_enabled')
|
||||
@mock.patch('glanceclient.Client')
|
||||
def test_create_glance_client_with_ssl(self, client_mock,
|
||||
ssl_enable_mock):
|
||||
self.flags(ca_file='foo.cert', cert_file='bar.cert',
|
||||
key_file='wut.key', group='ssl')
|
||||
ctxt = mock.MagicMock()
|
||||
glance._glanceclient_from_endpoint(ctxt, 'https://host4:9295', 2)
|
||||
client_mock.assert_called_once_with(
|
||||
'2', 'https://host4:9295', global_request_id=mock.ANY,
|
||||
insecure=False, ssl_compression=False,
|
||||
cert_file='bar.cert', key_file='wut.key', cacert='foo.cert',
|
||||
identity_headers=mock.ANY)
|
||||
|
||||
|
||||
class TestDownloadNoDirectUri(test.NoDBTestCase):
|
||||
|
||||
"""Tests the download method of the GlanceImageServiceV2 when the
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The ``ssl`` options were only used by Nova code that interacts with
|
||||
Glance client. These options are now defined and read by Keystoneauth.
|
||||
``api_insecure`` option from glance group is renamed to ``insecure``. The
|
||||
following ''ssl'' options are moved to ``glance`` group
|
||||
|
||||
- ``ca_file`` now called ``cafile``
|
||||
- ``cert_file`` now called ``certfile``
|
||||
- ``key_file`` now called ``keyfile``
|
Loading…
Reference in New Issue
Block a user