[RFE] Get me a network

Bug #1475792 reported by Brian Haley on 2015-07-17
18
This bug affects 2 people
Affects Status Importance Assigned to Milestone
neutron
Wishlist
Henry Gessau

Bug Description

As part of the "get me a network" work outlined in https://review.openstack.org/#/c/196803/ we need to be able to auto-allocate Neutron networks for tenants. This is an RFE for those changes.

The current Neutron v2 api calls that Nova makes to neutron live in nova/network/neutronv2/api.py - specifically in _get_available_networks(). In the 'nova boot' case where no network has been specified, it makes two calls to neutron:

            # (1) Retrieve non-public network list owned by the tenant.
            search_opts = {'tenant_id': project_id, 'shared': False}
            nets = neutron.list_networks(**search_opts).get('networks', [])
            # (2) Retrieve public network list.
            search_opts = {'shared': True}
            nets += neutron.list_networks(**search_opts).get('networks', [])

The first will get any existing networks with this tenant_id, the second any shared networks the admin as pre-configured. If nothing exists the boot will error out and fail.

I'm proposing a new API, tentatively called "retrieve_networks", that while similar to "list_networks", can also be given additional information such as a flag parameter, that can signal neutron to auto-allocate a network and return it to the caller. This will be created as an extension, such that a caller could determine if it is supported before calling it (or falling-back to the old method).

The arguments to it can either be similar to "list_networks", or something like { ids: [], tenant_id: None, flags: [] }, where flags can be one or more values such as:

SHARED - return any shared networks
ALLOCATE - if no network exists, auto-allocate one based on config settings

This new API call would only need to be used from the call to _get_available_networks() in allocate_for_instance(), and not from the others.

This could either be a single-step process, where a single POST is done, or a two-step process, such that a GET is used first. We need to ask the API working group what the current recommendation would be. An alternative approach would be to put this logic in a library that Nova can call, rather than baking it into Nova.

The neutron configuration will be done in a new database table, such that updating config files and restarting services are not required. Initially, this will be just a few variables:

 - network name to use (private_network)
 - subnet name to use (private_subnet)
 - subnet cidr to use (10.0.0.0/24)
 - router name to use (private_router)
 - external network to attach router to (must be a UUID ?)

This information - names and CIDR range for the initial subnet, can be the same for every tenant since they are private networks and over-lapping IPs are allowed in this case. The recommendation would be to use an address range in the RFC 1918 space unless otherwise specified.

A future enhancement could be to use subnet_pools for this.

In order to eliminate duplicate default networks being created, the database layer MUST use some sort of distributed locking (based on tenant_id) such that simultaneous calls to different neutron API servers for this new resource do not both succeed. The preferred outcome is for the second (and subsequent) calls to block, and return the network allocated by the first.

So it's in one place, the details that still need some ironing are:

1) Get recommendation from API working group
2) DB schema
3) DB locking
4) Buy-in from Nova, as this affects the nova-neutron API
5) Type of beer desired for first landed patch :) It's Friday here people!

Please feel free to comment!

Changed in neutron:
assignee: nobody → Brian Haley (brian-haley)
Kyle Mestery (mestery) wrote :

This seems like a reasonable thing to me, thanks for writing it up Brian! The subnetpools integration at a future date would be pretty cool, but it seems it's an enhancement and could be deferred to later as you indicate here.

Kyle Mestery (mestery) wrote :

I subscribed Monty and Jay here in the hopes of getting their comments.

Changed in neutron:
status: New → Confirmed
Kyle Mestery (mestery) wrote :

I think this should move to a spec, and if Carl, Doug, Akihiro and Kevin agree, one of them can move it to "Triaged" and Brian can file a simple spec defining the API.

Changed in neutron:
importance: Undecided → High
Alexis Lee (alexisl) wrote :

Instead of "retrieve_networks", where retrieve is essentially synonymous with get and so you'd expect it to not affect any change, what about "get_or_make_network"?

REST orthodoxy says that GETs lack side-effects and that PUT is generally used for creates (POST is for updates). I see no reason to deviate from that here.

Jay Pipes (jaypipes) wrote :

I would be totally fine just adding a single new Neutron API call that would be called, switched on some Nova CONF.auto_allocate_private_subnet option, that would do something like this:

            # (1) Retrieve non-public network list owned by the tenant.
            search_opts = {'tenant_id': project_id, 'shared': False}
            nets = neutron.list_networks(**search_opts).get('networks', [])
            if CONF.auto_allocate_private_subnet:
                nets += neutron.allocate_subnet_from_available_pools(tenant_id=project_id)
            else:
                # (2) Retrieve public network list.
                search_opts = {'shared': True}
                nets += neutron.list_networks(**search_opts).get('networks', [])

             if not nets:
                 raise exception.NoAvailableNetworks(...)

The Neutron API call could look something like this?

            POST /subnet_pools
            {
                 "tenant_id": project_id,
                 "allocate_first_available": true
            }

Kyle Mestery (mestery) wrote :

Thanks for the comments Alexis and Jay!

Brian, I hope this provides some more insight and we can move forward a bit more with this now.

Brian Haley (brian-haley) wrote :

@Alexis - so in your opinion this should stay a two-step process:

1) get a list of networks as we do today
2) allocate a network if none exist

And since GET can't have side-effects (like creating a resource), then a PUT is required?

@Jay - I'd rather not have to add a config option to Nova to make the call, but instead have all this logic live in Neutron, since it would have to be configured there by an admin to work anyway.

This would also allow what is allocated to be completely opaque to Nova - it could be a similar-looking 10.0.0.0/16 subnet for everyone, or it could be pulled from a subnetpool, but Nova doesn't need to know the details, only Neutron does.

And I don't think we should change this behavior:

1) get list of tenant-specific networks
2) get list of shared networks
3) if above yielded nothing, make a network

Some deployments will want to use a public (shared) network and want that to be the default.

Jay - not sure why you're specifying 'auto_allocate_private_subnet'? auto_allocate_network seems more general.

With my API-WG hat on, I think it's not really appropriate to create a network on the fly in response to a GET, because there's a state-change in neutron w.r.t the user's quota etc.

So really I think Jay's suggestion is right-on, except I would prefer to call 'allocate_subnet_from_available_pools' something like 'create_network_using_defaults'. The details of that network would come from neutron config. Is that similar to what you had in mind Bryan?

Adding 2 things to my above comment:

1/ the neutron config might be able to say "don't auto_create networks" in which case instance boot would fail

2/ The exact mechanics of REST API is not as simple as PUT=create/POST=update. We have API-WG advice under review at https://review.openstack.org/#/c/181912 - I would expect this to be a POST.

Alexis Lee (alexisl) wrote :

@Brian I don't think it needs to be a two-step process. If I PUT a calendar entry I might just get back a {"cal_id": 12345} record. My request body specifies request parameters which the server can interpret however it likes to create the resource. If I try to put the exact same calendar entry, I may get a new record or the server may choose to de-duplicate and return 12345 again. So I'm suggesting Neutron interpret PUT {} as "make a simple network" and if "a simple network" already exists, it de-duplicate.

GET is definitely not ok because of side-effects, yes. I prefer PUT to POST because POST is more of an append/update than a create, but de facto POST is used for create so whatever. There's also PATCH of course but that's totally update-y.

Alexis Lee (alexisl) wrote :

So the API-WG advice deviates from my understanding of PUT vs POST. Pragmatically I'd suggest you follow their advice rather than mine though :)

Brian Haley (brian-haley) wrote :

Ok, just to sum up things after seeing these responses and talking to Matthew.

We can create a new API call, for now let's call it "get_me_a_network" which is a PUT call, and takes the same params that "list_networks" does today. It will return a network based on some admin-controlled settings, but by default will:

1) Return a pre-existing tenant network
2) Return a shared network
3) Create and return a new tenant network

That seems to satisfy the API requirements, let me know if I mis-understood.

Alexis Lee (alexisl) wrote :

It appears to be all about whether you can subsequently GET the URI you're PUT/POSTing to. If you PUT, you must be able to GET the URI you PUT to. If you have a special "simple_network" URI, that is true so PUT is OK, even if the resultant network is also available from a UUID-based URI.

Kyle Mestery (mestery) wrote :

Marking Triaged, lets get this party started!

Changed in neutron:
status: Confirmed → Triaged
tags: added: rfe-approved
removed: get-me-a-network rfe
Changed in neutron:
importance: High → Wishlist
Changed in neutron:
milestone: none → mitaka-1
Changed in neutron:
milestone: mitaka-1 → mitaka-2
Changed in neutron:
milestone: mitaka-2 → mitaka-3
Henry Gessau (gessau) on 2016-01-25
summary: - Change Neutron so that it can auto-allocate networks
+ [RFE] Change Neutron so that it can auto-allocate networks
Henry Gessau (gessau) on 2016-01-26
summary: - [RFE] Change Neutron so that it can auto-allocate networks
+ [RFE] Get me a network
Changed in neutron:
status: Triaged → In Progress
Henry Gessau (gessau) on 2016-01-28
Changed in neutron:
assignee: Brian Haley (brian-haley) → Henry Gessau (gessau)

See bp whiteboard for updates

Code completed.

Changed in neutron:
status: In Progress → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Related blueprints