Fix nova proxy admin login

The Nova Python client changed how it handles Keystone authentication
during the Ocata release.  In particular it treats context.auth_token
as an authentication token.  This broke the Nova proxy admin login
that Trove uses because it was passing the user password on the
context.auth_token property.

User id and password authentication is still possible through Nova
client but the password must be explicitly passed on its own keyword
arg.  Additionally, Keystone user/password authentication has also
changed in the meantime and requires the passing of the user domain
name.

Additional changes were made in the code path to move away from old
deprecated Oslo context property names to the new names.

Closes-Bug: #1700586

Change-Id: Ic410692e07194bae64d9a3e49816bc24958969d4
This commit is contained in:
Samuel Matzek 2017-07-27 09:41:23 -05:00
parent 1bdd096934
commit c6ca687354
4 changed files with 36 additions and 7 deletions

View File

@ -362,6 +362,8 @@ common_opts = [
help="Admin tenant ID used to connect to Nova.", secret=True),
cfg.StrOpt('nova_proxy_admin_tenant_name', default='',
help="Admin tenant name used to connect to Nova.", secret=True),
cfg.StrOpt('nova_proxy_admin_user_domain_name', default='Default',
help="User domain of the admin user used to connect to Nova."),
cfg.StrOpt('network_label_regex', default='^private$',
help='Regular expression to match Trove network labels.'),
cfg.StrOpt('ip_regex', default=None,

View File

@ -84,11 +84,11 @@ def guest_client(context, id, manager=None):
return clazz(context, id)
def nova_client(context, region_name=None):
def nova_client(context, region_name=None, password=None):
if CONF.nova_compute_url:
url = '%(nova_url)s%(tenant)s' % {
'nova_url': normalize_url(CONF.nova_compute_url),
'tenant': context.tenant}
'tenant': context.project_id}
else:
url = get_endpoint(context.service_catalog,
service_type=CONF.nova_compute_service_type,
@ -97,9 +97,11 @@ def nova_client(context, region_name=None):
client = Client(CONF.nova_client_version,
username=context.user,
password=password,
endpoint_override=url,
project_id=context.tenant,
project_id=context.project_id,
project_domain_name=context.project_domain_name,
user_domain_name=context.user_domain_name,
auth_url=CONF.trove_auth_url,
auth_token=context.auth_token,
insecure=CONF.nova_api_insecure)
@ -113,7 +115,7 @@ def create_admin_nova_client(context):
Creates client that uses trove admin credentials
:return: a client for nova for the trove admin
"""
client = create_nova_client(context)
client = create_nova_client(context, password=CONF.nova_proxy_admin_pass)
return client

View File

@ -45,8 +45,8 @@ class Manager(periodic_task.PeriodicTasks):
super(Manager, self).__init__(CONF)
self.admin_context = TroveContext(
user=CONF.nova_proxy_admin_user,
auth_token=CONF.nova_proxy_admin_pass,
tenant=CONF.nova_proxy_admin_tenant_id)
tenant=CONF.nova_proxy_admin_tenant_id,
user_domain_name=CONF.nova_proxy_admin_user_domain_name)
if CONF.exists_notification_transformer:
self.exists_transformer = importutils.import_object(
CONF.exists_notification_transformer,

View File

@ -17,7 +17,7 @@
#
import uuid
from mock import patch, MagicMock
from mock import ANY, patch, MagicMock
import swiftclient.client
from testtools import ExpectedException, matchers
@ -363,6 +363,7 @@ class TestCreateNovaClient(trove_testtools.TestCase):
cfg.CONF.clear_override('nova_compute_url')
cfg.CONF.clear_override('nova_compute_service_type')
cfg.CONF.clear_override('os_region_name')
cfg.CONF.clear_override('nova_proxy_admin_pass')
def test_create_with_no_conf_no_catalog(self):
self.assertRaises(exception.EmptyCatalog,
@ -417,6 +418,30 @@ class TestCreateNovaClient(trove_testtools.TestCase):
self.assertEqual('%s%s' % (nova_url_from_conf, admin_tenant_id),
admin_client.client.endpoint_override)
@patch('trove.common.remote.Client', autospec=True)
def test_nova_client_password_passthrough(self, nova_mock):
test_domain = 'test_domain_name'
ctx = TroveContext(user='admin1',
project_id='project_id',
user_domain_name=test_domain,
service_catalog=self.service_catalog)
remote.nova_client(ctx, password='adminpass')
nova_mock.assert_called_with(ANY, username='admin1',
password='adminpass',
user_domain_name=test_domain,
project_id='project_id',
auth_token=None,
auth_url=ANY,
endpoint_override=ANY,
project_domain_name=ANY,
insecure=False)
@patch('trove.common.remote.create_nova_client', autospec=True)
def test_admin_client_password(self, nc_mock):
cfg.CONF.set_override('nova_proxy_admin_pass', 's3cr3t3')
remote.create_admin_nova_client('mycontext')
nc_mock.assert_called_with('mycontext', password='s3cr3t3')
class TestCreateSwiftClient(trove_testtools.TestCase):
def setUp(self):