summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glance_store/_drivers/cinder.py112
-rw-r--r--glance_store/tests/unit/test_cinder_store.py26
-rw-r--r--glance_store/tests/unit/test_multistore_cinder.py15
-rw-r--r--glance_store/tests/unit/test_opts.py2
-rw-r--r--releasenotes/notes/support-cinder-user-domain-420c76053dd50534.yaml10
5 files changed, 125 insertions, 40 deletions
diff --git a/glance_store/_drivers/cinder.py b/glance_store/_drivers/cinder.py
index 2db8e9b..37662dd 100644
--- a/glance_store/_drivers/cinder.py
+++ b/glance_store/_drivers/cinder.py
@@ -25,6 +25,9 @@ import time
from keystoneauth1.access import service_catalog as keystone_sc
from keystoneauth1 import exceptions as keystone_exc
+from keystoneauth1 import identity as ksa_identity
+from keystoneauth1 import session as ksa_session
+from keystoneauth1 import token_endpoint as ksa_token_endpoint
from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_utils import units
@@ -79,6 +82,8 @@ Related options:
* cinder_store_user_name
* cinder_store_project_name
* cinder_store_password
+ * cinder_store_project_domain_name
+ * cinder_store_user_domain_name
"""),
cfg.StrOpt('cinder_endpoint_template',
@@ -104,6 +109,8 @@ Related options:
* cinder_store_user_name
* cinder_store_project_name
* cinder_store_password
+ * cinder_store_project_domain_name
+ * cinder_store_user_domain_name
* cinder_catalog_info
"""),
@@ -215,6 +222,8 @@ Related options:
* cinder_store_user_name
* cinder_store_password
* cinder_store_project_name
+ * cinder_store_project_domain_name
+ * cinder_store_user_domain_name
"""),
cfg.StrOpt('cinder_store_user_name',
@@ -222,8 +231,9 @@ Related options:
help="""
User name to authenticate against cinder.
-This must be used with all the following related options. If any of these are
-not specified, the user of the current context is used.
+This must be used with all the following non-domain-related options.
+If any of these are not specified (except domain-related options),
+the user of the current context is used.
Possible values:
* A valid user name
@@ -232,14 +242,33 @@ Related options:
* cinder_store_auth_address
* cinder_store_password
* cinder_store_project_name
+ * cinder_store_project_domain_name
+ * cinder_store_user_domain_name
+
+"""),
+ cfg.StrOpt('cinder_store_user_domain_name',
+ default='Default',
+ help="""
+Domain of the user to authenticate against cinder.
+
+Possible values:
+ * A valid domain name for the user specified by ``cinder_store_user_name``
+
+Related options:
+ * cinder_store_auth_address
+ * cinder_store_password
+ * cinder_store_project_name
+ * cinder_store_project_domain_name
+ * cinder_store_user_name
"""),
cfg.StrOpt('cinder_store_password', secret=True,
help="""
Password for the user authenticating against cinder.
-This must be used with all the following related options. If any of these are
-not specified, the user of the current context is used.
+This must be used with all the following related options.
+If any of these are not specified (except domain-related options),
+the user of the current context is used.
Possible values:
* A valid password for the user specified by ``cinder_store_user_name``
@@ -248,6 +277,8 @@ Related options:
* cinder_store_auth_address
* cinder_store_user_name
* cinder_store_project_name
+ * cinder_store_project_domain_name
+ * cinder_store_user_domain_name
"""),
cfg.StrOpt('cinder_store_project_name',
@@ -258,8 +289,9 @@ Project name where the image volume is stored in cinder.
If this configuration option is not set, the project in current context is
used.
-This must be used with all the following related options. If any of these are
-not specified, the project of the current context is used.
+This must be used with all the following related options.
+If any of these are not specified (except domain-related options),
+the user of the current context is used.
Possible values:
* A valid project name
@@ -268,6 +300,25 @@ Related options:
* ``cinder_store_auth_address``
* ``cinder_store_user_name``
* ``cinder_store_password``
+ * ``cinder_store_project_domain_name``
+ * ``cinder_store_user_domain_name``
+
+"""),
+ cfg.StrOpt('cinder_store_project_domain_name',
+ default='Default',
+ help="""
+Domain of the project where the image volume is stored in cinder.
+
+Possible values:
+ * A valid domain name of the project specified by
+ ``cinder_store_project_name``
+
+Related options:
+ * ``cinder_store_auth_address``
+ * ``cinder_store_user_name``
+ * ``cinder_store_password``
+ * ``cinder_store_project_domain_name``
+ * ``cinder_store_user_domain_name``
"""),
cfg.StrOpt('rootwrap_config',
@@ -350,6 +401,34 @@ Possible values:
"""),
]
+CINDER_SESSION = None
+
+
+def _reset_cinder_session():
+ global CINDER_SESSION
+ CINDER_SESSION = None
+
+
+def get_cinder_session(conf):
+ global CINDER_SESSION
+ if not CINDER_SESSION:
+ auth = ksa_identity.V3Password(
+ password=conf.cinder_store_password,
+ username=conf.cinder_store_user_name,
+ user_domain_name=conf.cinder_store_user_domain_name,
+ project_name=conf.cinder_store_project_name,
+ project_domain_name=conf.cinder_store_project_domain_name,
+ auth_url=conf.cinder_store_auth_address
+ )
+ if conf.cinder_api_insecure:
+ verify = False
+ elif conf.cinder_ca_certificates_file:
+ verify = conf.cinder_ca_certificates_file
+ else:
+ verify = True
+ CINDER_SESSION = ksa_session.Session(auth=auth, verify=verify)
+ return CINDER_SESSION
+
class StoreLocation(glance_store.location.StoreLocation):
@@ -476,15 +555,18 @@ class Store(glance_store.driver.Store):
else:
user_overriden = self.is_user_overriden()
+ session = get_cinder_session(self.store_conf)
+
if user_overriden:
username = self.store_conf.cinder_store_user_name
- password = self.store_conf.cinder_store_password
- project = self.store_conf.cinder_store_project_name
url = self.store_conf.cinder_store_auth_address
+ # use auth that is already in the session
+ auth = None
else:
username = context.user_id
- password = context.auth_token
project = context.project_id
+ # noauth extracts user_id:project_id from auth_token
+ token = context.auth_token or '%s:%s' % (username, project)
if self.store_conf.cinder_endpoint_template:
template = self.store_conf.cinder_endpoint_template
@@ -504,23 +586,17 @@ class Store(glance_store.driver.Store):
reason = _("Failed to find Cinder from a service catalog.")
raise exceptions.BadStoreConfiguration(store_name="cinder",
reason=reason)
+ auth = ksa_token_endpoint.Token(endpoint=url, token=token)
c = cinderclient.Client(
- username, password, project, auth_url=url,
+ session=session, auth=auth,
region_name=self.store_conf.cinder_os_region_name,
- insecure=self.store_conf.cinder_api_insecure,
- retries=self.store_conf.cinder_http_retries,
- cacert=self.store_conf.cinder_ca_certificates_file)
+ retries=self.store_conf.cinder_http_retries)
LOG.debug(
'Cinderclient connection created for user %(user)s using URL: '
'%(url)s.', {'user': username, 'url': url})
- # noauth extracts user_id:project_id from auth_token
- if not user_overriden:
- c.client.auth_token = context.auth_token or '%s:%s' % (username,
- project)
- c.client.management_url = url
return c
@contextlib.contextmanager
diff --git a/glance_store/tests/unit/test_cinder_store.py b/glance_store/tests/unit/test_cinder_store.py
index 7ba655d..7abe0c3 100644
--- a/glance_store/tests/unit/test_cinder_store.py
+++ b/glance_store/tests/unit/test_cinder_store.py
@@ -26,7 +26,6 @@ import tempfile
import time
import uuid
-from cinderclient.v3 import client as cinderclient
from os_brick.initiator import connector
from oslo_concurrency import processutils
from oslo_utils.secretutils import md5
@@ -67,31 +66,30 @@ class TestCinderStore(base.StoreBaseTest,
auth_token='fake_token',
project_id='fake_project')
self.hash_algo = 'sha256'
+ cinder._reset_cinder_session()
def test_get_cinderclient(self):
cc = self.store.get_cinderclient(self.context)
- self.assertEqual('fake_token', cc.client.auth_token)
- self.assertEqual('http://foo/public_url', cc.client.management_url)
+ self.assertEqual('fake_token', cc.client.auth.token)
+ self.assertEqual('http://foo/public_url', cc.client.auth.endpoint)
- def test_get_cinderclient_with_user_overriden(self):
+ def _test_get_cinderclient_with_user_overriden(self):
self.config(cinder_store_user_name='test_user')
self.config(cinder_store_password='test_password')
self.config(cinder_store_project_name='test_project')
self.config(cinder_store_auth_address='test_address')
cc = self.store.get_cinderclient(self.context)
- self.assertIsNone(cc.client.auth_token)
- self.assertEqual('test_address', cc.client.management_url)
+ self.assertEqual('test_project', cc.client.session.auth.project_name)
+ self.assertEqual('Default', cc.client.session.auth.project_domain_name)
+ return cc
+
+ def test_get_cinderclient_with_user_overriden(self):
+ self._test_get_cinderclient_with_user_overriden()
def test_get_cinderclient_with_user_overriden_and_region(self):
self.config(cinder_os_region_name='test_region')
- fake_client = FakeObject(client=FakeObject(auth_token=None))
- with mock.patch.object(cinderclient, 'Client',
- return_value=fake_client) as mock_client:
- self.test_get_cinderclient_with_user_overriden()
- mock_client.assert_called_once_with(
- 'test_user', 'test_password', 'test_project',
- auth_url='test_address', cacert=None, insecure=False,
- region_name='test_region', retries=3)
+ cc = self._test_get_cinderclient_with_user_overriden()
+ self.assertEqual('test_region', cc.client.region_name)
def test_temporary_chown(self):
class fake_stat(object):
diff --git a/glance_store/tests/unit/test_multistore_cinder.py b/glance_store/tests/unit/test_multistore_cinder.py
index 1c6ae26..d87bdfc 100644
--- a/glance_store/tests/unit/test_multistore_cinder.py
+++ b/glance_store/tests/unit/test_multistore_cinder.py
@@ -98,14 +98,15 @@ class TestMultiCinderStore(base.MultiStoreBaseTest,
user_id='admin_user',
auth_token='admin_token',
project_id='admin_project')
+ cinder._reset_cinder_session()
def test_location_url_prefix_is_set(self):
self.assertEqual("cinder://cinder1", self.store.url_prefix)
def test_get_cinderclient(self):
cc = self.store.get_cinderclient(self.context)
- self.assertEqual('fake_token', cc.client.auth_token)
- self.assertEqual('http://foo/public_url', cc.client.management_url)
+ self.assertEqual('fake_token', cc.client.auth.token)
+ self.assertEqual('http://foo/public_url', cc.client.auth.endpoint)
def test_get_cinderclient_with_user_overriden(self):
self.config(cinder_store_user_name='test_user', group="cinder1")
@@ -113,16 +114,14 @@ class TestMultiCinderStore(base.MultiStoreBaseTest,
self.config(cinder_store_project_name='test_project', group="cinder1")
self.config(cinder_store_auth_address='test_address', group="cinder1")
cc = self.store.get_cinderclient(self.context)
- self.assertIsNone(cc.client.auth_token)
- self.assertEqual('test_address', cc.client.management_url)
+ self.assertEqual('Default', cc.client.session.auth.project_domain_name)
+ self.assertEqual('test_project', cc.client.session.auth.project_name)
def test_get_cinderclient_legacy_update(self):
cc = self.store.get_cinderclient(self.fake_admin_context,
legacy_update=True)
- self.assertEqual('admin_token', cc.client.auth_token)
- self.assertEqual('admin_user', cc.client.user)
- self.assertEqual('admin_project', cc.client.projectid)
- self.assertEqual('http://foo/public_url', cc.client.management_url)
+ self.assertEqual('admin_token', cc.client.auth.token)
+ self.assertEqual('http://foo/public_url', cc.client.auth.endpoint)
def test_temporary_chown(self):
class fake_stat(object):
diff --git a/glance_store/tests/unit/test_opts.py b/glance_store/tests/unit/test_opts.py
index 6f46d60..5928d4f 100644
--- a/glance_store/tests/unit/test_opts.py
+++ b/glance_store/tests/unit/test_opts.py
@@ -77,8 +77,10 @@ class OptsTestCase(base.StoreBaseTest):
'cinder_state_transition_timeout',
'cinder_store_auth_address',
'cinder_store_user_name',
+ 'cinder_store_user_domain_name',
'cinder_store_password',
'cinder_store_project_name',
+ 'cinder_store_project_domain_name',
'cinder_volume_type',
'cinder_use_multipath',
'cinder_enforce_multipath',
diff --git a/releasenotes/notes/support-cinder-user-domain-420c76053dd50534.yaml b/releasenotes/notes/support-cinder-user-domain-420c76053dd50534.yaml
new file mode 100644
index 0000000..7763366
--- /dev/null
+++ b/releasenotes/notes/support-cinder-user-domain-420c76053dd50534.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ For the Cinder store, if using an internal user to store images,
+ it is now possible to have the internal user and the internal project
+ in Keystone domains other than the ``Default`` one.
+ Two new config options ``cinder_store_user_domain_name`` and
+ ``cinder_store_project_domain_name`` are added
+ (both default to ``Default``) and now are possible to use in the
+ configuration of the Cinder store.