Comment 3 for bug 1731668

Revision history for this message
Jay Pipes (jaypipes) wrote :

OK, so I found the root cause of this problem.

Basically, what's going on is that we're checking for DBDuplicateError after running conn.execute(). And "conn" is an SQLAlchemy Connection object. The issue is that DBDuplicateError is not an SQLAlchemy exception. Instead, it is an oslo_db-specific exception that is used to mask differences between DB drivers that variably return an OperationalError or an IntegrityError when a duplicate key is found.

https://github.com/openstack/oslo.db/blob/master/oslo_db/sqlalchemy/exc_filters.py#L95-L108

In practice, what this means is that all calling locations that use the straight "conn.execute()" calling sequence cannot rely on catching DBDuplicateError (because SQLAlchemy's Connection.execute() method will never raise it). Instead, all of those calling locations need to be updated to use context.session.execute() instead. This will allow DBDuplicateError to be caught properly.

In addition, all the manual construction of transactions in resource_provider.py that do:

 with conn.begin()

will need to have those manual begin() calls removed. The reason is that oslo_db's Session object (which is what is injected by the enginefacade into the nova.context.RequestContext) automatically handles creation, commit and rollback of transactions based on whether the source entrypoint is a writer or reader context.