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 test_has_pending_migrations_one_migration_with_pending( self, mock_find): mock_migration1 = mock.Mock() mock_migration1.has_migrations.return_value = True mock_find.return_value = [mock_migration1] self.assertTrue(data_migrations.has_pending_migrations(mock.Mock()))
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 test_has_pending_migrations_one_migration_with_pending(self, mock_find): mock_migration1 = mock.Mock() mock_migration1.has_migrations.return_value = True mock_find.return_value = [mock_migration1] self.assertTrue(data_migrations.has_pending_migrations(mock.Mock()))
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))
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.', out)
def test_has_pending_migrations_mult_migration_no_pending(self, mock_find): mock_migration1 = mock.Mock() mock_migration1.has_migrations.return_value = False mock_migration2 = mock.Mock() mock_migration2.has_migrations.return_value = False mock_migration3 = mock.Mock() mock_migration3.has_migrations.return_value = False mock_find.return_value = [mock_migration1, mock_migration2, mock_migration3] self.assertFalse(data_migrations.has_pending_migrations(mock.Mock()))
def test_has_pending_migrations_mult_migration_no_pending(self, mock_find): mock_migration1 = mock.Mock() mock_migration1.has_migrations.return_value = False mock_migration2 = mock.Mock() mock_migration2.has_migrations.return_value = False mock_migration3 = mock.Mock() mock_migration3.has_migrations.return_value = False mock_find.return_value = [ mock_migration1, mock_migration2, mock_migration3 ] self.assertFalse(data_migrations.has_pending_migrations(mock.Mock()))
def test_check(self): exitcode, out = self._check_db(3) self.assertEqual(3, exitcode) self._db_command(db_method='expand') if data_migrations.has_pending_migrations(db_api.get_engine()): exitcode, out = self._check_db(4) self.assertEqual(4, exitcode) self._db_command(db_method='migrate') exitcode, out = self._check_db(5) self.assertEqual(5, exitcode) self._db_command(db_method='contract') exitcode, out = self._check_db(0) self.assertEqual(0, exitcode)
def test_check(self): exitcode, out = self._check_db(3) self.assertEqual(3, exitcode) self._db_command(db_method='expand') if data_migrations.has_pending_migrations(db_api.get_engine()): exitcode, out = self._check_db(4) self.assertEqual(4, exitcode) self._db_command(db_method='migrate') exitcode, out = self._check_db(5) self.assertEqual(5, exitcode) self._db_command(db_method='contract') exitcode, out = self._check_db(0) self.assertEqual(0, exitcode)
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 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_has_pending_migrations_no_migrations(self, mock_find): mock_find.return_value = None self.assertFalse(data_migrations.has_pending_migrations(mock.Mock()))
def test_has_pending_migrations_no_migrations(self, mock_find): mock_find.return_value = None self.assertFalse(data_migrations.has_pending_migrations(mock.Mock()))