Use keystoneauth1.loading instead of specifying V2 or V3 of keystone

In devstack, there is an error:
Not Found (HTTP 404) (Request-ID: req-c5b74593-ecd6-4c06-9db1-b1fa9c124fc1).
This is a keystone authentication failure.
Use keystoneauth1.load.get_plugin_loader to load and discovery dynamically
without explicitly specifying V2 or V3 of keystone.

Change-Id: I33d560e1c75b5a370cc2671849a10e4244f2934c
This commit is contained in:
gengchc2 2018-10-08 19:32:00 -07:00
parent f83d565ee9
commit f6e5b80dd3
2 changed files with 121 additions and 157 deletions

View File

@ -16,109 +16,35 @@ import unittest
import mock
from keystoneauth1 import loading as kaloading
from freezerclient.v1 import client
class TestSupportFunctions(unittest.TestCase):
def test_guess_auth_version_returns_none(self):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = ''
mock_opts.os_auth_url = ''
self.assertRaises(Exception, client.guess_auth_version, mock_opts)
def test_guess_auth_version_explicit_3(self):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '3'
self.assertEqual(client.guess_auth_version(mock_opts), '3')
def test_guess_auth_version_explicit_2(self):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '2.0'
self.assertEqual(client.guess_auth_version(mock_opts), '2.0')
def test_guess_auth_version_implicit_3(self):
mock_opts = mock.Mock()
mock_opts.os_auth_url = 'http://whatever/v3'
self.assertEqual(client.guess_auth_version(mock_opts), '3')
def test_guess_auth_version_implicit_2(self):
mock_opts = mock.Mock()
mock_opts.os_auth_url = 'http://whatever/v2.0'
self.assertEqual(client.guess_auth_version(mock_opts), '2.0')
@mock.patch('freezerclient.v1.client.v3')
@mock.patch('freezerclient.v1.client.v2')
def test_get_auth_plugin_v3_Password(self, mock_v2, mock_v3):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '3'
mock_opts.os_user_name = 'myuser'
mock_opts.os_token = ''
client.get_auth_plugin(mock_opts)
self.assertTrue(mock_v3.Password.called)
@mock.patch('freezerclient.v1.client.v3')
@mock.patch('freezerclient.v1.client.v2')
def test_get_auth_plugin_v3_Token(self, mock_v2, mock_v3):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '3'
mock_opts.os_username = ''
mock_opts.os_token = 'mytoken'
client.get_auth_plugin(mock_opts)
self.assertTrue(mock_v3.Token.called)
@mock.patch('freezerclient.v1.client.v3')
@mock.patch('freezerclient.v1.client.v2')
def test_get_auth_plugin_v2_Password(self, mock_v2, mock_v3):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '2.0'
mock_opts.os_user_name = 'myuser'
mock_opts.os_token = ''
client.get_auth_plugin(mock_opts)
self.assertTrue(mock_v2.Password.called)
@mock.patch('freezerclient.v1.client.v3')
@mock.patch('freezerclient.v1.client.v2')
def test_get_auth_plugin_v2_Token(self, mock_v2, mock_v3):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '2.0'
mock_opts.os_username = ''
mock_opts.os_token = 'mytoken'
client.get_auth_plugin(mock_opts)
self.assertTrue(mock_v2.Token.called)
@mock.patch('freezerclient.v1.client.v3')
@mock.patch('freezerclient.v1.client.v2')
def test_get_auth_plugin_raises_when_no_username_token(self, mock_v2,
mock_v3):
mock_opts = mock.Mock()
mock_opts.os_identity_api_version = '2.0'
mock_opts.os_username = ''
mock_opts.os_token = ''
self.assertRaises(Exception, client.get_auth_plugin, mock_opts)
class TestClientMock(unittest.TestCase):
@mock.patch('freezerclient.v1.client.ksa_session')
@mock.patch('freezerclient.v1.client.get_auth_plugin')
def test_client_new(self, mock_get_auth_plugin, mock_ksa_session):
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_client_new(self, mock_ks_loader, mock_ks_session):
session = mock_ks_session.return_value.load_from_options.return_value
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
c = client.Client(endpoint='blabla', auth_url='blabla')
self.assertIsInstance(c, client.Client)
self.assertEqual(session, c.session)
@mock.patch('freezerclient.v1.client.ksa_session')
@mock.patch('freezerclient.v1.client.get_auth_plugin')
def test_client_new_with_kwargs(self, mock_get_auth_plugin,
mock_ksa_session):
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_client_new_with_kwargs_session(self, mock_ks_loader,
mock_ks_session):
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
mock_session = mock.Mock()
kwargs = {'token': 'alpha',
'username': 'bravo',
'password': 'charlie',
'tenant_name': 'delta',
'auth_url': 'echo',
'session': 'foxtrot',
'endpoint': 'golf',
'version': 'hotel'}
'session': mock_session}
c = client.Client(**kwargs)
self.assertIsInstance(c, client.Client)
self.assertEqual('alpha', c.opts.os_token)
@ -126,13 +52,74 @@ class TestClientMock(unittest.TestCase):
self.assertEqual('charlie', c.opts.os_password)
self.assertEqual('delta', c.opts.os_tenant_name)
self.assertEqual('echo', c.opts.os_auth_url)
self.assertEqual('foxtrot', c._session)
self.assertEqual('foxtrot', c.session)
self.assertEqual(mock_session, c._session)
self.assertEqual(mock_session, c.session)
self.assertEqual('golf', c.endpoint)
@mock.patch('freezerclient.v1.client.ksa_session')
@mock.patch('freezerclient.v1.client.get_auth_plugin')
def test_get_token(self, mock_get_auth_plugin, mock_ksa_session):
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_client_new_with_kwargs_usename_password(self, mock_ks_loader,
mock_ks_session):
session = mock_ks_session.return_value.load_from_options.return_value
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
kwargs = {'auth_url': 'one',
'project_id': 'two',
'tenant_name': 'three',
'project_name': 'four',
'user_domain_id': 'five',
'user_domain_name': 'six',
'project_domain_id': 'senven',
'project_domain_name': 'eight',
'username': 'nine',
'password': 'ten'}
c = client.Client(**kwargs)
self.assertIsInstance(c, client.Client)
self.assertEqual('one', c.opts.os_auth_url)
self.assertEqual('two', c.opts.os_project_id)
self.assertEqual('three', c.opts.os_tenant_name)
self.assertEqual('four', c.opts.os_project_name)
self.assertEqual('five', c.opts.os_user_domain_id)
self.assertEqual('six', c.opts.os_user_domain_name)
self.assertEqual('senven', c.opts.os_project_domain_id)
self.assertEqual('eight', c.opts.os_project_domain_name)
self.assertEqual('nine', c.opts.os_username)
self.assertEqual('ten', c.opts.os_password)
self.assertEqual(session, c.session)
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_client_new_with_kwargs_token(self, mock_ks_loader,
mock_ks_session):
session = mock_ks_session.return_value.load_from_options.return_value
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
kwargs = {'auth_url': 'one',
'project_id': 'two',
'tenant_name': 'three',
'project_name': 'four',
'user_domain_id': 'five',
'user_domain_name': 'six',
'project_domain_id': 'senven',
'project_domain_name': 'eight',
'token': 'nine'}
c = client.Client(**kwargs)
self.assertIsInstance(c, client.Client)
self.assertEqual('one', c.opts.os_auth_url)
self.assertEqual('two', c.opts.os_project_id)
self.assertEqual('three', c.opts.os_tenant_name)
self.assertEqual('four', c.opts.os_project_name)
self.assertEqual('five', c.opts.os_user_domain_id)
self.assertEqual('six', c.opts.os_user_domain_name)
self.assertEqual('senven', c.opts.os_project_domain_id)
self.assertEqual('eight', c.opts.os_project_domain_name)
self.assertEqual('nine', c.opts.os_token)
self.assertEqual(session, c.session)
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_get_token(self, mock_ks_loader, mock_ks_session):
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
mock_session = mock.Mock()
mock_session.get_token.return_value = 'antaniX2'
c = client.Client(session=mock_session, endpoint='justtest',
@ -141,10 +128,11 @@ class TestClientMock(unittest.TestCase):
self.assertEqual(c.auth_token, 'antaniX2')
@mock.patch('freezerclient.v1.client.socket')
@mock.patch('freezerclient.v1.client.ksa_session')
@mock.patch('freezerclient.v1.client.get_auth_plugin')
def test_get_client_id(self, mock_get_auth_plugin, mock_ksa_session,
@mock.patch.object(kaloading.session, 'Session', autospec=True)
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
def test_get_client_id(self, mock_ks_loader, mock_ks_session,
mock_socket):
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
mock_socket.gethostname.return_value = 'parmenide'
mock_session = mock.Mock()
mock_session.get_project_id.return_value = 'H2O'

View File

@ -14,9 +14,7 @@
import socket
from keystoneauth1.identity import v2
from keystoneauth1.identity import v3
from keystoneauth1 import session as ksa_session
from keystoneauth1 import loading as kaloading
from freezerclient import utils
from freezerclient.v1.managers import actions
@ -28,58 +26,6 @@ from freezerclient.v1.managers import sessions
FREEZER_SERVICE_TYPE = 'backup'
def guess_auth_version(opts):
"""Guess keystone version to connect to"""
if opts.os_identity_api_version == '3':
return '3'
elif opts.os_identity_api_version == '2.0':
return '2.0'
elif opts.os_auth_url.endswith('v3'):
return '3'
elif opts.os_auth_url.endswith('v2.0'):
return '2.0'
raise Exception('Please provide valid keystone auth url with valid'
' keystone api version to use')
def get_auth_plugin(opts):
"""Create the right keystone connection depending on the version
for the api, if username/password and token are provided, username and
password takes precedence.
"""
auth_version = guess_auth_version(opts)
if opts.os_username:
if auth_version == '3':
return v3.Password(auth_url=opts.os_auth_url,
username=opts.os_username,
password=opts.os_password,
project_name=opts.os_project_name,
user_domain_name=opts.os_user_domain_name,
user_domain_id=opts.os_user_domain_id,
project_domain_name=opts.os_project_domain_name,
project_domain_id=opts.os_project_domain_id,
project_id=opts.os_project_id)
elif auth_version == '2.0':
return v2.Password(auth_url=opts.os_auth_url,
username=opts.os_username,
password=opts.os_password,
tenant_name=opts.os_tenant_name)
elif opts.os_token:
if auth_version == '3':
return v3.Token(auth_url=opts.os_auth_url,
token=opts.os_token,
project_name=opts.os_project_name,
project_domain_name=opts.os_project_domain_name,
project_domain_id=opts.os_project_domain_id,
project_id=opts.os_project_id)
elif auth_version == '2.0':
return v2.Token(auth_url=opts.os_auth_url,
token=opts.os_token,
tenant_name=opts.os_tenant_name)
raise Exception('Unable to determine correct auth method, please provide'
' either username or token')
class Client(object):
"""Client for the OpenStack Disaster Recovery v1 API.
"""
@ -107,7 +53,6 @@ class Client(object):
:param user_domain_id: only for version 3
:param project_domain_name: only for version 3
:param project_domain_id: only for version 3
:param project_id: only for version 3
:param insecure: The verification arguments to pass to requests.
These are of the same form as requests expects,
so True or False to verify (or not) against system
@ -116,9 +61,12 @@ class Client(object):
attempt to locate and use certificates. (optional,
defaults to True)
:param cert: Path to cert
:param project_id: only for version 3
:return: freezerclient.Client
"""
self.project_id = project_id
if opts is None:
self.opts = utils.Namespace({})
self.opts.os_token = token or None
@ -150,6 +98,7 @@ class Client(object):
verify = False
self.validate()
self.project_id = project_id or self.get_project_id
self.jobs = jobs.JobManager(self, verify=verify)
self.clients = clients.ClientManager(self, verify=verify)
@ -161,11 +110,34 @@ class Client(object):
def session(self):
if self._session:
return self._session
auth_plugin = get_auth_plugin(self.opts)
return ksa_session.Session(auth=auth_plugin,
verify=(self.cacert or
not self.opts.insecure),
cert=self.cert)
auth_type = 'password'
auth_kwargs = {
'auth_url': self.opts.os_auth_url,
'project_id': self.opts.os_project_id,
'tenant_name': self.opts.os_tenant_name,
'project_name': self.opts.os_project_name,
'user_domain_id': self.opts.os_user_domain_id,
'user_domain_name': self.opts.os_user_domain_name,
'project_domain_id': self.opts.os_project_domain_id,
'project_domain_name': self.opts.os_project_domain_name,
}
if self.opts.os_username and self.opts.os_password:
auth_kwargs.update({
'username': self.opts.os_username,
'password': self.opts.os_password,
})
elif self.opts.os_token:
auth_type = 'token'
auth_kwargs.update({
'token': self.opts.os_token,
})
loader = kaloading.get_plugin_loader(auth_type)
auth_plugin = loader.load_from_options(**auth_kwargs)
# Let keystoneauth do the necessary parameter conversions
session = kaloading.session.Session().load_from_options(
auth=auth_plugin, insecure=self.opts.insecure, cacert=self.cacert,
cert=self.cert)
return session
@utils.CachedProperty
def endpoint(self):
@ -183,6 +155,10 @@ class Client(object):
def auth_token(self):
return self.session.get_token()
@property
def get_project_id(self):
return self.session.get_project_id()
@utils.CachedProperty
def client_id(self):
return '{0}_{1}'.format(self.session.get_project_id(),