Search code examples
pythonopenstack

OpenStack sdk won't use keystone v3?


TL;DR: I'm trying to use the OpenStack SDK to connect to an OpenStack cloud that only offers Keystone v3 authentication. The SDK keeps trying to connect to the Keystone v2.0 endpoint.

I have a clouds.yaml file that look like this:

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

You'll note that I've set identity_api_version to 3, because our OpenStack environment does not have a legacy v2.0 endpoint.

If I try to access the openstack environment like this:

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

It fails with the following traceback:

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)

On the other hand, the standard openstack cli works just fine:

$ 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      |
+---------+------------+-----+------+-----------+-------+-----------+

I'm using version:

>>> openstack.version.__version__
'0.19.0'

Why is the openstack sdk trying to connect to the v2.0 endpoint?

Update

The full traceback:

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)

Solution

  • It turns out that in order to successfully use the v3 API, your clouds.yaml needs to include domain information. That is, instead of the example shown in the question, I needed:

    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
    

    Apparently the command line tools provide defaults for these values, which is why they worked just fine while using the sdk directly would fail.