Create auto allocated networks in disabled state
Under particular circumstances, multiple requests to the auto-allocated-topology extension may lead to the transient creation of duplicated resources. This is dealt with by the service plugin code, which cleans them up once the condition is detected. However the client may accidentally be impacted and potentially left in error (recoverable on retry). In order to address this error condition, the logic to provision the network for any given tenant is tweaked slightly so that the network is created in disabled state and re-enabled when it is safe to do so. A Neutron client should check the network status to see if the network is ready for use before getting its hands on it. Closes-bug: #1591766 Change-Id: Ia6ff5ad975673875216eb470080dfc0dcf6b9ab2
This commit is contained in:
parent
877778ee4c
commit
d91a4e1930
|
@ -27,6 +27,9 @@ import webob.exc
|
|||
|
||||
from neutron._i18n import _, _LI
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.plugins.common import constants as p_const
|
||||
|
||||
|
@ -150,6 +153,17 @@ def create_network(core_plugin, context, net, check_allow_post=True):
|
|||
return core_plugin.create_network(context, {'network': net_data})
|
||||
|
||||
|
||||
def update_network(core_plugin, context, network_id, net_data):
|
||||
network = core_plugin.update_network(
|
||||
context, network_id, {resources.NETWORK: net_data})
|
||||
# bundle the plugin API update with any other action required to
|
||||
# reflect a state change on the network, e.g. DHCP notifications
|
||||
registry.notify(resources.NETWORK, events.BEFORE_RESPONSE, core_plugin,
|
||||
context=context, data={resources.NETWORK: network},
|
||||
method_name='network.update.end')
|
||||
return network
|
||||
|
||||
|
||||
def create_subnet(core_plugin, context, subnet, check_allow_post=True):
|
||||
subnet_data = _fixup_res_dict(context, attributes.SUBNETS,
|
||||
subnet.get('subnet', {}),
|
||||
|
|
|
@ -223,7 +223,7 @@ class AutoAllocatedTopologyMixin(common_db_mixin.CommonDbMixin):
|
|||
try:
|
||||
network_args = {
|
||||
'name': 'auto_allocated_network',
|
||||
'admin_state_up': True,
|
||||
'admin_state_up': False,
|
||||
'tenant_id': tenant_id,
|
||||
'shared': False
|
||||
}
|
||||
|
@ -285,13 +285,17 @@ class AutoAllocatedTopologyMixin(common_db_mixin.CommonDbMixin):
|
|||
# NOTE(armax): saving the auto allocated topology in a
|
||||
# separate transaction will keep the Neutron DB and the
|
||||
# Neutron plugin backend in sync, thus allowing for a
|
||||
# more bullet proof cleanup.
|
||||
# more bullet proof cleanup. Any other error will have
|
||||
# to bubble up.
|
||||
with context.session.begin(subtransactions=True):
|
||||
context.session.add(
|
||||
models.AutoAllocatedTopology(
|
||||
tenant_id=tenant_id,
|
||||
network_id=network_id,
|
||||
router_id=router_id))
|
||||
p_utils.update_network(
|
||||
self.core_plugin, context,
|
||||
network_id, {'admin_state_up': True})
|
||||
except db_exc.DBDuplicateEntry:
|
||||
LOG.error(_LE("Multiple auto-allocated networks detected for "
|
||||
"tenant %(tenant)s. Attempting clean up for "
|
||||
|
@ -302,8 +306,7 @@ class AutoAllocatedTopologyMixin(common_db_mixin.CommonDbMixin):
|
|||
self._cleanup(
|
||||
context, network_id=network_id,
|
||||
router_id=router_id, subnets=subnets)
|
||||
network_id = self._get_auto_allocated_network(
|
||||
context, tenant_id)
|
||||
network_id = self._get_auto_allocated_network(context, tenant_id)
|
||||
return network_id
|
||||
|
||||
def _cleanup(self, context, network_id=None, router_id=None, subnets=None):
|
||||
|
|
|
@ -87,6 +87,8 @@ class TestAutoAllocatedTopology(base.BaseAdminNetworkTest):
|
|||
|
||||
network_id1 = topology['id']
|
||||
self.assertIsNotNone(network_id1)
|
||||
network = self.client.show_network(topology['id'])['network']
|
||||
self.assertTrue(network['admin_state_up'])
|
||||
resources_after1 = self._count_topology_resources()
|
||||
# One network, two subnets (v4 and v6) and one router
|
||||
self.assertEqual((1, self.num_subnetpools, 1), resources_after1)
|
||||
|
|
Loading…
Reference in New Issue