Currently the concept of 'external' network is somewhat similar to the concept of a 'shared' network. However, while every tenant can operate on a shared network, performing operations such as creating port, the set of operations a tenant can perform on a shared network is more limited, as it's currently restrained to setting external gateways on routers and creating floating IPs.
Nevertheless, the concept of 'external' implies some forms of sharing, and this has some bearing on the topologies that can be achieved. For instance it is not possible at the moment have an external network which is reserved to a specific tenant. That external network will always show up in queries performed by other tenants too.
The goal of this blueprint is to find a solution for limiting the visibility scope of an external network while preserving backward compatibility. If a reasonable solution which preserves backward compatibility can't be found this blueprint should be deferred to the next release.
Apparently the easiest solution is to decouple the concept of 'external' from the concept of sharing. External will qualify the network in topological terms, whereas 'shared' will qualify it in terms of access. In this way, the external network as we know it today would be 'external and shared', whereas a network which is simply external would be visible only to the tenant who owns it, as any other network.
This is 'kind of' backward compatible. Indeed a data migration can be used to set shared=True for each network where external=True, but the responses will be different since the 'shared' attribute would change from False to True for existing external networks.
Moreover, in order to preserve backward compatibility, setting a network as external should keep having the same behaviour as now. This will mean that the network has to be 'shared' and 'external' at the same time. If a user want a 'private' external network, he/she will have to submit a request with shared=False, external=True (and this is a bit awkward). Similarly when unsetting the 'external' attribute, the network will go back to the 'private' state.
The real problem comes however when considering the following sequence of operations:
- POST /networks with shared=True --> shared = True, external=False
- PUT /networks with external=True --> shared=True, external=False
- PUT /networks external=False --> shared=False, external=False
The resulting state of the network at step 3 differs from step 1, and this is unaccepable.
Also, there will be complications related to policy verifications in this case. [discuss further]
Public 'external' networks have no tenant
Set tenant_id=None for external networks which should be shared. Implications due to resources without tenant_id will cause get_networks to not return this network, and this will require some non-trivial changes into Neutron's db layer. Resources without owners might be troublesome also from an authZ perspective.
It is not adviced to follow this approach.
Basically the logic is: if an admin creates an external network, it will be shared, unless he/she explicitly creates it for another tenant, in which case it will be private for that tenant. This could be achieved with a data model API not exposed through the API. Implicitly set db field for privatising the network if it's external and the tenant_id selected != from context.tenant_id.
If there is a good reason for allowing programmatic control over sharing for external networks, this attribute (which we could call private) might be exposed through the API too. In this case we would be introducing a concept of private network. By default each network is private. A network can't be private and shared at the same time. A network however can be private and external at the same time.