def _save(self, context, tenant_id, network_id, router_id, subnets): """Save auto-allocated topology, or revert in case of DB errors.""" try: auto_allocate_obj.AutoAllocatedTopology( context, project_id=tenant_id, network_id=network_id, router_id=router_id).create() self.core_plugin.update_network( context, network_id, {'network': { 'admin_state_up': True }}) except obj_exc.NeutronDbObjectDuplicateEntry: LOG.debug( "Multiple auto-allocated networks detected for " "tenant %s. Attempting clean up for network %s " "and router %s.", tenant_id, network_id, router_id) self._cleanup(context, network_id=network_id, router_id=router_id, subnets=subnets) network_id = self._get_auto_allocated_network(context, tenant_id) except Exception as e: raise exceptions.UnknownProvisioningError(e, network_id=network_id, router_id=router_id, subnets=subnets) return network_id
def _provision_external_connectivity( self, context, default_external_network, subnets, tenant_id): """Uplink tenant subnet(s) to external network.""" router_args = { 'name': 'auto_allocated_router', l3.EXTERNAL_GW_INFO: {'network_id': default_external_network}, 'tenant_id': tenant_id, 'admin_state_up': True } router = None attached_subnets = [] try: router = self.l3_plugin.create_router( context, {'router': router_args}) for subnet in subnets: self.l3_plugin.add_router_interface( context, router['id'], {'subnet_id': subnet['id']}) attached_subnets.append(subnet) return router except n_exc.BadRequest as e: LOG.error(_LE("Unable to auto allocate topology for tenant " "%(tenant_id)s because of router errors. " "Reason: %(reason)s"), {'tenant_id': tenant_id, 'reason': e}) router_id = router['id'] if router else None self._cleanup(context, network_id=subnets[0]['network_id'], router_id=router_id, subnets=attached_subnets) raise exceptions.AutoAllocationFailure( reason=_("Unable to provide external connectivity")) except Exception as e: router_id = router['id'] if router else None raise exceptions.UnknownProvisioningError( e, network_id=subnets[0]['network_id'], router_id=router_id, subnets=subnets)
def _save(self, context, tenant_id, network_id, router_id, subnets): """Save auto-allocated topology, or revert in case of DB errors.""" try: # 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. 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)) self.core_plugin.update_network( context, network_id, {'network': {'admin_state_up': True}}) except db_exc.DBDuplicateEntry: LOG.debug("Multiple auto-allocated networks detected for " "tenant %s. Attempting clean up for network %s " "and router %s.", tenant_id, network_id, router_id) self._cleanup( context, network_id=network_id, router_id=router_id, subnets=subnets) network_id = self._get_auto_allocated_network(context, tenant_id) except Exception as e: raise exceptions.UnknownProvisioningError( e, network_id=network_id, router_id=router_id, subnets=subnets) return network_id
def test__build_topology_error_network_with_router(self): provisioning_exception = exceptions.UnknownProvisioningError( KeyError, network_id='foo_n', router_id='foo_r') with mock.patch.object(self.mixin, '_provision_tenant_private_network') as f: f.return_value = [{'network_id': 'foo_n'}] self._test__build_topology('_provision_external_connectivity', provisioning_exception)
def test__build_topology_error_only_network_again(self): provisioning_exception = exceptions.UnknownProvisioningError( AttributeError, network_id='foo') with mock.patch.object(self.mixin, '_provision_tenant_private_network') as f: f.return_value = [{'network_id': 'foo'}] self._test__build_topology('_provision_external_connectivity', provisioning_exception)
def test__build_topology_error_network_with_router_and_interfaces(self): provisioning_exception = exceptions.UnknownProvisioningError( db_exc.DBConnectionError, network_id='foo_n', router_id='foo_r', subnets=[{'id': 'foo_s'}]) with mock.patch.object(self.mixin, '_provision_tenant_private_network') as f,\ mock.patch.object(self.mixin, '_provision_external_connectivity') as g: f.return_value = [{'network_id': 'foo_n'}] g.return_value = {'id': 'foo_r'} self._test__build_topology( '_save', provisioning_exception)
def _provision_tenant_private_network(self, context, tenant_id): """Create a tenant private network/subnets. CCloud specific: use specific cidr range instead of default subnetpool """ network = None try: network_args = { 'name': 'auto_allocated_network', 'admin_state_up': False, 'tenant_id': tenant_id, 'shared': False } network = p_utils.create_network(self.core_plugin, context, {'network': network_args}) subnets = [] subnet_args = { 'name': 'auto_allocated_subnet_v4', 'network_id': network['id'], 'tenant_id': tenant_id, 'ip_version': 4, 'cidr': '10.180.0.0/24', } subnets.append( p_utils.create_subnet(self.core_plugin, context, {'subnet': subnet_args})) return subnets except (c_exc.SubnetAllocationError, ValueError, n_exc.BadRequest, n_exc.NotFound) as e: LOG.error( "Unable to auto allocate topology for tenant " "%(tenant_id)s due to missing or unmet " "requirements. Reason: %(reason)s", { 'tenant_id': tenant_id, 'reason': e }) if network: self._cleanup(context, network['id']) raise exceptions.AutoAllocationFailure( reason=_("Unable to provide tenant private network")) except Exception as e: network_id = network['id'] if network else None raise exceptions.UnknownProvisioningError(e, network_id=network_id)
def test__build_topology_provisioning_error_network_only(self): provisioning_exception = exceptions.UnknownProvisioningError( Exception, network_id='foo') self._test__build_topology( '_provision_tenant_private_network', provisioning_exception)
def test__build_topology_provisioning_error_no_toplogy(self): provisioning_exception = exceptions.UnknownProvisioningError( db_exc.DBError) self._test__build_topology( '_provision_tenant_private_network', provisioning_exception)