Fix _ensure_default_security_group logic
In a case when first attempt to fetch default security group fails and attempt to add it fails too due to a concurrent insertion, later attempt to fetch the same default sg may fail due to REPEATABLE READ transaction isolation level. For this case RetryRequest should be issued to restart the whole transaction and be able to see default group. The patch also removes 'while True' logic as it's unsafe Closes-Bug: #1475938 Change-Id: I20f65d3eae9421429aced1f4586cb6988ab577ff
This commit is contained in:
parent
194489b0f4
commit
80ee562dec
|
@ -13,7 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
import netaddr
|
||||
from oslo_db import exception
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
import sqlalchemy as sa
|
||||
|
@ -649,14 +649,23 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
|||
def _ensure_default_security_group(self, context, tenant_id):
|
||||
"""Create a default security group if one doesn't exist.
|
||||
|
||||
:returns: the default security group id.
|
||||
:returns: the default security group id for given tenant.
|
||||
"""
|
||||
query = self._model_query(context, DefaultSecurityGroup)
|
||||
# the next loop should do 2 iterations at max
|
||||
while True:
|
||||
# Make no more than two attempts
|
||||
for attempts in (1, 2):
|
||||
try:
|
||||
query = self._model_query(context, DefaultSecurityGroup)
|
||||
default_group = query.filter_by(tenant_id=tenant_id).one()
|
||||
except exc.NoResultFound:
|
||||
return default_group['security_group_id']
|
||||
except exc.NoResultFound as ex:
|
||||
if attempts > 1:
|
||||
# the second iteration means that attempt to add default
|
||||
# group failed with duplicate error. Since we're still
|
||||
# not seeing this group we're most probably inside a
|
||||
# transaction with REPEATABLE READ isolation level ->
|
||||
# need to restart the whole transaction
|
||||
raise db_exc.RetryRequest(ex)
|
||||
|
||||
security_group = {
|
||||
'security_group':
|
||||
{'name': 'default',
|
||||
|
@ -664,16 +673,13 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
|
|||
'description': _('Default security group')}
|
||||
}
|
||||
try:
|
||||
ret = self.create_security_group(
|
||||
security_group = self.create_security_group(
|
||||
context, security_group, default_sg=True)
|
||||
except exception.DBDuplicateEntry as ex:
|
||||
return security_group['id']
|
||||
except db_exc.DBDuplicateEntry as ex:
|
||||
# default security group was created concurrently
|
||||
LOG.debug("Duplicate default security group %s was "
|
||||
"not created", ex.value)
|
||||
continue
|
||||
else:
|
||||
return ret['id']
|
||||
else:
|
||||
return default_group['security_group_id']
|
||||
|
||||
def _get_security_groups_on_port(self, context, port):
|
||||
"""Check that all security groups on port belong to tenant.
|
||||
|
|
|
@ -563,6 +563,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
{'res': resource,
|
||||
'id': obj['result']['id']})
|
||||
|
||||
@oslo_db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
|
||||
retry_on_request=True)
|
||||
def _create_bulk_ml2(self, resource, context, request_items):
|
||||
objects = []
|
||||
collection = "%ss" % resource
|
||||
|
@ -1004,6 +1006,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
|
||||
return result, mech_context
|
||||
|
||||
@oslo_db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
|
||||
retry_on_request=True)
|
||||
def create_port(self, context, port):
|
||||
attrs = port[attributes.PORT]
|
||||
result, mech_context = self._create_port_db(context, port)
|
||||
|
|
Loading…
Reference in New Issue