OpenStack sdk 不会使用 keystone v3?

OpenStack sdk won't use keystone v3?

TL;DR:我正在尝试使用 OpenStack SDK 连接到仅提供 Keystone v3 身份验证的 OpenStack 云。 SDK 不断尝试连接到 Keystone v2.0 端点。

我有一个 clouds.yaml 文件,如下所示:

clouds:
  mycloud:
    auth:
      username: admin
      project_name: admin
      password: "secret"
      auth_url: "https://mycloud.example.com:13000"
    region: "os1"
    identity_api_version: 3
    interface: public

您会注意到我已将 identity_api_version 设置为 3,因为我们的 OpenStack 环境没有旧版 v2.0 端点。

如果我尝试像这样访问 openstack 环境:

>>> import openstack
>>> conn = openstack.connect(cloud='mycloud')
>>> conn.list_flavors()

它失败了,回溯如下:

Traceback (most recent call last):
  [...]
  File "/my/project/post-deploy/.venv/lib/python2.7/site-packages/keystoneauth1/session.py", line 869, in request
    raise exceptions.from_response(resp, method, url)
keystoneauth1.exceptions.http.NotFound: (https://mycloud.example.com:13000/v2.0/tokens): The resource could not be found. (HTTP 404) (Request-ID: req-30ec6dc4-f401-41f1-b560-c967d1d32281)

另一方面,标准 openstack cli 工作正常:

$ openstack --os-cloud mycloud flavor list
+---------+------------+-----+------+-----------+-------+-----------+
| ID      | Name       | RAM | Disk | Ephemeral | VCPUs | Is Public |
+---------+------------+-----+------+-----------+-------+-----------+
| 9cc9... | m1.xlarge  |  16 |   10 |         0 |     8 | True      |
| c3df... | m1.tiny    |   1 |   10 |         0 |     1 | True      |
| c64e... | m1.small   |   2 |   10 |         0 |     1 | True      |
+---------+------------+-----+------+-----------+-------+-----------+

我使用的版本:

>>> openstack.version.__version__
'0.19.0'

为什么 openstack sdk 尝试连接到 v2.0 端点?

更新

完整的回溯:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/cloud/openstackcloud.py", line 1891, in list_flavors
    '/flavors/detail', params=dict(is_public='None')),
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 328, in get
    return self.request(url, 'GET', **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/_adapter.py", line 145, in request
    **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 136, in submit_function
    return self.submit_task(task)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 125, in submit_task
    return self.run_task(task=task)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 157, in run_task
    return self._run_task(task)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 177, in _run_task
    return task.wait()
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 79, in wait
    self._traceback)
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 87, in run
    self.done(self.main())
  File "/my/project/.venv/lib/python2.7/site-packages/openstack/task_manager.py", line 59, in main
    return self._main(*self.args, **self.kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/adapter.py", line 213, in request
    return self.session.request(url, method, **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/session.py", line 684, in request
    auth_headers = self.get_auth_headers(auth)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/session.py", line 1071, in get_auth_headers
    return auth.get_headers(self, **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/plugin.py", line 95, in get_headers
    token = self.get_token(session)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/identity/base.py", line 88, in get_token
    return self.get_access(session).auth_token
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/identity/base.py", line 134, in get_access
    self.auth_ref = self.get_auth_ref(session)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/identity/generic/base.py", line 208, in get_auth_ref
    return self._plugin.get_auth_ref(session, **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/identity/v2.py", line 63, in get_auth_ref
    authenticated=False, log=False)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/session.py", line 1019, in post
    return self.request(url, 'POST', **kwargs)
  File "/my/project/.venv/lib/python2.7/site-packages/keystoneauth1/session.py", line 869, in request
    raise exceptions.from_response(resp, method, url)
keystoneauth1.exceptions.http.NotFound: (https://mycloud.example.com:13000/v2.0/tokens): The resource could not be found. (HTTP 404) (Request-ID: req-812aa7ac-d5bb-4fcb-a1f6-6124f5c7f982)

事实证明,为了成功使用 v3 API,您的 clouds.yaml 需要包含域信息。也就是说,我需要的不是问题中显示的示例:

clouds:
  mycloud:
    auth:
      username: admin
      project_name: admin
      password: "secret"
      auth_url: "https://mycloud.example.com:13000"
      user_domain_name: Default
      project_domain_name: Default
    region: "os1"
    identity_api_version: 3
    interface: public

显然,命令行工具为这些值提供了默认值,这就是为什么它们工作得很好,而直接使用 sdk 会失败的原因。