[openstack-dev] [nova] path forward on making project_id optional in API URLs

Sean Dague sean at dague.net
Wed Jan 13 14:06:44 UTC 2016


There is a snag at the moment in making project_id optional in API URLs
because of how python routes modules works.

When we call mapper.resource(...) it's creating a series of
mapper.connect(...) calls to setup routes. This just adds items to a
dictionary. When we later use the mapper to match a route it builds a
master regex out of everything in that dictionary, which it applies to
the inbound url. (Note: this is an extremely large regex in the case of
Nova).

Today our use of the mapper captures the {project_id} here -
https://github.com/openstack/nova/blob/21f7dabd01e5b4d771de4b88114878d93ffa9b18/nova/api/openstack/__init__.py#L200


The issue is that by default mapper captured variables are set to the
regex ([^\/]+) (i.e. match anything that's not a slash).

This makes for an ambiguous route when we consider the following url:

   /v2.1/extensions/os-agents

Because it could match extensions/{name} or it could match
{project_id}/os-agents. There are about a dozen extensions which create
a top level resource.

Because this regex is built from a dictionary, hash seed matters, and it
is not stable which will get precedence.


** Proposal for restriction of project_id **

There is a wrinkle here that, strictly speaking, project_id has no
schema in OpenStack.

If you are using upstream Keystone, your project_id is going to be a 32
character hex uuid. Unless you hack keystone really hard it's not
possible to get another answer.

RAX doesn't use Keystone, their project_id is an int.

I'd like to propose for Nova we restrict project_id in the URL to
[0-9a-f]+, which is any valid hex string. Ints are a subset of this so
RAX will be fine. This will be enough to prevent the collision in the
case of extensions. I tried to float a question out to the operators
list about this, but I actually think this is sufficiently obscure
internals that most people aren't even aware that project_id isn't
always a uuid.

This collision only happens when both sets of routes (with and without
project_id) are being run. That's what we're going to do for a while for
client compatibility. Either route set on it's own is fine.

This was caught by one stray functional test and took a while to figure
out what was going on. But if we come up with a resolution here we can
move forward on this work (which is part of what's needed in revising
the service catalog).

	-Sean

-- 
Sean Dague
http://dague.net



More information about the OpenStack-dev mailing list