def check(self): """Report any pending database upgrades. An exit code of 3 indicates db expand is needed, see stdout output. An exit code of 4 indicates db migrate is needed, see stdout output. An exit code of 5 indicates db contract is needed, see stdout output. """ engine = db_api.get_engine() self._validate_engine(engine) curr_heads = alembic_migrations.get_current_alembic_heads() expand_heads = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) contract_heads = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if (contract_heads in curr_heads): print(_('Database is up to date. No upgrades needed.')) sys.exit() elif ((not expand_heads) or (expand_heads not in curr_heads)): print( _('Your database is not up to date. ' 'Your first step is to run `glance-manage db expand`.')) sys.exit(3) elif data_migrations.has_pending_migrations(db_api.get_engine()): print( _('Your database is not up to date. ' 'Your next step is to run `glance-manage db migrate`.')) sys.exit(4) elif ((not contract_heads) or (contract_heads not in curr_heads)): print( _('Your database is not up to date. ' 'Your next step is to run `glance-manage db contract`.')) sys.exit(5)
def expand(self, online_migration=True): """Run the expansion phase of a database migration.""" if online_migration: self._validate_engine(db_api.get_engine()) curr_heads = alembic_migrations.get_current_alembic_heads() expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if not expand_head: sys.exit( _('Database expansion failed. Couldn\'t find head ' 'revision of expand branch.')) elif (contract_head in curr_heads): print(_('Database is up to date. No migrations needed.')) sys.exit() if expand_head not in curr_heads: self._sync(version=expand_head) curr_heads = alembic_migrations.get_current_alembic_heads() if expand_head not in curr_heads: sys.exit( _('Database expansion failed. Database expansion ' 'should have brought the database version up to ' '"%(e_rev)s" revision. But, current revisions are' ': %(curr_revs)s ') % { 'e_rev': expand_head, 'curr_revs': curr_heads }) else: print(_('Database expansion is up to date. No expansion needed.'))
def migrate(self, online_migration=True): """Run the data migration phase of a database migration.""" if online_migration: self._validate_engine(db_api.get_engine()) curr_heads = alembic_migrations.get_current_alembic_heads() contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if (contract_head in curr_heads): print(_('Database is up to date. No migrations needed.')) sys.exit() expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) if expand_head not in curr_heads: sys.exit( _('Data migration did not run. Data migration cannot be ' 'run before database expansion. Run database ' 'expansion first using "glance-manage db expand"')) if data_migrations.has_pending_migrations(db_api.get_engine()): rows_migrated = data_migrations.migrate(db_api.get_engine()) print(_('Migrated %s rows') % rows_migrated) else: print(_('Database migration is up to date. No migration needed.'))
def expand(self): """Run the expansion phase of a rolling upgrade procedure.""" engine = db_api.get_engine() if engine.engine.name != 'mysql': sys.exit( _('Rolling upgrades are currently supported only for ' 'MySQL')) expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) if not expand_head: sys.exit( _('Database expansion failed. Couldn\'t find head ' 'revision of expand branch.')) self.sync(version=expand_head) curr_heads = alembic_migrations.get_current_alembic_heads() if expand_head not in curr_heads: sys.exit( _('Database expansion failed. Database expansion should ' 'have brought the database version up to "%(e_rev)s" ' 'revision. But, current revisions are: %(curr_revs)s ') % { 'e_rev': expand_head, 'curr_revs': curr_heads })
def sync(self, version=None): """Perform a complete (offline) database migration""" global USE_TRIGGERS # This flags let's us bypass trigger setup & teardown for non-rolling # upgrades. We set this as a global variable immediately before handing # off to sqlalchemy-migrate, because we can't pass arguments directly # to migrations that depend on it. USE_TRIGGERS = False curr_heads = alembic_migrations.get_current_alembic_heads() contract = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if (contract in curr_heads): print(_('Database is up to date. No migrations needed.')) sys.exit() try: # NOTE(abhishekk): db_sync should not be used for online # migrations. self.expand(online_migration=False) self.migrate(online_migration=False) self.contract(online_migration=False) print(_('Database is synced successfully.')) except exception.GlanceException as e: sys.exit(_('Failed to sync database: ERROR: %s') % e)
def contract(self, online_migration=True): """Run the contraction phase of a database migration.""" if online_migration: self._validate_engine(db_api.get_engine()) curr_heads = alembic_migrations.get_current_alembic_heads() contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if not contract_head: sys.exit( _('Database contraction failed. Couldn\'t find head ' 'revision of contract branch.')) elif (contract_head in curr_heads): print(_('Database is up to date. No migrations needed.')) sys.exit() expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) if expand_head not in curr_heads: sys.exit( _('Database contraction did not run. Database ' 'contraction cannot be run before database expansion. ' 'Run database expansion first using ' '"glance-manage db expand"')) if data_migrations.has_pending_migrations(db_api.get_engine()): sys.exit( _('Database contraction did not run. Database ' 'contraction cannot be run before data migration is ' 'complete. Run data migration using "glance-manage db ' 'migrate".')) self._sync(version=contract_head) curr_heads = alembic_migrations.get_current_alembic_heads() if contract_head not in curr_heads: sys.exit( _('Database contraction failed. Database contraction ' 'should have brought the database version up to ' '"%(e_rev)s" revision. But, current revisions are: ' '%(curr_revs)s ') % { 'e_rev': expand_head, 'curr_revs': curr_heads })
def contract(self): """Run the contraction phase of a rolling upgrade procedure.""" engine = db_api.get_engine() if engine.engine.name != 'mysql': sys.exit( _('Rolling upgrades are currently supported only for ' 'MySQL')) contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) if not contract_head: sys.exit( _('Database contraction failed. Couldn\'t find head ' 'revision of contract branch.')) curr_heads = alembic_migrations.get_current_alembic_heads() expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) if expand_head not in curr_heads: sys.exit( _('Database contraction did not run. Database ' 'contraction cannot be run before database expansion. ' 'Run database expansion first using ' '"glance-manage db expand"')) if data_migrations.has_pending_migrations(db_api.get_engine()): sys.exit( _('Database contraction did not run. Database ' 'contraction cannot be run before data migration is ' 'complete. Run data migration using "glance-manage db ' 'migrate".')) self.sync(version=contract_head) curr_heads = alembic_migrations.get_current_alembic_heads() if contract_head not in curr_heads: sys.exit( _('Database contraction failed. Database contraction ' 'should have brought the database version up to ' '"%(e_rev)s" revision. But, current revisions are: ' '%(curr_revs)s ') % { 'e_rev': expand_head, 'curr_revs': curr_heads })
def test_sync(self): """Test DB sync which internally calls EMC""" self._db_command(db_method='sync') contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) cmd = ("sqlite3 {0} \"SELECT version_num FROM alembic_version\"" ).format(self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(contract_head, out.rstrip().decode("utf-8"))
def test_sync(self): """Test DB sync which internally calls EMC""" self._db_command(db_method='sync') contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) cmd = ( "sqlite3 {0} \"SELECT version_num FROM alembic_version\"").format( self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(contract_head, out.rstrip().decode("utf-8"))
def test_expand(self): """Test DB expand""" self._db_command(db_method='expand') expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) cmd = ("sqlite3 {0} \"SELECT version_num FROM alembic_version\"" ).format(self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(expand_head, out.rstrip().decode("utf-8")) exitcode, out, err = self._db_command(db_method='expand') self.assertIn('Database expansion is up to date. ' 'No expansion needed.', str(out))
def test_expand(self): """Test DB expand""" self._db_command(db_method='expand') expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) cmd = ( "sqlite3 {0} \"SELECT version_num FROM alembic_version\"").format( self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(expand_head, out.rstrip().decode("utf-8")) exitcode, out, err = self._db_command(db_method='expand') self.assertIn( 'Database expansion is up to date. ' 'No expansion needed.', out)
def test_contract(self): """Test DB contract""" self._db_command(db_method='expand') if data_migrations.has_pending_migrations(db_api.get_engine()): self._db_command(db_method='migrate') self._db_command(db_method='contract') contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) cmd = ( "sqlite3 {0} \"SELECT version_num FROM alembic_version\"").format( self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(contract_head, out.rstrip().decode("utf-8")) exitcode, out, err = self._db_command(db_method='contract') self.assertIn('Database is up to date. No migrations needed.', out)
def test_contract(self): """Test DB contract""" self._db_command(db_method='expand') if data_migrations.has_pending_migrations(db_api.get_engine()): self._db_command(db_method='migrate') self._db_command(db_method='contract') contract_head = alembic_migrations.get_alembic_branch_head( db_migration.CONTRACT_BRANCH) cmd = ("sqlite3 {0} \"SELECT version_num FROM alembic_version\"" ).format(self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(contract_head, out.rstrip().decode("utf-8")) exitcode, out, err = self._db_command(db_method='contract') self.assertIn('Database is up to date. No migrations needed.', str(out))
def migrate(self): engine = db_api.get_engine() if engine.engine.name != 'mysql': sys.exit( _('Rolling upgrades are currently supported only for ' 'MySQL')) curr_heads = alembic_migrations.get_current_alembic_heads() expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) if expand_head not in curr_heads: sys.exit( _('Data migration did not run. Data migration cannot be ' 'run before database expansion. Run database ' 'expansion first using "glance-manage db expand"')) rows_migrated = data_migrations.migrate(db_api.get_engine()) print(_('Migrated %s rows') % rows_migrated)
def test_migrate(self): """Test DB migrate""" self._db_command(db_method='expand') if data_migrations.has_pending_migrations(db_api.get_engine()): self._db_command(db_method='migrate') expand_head = alembic_migrations.get_alembic_branch_head( db_migration.EXPAND_BRANCH) cmd = ( "sqlite3 {0} \"SELECT version_num FROM alembic_version\"").format( self.db_filepath) exitcode, out, err = execute(cmd, raise_error=True) self.assertEqual(expand_head, out.rstrip().decode("utf-8")) self.assertEqual( False, data_migrations.has_pending_migrations(db_api.get_engine())) if data_migrations.has_pending_migrations(db_api.get_engine()): exitcode, out, err = self._db_command(db_method='migrate') self.assertIn( 'Database migration is up to date. No migration ' 'needed.', str(out))