diff --git a/contrib/devstack/lib/cue b/contrib/devstack/lib/cue index 20c6d0e8..e838d2af 100644 --- a/contrib/devstack/lib/cue +++ b/contrib/devstack/lib/cue @@ -105,10 +105,13 @@ function configure_cue { # Set flow create cluster node vm active retry count iniset $CUE_CONF flow_options create_cluster_node_vm_active_retry_count $CUE_TF_CREATE_CLUSTER_NODE_VM_ACTIVE_RETRY_COUNT - iniset $CUE_CONF openstack os_auth_url $KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v2.0 - iniset $CUE_CONF openstack os_tenant_name admin + iniset $CUE_CONF openstack os_auth_url $KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v3 + iniset $CUE_CONF openstack os_project_name admin iniset $CUE_CONF openstack os_username admin iniset $CUE_CONF openstack os_password $ADMIN_PASSWORD + iniset $CUE_CONF openstack os_project_domain_name default + iniset $CUE_CONF openstack os_user_domain_name default + iniset $CUE_CONF openstack os_auth_version 3 if [ "$SYSLOG" != "False" ]; then iniset $CUE_CONF DEFAULT use_syslog True diff --git a/cue/client.py b/cue/client.py index ab5f87bc..2c08b402 100644 --- a/cue/client.py +++ b/cue/client.py @@ -13,12 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. -import cinderclient.client as CinderClient +from keystoneclient.auth.identity import v2 as keystone_v2_auth +from keystoneclient.auth.identity import v3 as keystone_v3_auth +from keystoneclient import session as keystone_session import neutronclient.neutron.client as NeutronClient import novaclient.client as NovaClient from oslo_config import cfg +from oslo_log import log as logging +LOG = logging.getLogger(__name__) CONF = cfg.CONF @@ -26,18 +30,16 @@ OS_OPTS = [ cfg.StrOpt('os_region_name', help='Region name', default=None), - cfg.StrOpt('os_tenant_id', - help='Openstack Tenant ID', - default=None), - cfg.StrOpt('os_tenant_name', - help='Openstack Tenant Name', - default=None), cfg.StrOpt('os_username', help='Openstack Username', default=None), cfg.StrOpt('os_password', help='Openstack Password', default=None), + cfg.StrOpt('os_auth_version', + help='Openstack authentication version', + choices=('2.0', '3'), + default='3'), cfg.StrOpt('os_auth_url', help='Openstack Authentication (Identity) URL', default=None), @@ -53,6 +55,15 @@ OS_OPTS = [ cfg.StrOpt('os_cacert', help='Openstack cacert', default=None), + cfg.StrOpt('os_project_name', + help='Openstack project name', + default=None), + cfg.StrOpt('os_project_domain_name', + help='Openstack project domain name', + default=None), + cfg.StrOpt('os_user_domain_name', + help='Openstack user domain name', + default=None), ] opt_group = cfg.OptGroup( @@ -65,11 +76,9 @@ CONF.register_opts(OS_OPTS, group=opt_group) def nova_client(): + keystoneSession = get_keystone_session() return NovaClient.Client(2, - username=CONF.openstack.os_username, - api_key=CONF.openstack.os_password, - project_id=CONF.openstack.os_tenant_name, - tenant_id=CONF.openstack.os_tenant_id, + session=keystoneSession, auth_url=CONF.openstack.os_auth_url, region_name=CONF.openstack.os_region_name, insecure=CONF.openstack.os_insecure, @@ -77,24 +86,55 @@ def nova_client(): ) -def cinder_client(): - return CinderClient.Client('1', - CONF.openstack.os_username, - CONF.openstack.os_password, - CONF.openstack.os_tenant_name, - CONF.openstack.os_auth_url, - CONF.openstack.os_insecure, - cacert=CONF.openstack.os_cacert, - ) - - def neutron_client(): + keystoneSession = get_keystone_session() return NeutronClient.Client('2.0', - username=CONF.openstack.os_username, - password=CONF.openstack.os_password, - tenant_name=CONF.openstack.os_tenant_name, + session=keystoneSession, auth_url=CONF.openstack.os_auth_url, region_name=CONF.openstack.os_region_name, insecure=CONF.openstack.os_insecure, ca_cert=CONF.openstack.os_cacert, ) + + +def get_auth_v2(): + auth_url = CONF.openstack.os_auth_url + username = CONF.openstack.os_username + password = CONF.openstack.os_password + tenant_name = CONF.openstack.os_project_name + return keystone_v2_auth.Password(auth_url=auth_url, + username=username, + password=password, + tenant_name=tenant_name, + ) + + +def get_auth_v3(): + auth_url = CONF.openstack.os_auth_url + username = CONF.openstack.os_username + password = CONF.openstack.os_password + project_name = CONF.openstack.os_project_name + project_domain_name = CONF.openstack.os_project_domain_name + user_domain_name = CONF.openstack.os_user_domain_name + return keystone_v3_auth.Password(auth_url=auth_url, + username=username, + password=password, + project_name=project_name, + project_domain_name=project_domain_name, + user_domain_name=user_domain_name, + ) + + +def get_keystone_session(): + insecure = CONF.openstack.os_insecure + if insecure: + verify = False + else: + verify = CONF.openstack.os_cacert + + if CONF.openstack.os_auth_version == '2.0': + return keystone_session.Session(auth=get_auth_v2(), + verify=verify) + else: + return keystone_session.Session(auth=get_auth_v3(), + verify=verify) diff --git a/cue/tests/functional/api/__init__.py b/cue/tests/functional/api/__init__.py index 29a846ff..9f745dba 100644 --- a/cue/tests/functional/api/__init__.py +++ b/cue/tests/functional/api/__init__.py @@ -39,7 +39,7 @@ class APITest(base.FunctionalTestCase): def setUp(self): super(APITest, self).setUp() - self.CONF.config(auth_version="v2.0", + self.CONF.config(auth_version="v3", group=OPT_GROUP_NAME) self.app = self._make_app() self.auth_headers = {'X-User-Id': str(self.context.user_id), diff --git a/cue/tests/unit/test_client.py b/cue/tests/unit/test_client.py new file mode 100644 index 00000000..1fccbba9 --- /dev/null +++ b/cue/tests/unit/test_client.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# +# 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. + +import mock +from oslo_config import fixture as config_fixture + +from cue import client +from cue.tests.unit import base + + +class TestClient(base.UnitTestCase): + + def setUp(self): + + super(TestClient, self).setUp() + + # setup config fixture + self.CONF = config_fixture.Config() + self.useFixture(self.CONF) + + def tearDown(self): + + super(TestClient, self).tearDown() + self.CONF.reset() + + @mock.patch('keystoneclient.auth.identity.v2.Password') + def test_get_auth_v2(self, mock_auth_v2): + """Test cue.client get_auth_v2. + + Asserts that the keystone auth password is called. + """ + + os_auth_url = "http://localhost:5000/v2.0" + os_username = "test_user" + os_password = "test_password" + os_project_name = "test_tenant" + self.CONF.config(os_auth_url=os_auth_url, + os_username=os_username, + os_password=os_password, + os_project_name=os_project_name, + group="openstack") + client.get_auth_v2() + mock_auth_v2.assert_called_once_with(auth_url=os_auth_url, + password=os_password, + tenant_name=os_project_name, + username=os_username) + + @mock.patch('keystoneclient.auth.identity.v3.Password') + def test_get_auth_v3(self, mock_auth_v3): + """Test cue.client get_auth_v3. + + Asserts that the keystone auth password is called. + """ + + os_auth_url = "http://localhost:5000/v3" + os_username = "test_user" + os_password = "test_password" + os_project_name = "test_project" + os_project_domain_name = "test_domain" + os_user_domain_name = "test_domain" + self.CONF.config(os_auth_url=os_auth_url, + os_username=os_username, + os_password=os_password, + os_project_name=os_project_name, + os_project_domain_name=os_project_domain_name, + os_user_domain_name=os_user_domain_name, + group="openstack") + client.get_auth_v3() + mock_auth_v3.assert_called_once_with( + auth_url=os_auth_url, + password=os_password, + project_domain_name=os_project_domain_name, + project_name=os_project_name, + user_domain_name=os_user_domain_name, + username=os_username) + + @mock.patch('keystoneclient.session.Session') + @mock.patch('cue.client.get_auth_v2') + def test_get_keystone_session_v2(self, mock_auth_v2, mock_ks_session): + """Test cue.client get_keystone_session. + + Asserts that the keystone session and client get_auth_v2 is called. + """ + + os_auth_version = "2.0" + os_insecure = True + self.CONF.config(os_auth_version=os_auth_version, + os_insecure=os_insecure, + group="openstack") + client.get_keystone_session() + mock_auth_v2.assert_called_once_with() + mock_ks_session.assert_called_once_with(auth=mock_auth_v2(), + verify=False) + + @mock.patch('keystoneclient.session.Session') + @mock.patch('cue.client.get_auth_v3') + def test_get_keystone_session_v3(self, mock_auth_v3, mock_ks_session): + """Test cue.client get_keystone_session. + + Asserts that the keystone session and client get_auth_v3 is called. + """ + + os_auth_version = "3" + os_insecure = False + os_cacert = None + self.CONF.config(os_auth_version=os_auth_version, + os_insecure=os_insecure, + os_cacert=os_cacert, + group="openstack") + client.get_keystone_session() + mock_auth_v3.assert_called_once_with() + mock_ks_session.assert_called_once_with(auth=mock_auth_v3(), + verify=os_cacert) diff --git a/etc/cue/cue.conf.sample b/etc/cue/cue.conf.sample index c020479e..99b4b9ac 100644 --- a/etc/cue/cue.conf.sample +++ b/etc/cue/cue.conf.sample @@ -721,13 +721,13 @@ os_image_id= #os_tenant_id= # -# Openstack Tenant Name +# Openstack Project Name # -# Openstack Tenant ID and Tenant Name are not both required, +# Openstack Project ID and Project Name are not both required, # but at least one must be supplied. If both are supplied, -# Tenant ID will be preferred over the Tenant Name +# Project ID will be preferred over the Tenant Name # -#os_tenant_name= +#os_project_name= # # Openstack Username @@ -752,4 +752,25 @@ os_image_id= # # Openstack Availability zone # -#os_availability_zone= \ No newline at end of file +#os_availability_zone= + +# +# Openstack Auth version +# +# Openstack Auth version which must be supplied to authenticate +# against specific Keystone version '2.0'/'3'. +# +#os_auth_version= + +# +# Openstack Project Domain Name +# If using a project name specify either it’s owning +# domain name or ID. This is required only for keystone v3. +#os_project_domain_name= + +# +# Openstack User Domain Name +# If using a username specify either it’s owning +# domain name or ID. This is required only for keystone v3. +# +#os_user_domain_name= \ No newline at end of file