sqlalchemy-migrate allows you to have multiple migration repos. For example, in keystone we have keystone/common/sql/migrate_repo for the main migrations and keystone/contrib/federation/migrate_repo for federation-related tables (federation used to be an extension and therefore could be disabled and you didn't run the migrations in this case).
oslo_db.sqlalchemy.migration.db_version() allows it to be called with different abs_paths, so for example in keystone we'll call it with 'keystone/common/sql/migrate_repo' and 'keystone/contrib/federation/migrate_repo'.
When db_version() is called if versioning_api.db_version() returns DatabaseNotControlledError it then goes on and tries to put it under control, but only if it doesn't have any tables.
Here's the problem, if you call db_version('common') and then db_version('federation')
1) db_version('common') puts 'common' under version control. The way this is done is that a table called 'migrate_version' is created which essentially says 'common' is version 0.
2) db_version('federation') checks if there are any tables, and since the 'migrate_version' table exists it doesn't try to put 'federation' under version control and instead fails.
I don't think this is working as designed. The call to db_version('federation') after db_version('common') should have put 'federation' under version control rather than failing.
db_version should ignore the 'migrate_version' table when checking to see if there are already tables in the database.
I should note that this change would break keystone's unit tests because for some reason it assumes this call fails.