def db_sync(engine, abs_path, version=None, init_version=0, sanity_check=True): """Upgrade or downgrade a database. Function runs the upgrade() or downgrade() functions in change scripts. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository. :param version: Database will upgrade/downgrade until this version. If None - database will update to the latest available version. :param init_version: Initial database version :param sanity_check: Require schema sanity checking for all tables """ if version is not None: try: version = int(version) except ValueError: raise exception.DbMigrationError( message=("version should be an integer")) current_version = db_version(engine, abs_path, init_version) repository = _find_migrate_repo(abs_path) if sanity_check: _db_schema_sanity_check(engine) if version is None or version > current_version: return versioning_api.upgrade(engine, repository, version) else: return versioning_api.downgrade(engine, repository, version)
def _find_migrate_repo(abs_path): """Get the project's change script repository :param abs_path: Absolute path to migrate repository """ if not os.path.exists(abs_path): raise exception.DbMigrationError("Path %s not found" % abs_path) return Repository(abs_path)
def get_manager(): storage_db = CONF['storage:sqlalchemy'].connection pool_manager_cache_db = CONF['pool_manager_cache:sqlalchemy'].connection if storage_db == pool_manager_cache_db: raise exception.DbMigrationError( message=("Pool Manager Cache requires its own database." " Please check your config file.")) else: return utils.get_migration_manager(REPOSITORY, pool_manager_cache_db)
def create_schema(config=None, engine=None): """Create database schema from models description. Can be used for initial installation instead of upgrade('head'). """ if engine is None: engine = enginefacade.get_legacy_facade().get_engine() # NOTE(viktors): If we will use metadata.create_all() for non empty db # schema, it will only add the new tables, but leave # existing as is. So we should avoid of this situation. if version(engine=engine) is not None: raise db_exc.DbMigrationError("DB schema is already under version" " control. Use upgrade() instead") models.Base.metadata.create_all(engine) stamp('head', config=config)
def upgrade(self, revision): """Upgrade database with all available backends.""" # a revision exists only in a single plugin. Until we reached it, we # should upgrade to the plugins' heads. # revision=None is a special case meaning latest revision. rev_in_plugins = [p.has_revision(revision) for p in self._plugins] if not any(rev_in_plugins) and revision is not None: raise exception.DbMigrationError('Revision does not exist') results = [] for plugin, has_revision in zip(self._plugins, rev_in_plugins): if not has_revision or revision is None: results.append(plugin.upgrade(None)) else: results.append(plugin.upgrade(revision)) break return results
def schema_create(self, config=None, engine=None): """Create database schema from models description. Can be used for initial installation instead of upgrade('head'). :param config: Instance of alembic config :param engine: Instance of DB engine """ engine = engine or get_engine() # NOTE(viktors): If we will use metadata.create_all() for non empty db # schema, it will only add the new tables, but leave # existing as is. So we should avoid of this situation. if self.schema_revision(engine=engine) is not None: raise db_exc.DbMigrationError("DB schema is already under version" " control. Use upgrade() instead") models.BASE.metadata.create_all(engine) self.schema_stamp("head", config=config)
def downgrade(self, revision): """Downgrade database with available backends.""" # a revision exists only in a single plugin. Until we reached it, we # should upgrade to the plugins' first revision. # revision=None is a special case meaning initial revision. rev_in_plugins = [p.has_revision(revision) for p in self._plugins] if not any(rev_in_plugins) and revision is not None: raise exception.DbMigrationError('Revision does not exist') # downgrading should be performed in reversed order results = [] for plugin, has_revision in zip(reversed(self._plugins), reversed(rev_in_plugins)): if not has_revision or revision is None: results.append(plugin.downgrade(None)) else: results.append(plugin.downgrade(revision)) break return results
def db_version(engine, abs_path, init_version): """Show the current version of the repository. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository :param version: Initial database version """ repository = _find_migrate_repo(abs_path) try: return versioning_api.db_version(engine, repository) except versioning_exceptions.DatabaseNotControlledError: meta = sqlalchemy.MetaData() meta.reflect(bind=engine) tables = meta.tables if len(tables) == 0 or 'alembic_version' in tables: db_version_control(engine, abs_path, version=init_version) return versioning_api.db_version(engine, repository) else: raise exception.DbMigrationError(message=( "The database is not under version control, but has " "tables. Please stamp the current version of the schema " "manually."))